📄 colconv.cpp
字号:
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 + -