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

📄 colchan.cpp

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

    Indicates if the color channel data includes an alpha channel

Arguments:

    None

Return Value:

    TRUE  - An alpha channel is present
    FALSE - There is no alpha channel

--*/
BOOL
CColorChannelData::HasAlpha(
    VOID
    )
{
    //
    // If the source or destination is n-channel, or if either sRGB or scRGB have 4 channels,
    // we have an alpha channel
    //
    return m_dataType == nChannel || m_cChannels == 4;
}

/*++

Routine Name:

    CColorChannelData::GetAlphaChannelSize

Routine Description:

    Retrieves the count of bytes of the alpha channel

Arguments:

    pcbAlphaChannel - pointer to a variable that recieves the count of bytes of the alpha channel

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::GetAlphaChannelSize(
    __out DWORD* pcbAlphaChan
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pcbAlphaChan, E_POINTER)))
    {
        *pcbAlphaChan = 0;
        if (HasAlpha())
        {
            hr = GetChannelSizeFromType(m_channelType, pcbAlphaChan);
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::InitializeAlphaChannel

Routine Description:

    Initialize the alpha channel based off a source color channel data object

Arguments:

    pSrcChannelData - Pointer to a source color data channel object

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::InitializeAlphaChannel(
    __in CColorChannelData* pSrcChannelData
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pSrcChannelData, E_POINTER)))
    {
        if (HasAlpha())
        {
            FLOAT alpha = 1.0f;
            if (SUCCEEDED(hr) &&
                pSrcChannelData->HasAlpha() &&
                SUCCEEDED(hr = pSrcChannelData->GetAlphaAsFloat(&alpha)))
            {
                //
                // Ensure alpha lies between 0.0 and 1.0
                //
                if (alpha < 0.0)
                {
                    alpha = 0.0;
                }
                else if (alpha > 1.0)
                {
                    alpha = 1.0;
                }
            }

            switch (m_channelType)
            {
                case COLOR_BYTE:
                {
                    *m_pChannelData = static_cast<BYTE>(alpha * kMaxByteAsFloat);
                }
                break;

                case COLOR_WORD:
                {
                    *reinterpret_cast<WORD*>(m_pChannelData) = static_cast<WORD>(alpha * kMaxWordAsFloat);
                }
                break;

                case COLOR_FLOAT:
                {
                    *reinterpret_cast<FLOAT*>(m_pChannelData) = alpha;
                }
                break;

                case COLOR_S2DOT13FIXED:
                {
                    hr = E_NOTIMPL;
                }
                break;

                default:
                {
                    RIP("Unrecognised channel data format.\n");
                    hr = E_FAIL;
                }
                break;
            }
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::GetColor

Routine Description:

    Retrieves a COLOR object based of the channel data

Arguments:

    pColor - Pointer to a color structure to be filled in
    pType  - Pointer to storage to accept the color type

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::GetColor(
    __out PCOLOR     pColor,
    __out COLORTYPE* pType
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pColor, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(pType, E_POINTER)))
    {
        if (m_cChannels == 0)
        {
            hr = E_PENDING;
        }
    }

    DWORD cChannels = 0;
    if (SUCCEEDED(hr) &&
        SUCCEEDED(hr = GetChannelCountNoAlpha(&cChannels)))
    {
        if (cChannels <= 4)
        {
            hr = ColorToWord(reinterpret_cast<PWORD>(pColor), static_cast<UINT>(sizeof(COLOR)));
        }
        else if (cChannels <= 8)
        {
            hr = ColorToByte(reinterpret_cast<PBYTE>(pColor), static_cast<UINT>(sizeof(COLOR)));
        }
        else
        {
            hr = E_FAIL;
        }

        if (SUCCEEDED(hr))
        {
            if (m_dataType == sRGB ||
                m_dataType == scRGB)
            {
                *pType = COLOR_RGB;
            }
            else if (m_dataType == nChannel)
            {
                *pType = static_cast<COLORTYPE>(cChannels + 3);
            }
            else
            {
                RIP("Unrecognised data type.\n");

                hr = E_FAIL;
            }
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::SetColor

Routine Description:

    Sets the channel data based on a COLOR structure

Arguments:

    pColor - Pointer to a color structure to set the channel data from
    type   - The color type described by the color structure

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::SetColor(
    __in COLOR*           pColor,
    __in CONST COLORTYPE& type
    )
{
    HRESULT hr = S_OK;

    DWORD cChannels = 0;
    DWORD cbData = 0;
    PBYTE pData = NULL;

    if (SUCCEEDED(hr = CHECK_POINTER(pColor, E_POINTER)) &&
        SUCCEEDED(hr = GetChannelCountNoAlpha(&cChannels)) &&
        SUCCEEDED(hr = GetChannelDataNoAlpha(&cbData, reinterpret_cast<PVOID*>(&pData))))
    {
        DWORD cSrcChannels = 0;

        switch (type)
        {
            case COLOR_RGB:
            {
                if (m_dataType == sRGB ||
                    m_dataType == scRGB)
                {
                    cSrcChannels = 3;
                }
                else
                {
                    hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
                }
            }
            break;

            case COLOR_3_CHANNEL:
            case COLOR_CMYK:
            case COLOR_5_CHANNEL:
            case COLOR_6_CHANNEL:
            case COLOR_7_CHANNEL:
            case COLOR_8_CHANNEL:
            {
                if (m_dataType == nChannel)
                {
                    cSrcChannels = static_cast<DWORD>(type - 3);
                }
                else
                {
                    hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
                }
            }
            break;

            case COLOR_GRAY:
            case COLOR_XYZ:
            case COLOR_Yxy:
            case COLOR_Lab:
            case COLOR_NAMED:
            {
                hr = E_NOTIMPL;
            }
            break;

            default:
            {
                RIP("Unrecognised color type\n");
                hr = E_FAIL;
            }
            break;
        }

        if (SUCCEEDED(hr))
        {
            if (cChannels == cSrcChannels)
            {
                if (cSrcChannels <= 4)
                {
                    hr = ColorFromWord(reinterpret_cast<PWORD>(pColor), sizeof(COLOR));
                }
                else if (cSrcChannels <= 8)
                {
                    hr = ColorFromByte(reinterpret_cast<PBYTE>(pColor), sizeof(COLOR));
                }
                else
                {
                    RIP("Invalid channel count\n");
                    hr = E_FAIL;
                }
            }
            else
            {
                RIP("Miss-match between source channel count and current channel count\n");
                hr = E_FAIL;
            }
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::ColorToByte

Routine Description:

    Converts the channel data to a 8 bpc COLOR type

Arguments:

    pDstData  - Pointer to the data to be set
    cbDstData - Size of the destination buffer

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::ColorToByte(
    __out_bcount(cbDstData) PBYTE      pDstData,
    __in                    CONST UINT cbDstData
    )
{
    HRESULT hr = S_OK;

    DWORD cChannels = 0;
    DWORD cbData = 0;
    PBYTE pData = NULL;

    if (SUCCEEDED(hr = CHECK_POINTER(pDstData, E_POINTER)) &&
        SUCCEEDED(hr = GetChannelCountNoAlpha(&cChannels)) &&
        SUCCEEDED(hr = GetChannelDataNoAlpha(&cbData, reinterpret_cast<PVOID*>(&pData))))
    {
        ZeroMemory(pDstData, cbDstData);

        if (cbDstData < cChannels)
        {
            hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
        }
    }

    if (SUCCEEDED(hr))
    {
        if (cbDstData > 0)
        {
            switch (m_channelType)
            {
                case COLOR_BYTE:
                {
                    if (cbDstData >= cbData)
                    {
                        //
                        // Just copy all channels after alpha into the buffer
                        //
                        CopyMemory(pDstData, pData, cbData);
                    }
                    else
                    {
                        hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
                    }
                }
                break;

                case COLOR_WORD:
                {
                    if (cbDstData >= cChannels * sizeof(BYTE) &&
                        cbData    >= cChannels * sizeof(WORD))
                    {
                        PWORD pSrcData = reinterpret_cast<PWORD>(pData);

                        for (UINT cCurrChan = 0;
                             cCurrChan < cChannels;
                             cCurrChan++)
                        {
                            pDstData[cCurrChan] = static_cast<BYTE>(MulDiv(pSrcData[cCurrChan], 0xFF, 0xFFFF));
                        }
                    }
                    else
                    {
                        hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
                    }
                }
                break;

                case COLOR_FLOAT:
                {
                    //
                    // Make sure the float data runs between 0.0 and 1.0 for nChannel and sRGB and is
                    // truncated and scaled as follows for scRGB:
                    //
                    //    1. Truncate the input color to between -2.0 and +2.0
                    //    2. Offset the value by +2.0 to put it into the 0.0 to 4.0 range
                    //    3. Scale the value down by 4.0 to put it into the range 0.0 to 1.0
                    //    4. Set the 16 bit value according to the channel value from 0x00
                    //       for 0.0 to 0xFF for 1.0
                    //
                    if (cbDstData >= cChannels * sizeof(BYTE) &&
                        cbData    >= cChannels * sizeof(FLOAT))
                    {
                        PFLOAT pSrcData = reinterpret_cast<PFLOAT>(pData);

                        if (m_dataType == scRGB)
                        {
                            for (UINT cCurrChan = 0;
                                 cCurrChan < cChannels;
                                 cCurrChan++)
                            {
                                FLOAT channelValue = pSrcData[cCurrChan];
                                channelValue = channelValue < -2.0f ? -2.0f : channelValue;
                                channelValue = channelValue >  2.0f ?  2.0f : channelValue;
                                channelValue += 2.0f;
                                channelValue /= 4.0f;
                                pDstData[cCurrChan] = static_cast<BYTE>(channelValue * kMaxByteAsFloat);
                            }
                        }
                        else
                        {
                            if (SUCCEEDED(hr = ClampChannelValues(0.0f, 1.0f)))
                            {
                                for (UINT cCurrChan = 0;
                                     cCurrChan < cChannels;
                                     cCurrChan++)
                                {
                                    pDstData[cCurrChan] = static_cast<BYTE>(pSrcData[cCurrChan] * kMaxByteAsFloat);
                                }
                            }
                        }
                    }
                    else
                    {
                        hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
                    }
                }
                break;

                case COLOR_S2DOT13FIXED:
                {
                    hr = E_NOTIMPL;
                }
                break;

                default:
                {
                    RIP("Unrecognised color type\n");
                    hr = E_FAIL;
                }
                break;
            }
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorChannelData::ColorToWord

Routine Description:

    Converts the channel data to a 16 bpc COLOR type

Arguments:

    pDstData  - Pointer to the data to be set
    cbDstData - Size of the destination buffer

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorChannelData::ColorToWord(
    __out_bcount(cbDstData) PWORD      pDstData,
    __in                    CONST UINT cbDstData
    )
{
    HRESULT hr = S_OK;

    DWORD cChannels = 0;
    DWORD cbData = 0;
    PBYTE pData = NULL;

    if (SUCCEEDED(hr = CHECK_POINTER(pDstData, E_POINTER)) &&
        SUCCEEDED(hr = GetChannelCountNoAlpha(&cChannels)) &&
        SUCCEEDED(hr = GetChannelDataNoAlpha(&cbData, reinterpret_cast<PVOID*>(&pData))))
    {
        ZeroMemory(pDstData, cbDstData);

        if (cbDstData < cChannels)
        {
            hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
        }
    }

    if (SUCCEEDED(hr))
    {
        if (cbDstData > 0)
        {
            switch (m_channelType)
            {
                case COLOR_BYTE:
                {
                    if (cbDstData >= cChannels * sizeof(WORD) &&
                        cbData    >= cChannels * sizeof(BYTE))
                    {
                        for (UINT cCurrChan = 0;
                             cCurrChan < cChannels;
                             cCurrChan++)
                        {
                            pDstData[cCurrChan] = static_cast<WORD>(MulDiv(pData[cCurrChan], 0xFFFF, 0xFF));
                        }
                    }
                    else
                    {
                        hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
                    }
                }
                break;

                case COLOR_WORD:
                {
                    if (cbDstData - cbData > 0)
                    {
                        //
                        // Just copy all channels after alpha into the COLOR structure
                        //
                        CopyMemory(pDstData, pData, cbData);
                    }
                    else
                    {
                        hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
                    }
                }
                break;

                case COLOR_FLOAT:
                {
                    //

⌨️ 快捷键说明

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