📄 colchan.cpp
字号:
// 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 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
//
if (cbDstData >= cChannels * sizeof(WORD) &&
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<WORD>(channelValue * kMaxWordAsFloat);
}
}
else
{
if (SUCCEEDED(hr = ClampChannelValues(0.0f, 1.0f)))
{
for (UINT cCurrChan = 0;
cCurrChan < cChannels;
cCurrChan++)
{
pDstData[cCurrChan] = static_cast<WORD>(pSrcData[cCurrChan] * kMaxWordAsFloat);
}
}
}
}
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::ColorFromByte
Routine Description:
Uses an 8 bpc COLOR structure to set the channel data
Arguments:
pSrcData - Pointer to the source COLOR data
cbSrcData - Size of the source buffer in bytes
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::ColorFromByte(
__in_bcount(cbSrcData) PBYTE pSrcData,
__in CONST UINT& cbSrcData
)
{
HRESULT hr = S_OK;
DWORD cChannels = 0;
DWORD cbData = 0;
PBYTE pData = NULL;
if (SUCCEEDED(hr = CHECK_POINTER(pSrcData, E_POINTER)) &&
SUCCEEDED(hr = GetChannelCountNoAlpha(&cChannels)) &&
SUCCEEDED(hr = GetChannelDataNoAlpha(&cbData, reinterpret_cast<PVOID*>(&pData))))
{
ZeroMemory(pData, cbData);
if (cbSrcData > 0)
{
switch (m_channelType)
{
case COLOR_BYTE:
{
if (cbData >= cChannels * sizeof(BYTE) &&
cbSrcData >= cChannels * sizeof(BYTE))
{
//
// Just copy src to dst
//
CopyMemory(pData, pSrcData, cChannels * sizeof(BYTE));
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
}
break;
case COLOR_WORD:
{
if (cbData >= cChannels * sizeof(WORD) &&
cbSrcData >= cChannels * sizeof(BYTE))
{
PWORD pDstData = reinterpret_cast<PWORD>(pData);
for (UINT cCurrChan = 0;
cCurrChan < cChannels;
cCurrChan++)
{
pDstData[cCurrChan] = static_cast<WORD>(MulDiv(pSrcData[cCurrChan], 0xFFFF, 0xFF));
}
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
}
break;
case COLOR_FLOAT:
{
//
// Make sure the float data is scaled to 0.0 and 1.0 for nChannel and sRGB and is
// scaled as follows for scRGB:
//
// 1. Convert the WORD value from 0x00 - 0xFF to 0.0f - 1.0f
// 1. Scale the value up by 4.0 to put it into the range 0.0 to 2.0
// 2. Offset the value by -2.0 to put it into the -2.0 to 2.0 range
//
if (cbData >= cChannels * sizeof(FLOAT) &&
cbSrcData >= cChannels * sizeof(BYTE))
{
PFLOAT pDstData = reinterpret_cast<PFLOAT>(pData);
if (m_dataType == scRGB)
{
for (UINT cCurrChan = 0;
cCurrChan < cChannels;
cCurrChan++)
{
pDstData[cCurrChan] = ((static_cast<FLOAT>(pSrcData[cCurrChan])*4.0f)/kMaxByteAsFloat) - 2.0f;
}
}
else
{
for (UINT cCurrChan = 0;
cCurrChan < cChannels;
cCurrChan++)
{
pDstData[cCurrChan] = static_cast<FLOAT>(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::ColorFromWord
Routine Description:
Uses an 16 bpc COLOR structure to set the channel data
Arguments:
pSrcData - Pointer to the source COLOR data
cbSrcData - Size of the source buffer in bytes
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::ColorFromWord(
__in_bcount(cbSrcData) PWORD pSrcData,
__in CONST UINT& cbSrcData
)
{
HRESULT hr = S_OK;
DWORD cChannels = 0;
DWORD cbData = 0;
PBYTE pData = NULL;
if (SUCCEEDED(hr = CHECK_POINTER(pSrcData, E_POINTER)) &&
SUCCEEDED(hr = GetChannelCountNoAlpha(&cChannels)) &&
SUCCEEDED(hr = GetChannelDataNoAlpha(&cbData, reinterpret_cast<PVOID*>(&pData))))
{
ZeroMemory(pData, cbData);
if (cbSrcData > 0)
{
switch (m_channelType)
{
case COLOR_BYTE:
{
if (cbData >= cChannels * sizeof(BYTE) &&
cbSrcData >= cChannels * sizeof(WORD))
{
for (UINT cCurrChan = 0;
cCurrChan < cChannels;
cCurrChan++)
{
pData[cCurrChan] = static_cast<BYTE>(MulDiv(pSrcData[cCurrChan], 0xFF, 0xFFFF));
}
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
}
break;
case COLOR_WORD:
{
if (cbData >= cChannels * sizeof(WORD) &&
cbSrcData >= cChannels * sizeof(WORD))
{
//
// Just copy src to dst
//
CopyMemory(pData, pSrcData, cChannels * sizeof(WORD));
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
}
break;
case COLOR_FLOAT:
{
//
// Make sure the float data is scaled to 0.0 and 1.0 for nChannel and sRGB and is
// scaled as follows for scRGB:
//
// 1. Convert the WORD value from 0x0000 - 0xFFFF to 0.0f - 1.0f
// 1. Scale the value up by 4.0 to put it into the range 0.0 to 2.0
// 2. Offset the value by -2.0 to put it into the -2.0 to 2.0 range
//
if (cbData >= cChannels * sizeof(FLOAT) &&
cbSrcData >= cChannels * sizeof(WORD))
{
PFLOAT pDstData = reinterpret_cast<PFLOAT>(pData);
if (m_dataType == scRGB)
{
for (UINT cCurrChan = 0;
cCurrChan < cChannels;
cCurrChan++)
{
pDstData[cCurrChan] = ((static_cast<FLOAT>(pSrcData[cCurrChan])*4.0f)/kMaxWordAsFloat) - 2.0f;
}
}
else
{
for (UINT cCurrChan = 0;
cCurrChan < cChannels;
cCurrChan++)
{
pDstData[cCurrChan] = static_cast<FLOAT>(pSrcData[cCurrChan])/kMaxWordAsFloat;
}
}
}
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::GetChannelSizeFromType
Routine Description:
Retrieves the channel data size from the channel data type
Arguments:
channelType - The color channel data type
pcbChannelSize - Pointer to storage to recieve the channel data size
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::GetChannelSizeFromType(
__in CONST COLORDATATYPE& channelType,
__out DWORD* pcbChannelSize
)
{
HRESULT hr = S_OK;
if (SUCCEEDED(hr = CHECK_POINTER(pcbChannelSize, E_POINTER)))
{
if (channelType < COLOR_BYTE ||
channelType > COLOR_S2DOT13FIXED)
{
hr = E_INVALIDARG;
}
}
if (SUCCEEDED(hr))
{
*pcbChannelSize = g_cbChannelType[channelType - 1];
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CColorChannelData::ValidateDataSize
Routine Description:
Template method that validates the data size given the current channel data type
Arguments:
None
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
template <class _T>
HRESULT
CColorChannelData::ValidateDataSize(
VOID
)
{
HRESULT hr = S_OK;
DWORD cbDataSize = 0;
if (SUCCEEDED(hr = GetChannelSizeFromType(m_channelType, &cbDataSize)))
{
//
// Make sure the data being added matches the data type in size
//
if (sizeof(_T) != cbDataSize)
{
hr = E_INVALIDARG;
}
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CColorChannelData::AllocateChannelBuffers
Routine Description:
Allocates the channel data buffer
Arguments:
pcbBuffer - Pointer to variable that recieves the allocated buffer size
ppBuffer - Pointer to a pointer that recieves the buffer address
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::AllocateChannelBuffers(
__out UINT* pcbBuffer,
__deref_out_bcount(*pcbBuffer) PBYTE* ppBuffer
)
{
HRESULT hr = S_OK;
if (SUCCEEDED(hr = CHECK_POINTER(pcbBuffer, E_POINTER)) &&
SUCCEEDED(hr = CHECK_POINTER(ppBuffer, E_POINTER)))
{
//
// Allocate a buffer for the channel data MAX_CHANNEL_COUNT x MAX_CHANNEL_SIZE
// This guarantees we have enough storage for the maximum n-channel support
// in WCS
//
*pcbBuffer = MAX_CHANNEL_COUNT*MAX_CHANNEL_SIZE;
*ppBuffer = new BYTE[*pcbBuffer];
if (*ppBuffer == NULL)
{
*pcbBuffer = 0;
hr = E_OUTOFMEMORY;
}
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CColorChannelData::FreeChannelBuffers
Routine Description:
Releases channel buffer
Arguments:
None
Return Value:
None
--*/
VOID
CColorChannelData::FreeChannelBuffers(
VOID
)
{
if (m_pChannelData != NULL)
{
delete[] m_pChannelData;
m_pChannelData = NULL;
}
m_cbChannelData = 0;
}
/*++
Routine Name:
CColorChannelData::GetAlphaAsFloat
Routine Description:
Retrieves the alpha value of the channel data as a float
Arguments:
pAlpha - Pointer to a float that recieves the alpha value
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::GetAlphaAsFloat(
__out PFLOAT pAlpha
)
{
HRESULT hr = S_OK;
if (SUCCEEDED(hr = CHECK_POINTER(pAlpha, E_POINTER)))
{
*pAlpha = 0.0f;
if (HasAlpha())
{
switch (m_channelType)
{
case COLOR_BYTE:
{
*pAlpha = static_cast<FLOAT>(*m_pChannelData)/kMaxByteAsFloat;
}
break;
case COLOR_WORD:
{
*pAlpha = static_cast<FLOAT>(*reinterpret_cast<WORD*>(m_pChannelData))/kMaxWordAsFloat;
}
break;
case COLOR_FLOAT:
{
*pAlpha = *reinterpret_cast<PFLOAT>(m_pChannelData);
}
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -