Click here to Skip to main content
15,895,011 members
Articles / Desktop Programming / MFC

Load, show and convert miscellaneous file-formats using freeimage

Rate me:
Please Sign up or sign in to vote.
4.91/5 (21 votes)
1 May 20025 min read 852.6K   20.9K   170  
Shows the usage of the freeimage-library to show and convert various file-formats
// CDIBSectionLite.cpp : implementation file
//
// General purpose DIBsection wrapper class for Win9x, NT 4.0 and WinCE.
//
// Author      : Chris Maunder (cmaunder@dundas.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 <jam@3dfx.com>)

#include "stdafx.h"
#include "DIBSectionLite.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// 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(" - CDIBSectionLite: No dithering")
#endif
#ifdef DIBSECTION_NO_MEMDC_REUSE
#pragma message(" - CDIBSectionLite: No memory DC reuse")
#endif
#ifdef DIBSECTION_NO_PALETTE
#pragma message(" - CDIBSectionLite: No palette support")
#endif

// Standard colors
RGBQUAD CDIBSectionLite::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

/////////////////////////////////////////////////////////////////////////////
// CDIBSectionLite 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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::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_palInfo;                   
    pi_palInfo.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_palInfo.palPalEntry[0].peRed   = ms_StdColors[0].rgbRed;
        pi_palInfo.palPalEntry[0].peGreen = ms_StdColors[0].rgbGreen;
        pi_palInfo.palPalEntry[0].peBlue  = ms_StdColors[0].rgbBlue;
        pi_palInfo.palPalEntry[0].peFlags = 0;
        pi_palInfo.palPalEntry[1].peRed   = ms_StdColors[255].rgbRed;
        pi_palInfo.palPalEntry[1].peGreen = ms_StdColors[255].rgbGreen;
        pi_palInfo.palPalEntry[1].peBlue  = ms_StdColors[255].rgbBlue;
        pi_palInfo.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_palInfo.palPalEntry[i].peRed   = ms_StdColors[i].rgbRed;
           pi_palInfo.palPalEntry[i].peGreen = ms_StdColors[i].rgbGreen;
           pi_palInfo.palPalEntry[i].peBlue  = ms_StdColors[i].rgbBlue;
           pi_palInfo.palPalEntry[i].peFlags = 0;
       }
       for (i = 8; i < 16; i++)
       {
           pi_palInfo.palPalEntry[i].peRed   = ms_StdColors[248+i].rgbRed;
           pi_palInfo.palPalEntry[i].peGreen = ms_StdColors[248+i].rgbGreen;
           pi_palInfo.palPalEntry[i].peBlue  = ms_StdColors[248+i].rgbBlue;
           pi_palInfo.palPalEntry[i].peFlags = 0;
       }
   }
   else // if (nNumColors == 256)
   {
       // Fill palette with full halftone palette
       for (int i = 0; i < 256; i++)
       {
           pi_palInfo.palPalEntry[i].peRed   = ms_StdColors[i].rgbRed;
           pi_palInfo.palPalEntry[i].peGreen = ms_StdColors[i].rgbGreen;
           pi_palInfo.palPalEntry[i].peBlue  = ms_StdColors[i].rgbBlue;
           pi_palInfo.palPalEntry[i].peFlags = 0;
       }
   }

   return palette.CreatePalette((LPLOGPALETTE) pi_palInfo);
}
#endif // DIBSECTION_NO_PALETTE


/////////////////////////////////////////////////////////////////////////////
// CDIBSectionLite

CDIBSectionLite::CDIBSectionLite()
{
    // 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
}

CDIBSectionLite::~CDIBSectionLite()
{
    DeleteObject();
}

// --- In� :
// --- Out :
// --- Returns :
// --- Effect : Resets the object to an empty state, and frees all memory used.
void CDIBSectionLite::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;
}

/////////////////////////////////////////////////////////////////////////////
// CDIBSectionLite diagnostics

#ifdef _DEBUG
void CDIBSectionLite::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 CDIBSectionLite::Dump(CDumpContext& dc) const
{
	CObject::Dump(dc);
}

#endif //_DEBUG


/////////////////////////////////////////////////////////////////////////////
// CDIBSectionLite 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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::Copy(CDIBSectionLite& 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;
} 

/////////////////////////////////////////////////////////////////////////////
// CDIBSectionLite 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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::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_palInfo;
    pi_palInfo.palNumEntries = (WORD) pPalette->GetPaletteEntries(0, nColors, (LPPALETTEENTRY) pi_palInfo);
                          
    return SetLogPalette(&pi_palInfo);
}

// --- 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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite::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 CDIBSectionLite 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* CDIBSectionLite::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 CDIBSectionLite::ReleaseMemoryDC(BOOL bForceRelease /*=FALSE*/)
{
    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 CDIBSectionLite::_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 CDIBSectionLite::_ShowLastError() {}
#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions