📄 cmimg.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:
cmimg.cpp
Abstract:
Color managed image implementation. The CColorManagedImage class is responsible
for managing the image resource for a stored bitmap. This implements
the IResWriter interface so that the font can be added to the resource
cache.
--*/
#include "precomp.h"
#include "debug.h"
#include "globals.h"
#include "xdstring.h"
#include "xdexcept.h"
#include "cmimg.h"
#include "streamcnv.h"
using XDPrintSchema::JobOptimalDestinationColorProfile::EProfileOption;
using XDPrintSchema::JobOptimalDestinationColorProfile::RGB;
using XDPrintSchema::JobOptimalDestinationColorProfile::CMYK;
/*++
Routine Name:
CColorManagedImage::CColorManagedImage
Routine Description:
Constructor for the CColorManagedImage class which registers internally the
supplied resource URI and a pointer to the profile manager which will supply
suitable color transforms to apply to that resource
Arguments:
bstrResURI - String containing the URI to the resource to be handled
pProfManager - Pointer to a profile manager which will supply suitable
transforms to apply to the supplied resource
Return Value:
None
Throws CXDException(HRESULT) on an error
--*/
CColorManagedImage::CColorManagedImage(
__in BSTR bstrResURI,
__in CProfileManager* pProfManager,
__in IFixedPage* pFixedPage,
__in ResDeleteMap* pResDel
) :
m_pProfManager(pProfManager),
m_pFixedPage(pFixedPage),
m_bstrSrcProfileURI(NULL),
m_pResDel(pResDel)
{
HRESULT hr = S_OK;
if (SUCCEEDED(hr = CHECK_POINTER(pProfManager, E_POINTER)) &&
SUCCEEDED(hr = CHECK_POINTER(m_pFixedPage, E_POINTER)) &&
SUCCEEDED(hr = CHECK_POINTER(m_pResDel, E_POINTER)))
{
if (SysStringLen(bstrResURI) <= 0)
{
hr = E_INVALIDARG;
}
}
if (SUCCEEDED(hr))
{
CComBSTR bstrAttribute(bstrResURI);
if (bstrAttribute.Length() == 0)
{
hr = E_INVALIDARG;
}
else
{
try
{
//
// Process the mark-up looking for the bitmap URI and any associated profiles
//
CStringXDW cstrAttribute(bstrResURI);
CStringXDW cstrColConvBMP(L"{ColorConvertedBitmap ");
cstrAttribute.Trim();
INT cchFind = cstrAttribute.Find(cstrColConvBMP);
if (cchFind == -1)
{
//
// The mark-up is the bitmap URI
//
cstrAttribute.Trim();
m_bstrBitmapURI = cstrAttribute.AllocSysString();
}
else
{
//
// The mark-up is specifying a profile associated with the image.
// Extract the path and set this in the profile manager. The markup takes
// the form "{ColorConvertedBitmap image.ext profile.icc}".
//
//
// Delete leading string "{ColorConvertedBitmap " and the trailing "}"
//
cstrAttribute.Delete(0, cstrColConvBMP.GetLength());
cstrAttribute.Delete(cstrAttribute.GetLength() - 1, 1);
cstrAttribute.Trim();
//
// Find the seperating space
//
cchFind = cstrAttribute.Find(L" ");
//
// Construct the bitmap URI
//
m_bstrBitmapURI = cstrAttribute.Left(cchFind).AllocSysString();
//
// Delete the bitmap URI and space leaving the profile URI
//
cstrAttribute.Delete(0, cchFind+1);
m_bstrSrcProfileURI = cstrAttribute.AllocSysString();
}
}
catch (CXDException& e)
{
hr = e;
}
}
}
if (FAILED(hr))
{
throw CXDException(hr);
}
}
/*++
Routine Name:
CColorManagedImage::~CColorManagedImage
Routine Description:
Default destructor for the CColorManagedImage class
Arguments:
None
Return Value:
None
--*/
CColorManagedImage::~CColorManagedImage()
{
}
/*++
Routine Name:
CColorManagedImage::WriteData
Routine Description:
This method handles the decoding of a bitmap, the colour
translation applied to the bitmap and the re-encoding of the bitmap
Arguments:
pStream - Pointer to a stream to write the resource out to
Return Value:
HRESULT
S_OK - On success
E_* - On error
--*/
HRESULT
CColorManagedImage::WriteData(
__in IPartBase* pResource,
__in IPrintWriteStream* pStream
)
{
HRESULT hr = S_OK;
if (SUCCEEDED(hr = CHECK_POINTER(pResource, E_POINTER)) &&
SUCCEEDED(hr = CHECK_POINTER(pStream, E_POINTER)))
{
try
{
CComPtr<IUnknown> pRead(NULL);
CComPtr<IPartImage> pImagePart(NULL);
CComPtr<IPrintReadStream> pImageStream(NULL);
//
// Load the bitmap into memory and create a stream to read the bitmap from
//
if (SUCCEEDED(hr = m_pFixedPage->GetPagePart(m_bstrBitmapURI, &pRead)) &&
SUCCEEDED(hr = pRead.QueryInterface(&pImagePart)) &&
SUCCEEDED(hr = pImagePart->GetStream(&pImageStream)))
{
BOOL bApplyTransform = FALSE;
CComPtr<IStream> pInputImageStream(NULL);
EWICPixelFormat eDstPixFormat = kWICPixelFormatDontCare;
UINT cDstWidth = 0;
UINT cDstHeight = 0;
DOUBLE dpiDstX = 0.0;
DOUBLE dpiDstY = 0.0;
EProfileOption eProfileOption = RGB;
//
// Set up the source and destination bitmaps so they are ready for use by TranslateBitmapBits
//
pInputImageStream.Attach(new CPrintReadStreamToIStream(pImageStream));
if (SUCCEEDED(hr = CHECK_POINTER(pInputImageStream, E_OUTOFMEMORY)) &&
SUCCEEDED(hr = m_srcBmp.Initialize(pInputImageStream)) &&
SUCCEEDED(hr = m_srcBmp.GetSize(&cDstWidth, &cDstHeight)) &&
SUCCEEDED(hr = m_srcBmp.GetResolution(&dpiDstX, &dpiDstY)) &&
SUCCEEDED(hr = m_pProfManager->GetProfileOption(&eProfileOption)))
{
//
// The destination bitmap format can be one of:
//
// kWICPixelFormat128bppRGBFloat - scRGB output
// kWICPixelFormat128bppRGBAFloat - scRGB output with a source alpha channel
// kWICPixelFormat64bppCMYK - CMYK output
// kWICPixelFormat80bppCMYKAlpha - CMYK output with a source alpha channel
//
BOOL bScRGBOut = FALSE;
switch (eProfileOption)
{
case RGB:
{
eDstPixFormat = m_srcBmp.HasAlphaChannel() ? kWICPixelFormat128bppRGBAFloat : kWICPixelFormat128bppRGBFloat;
bScRGBOut = TRUE;
}
break;
case CMYK:
{
eDstPixFormat = m_srcBmp.HasAlphaChannel() ? kWICPixelFormat40bppCMYKAlpha : kWICPixelFormat32bppCMYK;
}
break;
default:
{
RIP("Unrecognised destination profile option.\n");
hr = E_FAIL;
}
break;
}
if (SUCCEEDED(hr))
{
//
// If the input is scRGB and the output is scRGB just pass through the bitmap
// Note: This should be optimised we do not write out a new bitmap but use the original
//
if (eDstPixFormat == m_srcBmp.GetPixelFormat() &&
bScRGBOut)
{
m_dstBmp = m_srcBmp;
}
else if (SUCCEEDED(hr = m_dstBmp.Initialize(eDstPixFormat, cDstWidth, cDstHeight, dpiDstX, dpiDstY)))
{
bApplyTransform = TRUE;
}
}
}
//
// Process the source and destination bitmaps a scanline at a time if the output image
// is still not set
//
if (SUCCEEDED(hr) &&
bApplyTransform)
{
//
// Create scanline iterator objects from the source and destination bitmaps
//
CScanIterator srcIter(m_srcBmp, NULL);
CScanIterator dstIter(m_dstBmp, NULL);
//
// Initialize the iterators, set the source profile and transform the scanlines
//
if (SUCCEEDED(hr = srcIter.Initialize(TRUE)) &&
SUCCEEDED(hr = dstIter.Initialize(FALSE)) &&
SUCCEEDED(hr = SetSrcProfile(&srcIter)) &&
SUCCEEDED(hr = TransformScanLines(&srcIter, &dstIter)))
{
//
// CMYK output requires an embedded profile
//
CComBSTR bstrProfile;
if (eProfileOption == CMYK &&
SUCCEEDED(hr = m_pProfManager->GetDstProfileName(&bstrProfile)))
{
hr = dstIter.SetProfile(bstrProfile);
}
}
if (SUCCEEDED(hr))
{
m_dstBmp = dstIter;
}
//
// If there's a problem loading a suitable source profile, just pass
// the bitmap through unmodified
//
if (hr == HRESULT_FROM_WIN32(ERROR_PROFILE_NOT_FOUND))
{
bApplyTransform = FALSE;
m_dstBmp = m_srcBmp;
hr = S_OK;
}
}
if (SUCCEEDED(hr))
{
//
// Create a write stream to accept the converted bitmap, fill from the output bitmap
// and write to the output stream (after ensuring the stream is pointing to the start).
//
CComPtr<IStream> pOutputImageStream(NULL);
LARGE_INTEGER cbMoveFromStart = {0};
PBYTE pBuff = new BYTE[CB_COPY_BUFFER];
if (SUCCEEDED(hr = CHECK_POINTER(pBuff, E_OUTOFMEMORY)) &&
SUCCEEDED(hr = CreateStreamOnHGlobal(NULL, TRUE, &pOutputImageStream)) &&
SUCCEEDED(hr = m_dstBmp.Write(GUID_ContainerFormatWmp, pOutputImageStream)) &&
SUCCEEDED(hr = pOutputImageStream->Seek(cbMoveFromStart, STREAM_SEEK_SET, NULL)))
{
ULONG cbRead = 0;
ULONG cbWritten = 0;
while (SUCCEEDED(hr) &&
SUCCEEDED(hr = pOutputImageStream->Read(pBuff, CB_COPY_BUFFER, &cbRead)) &&
cbRead > 0)
{
hr = pStream->WriteBytes(pBuff, cbRead, &cbWritten);
ASSERTMSG(cbRead == cbWritten, "Failed to write all data.\n");
}
}
if (pBuff != NULL)
{
delete[] pBuff;
pBuff = NULL;
}
}
//
// Set the content type of the image part
//
CComQIPtr<IPartImage> pImage = pResource;
if (SUCCEEDED(hr) &&
SUCCEEDED(hr = CHECK_POINTER(pImage, E_NOINTERFACE)))
{
hr = pImage->SetImageContent(CComBSTR(L"image/vnd.ms-photo"));
}
//
// If all is well mark the replaced bitmap and profile for deletion
//
if (SUCCEEDED(hr))
{
(*m_pResDel)[m_bstrBitmapURI.m_str] = TRUE;
if (m_bstrSrcProfileURI.Length() > 0)
{
(*m_pResDel)[m_bstrSrcProfileURI.m_str] = TRUE;
}
}
}
}
catch (CXDException& e)
{
hr = e;
}
catch (exception& DBG_ONLY(e))
{
ERR(e.what());
hr = E_FAIL;
}
}
ERR_ON_HR(hr);
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -