⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmimg.cpp

📁 WDK 自带的xpsdrv filter之 color
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 2005 Microsoft Corporation

All rights reserved.

THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

File Name:

   cmimg.cpp

Abstract:

   Color managed image implementation. The CColorManagedImage class is responsible
   for managing the image resource for a stored bitmap. This implements
   the IResWriter interface so that the font can be added to the resource
   cache.

--*/

#include "precomp.h"
#include "debug.h"
#include "globals.h"
#include "xdstring.h"
#include "xdexcept.h"
#include "cmimg.h"
#include "streamcnv.h"

using XDPrintSchema::JobOptimalDestinationColorProfile::EProfileOption;
using XDPrintSchema::JobOptimalDestinationColorProfile::RGB;
using XDPrintSchema::JobOptimalDestinationColorProfile::CMYK;

/*++

Routine Name:

    CColorManagedImage::CColorManagedImage

Routine Description:

    Constructor for the CColorManagedImage class which registers internally the
    supplied resource URI and a pointer to the profile manager which will supply
    suitable color transforms to apply to that resource

Arguments:

    bstrResURI   - String containing the URI to the resource to be handled
    pProfManager - Pointer to a profile manager which will supply suitable
                   transforms to apply to the supplied resource

Return Value:

    None
    Throws CXDException(HRESULT) on an error

--*/
CColorManagedImage::CColorManagedImage(
    __in BSTR             bstrResURI,
    __in CProfileManager* pProfManager,
    __in IFixedPage*      pFixedPage,
    __in ResDeleteMap*    pResDel
    ) :
    m_pProfManager(pProfManager),
    m_pFixedPage(pFixedPage),
    m_bstrSrcProfileURI(NULL),
    m_pResDel(pResDel)
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pProfManager, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(m_pFixedPage, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(m_pResDel, E_POINTER)))
    {
        if (SysStringLen(bstrResURI) <= 0)
        {
            hr = E_INVALIDARG;
        }
    }

    if (SUCCEEDED(hr))
    {
        CComBSTR bstrAttribute(bstrResURI);

        if (bstrAttribute.Length() == 0)
        {
            hr = E_INVALIDARG;
        }
        else
        {
            try
            {
                //
                // Process the mark-up looking for the bitmap URI and any associated profiles
                //
                CStringXDW cstrAttribute(bstrResURI);
                CStringXDW cstrColConvBMP(L"{ColorConvertedBitmap ");

                cstrAttribute.Trim();
                INT cchFind = cstrAttribute.Find(cstrColConvBMP);

                if (cchFind == -1)
                {
                    //
                    // The mark-up is the bitmap URI
                    //
                    cstrAttribute.Trim();
                    m_bstrBitmapURI = cstrAttribute.AllocSysString();
                }
                else
                {
                    //
                    // The mark-up is specifying a profile associated with the image.
                    // Extract the path and set this in the profile manager. The markup takes
                    // the form "{ColorConvertedBitmap image.ext profile.icc}".
                    //

                    //
                    // Delete leading string "{ColorConvertedBitmap " and the trailing "}"
                    //
                    cstrAttribute.Delete(0, cstrColConvBMP.GetLength());
                    cstrAttribute.Delete(cstrAttribute.GetLength() - 1, 1);
                    cstrAttribute.Trim();

                    //
                    // Find the seperating space
                    //
                    cchFind = cstrAttribute.Find(L" ");

                    //
                    // Construct the bitmap URI
                    //
                    m_bstrBitmapURI = cstrAttribute.Left(cchFind).AllocSysString();

                    //
                    // Delete the bitmap URI and space leaving the profile URI
                    //
                    cstrAttribute.Delete(0, cchFind+1);

                    m_bstrSrcProfileURI = cstrAttribute.AllocSysString();
                }
            }
            catch (CXDException& e)
            {
                hr = e;
            }
        }
    }

    if (FAILED(hr))
    {
        throw CXDException(hr);
    }
}

/*++

Routine Name:

    CColorManagedImage::~CColorManagedImage

Routine Description:

    Default destructor for the CColorManagedImage class

Arguments:

    None

Return Value:

    None

--*/
CColorManagedImage::~CColorManagedImage()
{
}

