www.pudn.com > Hook-api-mir.rar > dibapi.cpp


// Copyright: www.pudn.com,程序员联合开发网,www.programsalon.com 
// 如果要使用或修改本程序,请保留次信息 
// 
//  dibapi.cpp 
// 
//  Source file for Device-Independent Bitmap (DIB) API.  Provides 
//  the following functions: 
// 
//  PaintDIB()          - Painting routine for a DIB 
//  CreateDIBPalette()  - Creates a palette from a DIB 
//  FindDIBBits()       - Returns a pointer to the DIB bits 
//  DIBWidth()          - Gets the width of the DIB 
//  DIBHeight()         - Gets the height of the DIB 
//  PaletteSize()       - Gets the size required to store the DIB's palette 
//  DIBNumColors()      - Calculates the number of colors 
//                        in the DIB's color table 
//  CopyHandle()        - Makes a copy of the given global memory block 
// 
// This is a part of the Microsoft Foundation Classes C++ library. 
// Copyright (c) Microsoft Corporation.  All rights reserved. 
// 
// This source code is only intended as a supplement to the 
// Microsoft Foundation Classes Reference and related 
// electronic documentation provided with the library. 
// See these sources for detailed information regarding the 
// Microsoft Foundation Classes product. 
 
#include "stdafx.h" 
#include "dibapi.h" 
#include  
#include  
#include  
#include  
#include  
#include "util.h" 
 
 
#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B') 
 
/************************************************************************* 
 * 
 * PaintDIB() 
 * 
 * Parameters: 
 * 
 * HDC hDC          - DC to do output to 
 * 
 * LPRECT lpDCRect  - rectangle on DC to do output to 
 * 
 * HDIB hDIB        - handle to global memory with a DIB spec 
 *                    in it followed by the DIB bits 
 * 
 * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect 
 * 
 * CPalette* pPal   - pointer to CPalette containing DIB's palette 
 * 
 * Return Value: 
 * 
 * BOOL             - TRUE if DIB was drawn, FALSE otherwise 
 * 
 * Description: 
 *   Painting routine for a DIB.  Calls StretchDIBits() or 
 *   SetDIBitsToDevice() to paint the DIB.  The DIB is 
 *   output to the specified DC, at the coordinates given 
 *   in lpDCRect.  The area of the DIB to be output is 
 *   given by lpDIBRect. 
 * 
 ************************************************************************/ 
 
BOOL WINAPI PaintDIB(HDC     hDC, 
					LPRECT  lpDCRect, 
					HDIB    hDIB,	 
					LPRECT  lpDIBRect, 
					HPALETTE hPal) 
{ 
	LPSTR    lpDIBHdr;            // Pointer to BITMAPINFOHEADER 
	LPSTR    lpDIBBits;           // Pointer to DIB bits 
	BOOL     bSuccess=FALSE;      // Success/fail flag 
	//HPALETTE hPal=NULL;           // Our DIB's palette 
	HPALETTE hOldPal=NULL;        // Previous palette 
 
	/* Check for valid DIB handle */ 
	if (hDIB == NULL) 
		return FALSE; 
 
	/* Lock down the DIB, and get a pointer to the beginning of the bit 
	 *  buffer 
	 */ 
	lpDIBHdr  = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
	lpDIBBits = ::FindDIBBits(lpDIBHdr); 
 
	// Get the DIB's palette, then select it into DC 
	if (hPal != NULL) 
	{ 
		//hPal = (HPALETTE) pPal->m_hObject; 
 
		// Select as background since we have 
		// already realized in forground if needed 
		hOldPal = ::SelectPalette(hDC, hPal, TRUE); 
	} 
 
	/* Make sure to use the stretching mode best for color pictures */ 
	::SetStretchBltMode(hDC, COLORONCOLOR); 
 
	/* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */ 
	if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDIBRect)) && 
	   (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect))) 
		bSuccess = ::SetDIBitsToDevice(hDC,                    // hDC 
								   lpDCRect->left,             // DestX 
								   lpDCRect->top,              // DestY 
								   RECTWIDTH(lpDCRect),        // nDestWidth 
								   RECTHEIGHT(lpDCRect),       // nDestHeight 
								   lpDIBRect->left,            // SrcX 
								   (int)DIBHeight(lpDIBHdr) - 
									  lpDIBRect->top - 
									  RECTHEIGHT(lpDIBRect),   // SrcY 
								   0,                          // nStartScan 
								   (WORD)DIBHeight(lpDIBHdr),  // nNumScans 
								   lpDIBBits,                  // lpBits 
								   (LPBITMAPINFO)lpDIBHdr,     // lpBitsInfo 
								   DIB_RGB_COLORS);            // wUsage 
   else 
	  bSuccess = ::StretchDIBits(hDC,                          // hDC 
							   lpDCRect->left,                 // DestX 
							   lpDCRect->top,                  // DestY 
							   RECTWIDTH(lpDCRect),            // nDestWidth 
							   RECTHEIGHT(lpDCRect),           // nDestHeight 
							   lpDIBRect->left,                // SrcX 
							   lpDIBRect->top,                 // SrcY 
							   RECTWIDTH(lpDIBRect),           // wSrcWidth 
							   RECTHEIGHT(lpDIBRect),          // wSrcHeight 
							   lpDIBBits,                      // lpBits 
							   (LPBITMAPINFO)lpDIBHdr,         // lpBitsInfo 
							   DIB_RGB_COLORS,                 // wUsage 
							   SRCCOPY);                       // dwROP 
 
   ::GlobalUnlock((HGLOBAL) hDIB); 
 
	/* Reselect old palette */ 
	if (hOldPal != NULL) 
	{ 
		::SelectPalette(hDC, hOldPal, TRUE); 
	} 
 
   return bSuccess; 
} 
 
/************************************************************************* 
 * 
 * CreateDIBPalette() 
 * 
 * Parameter: 
 * 
 * HDIB hDIB        - specifies the DIB 
 * 
 * Return Value: 
 * 
 * HPALETTE         - specifies the palette 
 * 
 * Description: 
 * 
 * This function creates a palette from a DIB by allocating memory for the 
 * logical palette, reading and storing the colors from the DIB's color table 
 * into the logical palette, creating a palette from this logical palette, 
 * and then returning the palette's handle. This allows the DIB to be 
 * displayed using the best possible colors (important for DIBs with 256 or 
 * more colors). 
 * 
 ************************************************************************/ 
 
/*int g_palette[5][256*4] = 
{ 
	0,0,0,0,128,0,0,0,0,128,0,0,128,128,0,0,0,0,128,0,128,0,128,0,0,128,128,0,192,192,192,0,192,220,192, 
0,212,208,200,0,255,251,240,0,58,110,165,0,128,128,128,0,255,0,0,0,0,255,0,0,255,255,0,0,0, 
0,255,0,255,0,255,0,0,255,255,0,255,255,255,0,0,1,0,0,12,0,0,0,72,214,18,0,0,0,37,0,231,2, 
150,124 216,7,37,0,112,216,18,0,223,250,149,124 35,251,149,124 196,216,18,0,188,216,18,0,0, 
0,0,0,231,2,150,124 184,18,37,0,144,216,18,0,124,214,18,0,0,0,37,0,231,2,150,124 184,18,37,0,164,216,18,0,223,250,149,124 35,251,149,124 224,101,189,119 0,1,0,0,12,0,0,0,52,56,44,52 52,0,53,54 44,52,57,44 52,52,44,52 57,32,53,52 44,53,51,44 52,52,44,52 57,32,53,50,44,53,54,44 52,52,44,53 52,32,53,55 44,51,50,44 52,57,44,53 48,32,53,49 44,52,52,44 52,57,44,52 56,32,53,53 44,52,52,44 53,55,44,52 56,32,52,52 44,53,52,44 53,55,44,51 50,32,53,48 44,52,56,44 53,52,44,52 52,32,52,57 44,53,53,44 53,53,44,52 52,32,52,57 44,53,50,44 53,54,44,52 52,32,53,52 44,53,55,44 51,50,44,52 57,32,53,52 48,215,18,0,52,215,18,0,1,0,0,0,179,2,150,124 248,245,38,0,68,215,18,0,72,215,18,0,1,0,0,0,179,2,150,124 248,245,38,0,40,216,18,0,193,249,149,124 184,18,37,0,221,249,149,124 104,216,18,0,31,110,37,0,46,0,0,0,56,32,52,52 44,53,52,44 53,55,44,51 50,32,52,57 44,53,54,44 52,57,44,52 140,215,18,0,144,215,18,0,1,0,0,0,179,2,150,124 248,245,38,0,160,215,18,0,164,215,18,0,1,0,0,0,179,2,150,124 248,245,38,0,132,216,18,0,193,249,149,124 184,18,37,0,221,249,149,124 196,216,18,0,31,110,37,0,46,0,0,0,24,8,2,0,46,0,0,0,0,0,0,0,7,0,0, 
0,240,109,37,0,52,216,18,0,128,246,149,124 0,0,0,0,255,255,255,255 240,109,37,0,76,142,130,124 1,0,0,0,56,0,0,0,0,0,37,0,0,0,37,0,0,0,0,0,24,8,2,0,46,0,0,0,92,246,38,0,64,216,18,0,120,43,150,124 127,43,150,124 92,246,38,0,24,8,2,0,46,0,0,0,255,255,255,255 7,0,0,0,179,33,150,124 144,216,18,0,128,246,149,124 0,0,0,0,255,255,255,255 240,109,37,0,76,142,130,124 1,0,0,0,56,0,0,0,0,0,37,0,0,0,37,0,0,0,0,0,56,0,0,0,8,2,0,0,65,0,0,0,176,215,1,0,180,215,18,0,232,243,18,0,232,243,18,0,128,246,149,124 224,249,149,124 255,255,255,255 221,249,149,124 179,33,150,124 0,0,37,0,0,0,0,0,0,246,38,0,168,216,18,0,195,33,150,124 0,246,38,0,224,101,189,119 204,216,18,0,34,96,130,124 196,216,18,0,12,0,0,0,240,2,252,0,0,0,0,0,0,0,0,0,0,0,0,0,240,2,252,0,12,0,0,0,224,101,189,119 183,20,243,0,224,216,18,0,184,193,243,0,67,58,92,80,114,111,103,114 97,109,32,70,105,108,101,115 92,83,104,97 110,100,97,92 76,101,103,101 110,100,32,111 39,0,0,0,60,186,225,119 0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,238,217,18,0,10,0,0,0,238,217,18,0,120,217,18,0,0,0,0,0,255,255,255,255 0,0,0,0,1,0,0,0,160,217,18,0,152,185,225,119 239,217,18,0,0,0,0,0, 
160,217,18,0,222,185,225,119 238,217,18,0,238,217,18,0,237,217,18,0,246,221,18,0,63,184,225, 
119 0,0,0,0,11,0,136,1 0,0,0,0,1,0,0,0,0,0,0,0,254,255,255,255 60,192,243,0,212,217,18,0,0, 
0,0,32 255,255,255,255 50,50,50,0,245,3,0,0,0,0,0,0,0,0,0,0,109,40,0,0,180,217,18,0,232,168, 
225,119 228,217,18,0,48,192,243,0,196,217,18,0,1,0,0,0,29,102,189,119 7,102,189,119 160,18, 
1,47 11,0,136,1 0,0,0,0,240,2,252,0,88,243,18,0,86,35,243,0,160,18,1,47 11,0,136,1 
};*/ 
 
HPALETTE WINAPI CreateDIBPalette(HDIB hDIB) 
{ 
	HPALETTE hPal; 
	LPLOGPALETTE lpPal;      // pointer to a logical palette 
	HANDLE hLogPal;          // handle to a logical palette 
	int i;                   // loop index 
	WORD wNumColors;         // number of colors in color table 
	LPSTR lpbi;              // pointer to packed-DIB 
	LPBITMAPINFO lpbmi;      // pointer to BITMAPINFO structure (Win3.0) 
	LPBITMAPCOREINFO lpbmc;  // pointer to BITMAPCOREINFO structure (old) 
	BOOL bWinStyleDIB;       // flag which signifies whether this is a Win3.0,DIB 
	BOOL bResult = FALSE; 
 
	/* if handle to DIB is invalid, return FALSE */ 
 
	if (hDIB == NULL) 
	  return FALSE; 
 
   lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
 
   /* get pointer to BITMAPINFO (Win 3.0) */ 
   lpbmi = (LPBITMAPINFO)lpbi; 
 
   /* get pointer to BITMAPCOREINFO (old 1.x) */ 
   lpbmc = (LPBITMAPCOREINFO)lpbi; 
 
   /* get the number of colors in the DIB */ 
   wNumColors = ::DIBNumColors(lpbi); 
 
   if (wNumColors != 0) 
   { 
		/* allocate memory block for logical palette */ 
		hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) 
									+ sizeof(PALETTEENTRY) 
									* wNumColors); 
 
		/* if not enough memory, clean up and return NULL */ 
		if (hLogPal == 0) 
		{ 
			::GlobalUnlock((HGLOBAL) hDIB); 
			return FALSE; 
		} 
 
		lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal); 
 
		/* set version and number of palette entries */ 
		lpPal->palVersion = PALVERSION; 
		lpPal->palNumEntries = (WORD)wNumColors; 
		/* is this a Win 3.0,DIB? */ 
		char temp[4096], temp2[20]; 
		temp[0] =0; 
		bWinStyleDIB = IS_WIN30_DIB(lpbi); 
		 
