//------------------------------------------------------------------- // 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) { } CVOImage::~CVOImage() { if(m_hdc) DeleteDC(m_hdc); if(m_hbitmap) DeleteObject(m_hbitmap); } 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; #ifdef _WIN32_WCE HRESULT hr; DecompressImageInfo dii; #endif hFile = CreateFile(pcszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile == INVALID_HANDLE_VALUE) return FALSE; #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 ) 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 ); #endif // 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; } 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::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); } 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; }