www.pudn.com > yuzhishuanfa.zip > Dibapi.cpp


//  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 
//  DIBToBitmap()       - Creates a bitmap from a DIB 
//  BitmapToDIB()       - Creates a DIB from a bitmap 
//  以下是鲍捷的自定义函数 
//	Create24BitsBitmap()- Creates a bitmap of true colors (24 bits) 
//  CreateGrayBitmap()  - Creates a bitmap of gray colors(with 8 bits)    
// 
#include "stdafx.h" 
#include "dibapi.h" 
#include  
#include  
 
/************************************************************************* 
 * 
 * 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, 
					CPalette* pPal) 
{ 
	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 (pPal != 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)) &&      //当设备与DIB等大 
	   (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). 
 * 
 ************************************************************************/ 
 
 
BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal) 
{ 
	LPLOGPALETTE lpPal;      // pointer to a logical palette 
	HANDLE hLogPal;          // handle to a logical palette 
	HPALETTE hPal = NULL;    // handle to a 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? */ 
		bWinStyleDIB = IS_WIN30_DIB(lpbi); 
		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; 
			} 
		} 
 
		/* create the palette and get handle to it */ 
		bResult = pPal->CreatePalette(lpPal); 
		::GlobalUnlock((HGLOBAL) hLogPal); 
		::GlobalFree((HGLOBAL) hLogPal); 
	} 
 
	::GlobalUnlock((HGLOBAL) hDIB); 
 
	return bResult; 
} 
 
/************************************************************************* 
 * 
 * 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;//For Windows 3.0 DIB 
	lpbmc = (LPBITMAPCOREHEADER)lpDIB;//For OS/2 1.1 & 1.2 
 
	/* 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 = ::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; 
} 
 
/************************************************************************* 
 * 
 * DIBToBitmap() 
 * 
 * Parameters: 
 * 
 * HDIB hDIB        - specifies the DIB to convert 
 * 
 * HPALETTE hPal    - specifies the palette to use with the bitmap 
 *                    若为NULL则使用系统缺省调色板 
 * Return Value: 
 * 
 * HBITMAP          - identifies the device-dependent bitmap 
 * 
 * Description: 
 * 
 * This function creates a bitmap from a DIB using the specified palette. 
 * If no palette is specified, default is used. 
 * 
 * NOTE: 
 * 
 * The bitmap returned from this funciton is always a bitmap compatible 
 * with the screen (e.g. same bits/pixel and color planes) rather than 
 * a bitmap with the same attributes as the DIB.  This behavior is by 
 * design, and occurs because this function calls CreateDIBitmap to 
 * do its work, and CreateDIBitmap always creates a bitmap compatible 
 * with the hDC parameter passed in (because it in turn calls 
 * CreateCompatibleBitmap). 
 * 
 * 
 * So for instance, if your DIB is a monochrome DIB and you call this 
 * function, you will not get back a monochrome HBITMAP -- you will 
 * get an HBITMAP compatible with the screen DC, but with only 2 
 * colors used in the bitmap. 
 * 
 * 1998年12月25日,鲍捷作了如下修改: 
 *    将CreateDIBitmap改为CreateDIBSection,SetDIBits以解决调色板的色深改变问题 
 * 
 * If your application requires a monochrome HBITMAP returned for a 
 * monochrome DIB, use the function SetDIBits(). 
 * 
 * Also, the DIB passed in to the function is not destroyed on exit. This 
 * must be done later, once it is no longer needed. 
 * 
 ************************************************************************/ 
 
