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

📄 bmpconv.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:

   bmpconv.cpp

Abstract:

   WIC bitmap conversion class implementation. This class provides a wrapper to a bitmap
   stream that uses WIC to access bitmap data and provide conversion functionality.

--*/

#include "precomp.h"
#include "debug.h"
#include "globals.h"
#include "xdstring.h"
#include "xdexcept.h"
#include "bmpconv.h"

/*++

Routine Name:

    CBmpConverter::CBmpConverter

Routine Description:

    CBmpConverter default constructor

Arguments:

    None

Return Value:

    None
    Throws an exception on error.

--*/
CBmpConverter::CBmpConverter() :
    m_pImagingFactory(NULL),
    m_pBitmap(NULL),
    m_pColorContext(NULL),
    m_pCurrentLock(NULL),
    m_ePixelFormat(kWICPixelFormatDontCare)
{
    //
    // Make sure we have an imaging factory to work with
    //
    HRESULT hr = CreateImagingFactory();
    if (FAILED(hr))
    {
        throw CXDException(hr);
    }
}

/*++

Routine Name:

    CBmpConverter::CBmpConverter

Routine Description:

    CBmpConverter constructor

Arguments:

    ePixFormat - Bitmap pixel format
    cWidth     - Bitmap width
    cHeight    - Bitmap height
    dpiX       - Bitmap horizontal resolution
    dpiY       - Bitmap vertical resolution

Return Value:

    None
    Throws an exception on error.

--*/
CBmpConverter::CBmpConverter(
    __in CONST EWICPixelFormat& ePixFormat,
    __in CONST UINT&            cWidth,
    __in CONST UINT&            cHeight,
    __in CONST DOUBLE&          dpiX,
    __in CONST DOUBLE&          dpiY
    ) :
    m_pImagingFactory(NULL),
    m_pBitmap(NULL),
    m_pColorContext(NULL),
    m_pCurrentLock(NULL),
    m_ePixelFormat(ePixFormat)
{
    HRESULT hr = S_OK;

    //
    // Make sure we have an imaging factory to work with...
    //
    if (SUCCEEDED(hr = CreateImagingFactory()))
    {
        //
        // ...and that the underlying bitmap is created and intialized.
        //
        hr = Initialize(m_ePixelFormat, cWidth, cHeight, dpiX, dpiY);
    }

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

/*++

Routine Name:

    CBmpConverter::CBmpConverter

Routine Description:

    CBmpConverter constructor

Arguments:

    pStream - Stream containing the bitmap container data

Return Value:

    None
    Throws an exception on error.

--*/
CBmpConverter::CBmpConverter(
    __in IStream* pStream
    ) :
    m_pImagingFactory(NULL),
    m_pBitmap(NULL),
    m_pColorContext(NULL),
    m_pCurrentLock(NULL),
    m_ePixelFormat(kWICPixelFormatDontCare)
{
    HRESULT hr = S_OK;

    //
    // Make sure we have an imaging factory to work with...
    //
    if (SUCCEEDED(hr = CreateImagingFactory()))
    {
        //
        // ...and that the underlying bitmap is created and intialized from the input stream.
        //
        hr = Initialize(pStream);
    }

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

/*++

Routine Name:

    CBmpConverter::CBmpConverter

Routine Description:

    CBmpConverter constructor

Arguments:

    converter - Converter class to construct from

Return Value:

    None
    Throws an exception on error.

--*/
CBmpConverter::CBmpConverter(
    __in CONST CBmpConverter& converter
    ) :
    m_pImagingFactory(converter.m_pImagingFactory),
    m_pBitmap(converter.m_pBitmap),
    m_pColorContext(converter.m_pColorContext),
    m_pCurrentLock(converter.m_pCurrentLock),
    m_ePixelFormat(converter.m_ePixelFormat)
{
    ASSERTMSG(m_pCurrentLock == NULL, "Copying locked bitmap can lead to a deadlock when writing out the bitmap.\n");
}

/*++

Routine Name:

    CBmpConverter::~CBmpConverter

Routine Description:

    CBmpConverter destructor

Arguments:

    None

Return Value:

    None

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

/*++

Routine Name:

    CBmpConverter::Initialize

Routine Description:

    Initializes the bitmap given format, dimensions and resolution

Arguments:

    ePixFormat - Bitmap pixel format
    cWidth     - Bitmap width
    cHeight    - Bitmap height
    dpiX       - Bitmap horizontal resolution
    dpiY       - Bitmap vertical resolution

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CBmpConverter::Initialize(
    __in CONST EWICPixelFormat& ePixFormat,
    __in CONST UINT&            cWidth,
    __in CONST UINT&            cHeight,
    __in CONST DOUBLE&          dpiX,
    __in CONST DOUBLE&          dpiY
    )
{
    HRESULT hr = S_OK;

    if (ePixFormat <= kWICPixelFormatMin ||
        ePixFormat >= kWICPixelFormatMax ||
        cWidth == 0 ||
        cHeight == 0 ||
        dpiX <= 0 ||
        dpiY <= 0)
    {
        hr = E_INVALIDARG;
    }

    if (SUCCEEDED(hr) &&
        SUCCEEDED(hr = CHECK_POINTER(m_pImagingFactory, E_PENDING)))
    {
        //
        // Create the bitmap
        //
        m_pBitmap = NULL;
        m_ePixelFormat = ePixFormat;
        if (SUCCEEDED(hr = m_pImagingFactory->CreateBitmap(cWidth,
                                                           cHeight,
                                                           g_lutPixFrmtGuid[m_ePixelFormat],
                                                           WICBitmapCacheOnLoad,
                                                           &m_pBitmap)) &&
            SUCCEEDED(hr = CHECK_POINTER(m_pBitmap, E_FAIL)))
        {
            //
            // Make sure the resolution is preserved - this can lead to strange scaling
            // in an XPS document if the resoution changes
            //
            hr = m_pBitmap->SetResolution(dpiX, dpiY);
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CBmpConverter::Initialize

Routine Description:

    Initializes the bitmap from a stream containing the container information

Arguments:

    pStream - Streamed container information

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CBmpConverter::Initialize(
    __in IStream* pStream
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pStream, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(m_pImagingFactory, E_PENDING)))
    {
        CComPtr<IWICBitmapDecoder> pDecoder(NULL);
        CComPtr<IWICBitmapFrameDecode> pBitmapSrcFrame(NULL);
        LARGE_INTEGER cbMoveFromStart = {0};

        //
        // Ensure we have released any current color contexts
        //
        m_pColorContext = NULL;

        //
        // Create a decoder from the input stream and retrieve the first frame. Create a color context
        // to recieve any potential embedded color profiles.
        //
        if (SUCCEEDED(hr = pStream->Seek(cbMoveFromStart, STREAM_SEEK_SET, NULL)) &&
            SUCCEEDED(hr = m_pImagingFactory->CreateDecoderFromStream(pStream, NULL, WICDecodeMetadataCacheOnDemand, &pDecoder)) &&
            SUCCEEDED(hr = CHECK_POINTER(pDecoder, E_FAIL)) &&
            SUCCEEDED(hr = pDecoder->GetFrame(0, &pBitmapSrcFrame)) &&
            SUCCEEDED(hr = CHECK_POINTER(pDecoder, E_FAIL)) &&
            SUCCEEDED(hr = m_pImagingFactory->CreateColorContext(&m_pColorContext)) &&
            SUCCEEDED(hr = CHECK_POINTER(m_pColorContext, E_FAIL)))
        {
            //
            // Check for an embedded color context
            //
            UINT cColContexts = 0;
            if (SUCCEEDED(hr = pBitmapSrcFrame->GetColorContexts(1, &(m_pColorContext.p), &cColContexts)))
            {
                //
                // If there are no color contexts, ensure the color context is released
                //
                if (cColContexts == 0)
                {
                    m_pColorContext = NULL;
                }

                hr = Initialize(pBitmapSrcFrame);
            }
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CBmpConverter::Initialize

Routine Description:

    Intializes the bitmap from a WIC bitmap source

Arguments:

    pSource - pointer to the WIC bitmap source interface to intialize from

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CBmpConverter::Initialize(
    __in IWICBitmapSource* pSource
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pSource, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(m_pImagingFactory, E_PENDING)))
    {
        //
        // Make sure we have released any current bitmaps
        //
        m_pBitmap = NULL;

        //
        // Create the bitmap from the source and set the pixel format enumeration from the GUID
        //
        WICPixelFormatGUID guidPixFormat;
        if (SUCCEEDED(hr = m_pImagingFactory->CreateBitmapFromSource(pSource, WICBitmapCacheOnDemand, &m_pBitmap)) &&
            SUCCEEDED(hr = CHECK_POINTER(m_pBitmap, E_FAIL)) &&
            SUCCEEDED(hr = m_pBitmap->GetPixelFormat(&guidPixFormat)))
        {
            hr = PixelFormatFromGUID(guidPixFormat, &m_ePixelFormat);
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CBmpConverter::Write

Routine Description:

    Writes the bitmap to a stream using the requested container format

Arguments:

    guidContainerFormat - Requested container format to write out
    pStream             - The destination stream to write to

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CBmpConverter::Write(
    __in    REFGUID  guidContainerFormat,
    __inout IStream* pStream
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pStream, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(m_pBitmap, E_PENDING)) &&
        SUCCEEDED(hr = CHECK_POINTER(m_pImagingFactory, E_PENDING)))
    {
        CComPtr<IWICBitmapEncoder>     pEncoder(NULL);
        CComPtr<IWICBitmapFrameEncode> pFrame(NULL);
        CComPtr<IPropertyBag2>         pPropertyBag(NULL);

        UINT srcWidth = 0;
        UINT srcHeight = 0;

        DOUBLE xRes = 0.0;
        DOUBLE yRes = 0.0;

        WICPixelFormatGUID srcFormat;

        //
        // Create the appropriate encoder, set the stream to recieve the data and retrieve a frame.
        // Initialize the frame from the current bitmap data.
        //
        if (SUCCEEDED(hr = m_pImagingFactory->CreateEncoder(guidContainerFormat, NULL, &pEncoder)) &&
            SUCCEEDED(hr = pEncoder->Initialize(pStream, WICBitmapEncoderNoCache)) &&
            SUCCEEDED(hr = pEncoder->CreateNewFrame(&pFrame, &pPropertyBag)) &&
            SUCCEEDED(hr = CHECK_POINTER(pFrame, E_FAIL)) &&
            SUCCEEDED(hr = CHECK_POINTER(pPropertyBag, E_FAIL)) &&
            SUCCEEDED(hr = pFrame->Initialize(pPropertyBag)) &&
            SUCCEEDED(hr = m_pBitmap->GetSize(&srcWidth, &srcHeight)) &&
            SUCCEEDED(hr = m_pBitmap->GetResolution(&xRes, &yRes)) &&
            SUCCEEDED(hr = m_pBitmap->GetPixelFormat(&srcFormat)))
        {
            WICRect sizeSrc = {0};
            sizeSrc.Width  = static_cast<INT>(srcWidth);
            sizeSrc.Height = static_cast<INT>(srcHeight);

            if (SUCCEEDED(hr = pFrame->SetSize(srcWidth, srcHeight)) &&
                SUCCEEDED(hr = pFrame->SetResolution(xRes, yRes)) &&
                SUCCEEDED(hr = pFrame->SetPixelFormat(&srcFormat)))
            {
                if (HasColorContext())
                {
                    hr = pFrame->SetColorContexts(1, &m_pColorContext.p);
                }

                if (SUCCEEDED(hr))
                {
                    //
                    // Write the bitmap data to the frame.
                    //
                    hr = pFrame->WriteSource(m_pBitmap, &sizeSrc);
                }
            }
        }

        //
        // Commit the frame and the encoder - this sets the bitmap data and encodes the
        // bitmap into a container
        //
        if (SUCCEEDED(hr) &&
            SUCCEEDED(hr = pFrame->Commit()))
        {
            hr = pEncoder->Commit();
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CBmpConverter::Convert

Routine Description:

    Uses WIC to convert from the current pixel format to the requested pixel format

Arguments:

    ePixFormat   - the requested pixel format
    pbCanConvert - variable that recieves whether the conversion is possible

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CBmpConverter::Convert(
    __in  EWICPixelFormat ePixFormat,
    __out BOOL*           pbCanConvert
    )
{
    HRESULT hr = S_OK;

    if (ePixFormat > kWICPixelFormatDontCare &&
        ePixFormat < kWICPixelFormatMax)
    {
        if (SUCCEEDED(hr = CHECK_POINTER(pbCanConvert, E_POINTER)))
        {
            *pbCanConvert = TRUE;
        }
    }
    else
    {
        hr = E_INVALIDARG;
    }

    //
    // If the requested format differs from the original we need to do some work.
    //
    if (SUCCEEDED(hr) &&
        ePixFormat != m_ePixelFormat)
    {
        CComPtr<IWICFormatConverter> pConverter(NULL);

        WICPixelFormatGUID dstFormat = g_lutPixFrmtGuid[ePixFormat];
        WICPixelFormatGUID srcFormat;

        //
        // Retrieve a format converter, intialize from the current bitmap the use the converter
        // to reset the bitmap to the appropriate type.
        //
        if (SUCCEEDED(hr) &&
            SUCCEEDED(hr = CHECK_POINTER(m_pImagingFactory, E_PENDING)) &&
            SUCCEEDED(hr = CHECK_POINTER(m_pBitmap, E_PENDING)) &&
            SUCCEEDED(hr = m_pImagingFactory->CreateFormatConverter(&pConverter)) &&
            SUCCEEDED(hr = CHECK_POINTER(pConverter, E_FAIL)) &&
            SUCCEEDED(hr = m_pBitmap->GetPixelFormat(&srcFormat)) &&
            SUCCEEDED(hr = pConverter->CanConvert(srcFormat, dstFormat, pbCanConvert)) &&
            *pbCanConvert &&
            SUCCEEDED(hr = pConverter->Initialize(m_pBitmap, dstFormat, WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeCustom)))
        {
            hr = Initialize(pConverter);
        }
    }

⌨️ 快捷键说明

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