/*++

Routine Name:

    CColorManagedImage::WriteData

Routine Description:

    This method handles the decoding of a bitmap, the colour
    translation applied to the bitmap and the re-encoding of the bitmap

Arguments:

    pStream - Pointer to a stream to write the resource out to

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorManagedImage::WriteData(
    __in IPartBase*         pResource,
    __in IPrintWriteStream* pStream
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pResource, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(pStream, E_POINTER)))
    {
        try
        {
            CComPtr<IUnknown>         pRead(NULL);
            CComPtr<IPartImage>       pImagePart(NULL);
            CComPtr<IPrintReadStream> pImageStream(NULL);

            //
            // Load the bitmap into memory and create a stream to read the bitmap from
            //
            if (SUCCEEDED(hr = m_pFixedPage->GetPagePart(m_bstrBitmapURI, &pRead)) &&
                SUCCEEDED(hr = pRead.QueryInterface(&pImagePart)) &&
                SUCCEEDED(hr = pImagePart->GetStream(&pImageStream)))
            {
                BOOL bApplyTransform = FALSE;
                CComPtr<IStream> pInputImageStream(NULL);

                EWICPixelFormat eDstPixFormat = kWICPixelFormatDontCare;
                UINT            cDstWidth  = 0;
                UINT            cDstHeight = 0;
                DOUBLE          dpiDstX = 0.0;
                DOUBLE          dpiDstY = 0.0;

                EProfileOption eProfileOption = RGB;

                //
                // Set up the source and destination bitmaps so they are ready for use by TranslateBitmapBits
                //
                pInputImageStream.Attach(new CPrintReadStreamToIStream(pImageStream));
                if (SUCCEEDED(hr = CHECK_POINTER(pInputImageStream, E_OUTOFMEMORY)) &&
                    SUCCEEDED(hr = m_srcBmp.Initialize(pInputImageStream)) &&
                    SUCCEEDED(hr = m_srcBmp.GetSize(&cDstWidth, &cDstHeight)) &&
                    SUCCEEDED(hr = m_srcBmp.GetResolution(&dpiDstX, &dpiDstY)) &&
                    SUCCEEDED(hr = m_pProfManager->GetProfileOption(&eProfileOption)))
                {
                    //
                    // The destination bitmap format can be one of:
                    //
                    //    kWICPixelFormat128bppRGBFloat  - scRGB output
                    //    kWICPixelFormat128bppRGBAFloat - scRGB output with a source alpha channel
                    //    kWICPixelFormat64bppCMYK       - CMYK output
                    //    kWICPixelFormat80bppCMYKAlpha  - CMYK output with a source alpha channel
                    //
                    BOOL bScRGBOut = FALSE;
                    switch (eProfileOption)
                    {
                        case RGB:
                        {
                            eDstPixFormat = m_srcBmp.HasAlphaChannel() ? kWICPixelFormat128bppRGBAFloat : kWICPixelFormat128bppRGBFloat;
                            bScRGBOut = TRUE;
                        }
                        break;

                        case CMYK:
                        {
                            eDstPixFormat = m_srcBmp.HasAlphaChannel() ? kWICPixelFormat40bppCMYKAlpha : kWICPixelFormat32bppCMYK;
                        }
                        break;

                        default:
                        {
                            RIP("Unrecognised destination profile option.\n");

                            hr = E_FAIL;
                        }
                        break;
                    }

                    if (SUCCEEDED(hr))
                    {
                        //
                        // If the input is scRGB and the output is scRGB just pass through the bitmap
                        // Note: This should be optimised we do not write out a new bitmap but use the original
                        //
                        if (eDstPixFormat == m_srcBmp.GetPixelFormat() &&
                            bScRGBOut)
                        {
                            m_dstBmp = m_srcBmp;
                        }
                        else if (SUCCEEDED(hr = m_dstBmp.Initialize(eDstPixFormat, cDstWidth, cDstHeight, dpiDstX, dpiDstY)))
                        {
                            bApplyTransform = TRUE;
                        }
                    }
                }

                //
                // Process the source and destination bitmaps a scanline at a time if the output image
                // is still not set
                //
                if (SUCCEEDED(hr) &&
                    bApplyTransform)
                {
                    //
                    // Create scanline iterator objects from the source and destination bitmaps
                    //
                    CScanIterator srcIter(m_srcBmp, NULL);
                    CScanIterator dstIter(m_dstBmp, NULL);

                    //
                    // Initialize the iterators, set the source profile and transform the scanlines
                    //
                    if (SUCCEEDED(hr = srcIter.Initialize(TRUE)) &&
                        SUCCEEDED(hr = dstIter.Initialize(FALSE)) &&
                        SUCCEEDED(hr = SetSrcProfile(&srcIter)) &&
                        SUCCEEDED(hr = TransformScanLines(&srcIter, &dstIter)))
                    {
                        //
                        // CMYK output requires an embedded profile
                        //
                        CComBSTR bstrProfile;
                        if (eProfileOption == CMYK &&
                            SUCCEEDED(hr = m_pProfManager->GetDstProfileName(&bstrProfile)))
                        {
                            hr = dstIter.SetProfile(bstrProfile);
                        }
                    }

                    if (SUCCEEDED(hr))
                    {
                        m_dstBmp = dstIter;
                    }

                    //
                    // If there's a problem loading a suitable source profile, just pass
                    // the bitmap through unmodified
                    //
                    if (hr == HRESULT_FROM_WIN32(ERROR_PROFILE_NOT_FOUND))
                    {
                        bApplyTransform = FALSE;
                        m_dstBmp = m_srcBmp;
                        hr = S_OK;
                    }
                }

                if (SUCCEEDED(hr))
                {
                    //
                    // Create a write stream to accept the converted bitmap, fill from the output bitmap
                    // and write to the output stream (after ensuring the stream is pointing to the start).
                    //
                    CComPtr<IStream> pOutputImageStream(NULL);

                    LARGE_INTEGER cbMoveFromStart = {0};

                    PBYTE pBuff = new BYTE[CB_COPY_BUFFER];

                    if (SUCCEEDED(hr = CHECK_POINTER(pBuff, E_OUTOFMEMORY)) &&
                        SUCCEEDED(hr = CreateStreamOnHGlobal(NULL, TRUE, &pOutputImageStream)) &&
                        SUCCEEDED(hr = m_dstBmp.Write(GUID_ContainerFormatWmp, pOutputImageStream)) &&
                        SUCCEEDED(hr = pOutputImageStream->Seek(cbMoveFromStart, STREAM_SEEK_SET, NULL)))
                    {
                        ULONG cbRead = 0;
                        ULONG cbWritten = 0;

                        while (SUCCEEDED(hr) &&
                               SUCCEEDED(hr = pOutputImageStream->Read(pBuff, CB_COPY_BUFFER, &cbRead)) &&
                               cbRead > 0)
                        {
                            hr = pStream->WriteBytes(pBuff, cbRead, &cbWritten);
                            ASSERTMSG(cbRead == cbWritten, "Failed to write all data.\n");
                        }
                    }

                    if (pBuff != NULL)
                    {
                        delete[] pBuff;
                        pBuff = NULL;
                    }
                }

                //
                // Set the content type of the image part
                //
                CComQIPtr<IPartImage> pImage = pResource;
                if (SUCCEEDED(hr) &&
                    SUCCEEDED(hr = CHECK_POINTER(pImage, E_NOINTERFACE)))
                {
                    hr = pImage->SetImageContent(CComBSTR(L"image/vnd.ms-photo"));
                }

                //
                // If all is well mark the replaced bitmap and profile for deletion
                //
                if (SUCCEEDED(hr))
                {
                    (*m_pResDel)[m_bstrBitmapURI.m_str] = TRUE;

                    if (m_bstrSrcProfileURI.Length() > 0)
                    {
                        (*m_pResDel)[m_bstrSrcProfileURI.m_str] = TRUE;
                    }
                }
            }
        }
        catch (CXDException& e)
        {
            hr = e;
        }
        catch (exception& DBG_ONLY(e))
        {
            ERR(e.what());
            hr = E_FAIL;
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -