// CDIBSectionLite.cpp : implementation file // // General purpose DIBsection wrapper class for Win9x, NT 4.0, W2K and WinCE. // // Author : Chris Maunder (cmaunder@mail.com) // Date : 17 May 1999 // // Copyright © Dundas Software Ltd. 1999, 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. If // the source code in this file is used in any commercial application // then a simple email would be nice. // // 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 and as with all code expect bugs! // It's been tested but I'm not perfect. // // Please use and enjoy. Please let me know of any bugs/mods/improvements // that you have found/implemented and I will fix/incorporate them into this // file. // // History : 25 May 1999 - First release // 4 Jun 1999 - Fixed SetBitmap bug // 4 May 2000 - 16 or 32 bit compression bug fix (Jim Miller ) // Bug fix in Save() (saving 4 bytes too many - Tadeusz Dracz) // 12 Dec 2000 - KennyG@magenic.com - Massive MFC extraxtion, remove that bloat! // #include "stdafx.h" #include "CDIB.h" // Standard colors RGBQUAD CDIB::ms_StdColors[] = { { 0x00, 0x00, 0x00, 0 }, // System palette - first 10 colors { 0x80, 0x00, 0x00, 0 }, { 0x00, 0x80, 0x00, 0 }, { 0x80, 0x80, 0x00, 0 }, { 0x00, 0x00, 0x80, 0 }, { 0x80, 0x00, 0x80, 0 }, { 0x00, 0x80, 0x80, 0 }, { 0xC0, 0xC0, 0xC0, 0 }, { 0xC0, 0xDC, 0xC0, 0 }, { 0xA6, 0xCA, 0xF0, 0 }, { 0x2C, 0x00, 0x00, 0 }, { 0x56, 0x00, 0x00, 0 }, { 0x87, 0x00, 0x00, 0 }, { 0xC0, 0x00, 0x00, 0 }, { 0xFF, 0x00, 0x00, 0 }, { 0x00, 0x2C, 0x00, 0 }, { 0x2C, 0x2C, 0x00, 0 }, { 0x56, 0x2C, 0x00, 0 }, { 0x87, 0x2C, 0x00, 0 }, { 0xC0, 0x2C, 0x00, 0 }, { 0xFF, 0x2C, 0x00, 0 }, { 0x00, 0x56, 0x00, 0 }, { 0x2C, 0x56, 0x00, 0 }, { 0x56, 0x56, 0x00, 0 }, { 0x87, 0x56, 0x00, 0 }, { 0xC0, 0x56, 0x00, 0 }, { 0xFF, 0x56, 0x00, 0 }, { 0x00, 0x87, 0x00, 0 }, { 0x2C, 0x87, 0x00, 0 }, { 0x56, 0x87, 0x00, 0 }, { 0x87, 0x87, 0x00, 0 }, { 0xC0, 0x87, 0x00, 0 }, { 0xFF, 0x87, 0x00, 0 }, { 0x00, 0xC0, 0x00, 0 }, { 0x2C, 0xC0, 0x00, 0 }, { 0x56, 0xC0, 0x00, 0 }, { 0x87, 0xC0, 0x00, 0 }, { 0xC0, 0xC0, 0x00, 0 }, { 0xFF, 0xC0, 0x00, 0 }, { 0x00, 0xFF, 0x00, 0 }, { 0x2C, 0xFF, 0x00, 0 }, { 0x56, 0xFF, 0x00, 0 }, { 0x87, 0xFF, 0x00, 0 }, { 0xC0, 0xFF, 0x00, 0 }, { 0xFF, 0xFF, 0x00, 0 }, { 0x00, 0x00, 0x2C, 0 }, { 0x2C, 0x00, 0x2C, 0 }, { 0x56, 0x00, 0x2C, 0 }, { 0x87, 0x00, 0x2C, 0 }, { 0xC0, 0x00, 0x2C, 0 }, { 0xFF, 0x00, 0x2C, 0 }, { 0x00, 0x2C, 0x2C, 0 }, { 0x2C, 0x2C, 0x2C, 0 }, { 0x56, 0x2C, 0x2C, 0 }, { 0x87, 0x2C, 0x2C, 0 }, { 0xC0, 0x2C, 0x2C, 0 }, { 0xFF, 0x2C, 0x2C, 0 }, { 0x00, 0x56, 0x2C, 0 }, { 0x2C, 0x56, 0x2C, 0 }, { 0x56, 0x56, 0x2C, 0 }, { 0x87, 0x56, 0x2C, 0 }, { 0xC0, 0x56, 0x2C, 0 }, { 0xFF, 0x56, 0x2C, 0 }, { 0x00, 0x87, 0x2C, 0 }, { 0x2C, 0x87, 0x2C, 0 }, { 0x56, 0x87, 0x2C, 0 }, { 0x87, 0x87, 0x2C, 0 }, { 0xC0, 0x87, 0x2C, 0 }, { 0xFF, 0x87, 0x2C, 0 }, { 0x00, 0xC0, 0x2C, 0 }, { 0x2C, 0xC0, 0x2C, 0 }, { 0x56, 0xC0, 0x2C, 0 }, { 0x87, 0xC0, 0x2C, 0 }, { 0xC0, 0xC0, 0x2C, 0 }, { 0xFF, 0xC0, 0x2C, 0 }, { 0x00, 0xFF, 0x2C, 0 }, { 0x2C, 0xFF, 0x2C, 0 }, { 0x56, 0xFF, 0x2C, 0 }, { 0x87, 0xFF, 0x2C, 0 }, { 0xC0, 0xFF, 0x2C, 0 }, { 0xFF, 0xFF, 0x2C, 0 }, { 0x00, 0x00, 0x56, 0 }, { 0x2C, 0x00, 0x56, 0 }, { 0x56, 0x00, 0x56, 0 }, { 0x87, 0x00, 0x56, 0 }, { 0xC0, 0x00, 0x56, 0 }, { 0xFF, 0x00, 0x56, 0 }, { 0x00, 0x2C, 0x56, 0 }, { 0x2C, 0x2C, 0x56, 0 }, { 0x56, 0x2C, 0x56, 0 }, { 0x87, 0x2C, 0x56, 0 }, { 0xC0, 0x2C, 0x56, 0 }, { 0xFF, 0x2C, 0x56, 0 }, { 0x00, 0x56, 0x56, 0 }, { 0x2C, 0x56, 0x56, 0 }, { 0x56, 0x56, 0x56, 0 }, { 0x87, 0x56, 0x56, 0 }, { 0xC0, 0x56, 0x56, 0 }, { 0xFF, 0x56, 0x56, 0 }, { 0x00, 0x87, 0x56, 0 }, { 0x2C, 0x87, 0x56, 0 }, { 0x56, 0x87, 0x56, 0 }, { 0x87, 0x87, 0x56, 0 }, { 0xC0, 0x87, 0x56, 0 }, { 0xFF, 0x87, 0x56, 0 }, { 0x00, 0xC0, 0x56, 0 }, { 0x2C, 0xC0, 0x56, 0 }, { 0x56, 0xC0, 0x56, 0 }, { 0x87, 0xC0, 0x56, 0 }, { 0xC0, 0xC0, 0x56, 0 }, { 0xFF, 0xC0, 0x56, 0 }, { 0x00, 0xFF, 0x56, 0 }, { 0x2C, 0xFF, 0x56, 0 }, { 0x56, 0xFF, 0x56, 0 }, { 0x87, 0xFF, 0x56, 0 }, { 0xC0, 0xFF, 0x56, 0 }, { 0xFF, 0xFF, 0x56, 0 }, { 0x00, 0x00, 0x87, 0 }, { 0x2C, 0x00, 0x87, 0 }, { 0x56, 0x00, 0x87, 0 }, { 0x87, 0x00, 0x87, 0 }, { 0xC0, 0x00, 0x87, 0 }, { 0xFF, 0x00, 0x87, 0 }, { 0x00, 0x2C, 0x87, 0 }, { 0x2C, 0x2C, 0x87, 0 }, { 0x56, 0x2C, 0x87, 0 }, { 0x87, 0x2C, 0x87, 0 }, { 0xC0, 0x2C, 0x87, 0 }, { 0xFF, 0x2C, 0x87, 0 }, { 0x00, 0x56, 0x87, 0 }, { 0x2C, 0x56, 0x87, 0 }, { 0x56, 0x56, 0x87, 0 }, { 0x87, 0x56, 0x87, 0 }, { 0xC0, 0x56, 0x87, 0 }, { 0xFF, 0x56, 0x87, 0 }, { 0x00, 0x87, 0x87, 0 }, { 0x2C, 0x87, 0x87, 0 }, { 0x56, 0x87, 0x87, 0 }, { 0x87, 0x87, 0x87, 0 }, { 0xC0, 0x87, 0x87, 0 }, { 0xFF, 0x87, 0x87, 0 }, { 0x00, 0xC0, 0x87, 0 }, { 0x2C, 0xC0, 0x87, 0 }, { 0x56, 0xC0, 0x87, 0 }, { 0x87, 0xC0, 0x87, 0 }, { 0xC0, 0xC0, 0x87, 0 }, { 0xFF, 0xC0, 0x87, 0 }, { 0x00, 0xFF, 0x87, 0 }, { 0x2C, 0xFF, 0x87, 0 }, { 0x56, 0xFF, 0x87, 0 }, { 0x87, 0xFF, 0x87, 0 }, { 0xC0, 0xFF, 0x87, 0 }, { 0xFF, 0xFF, 0x87, 0 }, { 0x00, 0x00, 0xC0, 0 }, { 0x2C, 0x00, 0xC0, 0 }, { 0x56, 0x00, 0xC0, 0 }, { 0x87, 0x00, 0xC0, 0 }, { 0xC0, 0x00, 0xC0, 0 }, { 0xFF, 0x00, 0xC0, 0 }, { 0x00, 0x2C, 0xC0, 0 }, { 0x2C, 0x2C, 0xC0, 0 }, { 0x56, 0x2C, 0xC0, 0 }, { 0x87, 0x2C, 0xC0, 0 }, { 0xC0, 0x2C, 0xC0, 0 }, { 0xFF, 0x2C, 0xC0, 0 }, { 0x00, 0x56, 0xC0, 0 }, { 0x2C, 0x56, 0xC0, 0 }, { 0x56, 0x56, 0xC0, 0 }, { 0x87, 0x56, 0xC0, 0 }, { 0xC0, 0x56, 0xC0, 0 }, { 0xFF, 0x56, 0xC0, 0 }, { 0x00, 0x87, 0xC0, 0 }, { 0x2C, 0x87, 0xC0, 0 }, { 0x56, 0x87, 0xC0, 0 }, { 0x87, 0x87, 0xC0, 0 }, { 0xC0, 0x87, 0xC0, 0 }, { 0xFF, 0x87, 0xC0, 0 }, { 0x00, 0xC0, 0xC0, 0 }, { 0x2C, 0xC0, 0xC0, 0 }, { 0x56, 0xC0, 0xC0, 0 }, { 0x87, 0xC0, 0xC0, 0 }, { 0xFF, 0xC0, 0xC0, 0 }, { 0x00, 0xFF, 0xC0, 0 }, { 0x2C, 0xFF, 0xC0, 0 }, { 0x56, 0xFF, 0xC0, 0 }, { 0x87, 0xFF, 0xC0, 0 }, { 0xC0, 0xFF, 0xC0, 0 }, { 0xFF, 0xFF, 0xC0, 0 }, { 0x00, 0x00, 0xFF, 0 }, { 0x2C, 0x00, 0xFF, 0 }, { 0x56, 0x00, 0xFF, 0 }, { 0x87, 0x00, 0xFF, 0 }, { 0xC0, 0x00, 0xFF, 0 }, { 0xFF, 0x00, 0xFF, 0 }, { 0x00, 0x2C, 0xFF, 0 }, { 0x2C, 0x2C, 0xFF, 0 }, { 0x56, 0x2C, 0xFF, 0 }, { 0x87, 0x2C, 0xFF, 0 }, { 0xC0, 0x2C, 0xFF, 0 }, { 0xFF, 0x2C, 0xFF, 0 }, { 0x00, 0x56, 0xFF, 0 }, { 0x2C, 0x56, 0xFF, 0 }, { 0x56, 0x56, 0xFF, 0 }, { 0x87, 0x56, 0xFF, 0 }, { 0xC0, 0x56, 0xFF, 0 }, { 0xFF, 0x56, 0xFF, 0 }, { 0x00, 0x87, 0xFF, 0 }, { 0x2C, 0x87, 0xFF, 0 }, { 0x56, 0x87, 0xFF, 0 }, { 0x87, 0x87, 0xFF, 0 }, { 0xC0, 0x87, 0xFF, 0 }, { 0xFF, 0x87, 0xFF, 0 }, { 0x00, 0xC0, 0xFF, 0 }, { 0x2C, 0xC0, 0xFF, 0 }, { 0x56, 0xC0, 0xFF, 0 }, { 0x87, 0xC0, 0xFF, 0 }, { 0xC0, 0xC0, 0xFF, 0 }, { 0xFF, 0xC0, 0xFF, 0 }, { 0x2C, 0xFF, 0xFF, 0 }, { 0x56, 0xFF, 0xFF, 0 }, { 0x87, 0xFF, 0xFF, 0 }, { 0xC0, 0xFF, 0xFF, 0 }, { 0xFF, 0xFF, 0xFF, 0 }, { 0x11, 0x11, 0x11, 0 }, { 0x18, 0x18, 0x18, 0 }, { 0x1E, 0x1E, 0x1E, 0 }, { 0x25, 0x25, 0x25, 0 }, { 0x2C, 0x2C, 0x2C, 0 }, { 0x34, 0x34, 0x34, 0 }, { 0x3C, 0x3C, 0x3C, 0 }, { 0x44, 0x44, 0x44, 0 }, { 0x4D, 0x4D, 0x4D, 0 }, { 0x56, 0x56, 0x56, 0 }, { 0x5F, 0x5F, 0x5F, 0 }, { 0x69, 0x69, 0x69, 0 }, { 0x72, 0x72, 0x72, 0 }, { 0x7D, 0x7D, 0x7D, 0 }, { 0x92, 0x92, 0x92, 0 }, { 0x9D, 0x9D, 0x9D, 0 }, { 0xA8, 0xA8, 0xA8, 0 }, { 0xB4, 0xB4, 0xB4, 0 }, { 0xCC, 0xCC, 0xCC, 0 }, { 0xD8, 0xD8, 0xD8, 0 }, { 0xE5, 0xE5, 0xE5, 0 }, { 0xF2, 0xF2, 0xF2, 0 }, { 0xFF, 0xFF, 0xFF, 0 }, { 0xFF, 0xFB, 0xF0, 0 }, // System palette - last 10 colors { 0xA0, 0xA0, 0xA4, 0 }, { 0x80, 0x80, 0x80, 0 }, { 0xFF, 0x00, 0x00, 0 }, { 0x00, 0xFF, 0x00, 0 }, { 0xFF, 0xFF, 0x00, 0 }, { 0x00, 0x00, 0xFF, 0 }, { 0xFF, 0x00, 0xFF, 0 }, { 0x00, 0xFF, 0xFF, 0 }, { 0xFF, 0xFF, 0xFF, 0 }, }; ///////////////////////////////////////////////////////////////////////////// // CE DIBSection global functions #ifdef _WIN32_WCE UINT CEGetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries, RGBQUAD *pColors); #endif ///////////////////////////////////////////////////////////////////////////// // CDIB static functions // // --- In  : nBitsPerPixel - bits per pixel // nCompression - type of compression // --- Out : // --- Returns :The number of colors for this color depth // --- Effect : Returns the number of color table entries given the number // of bits per pixel of a bitmap /*static*/ int CDIB::NumColorEntries(int nBitsPerPixel, int nCompression) { int nColors = 0; switch (nBitsPerPixel) { case 1: nColors = 2; break; #ifdef _WIN32_WCE case 2: nColors = 4; break; // winCE only #endif case 4: nColors = 16; break; case 8: nColors = 256; break; case 24: nColors = 0; break; case 16: case 32: if (nCompression == BI_BITFIELDS) nColors = 3; // 16 or 32 bpp have 3 colors(masks) in the color table if bitfield compression else nColors = 0; // 16 or 32 bpp have no color table if no bitfield compression break; default: ASSERT(FALSE); } return nColors; } // // --- In  : nWidth - image width in pixels // nBitsPerPixel - bits per pixel // --- Out : // --- Returns : Returns the number of storage bytes needed for each scanline // in the bitmap // --- Effect : /*static*/ int CDIB::BytesPerLine(int nWidth, int nBitsPerPixel) { return ( (nWidth * nBitsPerPixel + 31) & (~31) ) / 8; } #ifndef DIBSECTION_NO_PALETTE // --- In  : palette - reference to a palette object which will be filled // nNumColors - number of color entries to fill // --- Out : // --- Returns : TRUE on success, false otherwise // --- Effect : Creates a halftone color palette independant of screen color depth. // palette will be filled with the colors, and nNumColors is the No. // of colors to file. If nNumColorsis 0 or > 256, then 256 colors are used. /*static*/ BOOL CDIB::CreateHalftonePalette(HPALETTE hPal, int nNumColors) { ::DeleteObject(hPal); // Sanity check on requested number of colours. if (nNumColors <= 0 || nNumColors > 256) nNumColors = 256; else if (nNumColors <= 2) nNumColors = 2; else if (nNumColors <= 16) nNumColors = 16; else if (nNumColors <= 256) nNumColors = 256; PALETTEINFO pi; pi.palNumEntries = (WORD) nNumColors; if (nNumColors == 2) { // According to the MS article "The Palette Manager: How and Why" // monochrome palettes not really needed (will use B&W) pi.palPalEntry[0].peRed = ms_StdColors[0].rgbRed; pi.palPalEntry[0].peGreen = ms_StdColors[0].rgbGreen; pi.palPalEntry[0].peBlue = ms_StdColors[0].rgbBlue; pi.palPalEntry[0].peFlags = 0; pi.palPalEntry[1].peRed = ms_StdColors[255].rgbRed; pi.palPalEntry[1].peGreen = ms_StdColors[255].rgbGreen; pi.palPalEntry[1].peBlue = ms_StdColors[255].rgbBlue; pi.palPalEntry[1].peFlags = 0; } else if (nNumColors == 16) { // According to the MS article "The Palette Manager: How and Why" // 4-bit palettes not really needed (will use VGA palette) for (int i = 0; i < 8; i++) { pi.palPalEntry[i].peRed = ms_StdColors[i].rgbRed; pi.palPalEntry[i].peGreen = ms_StdColors[i].rgbGreen; pi.palPalEntry[i].peBlue = ms_StdColors[i].rgbBlue; pi.palPalEntry[i].peFlags = 0; } for (i = 8; i < 16; i++) { pi.palPalEntry[i].peRed = ms_StdColors[248+i].rgbRed; pi.palPalEntry[i].peGreen = ms_StdColors[248+i].rgbGreen; pi.palPalEntry[i].peBlue = ms_StdColors[248+i].rgbBlue; pi.palPalEntry[i].peFlags = 0; } } else // if (nNumColors == 256) { // Fill palette with full halftone palette for (int i = 0; i < 256; i++) { pi.palPalEntry[i].peRed = ms_StdColors[i].rgbRed; pi.palPalEntry[i].peGreen = ms_StdColors[i].rgbGreen; pi.palPalEntry[i].peBlue = ms_StdColors[i].rgbBlue; pi.palPalEntry[i].peFlags = 0; } } hPal = ::CreatePalette((LPLOGPALETTE) pi); return (hPal != NULL); } #endif // DIBSECTION_NO_PALETTE ///////////////////////////////////////////////////////////////////////////// // CDIB CDIB::CDIB() { // Just in case... ASSERT(sizeof(ms_StdColors) / sizeof(ms_StdColors[0]) == 256); m_hBitmap = NULL; m_hOldBitmap = NULL; #ifndef DIBSECTION_NO_MEMDC_REUSE m_bReuseMemDC = FALSE; #endif #ifndef DIBSECTION_NO_PALETTE m_hOldPal = NULL; #endif } CDIB::~CDIB() { // Unselect the bitmap out of the memory DC before deleting bitmap ReleaseMemoryDC(TRUE); if (m_hBitmap) ::DeleteObject(m_hBitmap); m_hBitmap = NULL; m_ppvBits = NULL; #ifndef DIBSECTION_NO_PALETTE DeleteObject((HGDIOBJ) m_hPal); #endif memset(&m_DIBinfo, 0, sizeof(m_DIBinfo)); m_iColorDataType = DIB_RGB_COLORS; m_iColorTableSize = 0; } ///////////////////////////////////////////////////////////////////////////// // // CDIB operations // // --- In  : pDC - Pointer to a device context // ptDest - point at which the topleft corner of the image is drawn // --- Out : // --- Returns : TRUE on success // --- Effect : Draws the image 1:1 on the device context // /////////////////////////////////////////////////////////////////////////////// BOOL CDIB::Draw(HDC hDC, POINT& ptDest, BOOL bForceBackground /*=FALSE*/) { if (!m_hBitmap) return FALSE; SIZE size; // = GetSize(); POINT ptOrigin = {0,0}; BOOL bResult = FALSE; // Create a memory DC compatible with the destination DC HDC hMemDC = GetMemoryDC(hDC, FALSE); if (!hMemDC) return FALSE; #ifndef DIBSECTION_NO_PALETTE // Select and realize the palette HPALETTE hOldPalette = NULL; if (m_hPal && UsesPalette(hDC)) { hOldPalette = SelectPalette(hDC, m_hPal, bForceBackground ); RealizePalette(hDC); } #endif // DIBSECTION_NO_PALETTE bResult = BitBlt(hDC, ptDest.x, ptDest.y, size.cx, size.cy, hMemDC, ptOrigin.x, ptOrigin.y, SRCCOPY); #ifndef DIBSECTION_NO_PALETTE if (hOldPalette) SelectPalette(hDC, hOldPalette, FALSE); #endif // DIBSECTION_NO_PALETTE ReleaseMemoryDC(); return bResult; } /////////////////////////////////////////////////////////////////////////////// // // --- In  : pDC - Pointer to a device context // ptDest - point at which the topleft corner of the image is drawn // size - size to stretch the image // --- Out : // --- Returns : TRUE on success // --- Effect : Stretch draws the image to the desired size on the device context // /////////////////////////////////////////////////////////////////////////////// BOOL CDIB::Stretch(HDC hDC, POINT& ptDest, SIZE& size, BOOL bForceBackground /*=FALSE*/) { if (!m_hBitmap) return FALSE; BOOL bResult = FALSE; POINT ptOrigin = {0,0}; SIZE imagesize; GetSize(imagesize); #ifndef _WIN32_WCE //pDC->SetStretchBltMode(COLORONCOLOR); #endif // Create a memory DC compatible with the destination DC HDC hMemDC = GetMemoryDC(hDC, FALSE); if (!hMemDC) return FALSE; #ifndef DIBSECTION_NO_PALETTE // Select and realize the palette HPALETTE hOldPalette = NULL; if (m_hPal && UsesPalette(hDC)) { hOldPalette = SelectPalette(hDC, m_hPal, bForceBackground); RealizePalette(hDC); } #endif // DIBSECTION_NO_PALETTE bResult = StretchBlt(hDC, ptDest.x, ptDest.y, size.cx, size.cy, hMemDC, ptOrigin.x, ptOrigin.y, imagesize.cx, imagesize.cy, SRCCOPY); #ifndef DIBSECTION_NO_PALETTE if (hOldPalette) SelectPalette(hDC, hOldPalette, FALSE); #endif // DIBSECTION_NO_PALETTE ReleaseMemoryDC(); return bResult; } ////////////////////////////////////////////////////////////////////////////// // Setting the bitmap... // // --- In  : nIDResource - resource ID // --- Out : // --- Returns : Returns TRUE on success, FALSE otherwise // --- Effect : Initialises the bitmap from a resource. If failure, then object is // initialised back to an empty bitmap. // /////////////////////////////////////////////////////////////////////////////// BOOL CDIB::SetBitmap(UINT nIDResource, HINSTANCE hInst /*= NULL*/ ) { return SetBitmap(MAKEINTRESOURCE(nIDResource), hInst); } /////////////////////////////////////////////////////////////////////////////// // // --- In  : lpszResourceName - resource name // --- Out : // --- Returns : Returns TRUE on success, FALSE otherwise // --- Effect : Initialises the bitmap from a resource. If failure, then object is // initialised back to an empty bitmap. // /////////////////////////////////////////////////////////////////////////////// BOOL CDIB::SetBitmap(LPCTSTR lpszRes, HINSTANCE hInst /*= NULL*/ ) { HBITMAP hBmp = (HBITMAP)::LoadImage(hInst, lpszRes, IMAGE_BITMAP, 0,0,0); if (!hBmp) { TRACE0("Unable to LoadImage"); return FALSE; } BOOL bResult = SetBitmap(hBmp); ::DeleteObject(hBmp); return bResult; } /////////////////////////////////////////////////////////////////////////////// // // --- In  : lpBitmapInfo - pointer to a BITMAPINFO structure // lpBits - pointer to image bits // --- Out : // --- Returns : Returns TRUE on success, FALSE otherwise // --- Effect : Initialises the bitmap using the information in lpBitmapInfo to determine // the dimensions and colors, and the then sets the bits from the bits in // lpBits. If failure, then object is initialised back to an empty bitmap. // /////////////////////////////////////////////////////////////////////////////// BOOL CDIB::SetBitmap(LPBITMAPINFO lpBitmapInfo, LPVOID lpBits) { // DeleteObject(); if (!lpBitmapInfo || !lpBits) return FALSE; HDC hDC = NULL; BITMAPINFOHEADER& bmih = lpBitmapInfo->bmiHeader; // Compute the number of colors in the color table m_iColorTableSize = NumColorEntries(bmih.biBitCount, bmih.biCompression); DWORD dwBitmapInfoSize = sizeof(BITMAPINFO) + m_iColorTableSize*sizeof(RGBQUAD); // Copy over BITMAPINFO contents memcpy(&m_DIBinfo, lpBitmapInfo, dwBitmapInfoSize); // Should now have all the info we need to create the sucker. //TRACE(_T("Width %d, Height %d, Bits/pixel %d, Image Size %d\n"), // bmih.biWidth, bmih.biHeight, bmih.biBitCount, bmih.biSizeImage); // Create a DC which will be used to get DIB, then create DIBsection hDC = ::GetDC(NULL); if (!hDC) { TRACE0("Unable to get DC\n"); return FALSE; } m_hBitmap = CreateDIBSection(hDC, (const BITMAPINFO*) m_DIBinfo, m_iColorDataType, &m_ppvBits, NULL, 0); ::ReleaseDC(NULL, hDC); if (!m_hBitmap) { TRACE0("CreateDIBSection failed\n"); return FALSE; } if (m_DIBinfo.bmiHeader.biSizeImage == 0) { int nBytesPerLine = BytesPerLine(lpBitmapInfo->bmiHeader.biWidth, lpBitmapInfo->bmiHeader.biBitCount); m_DIBinfo.bmiHeader.biSizeImage = nBytesPerLine * lpBitmapInfo->bmiHeader.biHeight; } memcpy(m_ppvBits, lpBits, m_DIBinfo.bmiHeader.biSizeImage); #ifndef DIBSECTION_NO_PALETTE if (!CreatePalette()) { TRACE0("Unable to create palette\n"); return FALSE; } #endif // DIBSECTION_NO_PALETTE return TRUE; } ////////////////////////////////////////////////////////////////////////////////// // // --- In  : hBitmap - handle to image // pPalette - optional palette to use when setting image // --- Out : // --- Returns : Returns TRUE on success, FALSE otherwise // --- Effect : Initialises the bitmap from the HBITMAP supplied. If failure, then // object is initialised back to an empty bitmap. // /////////////////////////////////////////////////////////////////////////////// BOOL CDIB::SetBitmap(HBITMAP hBitmap, HPALETTE hPal /*= NULL*/) { // DeleteObject(); if (!hBitmap) return FALSE; // Get dimensions of bitmap BITMAP bm; if (!::GetObject(hBitmap, sizeof(bm),(LPVOID)&bm)) return FALSE; bm.bmHeight = abs(bm.bmHeight); HDC hDC = GetWindowDC(NULL); HPALETTE hOldPal = NULL; m_iColorTableSize = NumColorEntries(bm.bmBitsPixel, BI_RGB); // Initialize the BITMAPINFOHEADER in m_DIBinfo BITMAPINFOHEADER& bih = m_DIBinfo.bmiHeader; bih.biSize = sizeof(BITMAPINFOHEADER); bih.biWidth = bm.bmWidth; bih.biHeight = bm.bmHeight; bih.biPlanes = 1; // Must always be 1 according to docs bih.biBitCount = bm.bmBitsPixel; bih.biCompression = BI_RGB; bih.biSizeImage = BytesPerLine(bm.bmWidth, bm.bmBitsPixel) * bm.bmHeight; bih.biXPelsPerMeter = 0; bih.biYPelsPerMeter = 0; bih.biClrUsed = 0; bih.biClrImportant = 0; GetColorTableEntries(hDC, hBitmap); // If we have a palette supplied, then set the palette (and hance DIB color // table) using this palette if (hPal) SetPalette(hPal); if (hPal) { hOldPal = SelectPalette(hDC, m_hPal, FALSE); RealizePalette(hDC); } // Create it! m_hBitmap = CreateDIBSection(hDC, (const BITMAPINFO*) m_DIBinfo, m_iColorDataType, &m_ppvBits, NULL, 0); if (hOldPal) SelectPalette(hDC, hOldPal, FALSE); hOldPal = NULL; if (! m_hBitmap) { TRACE0("Unable to CreateDIBSection\n"); return FALSE; } // If palette was supplied then create a palette using the entries in the DIB // color table. if (! hPal) CreatePalette(); // Need to copy the supplied bitmap onto the newly created DIBsection HDC hMemDC = CreateCompatibleDC(hDC); HDC hCopyDC = CreateCompatibleDC(hDC); if (! hMemDC || ! hCopyDC) { TRACE0("Unable to create compatible DC's\n"); //AfxThrowResourceException(); } if (m_hPal) { SelectPalette(hMemDC, m_hPal, FALSE); RealizePalette(hMemDC); SelectPalette(hCopyDC, m_hPal, FALSE); RealizePalette(hCopyDC); } HBITMAP hOldMemBitmap = (HBITMAP) SelectObject(hMemDC, hBitmap); HBITMAP hOldCopyBitmap = (HBITMAP) SelectObject(hCopyDC, m_hBitmap); BitBlt(hCopyDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY); SelectObject(hMemDC, hOldMemBitmap); SelectObject(hCopyDC, hOldCopyBitmap); if (m_hPal) { HGDIOBJ hObj = ::GetStockObject(DEFAULT_PALETTE); SelectObject(hMemDC, hObj); SelectObject(hCopyDC, hObj); } ReleaseDC(NULL, hDC); return TRUE; } /////////////////////////////////////////////////////////////////////////////// // // CDIB palette stuff // // --- In  : nNumColors - number of colors to set // pColors - array of RGBQUAD's containing colors to set // --- Out : // --- Returns : Returns TRUE on success, FALSE otherwise // --- Effect : Sets the colors used by the image. Only works if # colors <= 256 // /////////////////////////////////////////////////////////////////////////////// BOOL CDIB::SetColorTable(UINT nNumColors, RGBQUAD *pColors) { if (!m_hBitmap ||!pColors || !nNumColors || m_iColorTableSize == 0 || nNumColors > 256) return FALSE; LPRGBQUAD pColorTable = GetColorTable(); ASSERT(pColorTable); int nCount = min(m_iColorTableSize, nNumColors); ::memset(pColorTable, 0, m_iColorTableSize*sizeof(RGBQUAD)); ::memcpy(pColorTable, pColors, nCount*sizeof(RGBQUAD)); return TRUE; } // --- In  : // --- Out : // --- Returns : TRUE on success // --- Effect : Creates the palette from the DIBSection's color table. Assumes // m_iColorTableSize has been set and the DIBsection m_hBitmap created // /////////////////////////////////////////////////////////////////////////////// BOOL CDIB::CreatePalette() { //m_hPal DeleteObject(); if (!m_hBitmap) return FALSE; // Create a 256 color halftone palette if there is no color table in the DIBSection if (m_iColorTableSize == 0) return CreateHalftonePalette(m_hPal, 256); // Get space for the color entries RGBQUAD *pRGB = new RGBQUAD[m_iColorTableSize]; if (!pRGB) return CreateHalftonePalette(m_hPal, m_iColorTableSize); HDC hDC = ::GetDC(NULL); if (!hDC) { delete [] pRGB; return FALSE; } // Create a memory DC compatible with the current DC HDC hMemDC = CreateCompatibleDC(hDC); if (!hMemDC) { delete [] pRGB; ReleaseDC(NULL, hDC); return CreateHalftonePalette(m_hPal, m_iColorTableSize); } ReleaseDC(NULL, hDC); HBITMAP hOldBitmap = (HBITMAP) SelectObject(hMemDC, m_hBitmap); if (!hOldBitmap) { delete [] pRGB; return CreateHalftonePalette(m_hPal, m_iColorTableSize); } // Get the colors used. WinCE does not support GetDIBColorTable so if you // are using this on a CE device with palettes, then you need to replace // the call with code that manually gets the color table from the m_DIBinfo structure. int nColors = CEGetDIBColorTable(hDC, 0, m_iColorTableSize, pRGB); // Clean up SelectObject(hMemDC, hOldBitmap); if (!nColors) // No colors retrieved => the bitmap in the DC is not a DIB section { delete [] pRGB; return CreateHalftonePalette(m_hPal, m_iColorTableSize); } // Create and fill a LOGPALETTE structure with the colors used. PALETTEINFO PaletteInfo; PaletteInfo.palNumEntries = m_iColorTableSize; for (int ii = 0; ii < nColors; ii++) { PaletteInfo.palPalEntry[ii].peRed = pRGB[ii].rgbRed; PaletteInfo.palPalEntry[ii].peGreen = pRGB[ii].rgbGreen; PaletteInfo.palPalEntry[ii].peBlue = pRGB[ii].rgbBlue; PaletteInfo.palPalEntry[ii].peFlags = 0; } delete [] pRGB; // Create Palette! m_hPal = ::CreatePalette( &PaletteInfo ); return (NULL != m_hPal); } // --- In  : pPalette - new palette to use // --- Out : // --- Returns : TRUE on success // --- Effect : Sets the current palette used by the image from the supplied CPalette, // and sets the color table in the DIBSection // /////////////////////////////////////////////////////////////////////////////// BOOL CDIB::SetPalette(HPALETTE hPal) { // m_Palette.DeleteObject(); if (!hPal) return FALSE; WORD nColors; ::GetObject(hPal, sizeof(WORD), &nColors); if (nColors <= 0 || nColors > 256) return FALSE; // Get palette entries PALETTEINFO pi; pi.palNumEntries = (WORD) ::GetPaletteEntries(hPal, 0, nColors, (LPPALETTEENTRY) pi); return SetLogPalette(&pi); } // --- In  : pLogPalette - new palette to use // --- Out : // --- Returns : TRUE on success // --- Effect : Sets the current palette used by the image from the supplied LOGPALETTE // /////////////////////////////////////////////////////////////////////////////// BOOL CDIB::SetLogPalette(LOGPALETTE* pLogPalette) { if (!pLogPalette) { CreatePalette(); return FALSE; } ASSERT(pLogPalette->palVersion == (WORD) 0x300); UINT nColors = pLogPalette->palNumEntries; if (nColors <= 0 || nColors > 256) { CreatePalette(); return FALSE; } // Create new palette DeleteObject( m_hPal ); m_hPal = ::CreatePalette(pLogPalette); if (!m_hPal) { CreatePalette(); return FALSE; } if (m_iColorTableSize == 0) return TRUE; // Set the DIB colors RGBQUAD RGBquads[256]; for (UINT i = 0; i < nColors; i++) { RGBquads[i].rgbRed = pLogPalette->palPalEntry[i].peRed; RGBquads[i].rgbGreen = pLogPalette->palPalEntry[i].peGreen; RGBquads[i].rgbBlue = pLogPalette->palPalEntry[i].peBlue; RGBquads[i].rgbReserved = 0; } return FillDIBColorTable(nColors, RGBquads); } // --- In  : nNumColors - number of colors to set // pRGB - colors to fill // --- Out : // --- Returns : Returns TRUE on success // --- Effect : Sets the colors used by the image. Only works if # colors <= 256 // /////////////////////////////////////////////////////////////////////////////// BOOL CDIB::FillDIBColorTable(UINT nNumColors, RGBQUAD *pRGB) { if (!pRGB || !nNumColors || !m_iColorTableSize || nNumColors > 256) return FALSE; // get the number of colors to return per BITMAPINFOHEADER docs UINT nColors; LPBITMAPINFOHEADER pBmih = GetBitmapInfoHeader(); if (pBmih->biClrUsed) nColors = pBmih->biClrUsed; else nColors = 1 << (pBmih->biBitCount*pBmih->biPlanes); // Initialize the loop variables nColors = min(nNumColors, nColors); LPRGBQUAD pColorTable = GetColorTable(); for (UINT iColor = 0; iColor < nColors; iColor++) { pColorTable[iColor].rgbReserved = 0; pColorTable[iColor].rgbBlue = pRGB[iColor].rgbBlue; pColorTable[iColor].rgbRed = pRGB[iColor].rgbRed; pColorTable[iColor].rgbGreen = pRGB[iColor].rgbGreen; } return TRUE; } //#endif // DIBSECTION_NO_PALETTE // --- In  : hdc - the Device Context in which the DIBSection is selected // hBitmap - the bitmap whose solor entries are to be queried // lpbi - a pointer to a BITMAPINFO structure that will have it's // color table filled. // --- Out : // --- Returns : the number of colors placed in the color table // --- Effect : This function is a replacement for GetDIBits, in that it retrieves // (or synthesizes) the color table from the given bitmap, and stores // the values in the BITMAPINFO structure supplied. // /////////////////////////////////////////////////////////////////////////////// UINT CDIB::GetColorTableEntries(HDC hdc, HBITMAP hBitmap) { if (!m_iColorTableSize) return 0; // Fill the color table with the colors from the bitmap's color table LPRGBQUAD pColorTable = GetColorTable(); // Get the color table from the HBITMAP and copy them over. UINT nCount; RGBQUAD* pRGB = new RGBQUAD[m_iColorTableSize]; if (pRGB) { HBITMAP hOldBitmap = (HBITMAP) SelectObject(hdc, hBitmap); nCount = CEGetDIBColorTable(hdc, 0, m_iColorTableSize, pRGB); SelectObject(hdc, hOldBitmap); if (nCount) { // m_iColorTableSize = nCount; memcpy(pColorTable, pRGB, nCount*sizeof(RGBQUAD)); } } delete [] pRGB; // Didn't work - so synthesize one. if (!nCount) { nCount = min( m_iColorTableSize, sizeof(ms_StdColors) / sizeof(ms_StdColors[0]) ); memcpy(pColorTable, ms_StdColors, nCount*sizeof(RGBQUAD)); } return nCount; } /////////////////////////////////////////////////////////////////////////////// // // This function is from the MS KB article "HOWTO: Get the Color Table of // DIBSection in Windows CE". // // PARAMETERS: // HDC - the Device Context in which the DIBSection is selected /// UINT - the index of the first color table entry to retrieve // UINT - the number of color table entries to retrieve // RGBQUAD - a buffer large enough to hold the number of RGBQUAD // entries requested // // RETURNS: // UINT - the number of colors placed in the buffer // // /////////////////////////////////////////////////////////////////////////////// UINT CEGetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries, RGBQUAD *pColors) { if (pColors == NULL) return 0; // No place to put them, fail // Get a description of the DIB Section HBITMAP hDIBSection = (HBITMAP) GetCurrentObject( hdc, OBJ_BITMAP ); DIBSECTION ds; DWORD dwSize = GetObject( hDIBSection, sizeof(DIBSECTION), &ds ); if (dwSize != sizeof(DIBSECTION)) return 0; // Must not be a DIBSection, fail if (ds.dsBmih.biBitCount > 8) return 0; // Not Palettized, fail // get the number of colors to return per BITMAPINFOHEADER docs UINT cColors; if (ds.dsBmih.biClrUsed) cColors = ds.dsBmih.biClrUsed; else cColors = 1 << (ds.dsBmih.biBitCount * ds.dsBmih.biPlanes); // Create a mask for the palette index bits for 1, 2, 4, and 8 bpp WORD wIndexMask = (0xFF << (8 - ds.dsBmih.biBitCount)) & 0x00FF; // Get the pointer to the image bits LPBYTE pBits = (LPBYTE) ds.dsBm.bmBits; // Initialize the loop variables cColors = min( cColors, cEntries ); BYTE OldPalIndex = *pBits; UINT TestPixelY; if (ds.dsBmih.biHeight > 0 ) // If button up DIB, pBits points to last row TestPixelY = ds.dsBm.bmHeight-1; else // If top down DIB, pBits points to first row TestPixelY = 0; for (UINT iColor = uStartIndex; iColor < cColors; iColor++) { COLORREF rgbColor; // Set the palette index for the test pixel, // modifying only the bits for one pixel *pBits = (iColor << (8 - ds.dsBmih.biBitCount)) | (*pBits & ~wIndexMask); // now get the resulting color rgbColor = GetPixel( hdc, 0, TestPixelY ); pColors[iColor - uStartIndex].rgbReserved = 0; pColors[iColor - uStartIndex].rgbBlue = GetBValue(rgbColor); pColors[iColor - uStartIndex].rgbRed = GetRValue(rgbColor); pColors[iColor - uStartIndex].rgbGreen = GetGValue(rgbColor); } // Restore the test pixel *pBits = OldPalIndex; return cColors; } /////////////////////////////////////////////////////////////////////////////// // // --- In  : pDC - device context to use when calling CreateCompatibleDC // bSelectPalette - if TRUE, the current palette will be preselected // --- Out : // --- Returns : A pointer to a memory DC // --- Effect : Creates a memory DC and selects in the current bitmap so it can be // modified using the GDI functions. Only one memDC can be created for // a given CDIB object. If you have a memDC but wish to recreate it // as compatible with a different DC, then call ReleaseMemoryDC first. // If the memory DC has already been created then it will be recycled. // Note that if using this in an environment where the color depth of // the screen may change, then you will need to set "m_bReuseMemDC" to FALSE // /////////////////////////////////////////////////////////////////////////////// HDC CDIB::GetMemoryDC(HDC hDC /*=NULL*/, BOOL bSelectPalette /*=TRUE*/) { #ifdef DIBSECTION_NO_MEMDC_REUSE ReleaseMemoryDC(TRUE); #else if (!m_bReuseMemDC) { ReleaseMemoryDC(TRUE); } else if (m_hMemDC) // Already created? { return m_hMemDC; } #endif // DIBSECTION_NO_MEMDC_REUSE // Create a memory DC compatible with the given DC m_hMemDC = CreateCompatibleDC(hDC); if (!m_hMemDC) return NULL; // Select in the bitmap m_hOldBitmap = (HBITMAP) ::SelectObject(m_hMemDC, m_hBitmap); // Select in the palette if (bSelectPalette && UsesPalette(m_hMemDC)) { // Palette should already have been created - but just in case... if (!m_hPal) CreatePalette(); m_hOldPal = SelectPalette( m_hMemDC, m_hPal, FALSE ); RealizePalette( m_hMemDC ); } else m_hOldPal = NULL; return m_hMemDC; } /////////////////////////////////////////////////////////////////////////////// // // --- In  : bForceRelease - if TRUE, then the memory DC is forcibly released // --- Out : // --- Returns : TRUE on success // --- Effect : Selects out the current bitmap and deletes the mem dc. If bForceRelease // is FALSE, then the DC release will not actually occur. This is provided // so you can have // // GetMemoryDC(...) // ... do something // ReleaseMemoryDC() // // bracketed calls. If m_bReuseMemDC is subsequently set to FALSE, then // the same code fragment will still work. // /////////////////////////////////////////////////////////////////////////////// BOOL CDIB::ReleaseMemoryDC(BOOL bForceRelease /*=FALSE*/) { if ( !m_hMemDC #ifndef DIBSECTION_NO_MEMDC_REUSE || (m_bReuseMemDC && !bForceRelease) #endif // DIBSECTION_NO_MEMDC_REUSE ) return TRUE; // Nothing to do // Select out the current bitmap if (m_hOldBitmap) ::SelectObject(m_hMemDC, m_hOldBitmap); m_hOldBitmap = NULL; #ifndef DIBSECTION_NO_PALETTE // Select out the current palette if (m_hOldPal) SelectPalette(m_hMemDC, m_hOldPal, FALSE); m_hOldPal = NULL; #endif // DIBSECTION_NO_PALETTE // Delete the memory DC return DeleteDC(m_hMemDC); }