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

📄 colconv.cpp

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

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorRefConverter::InitDstChannels(
    __in    CColorChannelData* pChannelDataSrc,
    __inout CColorChannelData* pChannelDataDst
    )
{
    HRESULT hr = S_OK;

    EProfileOption profileType = RGB;
    if (SUCCEEDED(hr = CHECK_POINTER(pChannelDataSrc, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(pChannelDataDst, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(m_pProfManager, E_FAIL)) &&
        SUCCEEDED(hr = m_pProfManager->GetDstProfileType(&profileType)))
    {
        //
        // Initialize the channel data based on the destination color profile
        // settings:
        //    RGB  = 3 channel with no src alpha
        //           4 channel with src alpha
        //    CMYK = 5 channel (nChannel always has an alpha channel)
        //
        // The color type is based off the OS. XP does not have access to WCS
        // and therefore floating point formats are converted to 16 bits per channel
        //
        // The conversion process for  downlevel handling depends on the source format.
        // If we are color matching for scRGB we convert the floating point value as
        // follows:
        //
        //    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 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 0x0000
        //       for 0.0 to 0xFFFF for 1.0
        //    5. Call TranslateColors passing the 16 bit value
        //    6. Reverse steps 1 - 4 to retrieve the floating point value
        //
        //  If we are color matching for context colors we apply the following conversion
        //
        //    1. Truncate the input color to between 0.0 and +1.0
        //    2. Set the 16 bit value according to the channel value from 0x0000
        //       for 0.0 to 0xFFFF for 1.0
        //    3. Call TranslateColors passing the 16 bit value
        //    4. Reverse steps 1 - 2 to retrieve the floating point value
        //
        //  Note: We do not modify the gamma during the scRGB conversion process as this will
        //        be applied by WCS/ICM as the gamma is encapsulated by the relevant ICC
        //        profile. i.e. The gamma is maintained linear as that is what the transform
        //        is expecting.
        //
        COLORDATATYPE colorDataType = COLOR_FLOAT;
        EColorDataType dataType = sRGB;

        DWORD cChannels = 0;
        if (profileType == RGB)
        {
            dataType = scRGB;
            cChannels = 3;
            if (pChannelDataSrc->HasAlpha())
            {
                cChannels++;
            }
        }
        else if (profileType == CMYK)
        {
            dataType = nChannel;
            cChannels = 5;
        }
        else
        {
            RIP("Unsupported color channel format\n");
            hr = E_FAIL;
        }

        if (SUCCEEDED(hr) &&
            SUCCEEDED(hr = pChannelDataDst->InitializeChannelData<FLOAT>(colorDataType, dataType, cChannels, 0.0f)))
        {
            hr = pChannelDataDst->InitializeAlphaChannel(pChannelDataSrc);
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorRefConverter::GetFloatChannelData

Routine Description:

    Method which converts a comma delimited set of floating point values
    defining color channels into floating point values in a list

Arguments:

    szColorRef   - The srting containing the comma seperated color values
    pChannelData - Pointer to the color channels object

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorRefConverter::GetFloatChannelData(
    __in    LPCWSTR            szColorRef,
    __inout CColorChannelData* pChannelData
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pChannelData, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(szColorRef, E_POINTER)) &&
        SUCCEEDED(hr = pChannelData->ResetChannelType(COLOR_FLOAT)))
    {
        try
        {
            CStringXDW cstrColorRef(szColorRef);
            cstrColorRef.Trim();
            cstrColorRef.MakeLower();

            INT cTokenIndex = 0;
            INT cChars = cstrColorRef.GetLength();
            while (SUCCEEDED(hr) &&
                   cTokenIndex < cChars &&
                   cTokenIndex != -1)
            {
                CStringXDW cstrChannel(cstrColorRef.Tokenize(L",", cTokenIndex));
                hr = pChannelData->AddChannelData(static_cast<FLOAT>(_wtof(cstrChannel)));
            }
        }
        catch (CXDException& e)
        {
            hr = e;
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorRefConverter::SetFloatChannelData

Routine Description:

    Method which converts channel data object into a comma delimited set of
    floating point values

Arguments:

    pChannelData      - Pointer to the color channel data
    pcstrChannelData  - Pointer to the color string to be populated

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorRefConverter::SetFloatChannelData(
    __in    CColorChannelData* pChannelData,
    __inout CStringXDW*        pcstrChannelData
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pChannelData, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(pcstrChannelData, E_POINTER)))
    {
        try
        {
            //
            // Over all channels, write out comma seperated float values
            //
            DWORD  cbData = 0;
            PFLOAT pData = NULL;
            DWORD cChanCount = 0;
            if (SUCCEEDED(hr = pChannelData->GetChannelData(&cbData, reinterpret_cast<PVOID*>(&pData))) &&
                SUCCEEDED(hr = pChannelData->GetChannelCount(&cChanCount)))
            {
                if (cChanCount == 0)
                {
                    hr = E_FAIL;
                }

                if (SUCCEEDED(hr) &&
                    cbData >= cChanCount * sizeof(FLOAT))
                {
                    CStringXDW cstrChannel;
                    cstrChannel.Format(L"%f", pData[0]);
                    pcstrChannelData->Append(cstrChannel);
                    for (DWORD cChan = 1; cChan < cChanCount; cChan++)
                    {
                        cstrChannel.Format(L",%f", pData[cChan]);
                        pcstrChannelData->Append(cstrChannel);
                    }
                }
                else
                {
                    hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
                }
            }
        }
        catch (CXDException& e)
        {
            hr = e;
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CColorRefConverter::ParseColorString

Routine Description:

    Method which converts a XML formatted color string into useable color data

Arguments:

    bstrColorRef - The color ref string to be parsed
    pChannelData - Pointer to the color channel data object to be populated

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CColorRefConverter::ParseColorString(
    __in    BSTR               bstrColorRef,
    __inout CColorChannelData* pChannelData,
    __out   BOOL*              pbIsResourceReference
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pChannelData, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(pbIsResourceReference, E_POINTER)))
    {
        *pbIsResourceReference = FALSE;

        if (SysStringLen(bstrColorRef) <= 0)
        {
            hr = E_INVALIDARG;
        }
    }

    if (SUCCEEDED(hr))
    {
        try
        {
            CStringXDW cstrColRef(bstrColorRef);
            cstrColRef.Trim();

            if (0 == cstrColRef.Find(L"sc#"))
            {
                //
                // Strip the "sc#" prefix ready to parse the floating point channels
                //
                cstrColRef.Delete(0, 3);

                //
                // Set the src profile to xdwscRGB.icc - this is an ICC profile with
                // the system wcsRGB profile embedded so should work down-level
                // Set the color data type and retrieve the channel data
                //
                if (SUCCEEDED(hr = m_pProfManager->SetSrcProfileFromColDir(L"xdwscRGB.icc")) &&
                    SUCCEEDED(hr = pChannelData->ResetChannelType(COLOR_FLOAT)) &&
                    SUCCEEDED(hr = pChannelData->SetColorDataType(scRGB)))
                {
                    hr = GetFloatChannelData(cstrColRef, pChannelData);
                }
            }
            else if (0 == cstrColRef.Find(L"ContextColor"))
            {
                //
                // Context colors always have an associated profile - retrieve
                // this and set it in the profile manager
                //
                cstrColRef.Delete(0, countof(L"ContextColor "));
                cstrColRef.Trim();
                CStringXDW cstrProfile(cstrColRef.Left(cstrColRef.Find(L" ")));
                cstrColRef.Delete(0, cstrProfile.GetLength());

                //
                // Set the source profile ready to create the transform, retrieve the channel data
                // and clamp between 0.0 and 1.0.
                //
                if (SUCCEEDED(hr = m_pProfManager->SetSrcProfileFromContainer(cstrProfile.GetBuffer())) &&
                    SUCCEEDED(hr = pChannelData->ResetChannelType(COLOR_FLOAT)) &&
                    SUCCEEDED(hr = pChannelData->SetColorDataType(nChannel)) &&
                    SUCCEEDED(hr = GetFloatChannelData(cstrColRef, pChannelData)) &&
                    SUCCEEDED(hr = pChannelData->ClampChannelValues(0.0f, 1.0f)))
                {
                    //
                    // Mark the color profile for deletion
                    //
                    (*m_pResDel)[cstrProfile] = TRUE;
                }
            }
            else if (0 == cstrColRef.Find(L"#"))
            {
                //
                // Delete the # symbol so we are just left with the RGB values
                //
                cstrColRef.Delete(0, 1);

                //
                // Set the source profile to sRGB rather than assume the default is set to
                // sRGB.
                //
                if (SUCCEEDED(hr = m_pProfManager->SetSrcProfileFromColDir(L"sRGB Color Space Profile.icm")) &&
                    SUCCEEDED(hr = pChannelData->ResetChannelType(COLOR_BYTE)) &&
                    SUCCEEDED(hr = pChannelData->SetColorDataType(sRGB)))
                {
                    while (SUCCEEDED(hr) &&
                           cstrColRef.GetLength() > 0)
                    {
                        //
                        // Add the channel data
                        //
                        hr = pChannelData->AddChannelData(static_cast<BYTE>(wcstol(cstrColRef.Left(2), NULL, 16)));

                        //
                        // Delete the channel from the color ref string
                        //
                        cstrColRef.Delete(0, 2);
                    }
                }
            }
            else if (0 == cstrColRef.Find(L"{StaticResource"))
            {
                *pbIsResourceReference = TRUE;
            }
            else
            {
                //
                // Unrecognised type
                //
                RIP("Unrecognised color syntax.");
                hr = E_FAIL;
            }
        }
        catch (CXDException& e)
        {
            hr = e;
        }
        catch (exception& DBG_ONLY(e))
        {
            ERR(e.what());
            hr = E_FAIL;
        }
    }

⌨️ 快捷键说明

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