#include "precomp.h" #include "gphelper.h" #include "psutil.h" using namespace Gdiplus; CGdiPlusHelper::CGdiPlusHelper(void) : m_pImageEncoderInfo(NULL), m_nImageEncoderCount(0), m_pImageDecoderInfo(NULL), m_nImageDecoderCount(0) #if defined(GDIPLUSHELPER_EXPLICIT_INITIALIZATION) ,m_bGdiplusInitialized(false) ,m_pGdiplusToken(NULL) #endif { Initialize(); } CGdiPlusHelper::~CGdiPlusHelper(void) { Destroy(); } HRESULT CGdiPlusHelper::Initialize(void) { #if defined(GDIPLUSHELPER_EXPLICIT_INITIALIZATION) // Make sure GDI+ is initialized Gdiplus::GdiplusStartupInput StartupInput; m_bGdiplusInitialized = (Gdiplus::GdiplusStartup(&m_pGdiplusToken,&StartupInput,NULL) == Gdiplus::Ok); #endif // Get the installed encoders HRESULT hr = E_FAIL; UINT cbCodecs = 0; GetImageEncodersSize( &m_nImageEncoderCount, &cbCodecs ); if (cbCodecs) { m_pImageEncoderInfo = static_cast(LocalAlloc(LPTR,cbCodecs)); if (m_pImageEncoderInfo) { GpStatus Status = GetImageEncoders( m_nImageEncoderCount, cbCodecs, m_pImageEncoderInfo ); if (Ok == Status) { for (UINT i=0;i(LocalAlloc(LPTR,cbCodecs)); if (m_pImageDecoderInfo) { GpStatus Status = GetImageDecoders( m_nImageDecoderCount, cbCodecs, m_pImageDecoderInfo ); if (Ok == Status) { hr = S_OK; } } } // If there was a problem, make sure there are no half-initialized things laying around if (FAILED(hr)) { Destroy(); } return hr; } void CGdiPlusHelper::Destroy(void) { #if defined(GDIPLUSHELPER_EXPLICIT_INITIALIZATION) // Shut down GDI+ if (m_bGdiplusInitialized) { Gdiplus::GdiplusShutdown(m_pGdiplusToken); m_bGdiplusInitialized = false; m_pGdiplusToken = NULL; } #endif // Free the lists of Encoders and Decoders if (m_pImageEncoderInfo) { LocalFree(m_pImageEncoderInfo); m_pImageEncoderInfo = NULL; } m_nImageEncoderCount = 0; if (m_pImageDecoderInfo) { LocalFree(m_pImageDecoderInfo); m_pImageDecoderInfo = NULL; } m_nImageDecoderCount = 0; } bool CGdiPlusHelper::IsValid(void) const { // Make sure we've been completely created #if defined(GDIPLUSHELPER_EXPLICIT_INITIALIZATION) return(m_bGdiplusInitialized && m_pImageEncoderInfo && m_nImageEncoderCount && m_pImageDecoderInfo && m_nImageDecoderCount); #else return(m_pImageEncoderInfo && m_nImageEncoderCount && m_pImageDecoderInfo && m_nImageDecoderCount); #endif } HRESULT CGdiPlusHelper::LoadAndScale( HBITMAP &hTargetBitmap, LPCTSTR pszFilename, UINT nMaxWidth, UINT nMaxHeight, bool bStretchSmallImages ) { hTargetBitmap = NULL; // Make sure we have a valid filename if (pszFilename && lstrlen(pszFilename)) { Bitmap SourceBitmap( CSimpleStringConvert::WideString(CSimpleString(pszFilename) ) ); if (Ok == SourceBitmap.GetLastStatus()) { // Get the image width and height UINT nSourceWidth = SourceBitmap.GetWidth(); UINT nSourceHeight = SourceBitmap.GetHeight(); // Make sure the width and height are non-zero if (nSourceWidth && nSourceHeight) { // Assume the source dimensions are fine UINT nTargetWidth = nSourceWidth; UINT nTargetHeight = nSourceHeight; // If the height or the width exceed the allowed maximum, scale it down, or if we are allowing stretching if ((nTargetWidth > nMaxWidth) || (nTargetHeight > nMaxHeight) || bStretchSmallImages) { SIZE sizeDesiredImageSize = PrintScanUtil::ScalePreserveAspectRatio( nMaxWidth, nMaxHeight, nTargetWidth, nTargetHeight ); nTargetWidth = sizeDesiredImageSize.cx; nTargetHeight = sizeDesiredImageSize.cy; } // Make sure we have valid sizes if (nTargetWidth && nTargetHeight) { // Create the target bitmap and make sure it succeeded Bitmap TargetBitmap( nTargetWidth, nTargetHeight ); if (Ok == TargetBitmap.GetLastStatus()) { // Get a graphics to render to Graphics *pGraphics = Graphics::FromImage(&TargetBitmap); if (pGraphics) { // Make sure it is valid if (pGraphics->GetLastStatus() == Ok) { // Draw scaled image if (pGraphics->DrawImage(&SourceBitmap, 0, 0, nTargetWidth, nTargetHeight) == Ok) { // Get an HBITMAP for this image TargetBitmap.GetHBITMAP( Color::Black, &hTargetBitmap ); } } // Clean up our dynamically allocated graphics delete pGraphics; } } } } } } return(hTargetBitmap ? S_OK : E_FAIL); } // Construct a string like this: JPG;BMP;PNG with all supported extensions HRESULT CGdiPlusHelper::ConstructCodecExtensionSearchStrings( CSimpleString &strExtensions, Gdiplus::ImageCodecInfo *pImageCodecInfo, UINT nImageCodecCount ) { for (UINT i=0;i(LocalAlloc(LPTR,cbCodecs)); if (pImageDecoderInfo) { // Get the actual decoder info if (Gdiplus::Ok == Gdiplus::GetImageDecoders( nImageDecoderCount, cbCodecs, pImageDecoderInfo )) { // Add each decoder to the format list for (UINT i=0;i m_nMaxSignatureLength) { m_nMaxSignatureLength = m_FileFormatVerifierList[i].Length(); } } // If we have a valid max length, allocate a buffer to hold the file's data if (m_nMaxSignatureLength) { m_pSignatureBuffer = new BYTE[m_nMaxSignatureLength]; } // If anything failed, free everything if (!IsValid()) { Destroy(); } } void CImageFileFormatVerifier::Destroy(void) { // Free the file signature buffer if (m_pSignatureBuffer) { delete[] m_pSignatureBuffer; m_pSignatureBuffer = NULL; } m_nMaxSignatureLength = 0; m_FileFormatVerifierList.Destroy(); } bool CImageFileFormatVerifier::IsValid(void) const { return (m_pSignatureBuffer && m_nMaxSignatureLength && m_FileFormatVerifierList.Size()); } CImageFileFormatVerifier::~CImageFileFormatVerifier(void) { Destroy(); } GUID CImageFileFormatVerifier::GetImageType( LPCTSTR pszFilename ) { // Assume we will not find a match GUID guidResult = IID_NULL; // Open the file for reading HANDLE hFile = CreateFile( pszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (INVALID_HANDLE_VALUE != hFile) { // Read the maximum signature length number of bytes DWORD dwBytesRead = 0; if (ReadFile( hFile, m_pSignatureBuffer, m_nMaxSignatureLength, &dwBytesRead, NULL )) { // Make sure we got some bytes if (dwBytesRead) { // Go though the list and try to find a match for (int i=0;i