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

📄 colchan.cpp

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

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:

   colchan.cpp

Abstract:

   Color channel class implementation. The color channel class is responsible for maintaining
   simple single color multiple channel data intialised from color references in the XPS markup.
   It provides methods for intialization, access and conversion of the data.

   Note regarding color formats: The CColorChannelData class is only used in the filter for
   processing color references in mark-up. As such we only ever see 8 bit per channel sRGB and
   floating point scRGB and n-channel colors and we only ever need convert to 16 bpc for
   down-level scRGB conversion. If the CColorChannelData is ever used when fixed point input
   or other output types are required then these formats need support added (see E_NOTIMPL
   return values).

--*/

#include "precomp.h"
#include "debug.h"
#include "globals.h"
#include "xdexcept.h"
#include "colchan.h"

#define MAX_CHANNEL_COUNT 9 // 1 alpha channel and 8 color channels
#define MAX_CHANNEL_SIZE  sizeof(FLOAT)

DWORD g_cbChannelType[] = {
    sizeof(BYTE),  // COLOR_BYTE
    sizeof(WORD),  // COLOR_WORD
    sizeof(FLOAT), // COLOR_FLOAT
    sizeof(WORD)   // COLOR_S2DOT13FIXED
};


/*++

Routine Name:

    CColorChannelData::CColorChannelData

Routine Description:

    CColorChannelData default constructor

Arguments:

    None

Return Value:

    None
    Throws an exception on failure.

--*/
CColorChannelData::CColorChannelData() :
    m_cChannels(0),
    m_channelType(COLOR_BYTE),
    m_pChannelData(NULL),
    m_cbChannelData(0),
    m_dataType(sRGB)
{
    if (FAILED(AllocateChannelBuffers(&m_cbChannelData, &m_pChannelData)))
    {
        throw CXDException(E_OUTOFMEMORY);
    }
}

/*++

Routine Name:

    CColorChannelData::~CColorChannelData

Routine Description:

    CColorChannelData destructor

Arguments:

    None

Return Value:

    None

--*/
CColorChannelData::~CColorChannelData()
{
    FreeChannelBuffers();
}

/*++

Routine Name:

    CColorChannelData::AddChannelData

Routine Description:

    Template method for adding channel data. This allows any of the available color
    channel data types to be added to the channel data buffer

Arguments:

    channelValue - Value for the channel to be added

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
template <class _T>
HRESULT
CColorChannelData::AddChannelData(
    __in CONST _T& channelValue
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = ValidateDataSize<_T>()))
    {
        if (m_cChannels < MAX_CHANNEL_COUNT)
        {
            _T* pChannelData = reinterpret_cast<_T*>(m_pChannelData);
            pChannelData[m_cChannels] = channelValue;
            m_cChannels++;
        }
        else
        {
            hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::GetChannelCount

Routine Description:

    Retrieves the current number of channels defining the color.

Arguments:

    pcChannels - Pointer to a variable that recieves the count of channels

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::GetChannelCount(
    __out DWORD* pcChannels
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pcChannels, E_POINTER)))
    {
        *pcChannels = m_cChannels;
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::GetChannelCountNoAlpha

Routine Description:

    Retrieves the number of channels less the alpha channel if present

Arguments:

    pcChannels - Pointer to a variable that recieves the count of non-alpha channels

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::GetChannelCountNoAlpha(
    __out DWORD* pcChannels
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = GetChannelCount(pcChannels)))
    {
        if (HasAlpha())
        {
            (*pcChannels)--;
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::GetChannelType

Routine Description:

    Retrieves the COLORDATATYPE for the channel data

Arguments:

    pChannelType - Pointer to a COLORDATATYPE variable that recieves the type

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::GetChannelType(
    __out COLORDATATYPE* pChannelType
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pChannelType, E_POINTER)))
    {
        *pChannelType = m_channelType;
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::ResetChannelType

Routine Description:

    Resets the underlying channel data type to the requested type

Arguments:

    channelType - The channel data type to reset to

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::ResetChannelType(
    __in CONST COLORDATATYPE& channelType
    )
{
    m_channelType = channelType;
    m_cChannels = 0;

    return S_OK;
}

/*++

Routine Name:

    CColorChannelData::GetChannelData

Routine Description:

    Retrieves the buffer and count of bytes of the channel data

Arguments:

    pcbDataSize - Pointer to variable that recieves the count of bytes in the buffer
    ppData      - Pointer to a BYTE pointer that recieves the buffer

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::GetChannelData(
    __out                            DWORD* pcbDataSize,
    __deref_out_bcount(*pcbDataSize) PVOID* ppData
    )
{
    HRESULT hr = S_OK;

    DWORD cbDataTypeSize = 0;
    if (SUCCEEDED(hr = CHECK_POINTER(pcbDataSize, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(ppData, E_POINTER)) &&
        SUCCEEDED(hr = GetChannelSizeFromType(m_channelType, &cbDataTypeSize)))
    {
        *ppData = NULL;
        *pcbDataSize = 0;

        if (m_cbChannelData >= m_cChannels * cbDataTypeSize)
        {
            if (m_cChannels > 0)
            {
                *pcbDataSize = m_cChannels * cbDataTypeSize;
                *ppData = m_pChannelData;
            }
        }
        else
        {
            hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::GetChannelDataNoAlpha

Routine Description:

    Retrieves the buffer and count of bytes of the channel data excluding the
    alpha channel if present

Arguments:

    pcbDataSize - Pointer to variable that recieves the count of bytes in the buffer
    ppData      - Pointer to a BYTE pointer that recieves the buffer

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::GetChannelDataNoAlpha(
    __out                            DWORD* pcbDataSize,
    __deref_out_bcount(*pcbDataSize) PVOID* ppData
    )
{
    HRESULT hr = S_OK;

    DWORD cbData = 0;
    PBYTE pData  = NULL;

    if (SUCCEEDED(hr = CHECK_POINTER(pcbDataSize, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(ppData, E_POINTER)) &&
        SUCCEEDED(hr = GetChannelData(&cbData, reinterpret_cast<PVOID*>(&pData))))
    {
        *pcbDataSize = cbData;
        *ppData = pData;

        if (HasAlpha())
        {
            DWORD cbChannelSize = 0;
            if (SUCCEEDED(hr = GetChannelSizeFromType(m_channelType, &cbChannelSize)))
            {
                if (cbData >= cbChannelSize)
                {
                    *pcbDataSize = cbData - cbChannelSize;
                    *ppData = pData + cbChannelSize;
                }
                else
                {
                    hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
                }
            }
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::ClampChannelValues

Routine Description:

    Template method that recieves the minimum and maximum value for a channel
    and applies this to all channels defining the color

Arguments:

    min - Minimum channel value
    max - Maximum channel value

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
template <class _T>
HRESULT
CColorChannelData::ClampChannelValues(
    __in CONST _T& min,
    __in CONST _T& max
    )
{
    HRESULT hr = S_OK;

    //
    // Validate the data size against the current type
    //
    if (SUCCEEDED(hr = ValidateDataSize<_T>()))
    {
        _T* pData = reinterpret_cast<_T*>(m_pChannelData);
        for (DWORD cChannel = 0; cChannel < m_cChannels; cChannel++, pData++)
        {
            if (*pData < min)
            {
                *pData = min;
            }
            else if (*pData > max)
            {
                *pData = max;
            }
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::InitializeChannelData

Routine Description:

    Initializes the channel data according to the type, count of channels and a default value

Arguments:

    channelType  - The required channel data format
    dataType     - The required data type
    cChannels    - The count of channels defining the color
    channelValue - The intial value for all channels

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
template <class _T>
HRESULT
CColorChannelData::InitializeChannelData(
    __in CONST COLORDATATYPE&  channelType,
    __in CONST EColorDataType& dataType,
    __in CONST DWORD&          cChannels,
    __in CONST _T&             channelValue
    )
{
    HRESULT hr = S_OK;

    //
    // Validate the data size against the current type
    //
    if (SUCCEEDED(hr = ResetChannelType(channelType)) &&
        SUCCEEDED(hr = ValidateDataSize<_T>()))
    {
        if (cChannels <= MAX_CHANNEL_COUNT)
        {
            m_dataType = dataType;
            m_cChannels = cChannels;
            _T* pChannelData = reinterpret_cast<_T*>(m_pChannelData);

            for (DWORD cChannel = 0; cChannel < m_cChannels; cChannel++, pChannelData++)
            {
                *pChannelData = channelValue;
            }
        }
        else
        {
            hr = E_INVALIDARG;
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::SetColorDataType

Routine Description:

    Sets the color data type

Arguments:

    dataType - The color data type

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::SetColorDataType(
    __in CONST EColorDataType& dataType
    )
{
    m_dataType = dataType;

    return S_OK;
}

/*++

Routine Name:

    CColorChannelData::GetColorDataType

Routine Description:

    Retrieves the current color data type

Arguments:

    pDataType - Pointer to a variable to recieve the color data type

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::GetColorDataType(
    EColorDataType* pDataType
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pDataType, E_POINTER)))
    {
        *pDataType = m_dataType;
    }

    return S_OK;
}

/*++

Routine Name:

    CColorChannelData::HasAlpha

Routine Description:

⌨️ 快捷键说明

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