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