WriteLog("palette version:%d, num_entry:%d", lpPal->palVersion, lpPal->palNumEntries); 
 
		for (i = 0; i < (int)wNumColors; i++) 
		{ 
			if (bWinStyleDIB) 
			{ 
				lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; 
				lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; 
				lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue; 
				lpPal->palPalEntry[i].peFlags = 0; 
			} 
			else 
			{ 
				lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed; 
				lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen; 
				lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue; 
				lpPal->palPalEntry[i].peFlags = 0; 
			} 
			wsprintf(temp2, " %d,%d,%d,%d,", 
				lpPal->palPalEntry[i].peRed, 
				lpPal->palPalEntry[i].peGreen, 
				lpPal->palPalEntry[i].peBlue, 
				lpPal->palPalEntry[i].peFlags); 
		} 
		WriteLog(temp); 
		/* create the palette and get handle to it */ 
		hPal = CreatePalette(lpPal); 
		::GlobalUnlock((HGLOBAL) hLogPal); 
		::GlobalFree((HGLOBAL) hLogPal); 
	} 
 
	::GlobalUnlock((HGLOBAL) hDIB); 
 
	return hPal; 
} 
 
/************************************************************************* 
 * 
 * FindDIBBits() 
 * 
 * Parameter: 
 * 
 * LPSTR lpbi       - pointer to packed-DIB memory block 
 * 
 * Return Value: 
 * 
 * LPSTR            - pointer to the DIB bits 
 * 
 * Description: 
 * 
 * This function calculates the address of the DIB's bits and returns a 
 * pointer to the DIB bits. 
 * 
 ************************************************************************/ 
 
 
LPSTR WINAPI FindDIBBits(LPSTR lpbi) 
{ 
	return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi)); 
} 
 
 
/************************************************************************* 
 * 
 * DIBWidth() 
 * 
 * Parameter: 
 * 
 * LPSTR lpbi       - pointer to packed-DIB memory block 
 * 
 * Return Value: 
 * 
 * DWORD            - width of the DIB 
 * 
 * Description: 
 * 
 * This function gets the width of the DIB from the BITMAPINFOHEADER 
 * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER 
 * width field if it is an other-style DIB. 
 * 
 ************************************************************************/ 
 
 
DWORD WINAPI DIBWidth(LPSTR lpDIB) 
{ 
	LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB 
	LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB 
 
	/* point to the header (whether Win 3.0,and old) */ 
 
	lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
	lpbmc = (LPBITMAPCOREHEADER)lpDIB; 
 
	/* return the DIB width if it is a Win 3.0,DIB */ 
	if (IS_WIN30_DIB(lpDIB)) 
		return lpbmi->biWidth; 
	else  /* it is an other-style DIB, so return its width */ 
		return (DWORD)lpbmc->bcWidth; 
} 
 
 
/************************************************************************* 
 * 
 * DIBHeight() 
 * 
 * Parameter: 
 * 
 * LPSTR lpbi       - pointer to packed-DIB memory block 
 * 
 * Return Value: 
 * 
 * DWORD            - height of the DIB 
 * 
 * Description: 
 * 
 * This function gets the height of the DIB from the BITMAPINFOHEADER 
 * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER 
 * height field if it is an other-style DIB. 
 * 
 ************************************************************************/ 
 
 
DWORD WINAPI DIBHeight(LPSTR lpDIB) 
{ 
	LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB 
	LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB 
 
	/* point to the header (whether old or Win 3.0,*/ 
 
	lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
	lpbmc = (LPBITMAPCOREHEADER)lpDIB; 
 
	/* return the DIB height if it is a Win 3.0,DIB */ 
	if (IS_WIN30_DIB(lpDIB)) 
		return lpbmi->biHeight; 
	else  /* it is an other-style DIB, so return its height */ 
		return (DWORD)lpbmc->bcHeight; 
} 
 
 
/************************************************************************* 
 * 
 * PaletteSize() 
 * 
 * Parameter: 
 * 
 * LPSTR lpbi       - pointer to packed-DIB memory block 
 * 
 * Return Value: 
 * 
 * WORD             - size of the color palette of the DIB 
 * 
 * Description: 
 * 
 * This function gets the size required to store the DIB's palette by 
 * multiplying the number of colors by the size of an RGBQUAD (for a 
 * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an other- 
 * style DIB). 
 * 
 ************************************************************************/ 
 
 
WORD WINAPI PaletteSize(LPSTR lpbi) 
{ 
   /* calculate the size required by the palette */ 
   if (IS_WIN30_DIB (lpbi)) 
	  return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD)); 
   else 
	  return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE)); 
} 
 
 
/************************************************************************* 
 * 
 * DIBNumColors() 
 * 
 * Parameter: 
 * 
 * LPSTR lpbi       - pointer to packed-DIB memory block 
 * 
 * Return Value: 
 * 
 * WORD             - number of colors in the color table 
 * 
 * Description: 
 * 
 * This function calculates the number of colors in the DIB's color table 
 * by finding the bits per pixel for the DIB (whether Win3.0,or other-style 
 * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256, 
 * if 24, no colors in color table. 
 * 
 ************************************************************************/ 
 
 
WORD WINAPI DIBNumColors(LPSTR lpbi) 
{ 
	WORD wBitCount;  // DIB bit count 
 
	/*  If this is a Windows-style DIB, the number of colors in the 
	 *  color table can be less than the number of bits per pixel 
	 *  allows for (i.e. lpbi->biClrUsed can be set to some value). 
	 *  If this is the case, return the appropriate value. 
	 */ 
 
	if (IS_WIN30_DIB(lpbi)) 
	{ 
		DWORD dwClrUsed; 
 
		dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; 
		if (dwClrUsed != 0) 
			return (WORD)dwClrUsed; 
	} 
 
	/*  Calculate the number of colors in the color table based on 
	 *  the number of bits per pixel for the DIB. 
	 */ 
	if (IS_WIN30_DIB(lpbi)) 
		wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; 
	else 
		wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; 
 
	/* return number of colors based on bits per pixel */ 
	switch (wBitCount) 
	{ 
		case 1: 
			return 2; 
 
		case 4: 
			return 16; 
 
		case 8: 
			return 256; 
 
		default: 
			return 0; 
	} 
} 
 
 
////////////////////////////////////////////////////////////////////////// 
//// Clipboard support 
 
//--------------------------------------------------------------------- 
// 
// Function:   CopyHandle (from SDK DibView sample clipbrd.c) 
// 
// Purpose:    Makes a copy of the given global memory block.  Returns 
//             a handle to the new memory block (NULL on error). 
// 
//             Routine stolen verbatim out of ShowDIB. 
// 
// Parms:      h == Handle to global memory to duplicate. 
// 
// Returns:    Handle to new global memory block. 
// 
//--------------------------------------------------------------------- 
 
HGLOBAL WINAPI CopyHandle (HGLOBAL h) 
{ 
	if (h == NULL) 
		return NULL; 
 
	DWORD dwLen = (DWORD)::GlobalSize((HGLOBAL) h); 
	HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen); 
 
	if (hCopy != NULL) 
	{ 
		void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); 
		void* lp     = ::GlobalLock((HGLOBAL) h); 
		memcpy(lpCopy, lp, dwLen); 
		::GlobalUnlock(hCopy); 
		::GlobalUnlock(h); 
	} 
 
	return hCopy; 
} 
 
/************************************************************************* 
 * 
 * SaveDIB() 
 * 
 * Saves the specified DIB into the specified CFile.  The CFile 
 * is opened and closed by the caller. 
 * 
 * Parameters: 
 * 
 * HDIB hDib - Handle to the dib to save 
 * 
 * CFile& file - open CFile used to save DIB 
 * 
 * Return value: TRUE if successful, else FALSE or CFileException 
 * 
 *************************************************************************/ 
 
 
/*BOOL WINAPI SaveDIB(HDIB hDib, CFile& file) 
{ 
	BITMAPFILEHEADER bmfHdr; // Header for Bitmap file 
	LPBITMAPINFOHEADER lpBI;   // Pointer to DIB info structure 
	UINT nDIBSize; 
 
	if (hDib == NULL) 
		return FALSE; 
 
	lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib); 
	if (lpBI == NULL) 
		return FALSE; 
 
	if (!IS_WIN30_DIB(lpBI)) 
	{ 
		::GlobalUnlock((HGLOBAL) hDib); 
		return FALSE;       // It's an other-style DIB (save not supported) 
	} 
 
	bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM" 
 
	// Calculating the size of the DIB is a bit tricky (if we want to 
	// do it right).  The easiest way to do this is to call GlobalSize() 
	// on our global handle, but since the size of our global memory may have 
	// been padded a few bytes, we may end up writing out a few too 
	// many bytes to the file (which may cause problems with some apps). 
	// 
	// So, instead let's calculate the size manually (if we can) 
	// 
	// First, find size of header plus size of color table.  Since the 
	// first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains 
	// the size of the structure, let's use this. 
 
	nDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);  // Partial Calculation 
 
	// Now calculate the size of the image 
 
	if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) 
	{ 
		// It's an RLE bitmap, we can't calculate size, so trust the 
		// biSizeImage field 
 
		nDIBSize += lpBI->biSizeImage; 
	} 
	else 
	{ 
		DWORD dwBmBitsSize;  // Size of Bitmap Bits only 
 
		// It's not RLE, so size is Width (DWORD aligned) * Height 
 
		dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight; 
 
		nDIBSize += dwBmBitsSize; 
 
		// Now, since we have calculated the correct size, why don't we 
		// fill in the biSizeImage field (this will fix any .BMP files which 
		// have this field incorrect). 
 
		lpBI->biSizeImage = dwBmBitsSize; 
	} 
 
 
	// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) 
 
	bmfHdr.bfSize = nDIBSize + sizeof(BITMAPFILEHEADER); 
	bmfHdr.bfReserved1 = 0; 
	bmfHdr.bfReserved2 = 0; 
 
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize 
											  + PaletteSize((LPSTR)lpBI); 
	TRY 
	{ 
		// Write the file header 
		file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); 
		// 
		// Write the DIB header and the bits 
		// 
		file.Write(lpBI, nDIBSize); 
	} 
	CATCH (CFileException, e) 
	{ 
		::GlobalUnlock((HGLOBAL) hDib); 
		THROW_LAST(); 
	} 
	END_CATCH 
 
	::GlobalUnlock((HGLOBAL) hDib); 
	return TRUE; 
} 
*/ 
 
/************************************************************************* 
 
  Function:  ReadDIBFile (CFile&) 
 
   Purpose:  Reads in the specified DIB file into a global chunk of 
			 memory. 
 
   Returns:  A handle to a dib (hDIB) if successful. 
			 NULL if an error occurs. 
 
  Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything 
			 from the end of the BITMAPFILEHEADER structure on is 
			 returned in the global memory handle. 
 
*************************************************************************/ 
 
 
HDIB WINAPI ReadDIBFile(char *fname) 
{ 
	BITMAPFILEHEADER bmfHeader; 
	UINT nBitsSize; 
	HDIB hDIB; 
	LPSTR pDIB; 
	FILE *fp =fopen(fname, "rb"); 
	if(fp ==NULL) return NULL; 
	/* 
	 * get length of DIB in bytes for use when reading 
	 */ 
 
	fseek(fp, 0, SEEK_END); 
	nBitsSize = (UINT)ftell(fp); 
	fseek(fp, 0, SEEK_SET); 
 
	/* 
	 * Go read the DIB file header and check if it's valid. 
	 */ 
	if (fread((LPSTR)&bmfHeader, 1, sizeof(bmfHeader), fp) != sizeof(bmfHeader)) 
	{ 
		fclose(fp); 
		return NULL; 
	} 
 
	if (bmfHeader.bfType != DIB_HEADER_MARKER) 
	{ 
		fclose(fp); 
		return NULL; 
	} 
 
	/* 
	 * Allocate memory for DIB 
	 */ 
	hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD)nBitsSize); 
	if (hDIB == 0) 
	{ 
		fclose(fp); 
		return NULL; 
	} 
	pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
 
	/* 
	 * Go read the bits. 
	 */ 
	if (fread(pDIB, 1, nBitsSize - sizeof(BITMAPFILEHEADER), fp) != 
		nBitsSize - sizeof(BITMAPFILEHEADER) ) 
	{ 
		::GlobalUnlock((HGLOBAL) hDIB); 
		::GlobalFree((HGLOBAL) hDIB); 
		fclose(fp); 
		return NULL; 
	} 
	::GlobalUnlock((HGLOBAL) hDIB); 
	fclose(fp); 
 
	return hDIB; 
}