284 lines
6.6 KiB
C++
284 lines
6.6 KiB
C++
/****************************************************************************
|
|
*
|
|
* (C) COPYRIGHT 2000, MICROSOFT CORP.
|
|
*
|
|
* FILE: gdipconv.cpp
|
|
*
|
|
* VERSION: 1.0
|
|
*
|
|
* DATE: 11/10/2000
|
|
*
|
|
* AUTHOR: Dave Parsons
|
|
*
|
|
* DESCRIPTION:
|
|
* Helper functions for using GDI+ to convert image formats.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "pch.h"
|
|
|
|
using namespace Gdiplus;
|
|
|
|
CWiauFormatConverter::CWiauFormatConverter() :
|
|
m_Token(NULL),
|
|
m_EncoderCount(0),
|
|
m_pEncoderInfo(NULL)
|
|
{
|
|
memset(&m_guidCodecBmp, 0, sizeof(m_guidCodecBmp));
|
|
}
|
|
|
|
CWiauFormatConverter::~CWiauFormatConverter()
|
|
{
|
|
if (m_pEncoderInfo)
|
|
{
|
|
delete []m_pEncoderInfo;
|
|
m_pEncoderInfo = NULL;
|
|
}
|
|
|
|
if (m_Token)
|
|
{
|
|
GdiplusShutdown(m_Token);
|
|
m_Token = NULL;
|
|
}
|
|
}
|
|
|
|
HRESULT CWiauFormatConverter::Init()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
GpStatus Status = Ok;
|
|
|
|
//
|
|
// Locals
|
|
//
|
|
GdiplusStartupInput gsi;
|
|
ImageCodecInfo *pEncoderInfo = NULL;
|
|
|
|
if (m_pEncoderInfo != NULL) {
|
|
wiauDbgError("Init", "Init has already been called");
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Start up GDI+
|
|
//
|
|
Status = GdiplusStartup(&m_Token, &gsi, NULL);
|
|
if (Status != Ok)
|
|
{
|
|
wiauDbgError("Init", "GdiplusStartup failed");
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
UINT cbCodecs = 0;
|
|
|
|
Status = GetImageEncodersSize(&m_EncoderCount, &cbCodecs);
|
|
if (Status != Ok)
|
|
{
|
|
wiauDbgError("Init", "GetImageEncodersSize failed");
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
m_pEncoderInfo = new BYTE[cbCodecs];
|
|
REQUIRE_ALLOC(m_pEncoderInfo, hr, "Init");
|
|
|
|
pEncoderInfo = (ImageCodecInfo *) m_pEncoderInfo;
|
|
|
|
Status = GetImageEncoders(m_EncoderCount, cbCodecs, pEncoderInfo);
|
|
if (Ok != Status)
|
|
{
|
|
wiauDbgError("Init", "GetImageEncoders failed");
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
for (UINT count = 0; count < m_EncoderCount; count++)
|
|
{
|
|
if (pEncoderInfo[count].FormatID == ImageFormatBMP)
|
|
{
|
|
m_guidCodecBmp = pEncoderInfo[count].Clsid;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
if (FAILED(hr)) {
|
|
if (m_pEncoderInfo)
|
|
delete []m_pEncoderInfo;
|
|
m_pEncoderInfo = NULL;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
BOOL CWiauFormatConverter::IsFormatSupported(const GUID *pguidFormat)
|
|
{
|
|
BOOL result = FALSE;
|
|
|
|
ImageCodecInfo *pEncoderInfo = (ImageCodecInfo *) m_pEncoderInfo;
|
|
|
|
for (UINT count = 0; count < m_EncoderCount; count++)
|
|
{
|
|
if (pEncoderInfo[count].FormatID == *pguidFormat)
|
|
{
|
|
result = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
HRESULT CWiauFormatConverter::ConvertToBmp(BYTE *pSource, INT iSourceSize,
|
|
BYTE **ppDest, INT *piDestSize,
|
|
BMP_IMAGE_INFO *pBmpImageInfo, SKIP_AMOUNT iSkipAmt)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Locals
|
|
//
|
|
GpStatus Status = Ok;
|
|
CImageStream *pInStream = NULL;
|
|
CImageStream *pOutStream = NULL;
|
|
Image *pSourceImage = NULL;
|
|
BYTE *pTempBuf = NULL;
|
|
SizeF gdipSize;
|
|
|
|
//
|
|
// Check args
|
|
//
|
|
REQUIRE_ARGS(!pSource || !ppDest || !piDestSize || !pBmpImageInfo, hr, "ConvertToBmp");
|
|
|
|
memset(pBmpImageInfo, 0, sizeof(*pBmpImageInfo));
|
|
|
|
//
|
|
// Create a CImageStream from the source memory
|
|
//
|
|
pInStream = new CImageStream;
|
|
REQUIRE_ALLOC(pInStream, hr, "ConvertToBmp");
|
|
|
|
hr = pInStream->SetBuffer(pSource, iSourceSize);
|
|
REQUIRE_SUCCESS(hr, "ConvertToBmp", "SetBuffer failed");
|
|
|
|
//
|
|
// Create a GDI+ Image object from the IStream
|
|
//
|
|
pSourceImage = new Image(pInStream);
|
|
REQUIRE_ALLOC(pSourceImage, hr, "ConvertToBmp");
|
|
|
|
if (pSourceImage->GetLastStatus() != Ok)
|
|
{
|
|
wiauDbgError("ConvertToBmp", "Image constructor failed");
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Ask GDI+ for the image dimensions, and fill in the
|
|
// passed structure
|
|
//
|
|
Status = pSourceImage->GetPhysicalDimension(&gdipSize);
|
|
if (Status != Ok)
|
|
{
|
|
wiauDbgError("ConvertToBmp", "GetPhysicalDimension failed");
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
pBmpImageInfo->Width = (INT) gdipSize.Width;
|
|
pBmpImageInfo->Height = (INT) gdipSize.Height;
|
|
|
|
PixelFormat PixFmt = pSourceImage->GetPixelFormat();
|
|
DWORD PixDepth = (PixFmt & 0xFFFF) >> 8; // Cannot assume image is always 24bits/pixel
|
|
if( PixDepth < 24 )
|
|
PixDepth = 24;
|
|
pBmpImageInfo->ByteWidth = ((pBmpImageInfo->Width * PixDepth + 31) & ~31) / 8;
|
|
pBmpImageInfo->Size = pBmpImageInfo->ByteWidth * pBmpImageInfo->Height;
|
|
|
|
switch (iSkipAmt) {
|
|
case SKIP_OFF:
|
|
pBmpImageInfo->Size += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
|
break;
|
|
case SKIP_FILEHDR:
|
|
pBmpImageInfo->Size += sizeof(BITMAPINFOHEADER);
|
|
break;
|
|
case SKIP_BOTHHDR:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (pBmpImageInfo->Size == 0)
|
|
{
|
|
wiauDbgError("ConvertToBmp", "Size of image is zero");
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// See if the caller passed in a destination buffer, and make sure
|
|
// it is big enough.
|
|
//
|
|
if (*ppDest) {
|
|
if (*piDestSize < pBmpImageInfo->Size) {
|
|
wiauDbgError("ConvertToBmp", "Passed buffer is too small");
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Otherwise allocate memory for a buffer
|
|
//
|
|
else
|
|
{
|
|
pTempBuf = new BYTE[pBmpImageInfo->Size];
|
|
REQUIRE_ALLOC(pTempBuf, hr, "ConvertToBmp");
|
|
|
|
*ppDest = pTempBuf;
|
|
*piDestSize = pBmpImageInfo->Size;
|
|
}
|
|
|
|
//
|
|
// Create output IStream
|
|
//
|
|
pOutStream = new CImageStream;
|
|
REQUIRE_ALLOC(pOutStream, hr, "ConvertToBmp");
|
|
|
|
hr = pOutStream->SetBuffer(*ppDest, pBmpImageInfo->Size, iSkipAmt);
|
|
REQUIRE_SUCCESS(hr, "ConvertToBmp", "SetBuffer failed");
|
|
|
|
//
|
|
// Write the Image to the output IStream in BMP format
|
|
//
|
|
pSourceImage->Save(pOutStream, &m_guidCodecBmp, NULL);
|
|
if (pSourceImage->GetLastStatus() != Ok)
|
|
{
|
|
wiauDbgError("ConvertToBmp", "GDI+ Save failed");
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
if (FAILED(hr)) {
|
|
if (pTempBuf) {
|
|
delete []pTempBuf;
|
|
pTempBuf = NULL;
|
|
*ppDest = NULL;
|
|
*piDestSize = 0;
|
|
}
|
|
}
|
|
if (pInStream) {
|
|
pInStream->Release();
|
|
}
|
|
if (pOutStream) {
|
|
pOutStream->Release();
|
|
}
|
|
if (pSourceImage) {
|
|
delete pSourceImage;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|