HBITMAP WINAPI DIBToBitmap(HDIB hDIB, HPALETTE hPal) 
{ 
    LPSTR       lpDIBHdr, lpDIBBits;  // pointer to DIB header, pointer to DIB bits 
    HBITMAP     hBitmap;            // handle to device-dependent bitmap 
    HDC         hDC;                    // DC句柄 
    HPALETTE    hOldPal = NULL;    // 调色板句柄 
 
    // 若句柄无效,返回NULL  
	 if (!hDIB) 
        return NULL; 
 
    // 锁定内存块,取得指针 
	 lpDIBHdr = (LPSTR)::GlobalLock(hDIB); 
 
    // get a pointer to the DIB bits 
	lpDIBBits = FindDIBBits(lpDIBHdr); 
 
    // get a DC  
	hDC = GetDC(NULL); 
    if (!hDC) 
    { 
        // clean up and return NULL 
	    GlobalUnlock(hDIB); 
        return NULL; 
    } 
 
    // select and realize palette 
	if (hPal) 
        hOldPal = SelectPalette(hDC, hPal, FALSE); 
	RealizePalette(hDC); 
 
	 // create bitmap from DIB info. and bits 
/*//1998.12.25 鲍捷去除 
    hBitmap = CreateDIBitmap(hDC,  
		                    (LPBITMAPINFOHEADER)lpDIBHdr,  
							CBM_INIT, 
							lpDIBBits,  
							(LPBITMAPINFO)lpDIBHdr, 
							DIB_RGB_COLORS); 
 
*/ 
//{{ 
	//The CreateDIBSection function creates a device-independent  
	//bitmap (DIB) that applications can write to directly. The  
	//function gives you a pointer to the location of the bitmap’s  
	//bit values. You can supply a handle to a file mapping object  
	//that the function will use to create the bitmap, or you can  
	//let the operating system allocate the memory for the bitmap.  
	hBitmap = CreateDIBSection(hDC,// HDC hdc,  // handle to device context  
		(LPBITMAPINFO)lpDIBHdr,//CONST BITMAPINFO *pbmi,  // pointer to structure containing bitmap size, format, and color data  
		DIB_RGB_COLORS,//UINT iUsage,  // color data type indicator: RGB values or palette indices  
		(void **)lpDIBBits,//VOID *ppvBits,  // pointer to variable to receive a pointer to the bitmap’s bit values  
		NULL,//HANDLE hSection,  // optional handle to a file mapping object  
		0//DWORD dwOffset  // offset to the bitmap bit values within the file mapping object  
		);  
 
	int cyDIB = (int) ::DIBHeight(lpDIBHdr);        // Size of DIB - y 
	// The SetDIBits function sets the pixels in a bitmap using  
	//the color data found in the specified device-independent bitmap (DIB).  
	SetDIBits( hDC,//HDC hdc,  // handle of device context  
		hBitmap,//HBITMAP hbmp,  // handle of bitmap  
		0,//UINT uStartScan,  // starting scan line  
		cyDIB,//UINT cScanLines,  // number of scan lines  
		lpDIBBits,//CONST VOID *lpvBits,  // array of bitmap bits  
		(LPBITMAPINFO)lpDIBHdr,//CONST BITMAPINFO *lpbmi,  // address of structure with bitmap data  
		DIB_RGB_COLORS//UINT fuColorUse  // type of color indices to use  
		);  
//}}  
 
 
	if(!hBitmap) 
		AfxMessageBox("设备相关位图建立错误"); 
 
    // 恢复原有调色板 
    if (hOldPal) 
        SelectPalette(hDC, hOldPal, FALSE); 
    // clean up 
    ReleaseDC(NULL, hDC); 
    GlobalUnlock(hDIB); 
 
    return hBitmap;  //返回HBITMAP句柄 
} 
 
 
/************************************************************************* 
 * 
 * BitmapToDIB() 
 * 
 * Parameters: 
 * 
 * HBITMAP hBitmap  - specifies the bitmap to convert 
 * 
 * HPALETTE hPal    - specifies the palette to use with the bitmap 
 *                     若为NULL则使用系统缺省调色板  
 * Return Value: 
 * 
 * HDIB             - identifies the device-dependent bitmap 
 * 
 * Description: 
 * 
 * This function creates a DIB from a bitmap using the specified palette. 
 * 
 ************************************************************************/ 
 
HDIB WINAPI BitmapToDIB(HBITMAP hBitmap, HPALETTE hPal) 
{ 
    BITMAP              bm;         // bitmap structure 
    BITMAPINFOHEADER    bi;         // bitmap header 
    LPBITMAPINFOHEADER  lpbi;       // pointer to BITMAPINFOHEADER 
    DWORD               dwLen;      // size of memory block 
    HDIB              hDIB, h;    // handle to DIB, temp handle 
    HDC                 hDC;        // handle to DC 
    WORD                biBits;     // bits per pixel 
 
    // check if bitmap handle is valid 
 
    if (!hBitmap) 
        return NULL; 
 
    // fill in BITMAP structure, return NULL if it didn't work 
 
    if (!GetObject(hBitmap, sizeof(bm), (LPSTR)&bm)) 
        return NULL; 
 
    // if no palette is specified, use default palette 
 
    if (hPal == NULL) 
        hPal = (HPALETTE)::GetStockObject(DEFAULT_PALETTE); 
 
    // calculate bits per pixel 
 
    biBits = bm.bmPlanes * bm.bmBitsPixel; 
 
    // make sure bits per pixel is valid 
 
    if (biBits <= 1) 
        biBits = 1; 
    else if (biBits <= 4) 
        biBits = 4; 
    else if (biBits <= 8) 
        biBits = 8; 
    else // if greater than 8-bit, force to 24-bit 
        biBits = 24; 
 
    // initialize BITMAPINFOHEADER 
 
    bi.biSize = sizeof(BITMAPINFOHEADER); 
    bi.biWidth = bm.bmWidth; 
    bi.biHeight = bm.bmHeight; 
    bi.biPlanes = 1; 
    bi.biBitCount = biBits; 
    bi.biCompression = BI_RGB; 
    bi.biSizeImage = 0; 
    bi.biXPelsPerMeter = 0; 
    bi.biYPelsPerMeter = 0; 
    bi.biClrUsed = 0; 
    bi.biClrImportant = 0; 
 
    // calculate size of memory block required to store BITMAPINFO 
 
    dwLen = bi.biSize + PaletteSize((LPSTR)&bi); 
 
    // get a DC 
 
    hDC = GetDC(NULL); 
 
    // select and realize our palette 
 
    hPal = SelectPalette(hDC, hPal, FALSE); 
    RealizePalette(hDC); 
 
    // alloc memory block to store our bitmap 
 
    hDIB = (HDIB)::GlobalAlloc(GHND, dwLen); 
 
    // if we couldn't get memory block 
 
    if (!hDIB) 
    { 
      // clean up and return NULL 
 
      SelectPalette(hDC, hPal, TRUE); 
      RealizePalette(hDC); 
      ReleaseDC(NULL, hDC); 
      return NULL; 
    } 
 
    // lock memory and get pointer to it 
 
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); 
 
    /// use our bitmap info. to fill BITMAPINFOHEADER 
 
    *lpbi = bi; 
 
    // call GetDIBits with a NULL lpBits param, so it will calculate the 
    // biSizeImage field for us     
 
    GetDIBits(hDC, hBitmap, 0, (UINT)bi.biHeight, NULL, (LPBITMAPINFO)lpbi, 
        DIB_RGB_COLORS); 
 
    // get the info. returned by GetDIBits and unlock memory block 
 
    bi = *lpbi; 
    GlobalUnlock(hDIB); 
 
    // if the driver did not fill in the biSizeImage field, make one up  
    if (bi.biSizeImage == 0) 
        bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight; 
 
    // realloc the buffer big enough to hold all the bits 
 
    dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage; 
 
    if (h = (HDIB)::GlobalReAlloc(hDIB, dwLen, 0)) 
        hDIB = h; 
    else 
    { 
        // clean up and return NULL 
 
        GlobalFree(hDIB); 
        hDIB = NULL; 
        SelectPalette(hDC, hPal, TRUE); 
        RealizePalette(hDC); 
        ReleaseDC(NULL, hDC); 
        return NULL; 
    } 
 
    // lock memory block and get pointer to it */ 
 
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); 
 
    // call GetDIBits with a NON-NULL lpBits param, and actualy get the 
    // bits this time 
 
    if (GetDIBits(hDC,  
		          hBitmap, 
				  0, 
				  (UINT)bi.biHeight,  
				  (LPSTR)lpbi +(WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),  
				  (LPBITMAPINFO)lpbi, 
                  DIB_RGB_COLORS) == 0) 
    { 
        // clean up and return NULL 
 
        GlobalUnlock(hDIB); 
        hDIB = NULL; 
        SelectPalette(hDC, hPal, TRUE); 
        RealizePalette(hDC); 
        ReleaseDC(NULL, hDC); 
        return NULL; 
    } 
 
    bi = *lpbi; 
 
    // clean up  
    GlobalUnlock(hDIB); 
    SelectPalette(hDC, hPal, TRUE); 
    RealizePalette(hDC); 
    ReleaseDC(NULL, hDC); 
 
    // return handle to the DIB 
    return hDIB; 
} 
 
/************************************************************************* 
 * 
 * Create24BitsBitmap() 
 * 
 * Parameters: 
 *     DWORD Width     宽 
 *     DWORD Height    高 
 * Return Value: 
 * 
 * HBITMAP             - 位图句柄 
 * 
 * Description: 
 * 
 *   该函数根据宽、高建立一个真彩位图 
 * 
 ************************************************************************/ 
 
 
HBITMAP   WINAPI  Create24BitsBitmap(DWORD Width,DWORD Height) 
{ 
   	HANDLE             hBits=::GlobalAlloc(GHND,Width*Height*3); 
	LPSTR              lpBits=(LPSTR)::GlobalLock(hBits); 
	BITMAPINFOHEADER   Header; 
	HBITMAP			   hBitmap; 
	memset(lpBits,255,Width*Height*3);         //底色白色 
	 
	Header.biSize=sizeof(BITMAPINFOHEADER);  
    Header.biWidth=Width;  
    Header.biHeight=Height;  
    Header.biPlanes=1L;  
    Header.biBitCount=24L;  
    Header.biCompression=BI_RGB;  
    Header.biSizeImage=(long)Width * Height * 3;  
    Header.biXPelsPerMeter=0;  
    Header.biYPelsPerMeter=0;  
    Header.biClrUsed=0;  
    Header.biClrImportant=0;  
 
	HDC hDC = GetDC(NULL); 
    if (!hDC) 
    { 
        // clean up and return NULL 
	   ::GlobalUnlock(hBits); 
	   ::GlobalFree((HGLOBAL)hBits); 
	   return NULL; 
    } 
    // create bitmap from DIB info. and bits 
	hBitmap=::CreateDIBitmap(hDC, 
		                       (LPBITMAPINFOHEADER)&Header, 
							   CBM_INIT, 
							   lpBits, 
							   (LPBITMAPINFO)&Header, //24位位图无调色板 
							                          //BITMAPINFOHEADER与BITMAPINFO相同 
		                       DIB_RGB_COLORS ); 
	ReleaseDC(NULL, hDC); 
	 
	::GlobalUnlock(hBits); 
	::GlobalFree((HGLOBAL)hBits); 
	 
	if(hBitmap==NULL) 
	{ 
		AfxMessageBox("新建位图错误"); 
		return NULL; 
	} 
	 
	return hBitmap; 
 
} 
 
 
 
 
/************************************************************************* 
 * 
 * Create8BitsBitmap()                      1998.6.7 
 * 
 * Parameters: 
 *     DWORD Width     宽 
 *     DWORD Height    高 
 * Return Value: 
 * 
 * HBITMAP             - 位图句柄 
 * 
 * Description: 
 * 
 *   该函数根据宽、高建立一个256色位图 
 * 
 ************************************************************************/ 
 
HBITMAP   WINAPI  Create8BitsBitmap(DWORD Width,DWORD Height) 
{ 
    //位图初始化数据 
	HANDLE               hBits=::GlobalAlloc(GHND,Width*Height);   
	LPSTR                lpBits=(LPSTR)::GlobalLock(hBits); 
	memset(lpBits,255,Width*Height);         //底色白色 
	 
    //BITMAPINFO位图头和调色板 
	HANDLE               hbmi=::GlobalAlloc(GHND, 
		                              sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256);    
	LPBITMAPINFO         lpbmi =(LPBITMAPINFO)::GlobalLock(hbmi); 
	LPBITMAPINFOHEADER   Header=(LPBITMAPINFOHEADER)lpbmi; 
	 
	Header->biSize=sizeof(BITMAPINFOHEADER);  
    Header->biWidth=Width;  
    Header->biHeight=Height;  
    Header->biPlanes=1L;  
    Header->biBitCount=8L;  
    Header->biCompression=BI_RGB;  
    Header->biSizeImage=(long)Width * Height;  
    Header->biXPelsPerMeter=0;  
    Header->biYPelsPerMeter=0;  
    Header->biClrUsed=0;  
    Header->biClrImportant=0;  
 
	// 建立灰度调色板  
    RGBQUAD pPal[256]; 
    BYTE red,green,blue; 
	red = green = blue = 0; 
    for (BYTE i = 0; i < 256; i++) 
	 { 
          pPal[i].rgbRed   = red; 
          pPal[i].rgbGreen = green; 
          pPal[i].rgbBlue  = blue; 
          pPal[i].rgbReserved = (BYTE)0; 
          if (!(red += 32)) 
                if (!(green += 32)) 
                    blue += 64; 
       } 
	memcpy(lpbmi->bmiColors,pPal,sizeof(RGBQUAD)*256); 
     
	//建立内存设备文本和位图 
	HDC hDC = GetDC(NULL); 
    if (!hDC) 
    { 
        // clean up and return NULL 
	   ::GlobalUnlock(hBits); 
	   ::GlobalFree((HGLOBAL)hBits); 
	   ::GlobalUnlock(hbmi); 
	   ::GlobalFree((HGLOBAL)hbmi); 
	   return NULL; 
    } 
    // create bitmap from DIB info. and bits 
	HBITMAP			     hBitmap; 
	hBitmap=::CreateDIBitmap(hDC, 
		                       Header, 
							   CBM_INIT, 
							   lpBits, 
							   lpbmi, 
          	                   DIB_RGB_COLORS ); 
    //释放资源,返回位图 
    ::ReleaseDC(NULL, hDC); 
    ::GlobalUnlock(hBits); 
	::GlobalFree((HGLOBAL)hBits); 
	::GlobalUnlock(hbmi); 
	::GlobalFree((HGLOBAL)hbmi); 
	    
	if(hBitmap==NULL) 
	{ 
		AfxMessageBox("新建位图错误"); 
		return NULL; 
	} 
	 
	return hBitmap; 
}