📄 colchan.cpp
字号:
/*++
Copyright (c) 2005 Microsoft Corporation
All rights reserved.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
File Name:
colchan.cpp
Abstract:
Color channel class implementation. The color channel class is responsible for maintaining
simple single color multiple channel data intialised from color references in the XPS markup.
It provides methods for intialization, access and conversion of the data.
Note regarding color formats: The CColorChannelData class is only used in the filter for
processing color references in mark-up. As such we only ever see 8 bit per channel sRGB and
floating point scRGB and n-channel colors and we only ever need convert to 16 bpc for
down-level scRGB conversion. If the CColorChannelData is ever used when fixed point input
or other output types are required then these formats need support added (see E_NOTIMPL
return values).
--*/
#include "precomp.h"
#include "debug.h"
#include "globals.h"
#include "xdexcept.h"
#include "colchan.h"
#define MAX_CHANNEL_COUNT 9 // 1 alpha channel and 8 color channels
#define MAX_CHANNEL_SIZE sizeof(FLOAT)
DWORD g_cbChannelType[] = {
sizeof(BYTE), // COLOR_BYTE
sizeof(WORD), // COLOR_WORD
sizeof(FLOAT), // COLOR_FLOAT
sizeof(WORD) // COLOR_S2DOT13FIXED
};
/*++
Routine Name:
CColorChannelData::CColorChannelData
Routine Description:
CColorChannelData default constructor
Arguments:
None
Return Value:
None
Throws an exception on failure.
--*/
CColorChannelData::CColorChannelData() :
m_cChannels(0),
m_channelType(COLOR_BYTE),
m_pChannelData(NULL),
m_cbChannelData(0),
m_dataType(sRGB)
{
if (FAILED(AllocateChannelBuffers(&m_cbChannelData, &m_pChannelData)))
{
throw CXDException(E_OUTOFMEMORY);
}
}
/*++
Routine Name:
CColorChannelData::~CColorChannelData
Routine Description:
CColorChannelData destructor
Arguments:
None
Return Value:
None
--*/
CColorChannelData::~CColorChannelData()
{
FreeChannelBuffers();
}
/*++
Routine Name:
CColorChannelData::AddChannelData
Routine Description:
Template method for adding channel data. This allows any of the available color
channel data types to be added to the channel data buffer
Arguments:
channelValue - Value for the channel to be added
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
template <class _T>
HRESULT
CColorChannelData::AddChannelData(
__in CONST _T& channelValue
)
{
HRESULT hr = S_OK;
if (SUCCEEDED(hr = ValidateDataSize<_T>()))
{
if (m_cChannels < MAX_CHANNEL_COUNT)
{
_T* pChannelData = reinterpret_cast<_T*>(m_pChannelData);
pChannelData[m_cChannels] = channelValue;
m_cChannels++;
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CColorChannelData::GetChannelCount
Routine Description:
Retrieves the current number of channels defining the color.
Arguments:
pcChannels - Pointer to a variable that recieves the count of channels
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::GetChannelCount(
__out DWORD* pcChannels
)
{
HRESULT hr = S_OK;
if (SUCCEEDED(hr = CHECK_POINTER(pcChannels, E_POINTER)))
{
*pcChannels = m_cChannels;
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CColorChannelData::GetChannelCountNoAlpha
Routine Description:
Retrieves the number of channels less the alpha channel if present
Arguments:
pcChannels - Pointer to a variable that recieves the count of non-alpha channels
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::GetChannelCountNoAlpha(
__out DWORD* pcChannels
)
{
HRESULT hr = S_OK;
if (SUCCEEDED(hr = GetChannelCount(pcChannels)))
{
if (HasAlpha())
{
(*pcChannels)--;
}
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CColorChannelData::GetChannelType
Routine Description:
Retrieves the COLORDATATYPE for the channel data
Arguments:
pChannelType - Pointer to a COLORDATATYPE variable that recieves the type
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::GetChannelType(
__out COLORDATATYPE* pChannelType
)
{
HRESULT hr = S_OK;
if (SUCCEEDED(hr = CHECK_POINTER(pChannelType, E_POINTER)))
{
*pChannelType = m_channelType;
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CColorChannelData::ResetChannelType
Routine Description:
Resets the underlying channel data type to the requested type
Arguments:
channelType - The channel data type to reset to
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::ResetChannelType(
__in CONST COLORDATATYPE& channelType
)
{
m_channelType = channelType;
m_cChannels = 0;
return S_OK;
}
/*++
Routine Name:
CColorChannelData::GetChannelData
Routine Description:
Retrieves the buffer and count of bytes of the channel data
Arguments:
pcbDataSize - Pointer to variable that recieves the count of bytes in the buffer
ppData - Pointer to a BYTE pointer that recieves the buffer
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::GetChannelData(
__out DWORD* pcbDataSize,
__deref_out_bcount(*pcbDataSize) PVOID* ppData
)
{
HRESULT hr = S_OK;
DWORD cbDataTypeSize = 0;
if (SUCCEEDED(hr = CHECK_POINTER(pcbDataSize, E_POINTER)) &&
SUCCEEDED(hr = CHECK_POINTER(ppData, E_POINTER)) &&
SUCCEEDED(hr = GetChannelSizeFromType(m_channelType, &cbDataTypeSize)))
{
*ppData = NULL;
*pcbDataSize = 0;
if (m_cbChannelData >= m_cChannels * cbDataTypeSize)
{
if (m_cChannels > 0)
{
*pcbDataSize = m_cChannels * cbDataTypeSize;
*ppData = m_pChannelData;
}
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CColorChannelData::GetChannelDataNoAlpha
Routine Description:
Retrieves the buffer and count of bytes of the channel data excluding the
alpha channel if present
Arguments:
pcbDataSize - Pointer to variable that recieves the count of bytes in the buffer
ppData - Pointer to a BYTE pointer that recieves the buffer
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::GetChannelDataNoAlpha(
__out DWORD* pcbDataSize,
__deref_out_bcount(*pcbDataSize) PVOID* ppData
)
{
HRESULT hr = S_OK;
DWORD cbData = 0;
PBYTE pData = NULL;
if (SUCCEEDED(hr = CHECK_POINTER(pcbDataSize, E_POINTER)) &&
SUCCEEDED(hr = CHECK_POINTER(ppData, E_POINTER)) &&
SUCCEEDED(hr = GetChannelData(&cbData, reinterpret_cast<PVOID*>(&pData))))
{
*pcbDataSize = cbData;
*ppData = pData;
if (HasAlpha())
{
DWORD cbChannelSize = 0;
if (SUCCEEDED(hr = GetChannelSizeFromType(m_channelType, &cbChannelSize)))
{
if (cbData >= cbChannelSize)
{
*pcbDataSize = cbData - cbChannelSize;
*ppData = pData + cbChannelSize;
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
}
}
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CColorChannelData::ClampChannelValues
Routine Description:
Template method that recieves the minimum and maximum value for a channel
and applies this to all channels defining the color
Arguments:
min - Minimum channel value
max - Maximum channel value
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
template <class _T>
HRESULT
CColorChannelData::ClampChannelValues(
__in CONST _T& min,
__in CONST _T& max
)
{
HRESULT hr = S_OK;
//
// Validate the data size against the current type
//
if (SUCCEEDED(hr = ValidateDataSize<_T>()))
{
_T* pData = reinterpret_cast<_T*>(m_pChannelData);
for (DWORD cChannel = 0; cChannel < m_cChannels; cChannel++, pData++)
{
if (*pData < min)
{
*pData = min;
}
else if (*pData > max)
{
*pData = max;
}
}
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CColorChannelData::InitializeChannelData
Routine Description:
Initializes the channel data according to the type, count of channels and a default value
Arguments:
channelType - The required channel data format
dataType - The required data type
cChannels - The count of channels defining the color
channelValue - The intial value for all channels
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
template <class _T>
HRESULT
CColorChannelData::InitializeChannelData(
__in CONST COLORDATATYPE& channelType,
__in CONST EColorDataType& dataType,
__in CONST DWORD& cChannels,
__in CONST _T& channelValue
)
{
HRESULT hr = S_OK;
//
// Validate the data size against the current type
//
if (SUCCEEDED(hr = ResetChannelType(channelType)) &&
SUCCEEDED(hr = ValidateDataSize<_T>()))
{
if (cChannels <= MAX_CHANNEL_COUNT)
{
m_dataType = dataType;
m_cChannels = cChannels;
_T* pChannelData = reinterpret_cast<_T*>(m_pChannelData);
for (DWORD cChannel = 0; cChannel < m_cChannels; cChannel++, pChannelData++)
{
*pChannelData = channelValue;
}
}
else
{
hr = E_INVALIDARG;
}
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CColorChannelData::SetColorDataType
Routine Description:
Sets the color data type
Arguments:
dataType - The color data type
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::SetColorDataType(
__in CONST EColorDataType& dataType
)
{
m_dataType = dataType;
return S_OK;
}
/*++
Routine Name:
CColorChannelData::GetColorDataType
Routine Description:
Retrieves the current color data type
Arguments:
pDataType - Pointer to a variable to recieve the color data type
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorChannelData::GetColorDataType(
EColorDataType* pDataType
)
{
HRESULT hr = S_OK;
if (SUCCEEDED(hr = CHECK_POINTER(pDataType, E_POINTER)))
{
*pDataType = m_dataType;
}
return S_OK;
}
/*++
Routine Name:
CColorChannelData::HasAlpha
Routine Description:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -