//-------------------------------------------------------------------
// VOImage implementation
//-------------------------------------------------------------------
//
// Copyright �2000 Virtual Office Systems Incorporated
// All Rights Reserved
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name is included.
//
// This code can be compiled, modified and distributed freely, providing
// that this copyright information remains intact in the distribution.
//
// This code may be compiled in original or modified form in any private
// or commercial application.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage, in any form, caused
// by this code. Use it at your own risk.
//-------------------------------------------------------------------
#include "stdafx.h"
#include "VOImage.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#ifdef _WIN32_WCE
#pragma comment(lib, "imgdecmp.lib")
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
int CVOImage::g_iScale = 100;
int CVOImage::g_iMaxWidth = 10000;
int CVOImage::g_iMaxHeight = 10000;
BOOL CVOImage::g_bStretchBlt = FALSE;
CVOImage::CVOImage() : m_hdc(0), m_hbitmap(0), m_dwWidth(0), m_dwHeight(0), m_hmoduleResource(0), m_dwResourceID(0)
{
m_pMemFileData=NULL;
}
CVOImage::~CVOImage()
{
if(m_pMemFileData) delete m_pMemFileData; m_pMemFileData=NULL;
if(m_hbitmap) DeleteObject(m_hbitmap);m_hbitmap=NULL;
if(m_hdc) DeleteDC(m_hdc); m_hdc=NULL;
}
BOOL CVOImage::Load(HDC hdc, LPCTSTR pcszFileName)
{
if(m_hbitmap)
{
if(GetFileName().GetLength() && GetFileName() == pcszFileName)
return TRUE; // Already Loaded
DeleteObject(m_hbitmap);
}
if(!m_hdc)
{
m_hdc = CreateCompatibleDC(hdc);
HBITMAP hbitmap = CreateCompatibleBitmap(hdc, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES));
SelectObject(m_hdc, hbitmap);
}
BYTE szBuffer[1024] = {0};
HANDLE hFile = INVALID_HANDLE_VALUE;
HRESULT hr;
DecompressImageInfo dii;
hFile = CreateFile(pcszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
// Fill in the 'DecompressImageInfo' structure
dii.dwSize = sizeof( DecompressImageInfo ); // Size of this structure
dii.pbBuffer = szBuffer; // Pointer to the buffer to use for data
dii.dwBufferMax = 1024; // Size of the buffer
dii.dwBufferCurrent = 0; // The amount of data which is current in the buffer
dii.phBM = &m_hbitmap; // Pointer to the bitmap returned (can be NULL)
dii.ppImageRender = NULL; // Pointer to an IImageRender object (can be NULL)
dii.iBitDepth = GetDeviceCaps(hdc,BITSPIXEL); // Bit depth of the output image
dii.lParam = ( LPARAM ) hFile; // User parameter for callback functions
dii.hdc = m_hdc; // HDC to use for retrieving palettes
dii.iScale = g_iScale; // Scale factor (1 - 100)
dii.iMaxWidth = g_iMaxWidth; // Maximum width of the output image
dii.iMaxHeight = g_iMaxHeight; // Maxumum height of the output image
dii.pfnGetData = GetImageData; // Callback function to get image data
dii.pfnImageProgress = ImageProgress; // Callback function to notify caller of progress decoding the image
dii.crTransparentOverride = ( UINT ) -1; // If this color is not (UINT)-1, it will override the
// transparent color in the image with this color. (GIF ONLY)
// Process and decompress the image data
hr = DecompressImageIndirect( &dii );
// Clean up
CloseHandle( hFile );
HBITMAP hbitmapOld = (HBITMAP)SelectObject(m_hdc, m_hbitmap);
DeleteObject(hbitmapOld);
BITMAP bmp;
GetObject(m_hbitmap, sizeof(BITMAP), &bmp);
m_dwWidth = bmp.bmWidth;
m_dwHeight = bmp.bmHeight;
m_strFileName = pcszFileName;
m_dwResourceID = 0;
m_hmoduleResource = 0;
return TRUE;
}
BOOL CVOImage::Load(HDC hdc, BYTE *pImageBuffer, DWORD dwImageSize)
{
if(m_hbitmap)
{
DeleteObject(m_hbitmap);
}
if(!m_hdc)
{
m_hdc = CreateCompatibleDC(hdc);
HBITMAP hbitmap = CreateCompatibleBitmap(hdc, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES));
SelectObject(m_hdc, hbitmap);
}
BYTE szBuffer[1024] = {0};
HANDLE hFile = INVALID_HANDLE_VALUE;
HRESULT hr;
DecompressImageInfo dii;
m_pMemFileData=new CMemFileData;
m_pMemFileData->m_pImageBuffer=pImageBuffer;
m_pMemFileData->m_dwCurrentPos=0;
m_pMemFileData->m_dwSize=dwImageSize;
// Fill in the 'DecompressImageInfo' structure
dii.dwSize = sizeof( DecompressImageInfo ); // Size of this structure
dii.pbBuffer = szBuffer; // Pointer to the buffer to use for data
dii.dwBufferMax = 1024; // Size of the buffer
dii.dwBufferCurrent = 0; // The amount of data which is current in the buffer
dii.phBM = &m_hbitmap; // Pointer to the bitmap returned (can be NULL)
dii.ppImageRender = NULL; // Pointer to an IImageRender object (can be NULL)
dii.iBitDepth = GetDeviceCaps(hdc,BITSPIXEL); // Bit depth of the output image
dii.lParam = (LPARAM)m_pMemFileData; // User parameter for callback functions
dii.hdc = m_hdc; // HDC to use for retrieving palettes
dii.iScale = g_iScale; // Scale factor (1 - 100)
dii.iMaxWidth = g_iMaxWidth; // Maximum width of the output image
dii.iMaxHeight = g_iMaxHeight; // Maxumum height of the output image
dii.pfnGetData = GetImageDataEx; // Callback function to get image data
dii.pfnImageProgress = ImageProgress; // Callback function to notify caller of progress decoding the image
dii.crTransparentOverride = ( UINT ) -1; // If this color is not (UINT)-1, it will override the
// transparent color in the image with this color. (GIF ONLY)
// Process and decompress the image data
hr = DecompressImageIndirect( &dii );
delete m_pMemFileData;
m_pMemFileData=NULL;
HBITMAP hbitmapOld = (HBITMAP)SelectObject(m_hdc, m_hbitmap);
DeleteObject(hbitmapOld);
BITMAP bmp;
GetObject(m_hbitmap, sizeof(BITMAP), &bmp);
m_dwWidth = bmp.bmWidth;
m_dwHeight = bmp.bmHeight;
m_strFileName.Format(_T("BufferImage"));
m_dwResourceID = 0;
m_hmoduleResource = 0;
return TRUE;
}
HBITMAP CVOImage::Copy(int cx, int cy, int nCanvasWidth, int nCanvasHeight)
{
BITMAP bm, bmNew;
HBITMAP hNew;
BOOL fStretch = (cx == -1) || (cy == -1);
::GetObject(m_hbitmap, sizeof(BITMAP), &bm);
HDC hdc = CreateCompatibleDC(m_hdc);
if(cx == -1)
{
if(cy == -1)
{ // Both are default.
cx = bm.bmWidth;
cy = bm.bmHeight;
fStretch = FALSE;
}
else
{ // Get cx from cy value
float fltAspect = (float)bm.bmWidth / (float)bm.bmHeight;
cx = (int) ((float)cy * fltAspect);
}
}
else if(cy == -1)
{ // Get cy from cx value
float fltAspect = (float)bm.bmHeight / (float)bm.bmWidth;
cy = (int) ((float)cx * fltAspect);
}
if((nCanvasWidth == -1) || (nCanvasHeight == -1))
{
if(cx < cy)
{
nCanvasWidth = cy;
nCanvasHeight = cy;
}
else
{
nCanvasWidth = cx;
nCanvasHeight = cx;
}
}
// hNew = CreateCompatibleBitmap(m_hdc, cx, cy);
hNew = CreateCompatibleBitmap(m_hdc, nCanvasWidth, nCanvasHeight);
SelectObject(hdc, hNew);
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = nCanvasWidth;
rect.bottom = nCanvasHeight;
// HBRUSH hbrushBG = CreateSolidBrush(GetPixel(0, 0));
FillRect(hdc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
// FillRect(hdc, &rect, hbrushBG);
// DeleteObject(hbrushBG);
if(DrawTransparent(hdc, 0, 0, cx, cy, GetPixel(0, 0)) )
{
HBITMAP hPrev = (HBITMAP) ::GetObject(hNew, sizeof(BITMAP), &bmNew);
::SelectObject(hdc, hPrev);
}
DeleteDC(hdc);
return hNew;
}
BOOL CVOImage::Draw(HDC hdc, int x, int y, int cx, int cy)
{
BITMAP bmp;
g_bStretchBlt = !(cx == -1 && cy == -1);
GetObject(m_hbitmap, sizeof(BITMAP), &bmp);
if (g_bStretchBlt) // Stretch to fit
StretchBlt(hdc, x , y, cx, cy, m_hdc,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY );
else
BitBlt(hdc, x, y, bmp.bmWidth, bmp.bmHeight, m_hdc,0,0,SRCCOPY );
return TRUE;
}
BOOL CVOImage::DrawTranslucent(HDC hdc, int x, int y, int nPercent, int cx, int cy, COLORREF TransparentColor)
{
BITMAP bmpBG, bmpImage;
HDC hdcBG = CreateCompatibleDC(hdc);
HDC hdcImage = CreateCompatibleDC(hdc);
if(cx == -1)
cx = GetWidth();
if(cy == -1)
cy = GetHeight();
BITMAPINFO i;
memset( &i.bmiHeader, 0, sizeof(BITMAPINFOHEADER) );
i.bmiHeader.biWidth=cx;
i.bmiHeader.biHeight=cy;
i.bmiHeader.biPlanes=1;
i.bmiHeader.biBitCount=24;
i.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
PBYTE pBitsBG;
HBITMAP hbitmapBG = CreateDIBSection(hdc, &i, DIB_RGB_COLORS, (PVOID*)&pBitsBG, NULL, 0 );
if(hbitmapBG == 0)
{
DWORD dwError = GetLastError();
DebugBreak();
return FALSE;
}
// Copy the background into the 24bit Background DIB
HBITMAP hbitmapOld = (HBITMAP)SelectObject(hdcBG, hbitmapBG);
BitBlt(hdcBG, 0, 0, cx, cy, hdc, x, y, SRCCOPY);
SelectObject(hdcBG, hbitmapOld);
// Create a matching 24bit DIB Section to hold the image data
PBYTE pBitsImage;
HBITMAP hbitmapImage = CreateDIBSection(hdc, &i, DIB_RGB_COLORS, (PVOID*)&pBitsImage, NULL, 0 );
if(hbitmapImage == 0)
{
DWORD dwError = GetLastError();
DebugBreak();
return FALSE;
}
// Copy the bitmap into the 24bit DIB
hbitmapOld = (HBITMAP)SelectObject(hdcImage, hbitmapImage);
if(TransparentColor == RGB(192, 192, 192))
StretchBlt(hdcImage, 0, 0, cx, cy, m_hdc, 0, 0, GetWidth(), GetHeight(), SRCCOPY);
else
{
#ifdef _WIN32_WCE
BitBlt(hdcImage, 0, 0, cx, cy, hdc, x, y, SRCCOPY);
TransparentImage(hdcImage, 0, 0, cx, cy, m_hdc, 0, 0, GetWidth(), GetHeight(), TransparentColor);
#else
StretchBlt(hdcImage, 0, 0, cx, cy, m_hdc, 0, 0, GetWidth(), GetHeight(), SRCCOPY);
#endif
}
SelectObject(hdcImage, hbitmapOld);
GetObject(hbitmapImage, sizeof(BITMAP), &bmpImage);
GetObject(hbitmapBG, sizeof(BITMAP), &bmpBG);
PBYTE pPixelBG;
PBYTE pPixelImage;
int r, g, b;
int nPercentBG = 100 - nPercent;
for(int yOffset = 0; yOffset < cy; yOffset++)
{
for(int xOffset = 0; xOffset < cx; xOffset++)
{
pPixelBG = (PBYTE)bmpBG.bmBits + (cx * yOffset + xOffset) * 3;
pPixelImage = (PBYTE)bmpImage.bmBits + (cx * yOffset + xOffset) * 3;
r = ((pPixelImage[2] * nPercent / 100) + ((int)pPixelBG[2] * nPercentBG / 100));
g = ((pPixelImage[1] * nPercent / 100) + ((int)pPixelBG[1] * nPercentBG / 100));
b = ((pPixelImage[0] * nPercent / 100) + ((int)pPixelBG[0] * nPercentBG / 100));
pPixelBG[2] = r;
pPixelBG[1] = g;
pPixelBG[0] = b;
}
}
hbitmapOld = (HBITMAP)SelectObject(hdcBG, hbitmapBG);
BitBlt(hdc, x, y, cx, cy, hdcBG, 0, 0,SRCCOPY );
SelectObject(hdcBG, hbitmapOld);
DeleteObject(hbitmapImage);
DeleteObject(hbitmapBG);
DeleteDC(hdcImage);
DeleteDC(hdcBG);
return TRUE;
}
BOOL CVOImage::DrawTransparent(HDC hdc, int x, int y, int cx, int cy, COLORREF TransparentColor)
{
if(cx == -1)
cx = GetWidth();
if(cy == -1)
cy = GetHeight();
if(TransparentColor == RGB(192, 192, 192))
TransparentColor = GetPixel(0, 0); // If none of the above conditions are met, use the pixel at 0,0 (Uppler Left)
#ifdef _WIN32_WCE
return TransparentImage(hdc, x, y, cx, cy, m_hdc, 0, 0, GetWidth(), GetHeight(), TransparentColor);
#else
return FALSE;
#endif
}
DWORD CVOImage::GetHeight()
{
return m_dwHeight;
}
DWORD CVOImage::GetWidth()
{
return m_dwWidth;
}
BOOL CVOImage::SetBitmap(HDC hdc, DWORD dwResourceID, LPCTSTR pcszClass, HMODULE hModule)
{
if(m_hbitmap)
{
if(m_hmoduleResource == hModule && m_dwResourceID == dwResourceID)
return TRUE; // Already loaded
DeleteObject(m_hbitmap);
}
if(!m_hdc)
{
m_hdc = CreateCompatibleDC(hdc);
HBITMAP hbitmap = CreateCompatibleBitmap(hdc, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES));
SelectObject(m_hdc, hbitmap);
}
BYTE szBuffer[1024] = {0};
#ifdef _WIN32_WCE
HRESULT hr;
DecompressImageInfo dii;
#endif
if(hModule == 0)
hModule = GetModuleHandle(NULL);
CVOResource res(hModule, dwResourceID, pcszClass);
if(!res.IsLoaded())
return FALSE;
res.SetUserData(0); // Use this for the current resource offset
#ifdef _WIN32_WCE
// Fill in the 'DecompressImageInfo' structure
dii.dwSize = sizeof( DecompressImageInfo ); // Size of this structure
dii.pbBuffer = szBuffer; // Pointer to the buffer to use for data
dii.dwBufferMax = 1024; // Size of the buffer
dii.dwBufferCurrent = 0; // The amount of data which is current in the buffer
dii.phBM = &m_hbitmap; // Pointer to the bitmap returned (can be NULL)
dii.ppImageRender = NULL; // Pointer to an IImageRender object (can be NULL)
dii.iBitDepth = GetDeviceCaps(hdc,BITSPIXEL); // Bit depth of the output image
dii.lParam = ( LPARAM ) &res; // User parameter for callback functions
dii.hdc = m_hdc; // HDC to use for retrieving palettes
dii.iScale = g_iScale; // Scale factor (1 - 100)
dii.iMaxWidth = g_iMaxWidth; // Maximum width of the output image
dii.iMaxHeight = g_iMaxHeight; // Maxumum height of the output image
dii.pfnGetData = GetImageResourceData; // Callback function to get image data
dii.pfnImageProgress = ImageProgress; // Callback function to notify caller of progress decoding the image
dii.crTransparentOverride = ( UINT ) -1; // If this color is not (UINT)-1, it will override the
// transparent color in the image with this color. (GIF ONLY)
// Process and decompress the image data
hr = DecompressImageIndirect( &dii );
#endif
HBITMAP hbitmapOld = (HBITMAP)SelectObject(m_hdc, m_hbitmap);
DeleteObject(hbitmapOld);
BITMAP bmp;
GetObject(m_hbitmap, sizeof(BITMAP), &bmp);
m_dwWidth = bmp.bmWidth;
m_dwHeight = bmp.bmHeight;
m_strFileName = TEXT("");
m_hmoduleResource = hModule;
m_dwResourceID = dwResourceID;
return TRUE;
}
DWORD CALLBACK CVOImage::GetImageData(LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam )
{
DWORD dwNumberOfBytesRead;
if ( (HANDLE)lParam == INVALID_HANDLE_VALUE )
return 0;
ReadFile( (HANDLE)lParam, szBuffer, dwBufferMax, &dwNumberOfBytesRead, NULL );
// Return number of bytes read
return dwNumberOfBytesRead;
}
DWORD CALLBACK CVOImage::GetImageDataEx(LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam )
{
DWORD dwNumberOfBytesRead=0;
CMemFileData *pData=(CMemFileData*)lParam;
if (pData==NULL)
return 0;
dwNumberOfBytesRead=dwBufferMax;
if (pData->m_dwCurrentPos+dwNumberOfBytesRead>pData->m_dwSize)
{
dwNumberOfBytesRead=pData->m_dwSize-pData->m_dwCurrentPos;
}
memcpy(szBuffer,&pData->m_pImageBuffer[pData->m_dwCurrentPos],dwNumberOfBytesRead);
pData->m_dwCurrentPos+=dwNumberOfBytesRead;
// Return number of bytes read
return dwNumberOfBytesRead;
}
DWORD CALLBACK CVOImage::GetImageResourceData(LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam)
{
DWORD dwNumberOfBytesToRead = dwBufferMax;
CVOResource* pRes = (CVOResource*) lParam;
if(!pRes)
return 0;
DWORD dwResourceOffset = pRes->GetUserData();
if(dwResourceOffset + dwNumberOfBytesToRead > pRes->GetSize() )
dwNumberOfBytesToRead = pRes->GetSize() - dwResourceOffset;
memmove(szBuffer, pRes->GetData() + dwResourceOffset, dwNumberOfBytesToRead);
pRes->SetUserData(dwResourceOffset + dwNumberOfBytesToRead);
return dwNumberOfBytesToRead; // return amount read
}
#ifdef _WIN32_WCE
void CALLBACK CVOImage::ImageProgress(IImageRender *pRender, BOOL bComplete, LPARAM lParam )
{
if( bComplete )
{
;// (Optional) add code here for completion processing
}
}
#endif
BOOL CVOImage::IsLoaded()
{
return (m_hbitmap != 0);
}
HBITMAP CVOImage::GetHBitmap()
{
return m_hbitmap;
}
CVOResource::CVOResource(HMODULE hModule, DWORD dwResourceID, LPCTSTR pcszClass)
{
m_dwSize = 0;
m_hGlobal = 0;
m_pData = 0;
m_hrsrc = FindResource(hModule, (LPCTSTR)dwResourceID, pcszClass);
if(m_hrsrc == 0)
return;
m_dwSize = SizeofResource(hModule, m_hrsrc);
m_hGlobal = LoadResource(hModule, m_hrsrc);
m_pData = (PBYTE) LockResource(m_hGlobal);
}
CVOResource::~CVOResource()
{
if(m_hGlobal)
DeleteObject(m_hGlobal);
}
BOOL CVOResource::IsLoaded()
{
return (m_pData != NULL);
}
COLORREF CVOImage::GetPixel(int x, int y)
{
if(m_hdc == 0)
return RGB(0, 0, 0);
return ::GetPixel(m_hdc, x, y);
}
BOOL CVOImage::SetCanvasSize(int x, int y, COLORREF rgbBackground, BOOL fHCenter, BOOL fVCenter)
{
if(rgbBackground == RGB(1, 1, 1))
rgbBackground = GetPixel(0, 0);
if(x < (int)GetWidth() || y < (int)GetHeight())
return FALSE; // Cropping may be implemented at some point in the future
int nOffsetX = 0;
int nOffsetY = 0;
if(fHCenter)
nOffsetX = (x - GetWidth()) / 2;
if(fVCenter)
nOffsetY = (y - GetHeight()) / 2;
BITMAP bm, bmNew;
HBITMAP hbitmapNew;
::GetObject(m_hbitmap, sizeof(BITMAP), &bm);
HDC hdc = CreateCompatibleDC(m_hdc);
hbitmapNew = CreateCompatibleBitmap(m_hdc, x, y);
SelectObject(hdc, hbitmapNew);
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = x;
rect.bottom = y;
FillRect(hdc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
if(!BitBlt(hdc, nOffsetX, nOffsetY, GetWidth(), GetHeight(), m_hdc, 0, 0, SRCCOPY))
{
DeleteDC(hdc);
DeleteObject(hbitmapNew);
return FALSE;
}
HBITMAP hPrev = (HBITMAP) ::GetObject(hbitmapNew, sizeof(BITMAP), &bmNew);
::SelectObject(hdc, hPrev);
DeleteDC(m_hdc);
DeleteObject(m_hbitmap);
m_hdc = hdc;
m_hbitmap = hbitmapNew;
return TRUE;
}