📄 wictobmscn.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:
wictobmscn.cpp
Abstract:
WIC pixel format to BMFORMAT conversion class implementation. This class provides methods
for converting between a source WIC scanline to a target destination BMFORMAT scanline.
--*/
#include "precomp.h"
#include "debug.h"
#include "globals.h"
#include "wictobmscn.h"
/*++
Routine Name:
CWICToBMFormatScan::CWICToBMFormatScan
Routine Description:
CWICToBMFormatScan constructor
Arguments:
None
Return Value:
None
--*/
CWICToBMFormatScan::CWICToBMFormatScan() :
m_pScanBuffer(NULL),
m_cbScanBuffer(0),
m_cWidth(0),
m_pData(NULL),
m_cbData(0),
m_bInitialized(FALSE)
{
}
/*++
Routine Name:
CWICToBMFormatScan::~CWICToBMFormatScan
Routine Description:
CWICToBMFormatScan destructor
Arguments:
None
Return Value:
None
--*/
CWICToBMFormatScan::~CWICToBMFormatScan()
{
FreeScanBuffer();
}
/*++
Routine Name:
CWICToBMFormatScan::Initialize
Routine Description:
Initializes the WIC to BMFORMAT transform data from the WICToBMFORMAT structure
Arguments:
WICToBM - Structure containing WIC pixel format to BMFORMAT conversion information
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CWICToBMFormatScan::Initialize(
__in CONST WICToBMFORMAT& WICToBM
)
{
HRESULT hr = S_OK;
m_convData = WICToBM;
if (m_convData.m_pixFormTarget <= kWICPixelFormatMin ||
m_convData.m_pixFormTarget >= kWICPixelFormatMax ||
m_convData.m_bmFormTarget < kICMPixelFormatMin ||
m_convData.m_bmFormTarget >= kICMPixelFormatMax)
{
hr = E_INVALIDARG;
}
if (SUCCEEDED(hr) &&
!IsVista())
{
//
// When processing color data down-level from Vista, we cannot use fixed or float
// BMFORMAT types. In these circumstances we need to convert to a 16 bpc equivalent,
// then back again.
//
if (m_convData.m_bmFormTarget == kBM_32b_scRGB ||
m_convData.m_bmFormTarget == kBM_32b_scARGB ||
m_convData.m_bmFormTarget == kBM_S2DOT13FIXED_scRGB ||
m_convData.m_bmFormTarget == kBM_S2DOT13FIXED_scARGB)
{
m_convData.m_bNeedsScanBuffer = TRUE;
m_convData.m_bmFormTarget = kBM_16b_RGB;
}
}
if (SUCCEEDED(hr))
{
m_bInitialized = TRUE;
}
ERR_ON_HR(hr);
return hr;
}
/*++
Routine Name:
CWICToBMFormatScan::SetData
Routine Description:
Set the current WIC data. This method takes the WIC scanline data and
applies any necessary conversion to achieve the required BMFORMAT
Arguments:
bIsSrc - Indicates if this is a source scanline (i.e. is the conversion required as the scanline is input)
pWicPxData - Pointer to the WIC data
cbWicPxData - Count of bytes in the WIC data buffer
cWidth - Count of pixels inthe scanline
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CWICToBMFormatScan::SetData(
__in CONST BOOL bIsSrc,
__in_bcount(cbWicPxData) PBYTE pWicPxData,
__in CONST UINT cbWicPxData,
__in CONST UINT cWidth
)
{
HRESULT hr = m_bInitialized ? S_OK : E_PENDING;
COLORDATATYPE srcColType = COLOR_BYTE;
EICMPixelFormat eICMFormSrc = kBM_RGBTRIPLETS;
COLORDATATYPE dstColType = COLOR_BYTE;
EICMPixelFormat eICMFormDst = kBM_RGBTRIPLETS;
//
// Validate input
//
if (SUCCEEDED(hr) &&
SUCCEEDED(hr = CHECK_POINTER(pWicPxData, E_POINTER)))
{
if (m_convData.m_pixFormTarget >= kWICPixelFormatMin &&
m_convData.m_pixFormTarget < kWICPixelFormatMax)
{
//
// Set up the destination and source formats
//
eICMFormSrc = g_lutWICToBMFormat[m_convData.m_pixFormTarget].m_bmFormTarget;
srcColType = g_lutWICToBMFormat[m_convData.m_pixFormTarget].m_colDataType;
if (m_convData.m_bmFormTarget < kICMPixelFormatMax &&
m_convData.m_bmFormTarget >= kICMPixelFormatMin)
{
dstColType = g_lutBMFormatData[m_convData.m_bmFormTarget].m_colDataType;
eICMFormDst = m_convData.m_bmFormTarget;
}
else
{
hr = E_FAIL;
}
}
else
{
hr = E_FAIL;
}
}
//
// Validate source and destination formats
//
if (SUCCEEDED(hr))
{
if (eICMFormSrc < kICMPixelFormatMin ||
eICMFormSrc >= kICMPixelFormatMax ||
eICMFormDst < kICMPixelFormatMin ||
eICMFormDst >= kICMPixelFormatMax)
{
RIP("Invalid pixel format.\n");
hr = E_FAIL;
}
else if (srcColType < COLOR_BYTE ||
srcColType > COLOR_S2DOT13FIXED ||
dstColType < COLOR_BYTE ||
dstColType > COLOR_S2DOT13FIXED)
{
RIP("Invalid color data type.\n");
hr = E_FAIL;
}
}
if (SUCCEEDED(hr))
{
m_cWidth = cWidth;
if (m_convData.m_bNeedsScanBuffer)
{
//
// We need to convert in one way or another - create a buffer to
// hold the intermediate scanline data
//
if (SUCCEEDED(hr) &&
SUCCEEDED(hr = CreateScanBuffer(m_cWidth,
g_lutColorDataSize[dstColType],
g_lutBMFormatData[eICMFormDst].m_cChannels)))
{
if (bIsSrc)
{
//
// We need to initialise the buffer from the WIC buffer passed in. Here we
// are doing one of two things:
//
// 1. Copying data directly as we have parity between the WIC and
// ICM pixel formats
// 2. Convert from the WIC format to the ICM format and copy.
//
//
// Set up the source and destination pointers
//
PBYTE pSrc = pWicPxData;
UINT cSrcChannels = g_lutWICToBMFormat[m_convData.m_pixFormTarget].m_cChannels;
size_t cbSrcBytesPerPixel = g_lutColorDataSize[srcColType] * cSrcChannels;
PBYTE pDst = m_pScanBuffer;
UINT cDstChannels = g_lutBMFormatData[eICMFormDst].m_cChannels;
size_t cbDstBytesPerPixel = g_lutColorDataSize[dstColType] * cDstChannels;
PBYTE pSrcEnd = pSrc + cbWicPxData;
PBYTE pDstEnd = pDst + m_cbScanBuffer;
if (dstColType == m_convData.m_colDataType)
{
while (pSrc < pSrcEnd &&
pDst < pDstEnd)
{
if (pSrc + cbDstBytesPerPixel < pSrcEnd)
{
CopyMemory(pDst, pSrc, cbDstBytesPerPixel);
}
pSrc += cbSrcBytesPerPixel;
pDst += cbDstBytesPerPixel;
}
}
else
{
//
// We should only ever be required to convert from floating point and fixed point
// scRGB formats to 16 bpc RGB
//
if (eICMFormDst == kBM_16b_RGB &&
(eICMFormSrc == kBM_32b_scRGB ||
eICMFormSrc == kBM_32b_scARGB))
{
FLOAT* pSrcData = reinterpret_cast<FLOAT*>(pSrc);
WORD* pDstData = reinterpret_cast<WORD*>(pDst);
while (pSrcData <= reinterpret_cast<FLOAT*>(pSrcEnd) - cSrcChannels &&
pDstData <= reinterpret_cast<WORD*>(pDstEnd) - cDstChannels)
{
for (UINT cChan = 0;
cChan < cDstChannels && cChan < cSrcChannels;
cChan++)
{
//
// Note: We are only converting from FLOAT and not applying gamma modification
// as the transform should account for this given the input scRGB ICC source profile.
//
if (pSrcData[cChan] <= -2.0f)
{
pDstData[cChan] = 0;
}
else if (pSrcData[cChan] >= 2.0f)
{
pDstData[cChan] = 0xFFFF;
}
else
{
pDstData[cChan] = static_cast<WORD>(kMaxWordAsFloat * (pSrcData[cChan] + 2.0) / 4.0f);
}
}
pSrcData += cSrcChannels;
pDstData += cDstChannels;
}
}
else if (eICMFormDst == kBM_16b_RGB &&
(eICMFormSrc == kBM_S2DOT13FIXED_scRGB ||
eICMFormSrc == kBM_S2DOT13FIXED_scARGB))
{
WORD* pSrcData = reinterpret_cast<WORD*>(pSrc);
WORD* pDstData = reinterpret_cast<WORD*>(pDst);
while (pSrcData <= reinterpret_cast<WORD*>(pSrcEnd) - cSrcChannels &&
pDstData <= reinterpret_cast<WORD*>(pDstEnd) - cDstChannels)
{
for (UINT cChan = 0;
cChan < cDstChannels && cChan < cSrcChannels;
cChan++)
{
//
// Note: We are only converting from S2DOT13FIXED and not applying gamma modification
// as the transform should account for this given the input scRGB ICC source profile.
//
pDstData[cChan] = pSrcData[cChan] & kS2Dot13Neg ? pSrcData[cChan] ^ 0xFFFF : pSrcData[cChan] | kS2Dot13Neg;
}
pSrcData += cSrcChannels;
pDstData += cDstChannels;
}
}
else
{
hr = E_NOTIMPL;
}
}
}
//
// Set the out buffer pointer and size to the copy buffer
//
if (SUCCEEDED(hr))
{
m_pData = m_pScanBuffer;
m_cbData = m_cbScanBuffer;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -