www.pudn.com > VCдµÄMP3²¥·ÅÆ÷Ô´´úÂë.zip > GWExtDIBSectionLite.cpp


// GWExtDIBSectionLite.cpp: implementation of the GWExtDIBSectionLite class. 
// 
////////////////////////////////////////////////////////////////////// 
//******************************************************************************* 
// °æÈ¨ÉùÃ÷ 
// ------------------------------------------------------------------------------ 
// ´Ë¶Î´úÂëÊÇAppBuilderÀ©Õ¹Àà¿âGWCµÄÒ»²¿·Ö. 
// Äã¿ÉÒÔʹÓá¢ÖØÐ±àÒë¡¢»òÕß±àÒë³ÉÄãµÄ·¢ÐÐÈí¼þµÄÒ»²¿·Ö¡£ 
// µ«ÊÇÔÚûÓо­¹ýÎÒÃÇÊéÃæÍ¬ÒâµÄÇé¿öÏ£¬Äã²»ÄÜÖ±½Ó·¢Ðд˴úÂëÎļþ. 
//------------------------------------------------------------------------------- 
// °æÈ¨ËùÓÐ. 
// ×÷Õß:ÕÅÐÞÓÂ 
// ¿½±´ÈÕÆÚ:2000Äê10ÔÂ05ÈÕ 
//------------------------------------------------------------------------------- 
// Ö÷Ò³:   http://www.ucancode.com 
// ¼¼ÊõÖ§³ÖE-Mail: AppBuilder@hotmail.com 
//******************************************************************************* 
 
 
#include "stdafx.h" 
#include "GWExtDIBSectionLite.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
// Use C++ exception handling instead of structured on non-CE platforms. 
#ifndef _WIN32_WCE   
#undef TRY 
#undef CATCH 
#undef END_CATCH 
#define TRY try 
#define CATCH(ex_class, ex_object) catch(ex_class* ex_object) 
#define END_CATCH 
#endif  // _WIN32_WCE 
 
// Spit out some messages as a sanity check for programmers 
#ifdef DIBSECTION_NO_DITHER 
#pragma message(" - GWExtDIBSectionLite: No dithering") 
#endif 
#ifdef DIBSECTION_NO_MEMDC_REUSE 
#pragma message(" - GWExtDIBSectionLite: No memory DC reuse") 
#endif 
#ifdef DIBSECTION_NO_PALETTE 
#pragma message(" - GWExtDIBSectionLite: No palette support") 
#endif 
 
// Standard colors 
RGBQUAD GWExtDIBSectionLite::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 
 
///////////////////////////////////////////////////////////////////////////// 
// GWExtDIBSectionLite 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 GWExtDIBSectionLite::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; 
        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 GWExtDIBSectionLite::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 GWExtDIBSectionLite::CreateHalftonePalette(CPalette& palette, int nNumColors) 
{ 
    palette.DeleteObject(); 
 
    // 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; 
       } 
   } 
 
   return palette.CreatePalette((LPLOGPALETTE) pi); 
} 
#endif // DIBSECTION_NO_PALETTE 
 
 
///////////////////////////////////////////////////////////////////////////// 
// GWExtDIBSectionLite 
 
GWExtDIBSectionLite::GWExtDIBSectionLite() 
{ 
    // 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_pOldPalette = NULL; 
#endif 
 
#ifndef DIBSECTION_NO_DITHER 
    m_bDither     = FALSE; 
    m_hDrawDib    = NULL; 
#endif 
 
    DeleteObject(); // This will initialise to a known state - ie. empty 
} 
 
GWExtDIBSectionLite::~GWExtDIBSectionLite() 
{ 
    DeleteObject(); 
} 
 
// --- In  : 
// --- Out : 
// --- Returns : 
// --- Effect : Resets the object to an empty state, and frees all memory used. 
void GWExtDIBSectionLite::DeleteObject() 
{ 
    // 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 
    m_Palette.DeleteObject(); 
#endif 
 
    memset(&m_DIBinfo, 0, sizeof(m_DIBinfo)); 
 
#ifndef DIBSECTION_NO_DITHER 
    if (m_hDrawDib) 
        DrawDibClose(m_hDrawDib); 
    m_hDrawDib = NULL; 
#endif 
 
    m_iColorDataType = DIB_RGB_COLORS; 
    m_iColorTableSize = 0; 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// GWExtDIBSectionLite diagnostics 
 
#ifdef _DEBUG 
void GWExtDIBSectionLite::AssertValid() const 
{ 
    ASSERT(m_hBitmap); 
 
    DIBSECTION ds; 
    DWORD dwSize = GetObject( m_hBitmap, sizeof(DIBSECTION), &ds ); 
    ASSERT(dwSize == sizeof(DIBSECTION)); 
 
    ASSERT(0 <= m_iColorTableSize && m_iColorTableSize <= 256); 
 
	CObject::AssertValid(); 
} 
 
void GWExtDIBSectionLite::Dump(CDumpContext& dc) const 
{ 
	CObject::Dump(dc); 
} 
 
#endif //_DEBUG 
 
 
///////////////////////////////////////////////////////////////////////////// 
// GWExtDIBSectionLite operations 
 
#ifndef DIBSECTION_NO_DITHER 
// --- In  : bDither - whether or not dithering should be enabled 
// --- Out : 
// --- Returns : TRUE on success 
// --- Effect : Turns dithering on by using the DrawDib functions instead of  
//              the GDI functions 
BOOL GWExtDIBSectionLite::SetDither(BOOL bDither) 
{ 
    if ( (m_bDither == bDither) && 
         ((m_hDrawDib && m_bDither) || (!m_hDrawDib && !m_bDither)) ) 
        return TRUE; 
 
    if (!bDither && m_hDrawDib != NULL) 
    { 
        DrawDibClose(m_hDrawDib); 
        m_hDrawDib = NULL; 
    } 
 
    m_bDither = bDither; 
 
    return TRUE; 
} 
 
// --- In  :  
// --- Out : 
// --- Returns : TRUE if dithering is used 
// --- Effect : Returns whether or not the DrawDib functions (and hence dithering) 
//              is being used. 
BOOL GWExtDIBSectionLite::GetDither() 
{ 
    return (m_bDither && GetBitCount() > 8); 
} 
 
// --- In  :  
// --- Out : 
// --- Returns : A DrawDib context if dithering is supported, else NULL 
// --- Effect : Returns a drawdib context for use with DrawDib routines 
HDRAWDIB GWExtDIBSectionLite::GetDrawDibContext() 
{ 
    if (!GetDither()) 
        return NULL; 
 
    if (m_hDrawDib) 
        return m_hDrawDib; 
 
    m_hDrawDib = DrawDibOpen(); 
 
    return m_hDrawDib; 
} 
 
 
#endif 
 
// --- 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 GWExtDIBSectionLite::Draw(CDC* pDC, CPoint ptDest, BOOL bForceBackground /*=FALSE*/)  
{  
    if (!m_hBitmap) 
        return FALSE; 
 
    CSize size = GetSize(); 
    CPoint ptOrigin = CPoint(0,0); 
 
    BOOL bResult = FALSE; 
 
#ifndef DIBSECTION_NO_DITHER 
   // We will only be able to get a HDRAWDIB if dithering is enabled 
    HDRAWDIB hDrawDib = GetDrawDibContext(); 
    if (hDrawDib) 
    { 
#ifndef DIBSECTION_NO_PALETTE 
        DrawDibSetPalette( hDrawDib, (HPALETTE)m_Palette); 
        DrawDibRealize( hDrawDib,  pDC->GetSafeHdc(),  FALSE); 
#endif // DIBSECTION_NO_PALETTE 
        bResult = DrawDibDraw(hDrawDib, pDC->GetSafeHdc(),  
                              ptDest.x, ptDest.y, size.cx, size.cy,  
                              GetBitmapInfoHeader(), GetDIBits(),  
                              ptOrigin.x, ptOrigin.y, size.cx, size.cy,  
                              0/*DDF_HALFTONE*/); 
    } 
    else 
    { 
#endif 
        // Create a memory DC compatible with the destination DC 
        CDC* pMemDC = GetMemoryDC(pDC, FALSE); 
        if (!pMemDC) 
            return FALSE; 
         
#ifndef DIBSECTION_NO_PALETTE 
        // Select and realize the palette 
        CPalette* pOldPalette = NULL; 
        if (m_Palette.m_hObject && UsesPalette(pDC)) 
        { 
            pOldPalette = pDC->SelectPalette(&m_Palette, bForceBackground); 
            pDC->RealizePalette(); 
        } 
#endif // DIBSECTION_NO_PALETTE 
         
        bResult = pDC->BitBlt(ptDest.x, ptDest.y, size.cx, size.cy, pMemDC,  
                              ptOrigin.x, ptOrigin.y, SRCCOPY); 
         
#ifndef DIBSECTION_NO_PALETTE 
        if (pOldPalette) 
            pDC->SelectPalette(pOldPalette, FALSE); 
#endif // DIBSECTION_NO_PALETTE 
         
    ReleaseMemoryDC(); 
#ifndef DIBSECTION_NO_DITHER 
    } 
#endif // DIBSECTION_NO_DITHER 
 
    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 GWExtDIBSectionLite::Stretch(CDC* pDC, CPoint ptDest, CSize size, 
                              BOOL bForceBackground /*=FALSE*/)  
{  
    if (!m_hBitmap) 
        return FALSE; 
 
    CPoint ptOrigin = CPoint(0,0); 
    CSize imagesize = GetSize(); 
 
    BOOL bResult = FALSE; 
 
#ifndef _WIN32_WCE 
    pDC->SetStretchBltMode(COLORONCOLOR); 
#endif 
 
#ifndef DIBSECTION_NO_DITHER 
    // We will only be able to get a HDRAWDIB if dithering is enabled 
    HDRAWDIB hDrawDib = GetDrawDibContext(); 
    if (hDrawDib) 
    { 
#ifndef DIBSECTION_NO_PALETTE 
        DrawDibSetPalette( hDrawDib, (HPALETTE)m_Palette); 
        DrawDibRealize( hDrawDib,  pDC->GetSafeHdc(),  FALSE); 
#endif // DIBSECTION_NO_PALETTE 
 
	    bResult = DrawDibDraw(hDrawDib, pDC->GetSafeHdc(),  
                              ptDest.x, ptDest.y, size.cx, size.cy,  
                              GetBitmapInfoHeader(), GetDIBits(),  
                              0,0, GetWidth(), GetHeight(),  
                              0/*DDF_HALFTONE*/); 
    } 
    else 
    { 
#endif // DIBSECTION_NO_DITHER 
        // Create a memory DC compatible with the destination DC 
        CDC* pMemDC = GetMemoryDC(pDC, FALSE); 
        if (!pMemDC) 
            return FALSE; 
         
#ifndef DIBSECTION_NO_PALETTE 
        // Select and realize the palette 
        CPalette* pOldPalette = NULL; 
        if (m_Palette.m_hObject && UsesPalette(pDC)) 
        { 
            pOldPalette = pDC->SelectPalette(&m_Palette, bForceBackground); 
            pDC->RealizePalette(); 
        } 
#endif // DIBSECTION_NO_PALETTE 
         
#ifndef _WIN32_WCE 
        pDC->SetStretchBltMode(COLORONCOLOR); 
#endif // _WIN32_WCE 
         
        bResult = pDC->StretchBlt(ptDest.x, ptDest.y, size.cx, size.cy,  
                                  pMemDC,  
                                  ptOrigin.x, ptOrigin.y, imagesize.cx, imagesize.cy,  
                                  SRCCOPY); 
         
#ifndef DIBSECTION_NO_PALETTE 
        if (pOldPalette) 
            pDC->SelectPalette(pOldPalette, FALSE); 
#endif // DIBSECTION_NO_PALETTE 
         
        ReleaseMemoryDC(); 
#ifndef DIBSECTION_NO_DITHER 
    } 
#endif // DIBSECTION_NO_DITHER 
 
    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 GWExtDIBSectionLite::SetBitmap(UINT nIDResource) 
{ 
    return SetBitmap(MAKEINTRESOURCE(nIDResource)); 
} 
 
// --- 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 GWExtDIBSectionLite::SetBitmap(LPCTSTR lpszResourceName) 
{ 
    HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetResourceHandle(),  
                                        lpszResourceName, 
                                        IMAGE_BITMAP,  
                                        0,0,  
#ifdef _WIN32_WCE 
                                        0 
#else 
                                        LR_CREATEDIBSECTION 
#endif 
                                        ); 
 
    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 GWExtDIBSectionLite::SetBitmap(LPBITMAPINFO lpBitmapInfo, LPVOID lpBits) 
{ 
    DeleteObject(); 
 
    if (!lpBitmapInfo || !lpBits) 
        return FALSE; 
 
    HDC hDC = NULL; 
    TRY { 
        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"); 
            AfxThrowResourceException(); 
        } 
 
        m_hBitmap = CreateDIBSection(hDC, (const BITMAPINFO*) m_DIBinfo, 
                                     m_iColorDataType, &m_ppvBits, NULL, 0); 
        ::ReleaseDC(NULL, hDC); 
        if (!m_hBitmap) 
        { 
            TRACE0("CreateDIBSection failed\n"); 
            AfxThrowResourceException(); 
        } 
 
        if (m_DIBinfo.bmiHeader.biSizeImage == 0) 
        { 
            int nBytesPerLine = BytesPerLine(lpBitmapInfo->bmiHeader.biWidth,  
                                             lpBitmapInfo->bmiHeader.biBitCount); 
            m_DIBinfo.bmiHeader.biSizeImage = nBytesPerLine * lpBitmapInfo->bmiHeader.biHeight; 
        } 
 
#ifndef _WIN32_WCE 
        // Flush the GDI batch queue  
        GdiFlush(); 
#endif 
 
        memcpy(m_ppvBits, lpBits, m_DIBinfo.bmiHeader.biSizeImage); 
 
#ifndef DIBSECTION_NO_PALETTE 
        if (!CreatePalette()) 
        { 
            TRACE0("Unable to create palette\n"); 
            AfxThrowResourceException(); 
        } 
#endif // DIBSECTION_NO_PALETTE 
    } 
    CATCH (CException, e) 
    { 
        e->Delete(); 
        _ShowLastError(); 
        if (hDC)  
            ::ReleaseDC(NULL, hDC); 
        DeleteObject(); 
        return FALSE; 
    } 
    END_CATCH 
 
    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 GWExtDIBSectionLite::SetBitmap(HBITMAP hBitmap 
#ifndef DIBSECTION_NO_PALETTE 
                                , CPalette* pPalette /*= NULL*/ 
#endif 
                                ) 
{ 
    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); 
 
    CWindowDC dc(NULL); 
#ifndef DIBSECTION_NO_PALETTE 
    CPalette* pOldPalette = NULL; 
#endif // DIBSECTION_NO_PALETTE 
 
    TRY { 
        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(dc.GetSafeHdc(), hBitmap); 
 
#ifndef DIBSECTION_NO_PALETTE 
        // If we have a palette supplied, then set the palette (and hance DIB color 
        // table) using this palette 
        if (pPalette) 
            SetPalette(pPalette); 
 
        if (m_Palette.GetSafeHandle()) 
        { 
            pOldPalette = dc.SelectPalette(&m_Palette, FALSE); 
            dc.RealizePalette(); 
        } 
#endif // DIBSECTION_NO_PALETTE 
 
        // Create it! 
        m_hBitmap = CreateDIBSection(dc.m_hDC,  
                                     (const BITMAPINFO*) m_DIBinfo, 
                                     m_iColorDataType, 
                                     &m_ppvBits,  
                                     NULL, 0); 
#ifndef DIBSECTION_NO_PALETTE 
        if (pOldPalette) 
            dc.SelectPalette(pOldPalette, FALSE); 
        pOldPalette = NULL;  
#endif // DIBSECTION_NO_PALETTE 
 
        if (!m_hBitmap) 
        { 
            TRACE0("Unable to CreateDIBSection\n"); 
            AfxThrowResourceException(); 
        } 
 
#ifndef DIBSECTION_NO_PALETTE 
        // If palette was supplied then create a palette using the entries in the DIB 
        // color table. 
        if (!pPalette) 
            CreatePalette(); 
#endif // DIBSECTION_NO_PALETTE 
    
        // Need to copy the supplied bitmap onto the newly created DIBsection 
        CDC memDC, CopyDC; 
        if (!CopyDC.CreateCompatibleDC(&dc) || !memDC.CreateCompatibleDC(&dc))  
        { 
            TRACE0("Unable to create compatible DC's\n"); 
            AfxThrowResourceException(); 
        } 
 
#ifndef DIBSECTION_NO_PALETTE 
        if (m_Palette.GetSafeHandle()) 
        { 
            memDC.SelectPalette(&m_Palette, FALSE);  memDC.RealizePalette(); 
            CopyDC.SelectPalette(&m_Palette, FALSE); CopyDC.RealizePalette(); 
        } 
#endif // DIBSECTION_NO_PALETTE 
 
#ifndef _WIN32_WCE 
        // Flush the GDI batch queue  
        GdiFlush(); 
#endif 
 
        HBITMAP hOldMemBitmap  = (HBITMAP) SelectObject(memDC.m_hDC,  hBitmap); 
        HBITMAP hOldCopyBitmap = (HBITMAP) SelectObject(CopyDC.m_hDC, m_hBitmap); 
 
        CopyDC.BitBlt(0,0, bm.bmWidth, bm.bmHeight, &memDC, 0,0, SRCCOPY); 
 
        SelectObject(memDC.m_hDC, hOldMemBitmap); 
        SelectObject(CopyDC.m_hDC, hOldCopyBitmap); 
 
#ifndef DIBSECTION_NO_PALETTE 
        if (m_Palette.GetSafeHandle()) 
        { 
            memDC.SelectStockObject(DEFAULT_PALETTE); 
            CopyDC.SelectStockObject(DEFAULT_PALETTE); 
        } 
#endif // DIBSECTION_NO_PALETTE 
    } 
    CATCH (CException, e) 
    { 
        e->Delete(); 
        _ShowLastError(); 
#ifndef DIBSECTION_NO_PALETTE 
        if (pOldPalette) 
            dc.SelectPalette(pOldPalette, FALSE); 
 #endif // DIBSECTION_NO_PALETTE 
        DeleteObject(); 
        return FALSE; 
    } 
    END_CATCH 
 
    return TRUE; 
} 
 
 
////////////////////////////////////////////////////////////////////////////// 
// Persistance... 
 
// --- In  : lpszFileName - image filename 
// --- Out : 
// --- Returns : Returns TRUE on success, FALSE otherwise 
// --- Effect : Loads the bitmap from a bitmap file with the name lpszFileName.  
//              If failure, then object is initialised back to an empty bitmap. 
BOOL GWExtDIBSectionLite::Load(LPCTSTR lpszFileName) 
{ 
    CFile file; 
    if (!file.Open(lpszFileName, CFile::modeRead)) 
        return FALSE; 
 
    // Get the current file position.   
    DWORD dwFileStart = file.GetPosition(); 
 
    // The first part of the file contains the file header. 
	// This will tell us if it is a bitmap, how big the header is, and how big  
    // the file is. The header size in the file header includes the color table. 
	BITMAPFILEHEADER BmpFileHdr; 
    int nBytes; 
    nBytes = file.Read(&BmpFileHdr, sizeof(BmpFileHdr)); 
    if (nBytes != sizeof(BmpFileHdr))  
    { 
        TRACE0("Failed to read file header\n"); 
        return FALSE; 
    } 
 
    // Check that we have the magic 'BM' at the start. 
    if (BmpFileHdr.bfType != DS_BITMAP_FILEMARKER) 
    { 
        TRACE0("Not a bitmap file\n"); 
        return FALSE; 
    } 
 
    // Read the header (assuming it's a DIB).  
	DIBINFO	BmpInfo; 
    nBytes = file.Read(&BmpInfo, sizeof(BITMAPINFOHEADER));  
    if (nBytes != sizeof(BITMAPINFOHEADER))  
    { 
        TRACE0("Failed to read BITMAPINFOHEADER\n"); 
        return FALSE; 
    } 
 
    // Check that we have a real Windows DIB file. 
    if (BmpInfo.bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) 
    { 
        TRACE0(" File is not a Windows DIB\n"); 
        return FALSE; 
    } 
 
    // See how big the color table is in the file (if there is one).   
    int nColors = NumColorEntries(BmpInfo.bmiHeader.biBitCount, BmpInfo.bmiHeader.biCompression); 
	if (nColors > 0)  
    { 
        // Read the color table from the file. 
        int nColorTableSize = nColors * sizeof(RGBQUAD); 
		nBytes = file.Read(BmpInfo.ColorTable(), nColorTableSize); 
		if (nBytes != nColorTableSize)  
        { 
			TRACE0("Failed to read color table\n"); 
			return FALSE; 
        } 
	} 
 
	// So how big the bitmap surface is. 
    int nBitsSize = BmpFileHdr.bfSize - BmpFileHdr.bfOffBits; 
 
    // Allocate the memory for the bits and read the bits from the file. 
    BYTE* pBits = (BYTE*) malloc(nBitsSize); 
    if (!pBits)  
    { 
        TRACE0("Out of memory for DIB bits\n"); 
        return FALSE; 
    } 
 
    // Seek to the bits in the file. 
    file.Seek(dwFileStart + BmpFileHdr.bfOffBits, CFile::begin); 
 
    // read the bits 
    nBytes = file.Read(pBits, nBitsSize); 
    if (nBytes != nBitsSize)  
    { 
        TRACE0("Failed to read bits\n"); 
        free(pBits); 
		return FALSE; 
    } 
 
	// Everything went OK. 
	BmpInfo.bmiHeader.biSizeImage = nBitsSize; 
 
    if (!SetBitmap((LPBITMAPINFO) BmpInfo, pBits)) 
    { 
        TRACE0("Failed to set bitmap info\n"); 
        free(pBits); 
		return FALSE; 
    } 
 
    free(pBits); 
 
    return TRUE; 
} 
 
// --- In  : lpszFileName - image filename 
// --- Out : 
// --- Returns : Returns TRUE on success, FALSE otherwise 
// --- Effect : Saves the image to file. 
BOOL GWExtDIBSectionLite::Save(LPCTSTR lpszFileName) 
{ 
    BITMAPFILEHEADER   hdr; 
    LPBITMAPINFOHEADER lpbi = GetBitmapInfoHeader(); 
 
    if (!lpbi || !lpszFileName) 
        return FALSE; 
 
    CFile file; 
    if (!file.Open(lpszFileName, CFile::modeWrite|CFile::modeCreate)) 
        return FALSE; 
 
    DWORD dwBitmapInfoSize = sizeof(BITMAPINFO) + m_iColorTableSize*sizeof(RGBQUAD); 
    DWORD dwFileHeaderSize = dwBitmapInfoSize + sizeof(hdr); 
 
    // Fill in the fields of the file header  
    hdr.bfType       = DS_BITMAP_FILEMARKER; 
    hdr.bfSize       = dwFileHeaderSize + lpbi->biSizeImage; 
    hdr.bfReserved1  = 0; 
    hdr.bfReserved2  = 0; 
    hdr.bfOffBits    = dwFileHeaderSize; 
 
    // Write the file header  
    file.Write(&hdr, sizeof(hdr)); 
 
    // Write the DIB header 
    file.Write(lpbi, dwBitmapInfoSize); 
     
    // Write DIB bits 
    file.Write(GetDIBits(), lpbi->biSizeImage); 
 
    return TRUE; 
} 
 
// --- In  : Bitmap - DIBSection object to be copied 
// --- Out : 
// --- Returns : Returns TRUE on success, FALSE otherwise 
// --- Effect : Creates a copy of another CDIBSection object 
BOOL GWExtDIBSectionLite::Copy(GWExtDIBSectionLite& Bitmap)  
{  
    BOOL bResult = SetBitmap(Bitmap.GetBitmapInfo(), Bitmap.GetDIBits());  
 
    if (bResult) 
    { 
        SetColorTable(Bitmap.GetColorTableSize(), Bitmap.GetColorTable()); 
#ifndef DIBSECTION_NO_PALETTE 
        CreatePalette(); 
#endif 
#ifndef DIBSECTION_NO_DITHER 
        SetDither(Bitmap.GetDither()); 
#endif 
    } 
 
    return bResult; 
}  
 
///////////////////////////////////////////////////////////////////////////// 
// GWExtDIBSectionLite 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 GWExtDIBSectionLite::SetColorTable(UINT nNumColors, RGBQUAD *pColors) 
{ 
    if (!m_hBitmap ||!pColors || !nNumColors || m_iColorTableSize == 0  
        || nNumColors > 256) 
        return FALSE; 
 
#ifdef _WIN32_WCE 
    LPRGBQUAD pColorTable = GetColorTable(); 
    ASSERT(pColorTable); 
 
    int nCount = min(m_iColorTableSize, nNumColors); 
    ::memset(pColorTable, 0, m_iColorTableSize*sizeof(RGBQUAD)); 
    ::memcpy(pColorTable, pColors, nCount*sizeof(RGBQUAD)); 
#else 
    // Create a memory DC compatible with the screen 
    CDC MemDC; 
    if (!MemDC.CreateCompatibleDC(NULL)) 
        return FALSE; 
 
    HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(MemDC.GetSafeHdc(), m_hBitmap); 
 
    ::SetDIBColorTable(MemDC.GetSafeHdc(), 0, nNumColors, pColors); 
 
    // Clean up 
    if (hOldBitmap) 
        ::SelectObject(MemDC.GetSafeHdc(), hOldBitmap); 
#endif 
 
    return TRUE; 
} 
 
#ifndef DIBSECTION_NO_PALETTE 
 
// --- 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 GWExtDIBSectionLite::CreatePalette() 
{ 
    m_Palette.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_Palette, 256); 
 
    // Get space for the color entries 
    RGBQUAD *pRGB = new RGBQUAD[m_iColorTableSize]; 
    if (!pRGB) 
        return CreateHalftonePalette(m_Palette, m_iColorTableSize); 
 
    HDC hDC = ::GetDC(NULL); 
    if (!hDC) 
    { 
        delete [] pRGB; 
        return FALSE; 
    } 
 
    // Create a memory DC compatible with the current DC 
    CDC MemDC; 
    MemDC.CreateCompatibleDC(CDC::FromHandle(hDC)); 
    if (!MemDC.GetSafeHdc()) 
    { 
        delete [] pRGB; 
        ::ReleaseDC(NULL, hDC); 
        return CreateHalftonePalette(m_Palette, m_iColorTableSize); 
    } 
    ::ReleaseDC(NULL, hDC); 
     
    HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(MemDC.GetSafeHdc(), m_hBitmap); 
    if (!hOldBitmap) 
    { 
        delete [] pRGB; 
        return CreateHalftonePalette(m_Palette, 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. 
#ifdef _WIN32_WCE 
    int nColors = ::CEGetDIBColorTable(MemDC.GetSafeHdc(), 0, m_iColorTableSize, pRGB); 
#else 
    int nColors = ::GetDIBColorTable(MemDC.GetSafeHdc(), 0, m_iColorTableSize, pRGB); 
#endif 
 
    // Clean up 
    ::SelectObject(MemDC.GetSafeHdc(), hOldBitmap); 
 
    if (!nColors)   // No colors retrieved => the bitmap in the DC is not a DIB section 
    { 
        delete [] pRGB; 
        return CreateHalftonePalette(m_Palette, m_iColorTableSize); 
    }    
     
    // Create and fill a LOGPALETTE structure with the colors used. 
    PALETTEINFO PaletteInfo; 
    PaletteInfo.palNumEntries = m_iColorTableSize; 
                         
    for (int i = 0; i < nColors; i++) 
    { 
        PaletteInfo.palPalEntry[i].peRed   = pRGB[i].rgbRed; 
        PaletteInfo.palPalEntry[i].peGreen = pRGB[i].rgbGreen; 
        PaletteInfo.palPalEntry[i].peBlue  = pRGB[i].rgbBlue; 
        PaletteInfo.palPalEntry[i].peFlags = 0; 
    } 
 
    delete [] pRGB; 
 
    // Create Palette! 
    return m_Palette.CreatePalette(&PaletteInfo); 
} 
 
// --- 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 GWExtDIBSectionLite::SetPalette(CPalette* pPalette) 
{ 
    m_Palette.DeleteObject(); 
 
    if (!pPalette) 
        return FALSE; 
 
    UINT nColors = pPalette->GetEntryCount(); 
    if (nColors <= 0 || nColors > 256) 
        return FALSE; 
 
    // Get palette entries 
    PALETTEINFO pi; 
    pi.palNumEntries = (WORD) pPalette->GetPaletteEntries(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 GWExtDIBSectionLite::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 
    m_Palette.DeleteObject(); 
    if (!m_Palette.CreatePalette(pLogPalette)) 
    { 
        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 GWExtDIBSectionLite::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 GWExtDIBSectionLite::GetColorTableEntries(HDC hdc, HBITMAP hBitmap) 
{ 
#ifndef _WIN32_WCE 
 
    // Call GetDIBits with NULL bits pointer to fill in the BITMAPINFOHEADER data 
    // Basically we are just getting the color table entries with a minimum of 
    // effort 
    if (!::GetDIBits(hdc, hBitmap, 0, GetHeight(), NULL, m_DIBinfo, m_iColorDataType)) 
    { 
        TRACE0("Unable to GetDIBits\n"); 
        AfxThrowResourceException(); 
    } 
     
    // If the driver did not fill in the biSizeImage field, then compute it 
    // Each scan line of the image is aligned on a DWORD (32bit) boundary 
    if (m_DIBinfo.bmiHeader.biSizeImage == 0) 
        m_DIBinfo.bmiHeader.biSizeImage = BytesPerLine(m_DIBinfo.bmiHeader.biWidth,  
                                                       m_DIBinfo.bmiHeader.biBitCount)  
                                            * m_DIBinfo.bmiHeader.biHeight; 
 
    return m_iColorTableSize; 
 
#else 
 
    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; 
#endif 
} 
 
#ifdef _WIN32_WCE 
/********************************************************************** 
This function is from the MS KB article "HOWTO: Get the Color Table of  
a 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; 
} 
#endif 
 
// --- 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 GWExtDIBSectionLite 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 
CDC* GWExtDIBSectionLite::GetMemoryDC(CDC* pDC /*=NULL*/, BOOL bSelectPalette /*=TRUE*/) 
{ 
#ifdef DIBSECTION_NO_MEMDC_REUSE 
    ReleaseMemoryDC(TRUE); 
#else 
    if (!m_bReuseMemDC) 
        ReleaseMemoryDC(TRUE); 
    else if (m_MemDC.GetSafeHdc())   // Already created? 
    { 
#ifndef _WIN32_WCE 
        // Flush the GDI batch queue  
        GdiFlush(); 
#endif 
        return &m_MemDC; 
    } 
#endif // DIBSECTION_NO_MEMDC_REUSE 
 
    // Create a memory DC compatible with the given DC 
    if (!m_MemDC.CreateCompatibleDC(pDC)) 
        return NULL; 
 
    // Select in the bitmap 
    m_hOldBitmap = (HBITMAP) ::SelectObject(m_MemDC.GetSafeHdc(), m_hBitmap); 
 
#ifndef DIBSECTION_NO_PALETTE 
    // Select in the palette 
    if (bSelectPalette && UsesPalette(&m_MemDC)) 
    { 
        // Palette should already have been created - but just in case... 
        if (!m_Palette.GetSafeHandle()) 
            CreatePalette(); 
 
        m_pOldPalette = m_MemDC.SelectPalette(&m_Palette, FALSE); 
        m_MemDC.RealizePalette(); 
    } 
    else 
        m_pOldPalette = NULL; 
#endif // DIBSECTION_NO_PALETTE 
 
#ifndef _WIN32_WCE 
    // Flush the GDI batch queue  
    GdiFlush(); 
#endif // _WIN32_WCE 
 
    return &m_MemDC; 
} 
 
// --- 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 GWExtDIBSectionLite::ReleaseMemoryDC(BOOL bForceRelease /*=FALSE*/) 
{ 
	bForceRelease; 
    if ( !m_MemDC.GetSafeHdc()  
#ifndef DIBSECTION_NO_MEMDC_REUSE 
        || (m_bReuseMemDC && !bForceRelease)  
#endif // DIBSECTION_NO_MEMDC_REUSE 
        ) 
        return TRUE; // Nothing to do 
 
#ifndef _WIN32_WCE 
    // Flush the GDI batch queue  
    GdiFlush(); 
#endif // _WIN32_WCE 
 
    // Select out the current bitmap 
    if (m_hOldBitmap) 
        ::SelectObject(m_MemDC.GetSafeHdc(), m_hOldBitmap); 
    m_hOldBitmap = NULL; 
 
#ifndef DIBSECTION_NO_PALETTE 
    // Select out the current palette 
    if (m_pOldPalette) 
        m_MemDC.SelectPalette(m_pOldPalette, FALSE); 
    m_pOldPalette = NULL; 
#endif // DIBSECTION_NO_PALETTE 
 
    // Delete the memory DC 
    return m_MemDC.DeleteDC(); 
} 
 
 
#ifdef _DEBUG 
// Makes trace windows a little bit more informative... 
void GWExtDIBSectionLite::_ShowLastError() 
{ 
    LPVOID lpMsgBuf; 
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,     
                  NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),  
                  (LPTSTR) &lpMsgBuf, 0, NULL); 
    TRACE1("Last error: %s\n", lpMsgBuf); 
    LocalFree(lpMsgBuf); 
} 
#else 
void GWExtDIBSectionLite::_ShowLastError() {} 
#endif