www.pudn.com > fingerprint.rar > 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 
// 
// This is a part of the Microsoft Foundation Classes C++ library. 
// Copyright (C) 1992-1998 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  
DWORD WINAPI BytesPerLine( LPBITMAPINFOHEADER lpBMIH ) 
{    return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount);} 
 
/************************************************************************* 
 * 
 * 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 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) 
	{ 
		// 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; 
} 
 
 
 
/************************************************************************* 
 * 
 * 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) 
			+MaskSize(lpbi));	/////fixed by countercloc 
} 
 
 
/************************************************************************* 
 * 
 * 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)); 
} 
/********************************************************************* 
 * MaskSize() 
 * 
 * Parameter: 
 * 
 * LPSTR lpbi       - pointer to packed-DIB memory block 
 * 
 * Return Value: 
 * 
 * WORD             - size of the color mask of the DIB 
 * 
 * Description: 
 * 
 
 * History:   Date      Author               
 *            2/08/02   ÚùêÆ³©          
 * 
 **********************************************************************/ 
WORD WINAPI MaskSize(LPSTR lpbi) 
{ 
	return ((LPBITMAPINFOHEADER)lpbi)->biCompression==BI_BITFIELDS?12:0; 
} 
/// 
/************************************************************************* 
 * 
 * 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; 
} 
 
// 
//  Source file for Device-Independent Bitmap (DIB) API.  Provides 
//  the following functions: 
// 
//  SaveDIB()           - Saves the specified dib in a file 
//  ReadDIBFile()       - Loads a DIB from a file 
// 
// 
// This is a part of the Microsoft Foundation Classes C++ library. 
// Copyright (C) 1992-1998 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  
#include  
#include  
#include "dibapi.h" 
 
/* 
 * Dib Header Marker - used in writing DIBs to files 
 */ 
#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B') 
 
 
/************************************************************************* 
 * 
 * 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 
 * 
 *************************************************************************/ 
 
 
/************************************************************************* 
 
  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(HANDLE hFile) 
{ 
	BITMAPFILEHEADER bmfHeader; 
	DWORD dwBitsSize,dwRead; 
	HDIB hDIB; 
	LPSTR pDIB; 
 
	/* 
	 * get length of DIB in bytes for use when reading 
	 */ 
 
	dwBitsSize = GetFileSize(hFile,NULL); 
 
	/* 
	 * Go read the DIB file header and check if it's valid. 
	 */ 
	ReadFile(hFile,&bmfHeader,sizeof(BITMAPFILEHEADER),&dwRead,NULL); 
	if (dwRead!= sizeof(bmfHeader)) 
		return NULL; 
 
	if (bmfHeader.bfType != DIB_HEADER_MARKER) 
		return NULL; 
 
	/* 
	 * Allocate memory for DIB 
	 */ 
	hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); 
	if (hDIB == 0) 
	{ 
		return NULL; 
	} 
	pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
 
	/* 
	 * Go read the bits. 
	 */ 
	ReadFile(hFile,pDIB,dwBitsSize - sizeof(BITMAPFILEHEADER),&dwRead,NULL); 
	if (dwRead!= 
		dwBitsSize - sizeof(BITMAPFILEHEADER) ) 
	{ 
		::GlobalUnlock((HGLOBAL) hDIB); 
		::GlobalFree((HGLOBAL) hDIB); 
		return NULL; 
	} 
	::GlobalUnlock((HGLOBAL) hDIB); 
	return hDIB; 
} 
 
/**************************************************************************** 
* 
*     FUNCTION: ConvertDIBFormat 
* 
*     PURPOSE:  Creates a new DIB of the requested format, copies the source 
*               image to the new DIB. 
* 
*     PARAMS:   LPBITMAPINFO lpSrcDIB - the source CF_DIB 
*               UINT         nWidth   - width for new DIB 
*               UINT         nHeight  - height for new DIB 
*               UINT         nbpp     - bpp for new DIB 
*               BOOL         bStretch - TRUE to stretch source to dest 
*                                       FALSE to take upper left of image 
* 
*     RETURNS:  LPBYTE - pointer to new CF_DIB memory block with new image 
*               NULL on failure 
* 
* History: 
*                July '95 - Created 
* 
\****************************************************************************/ 
 
BOOL WINAPI CopyColorTable( LPBITMAPINFO lpTarget, LPBITMAPINFO lpSource ) 
{ 
    // What we do depends on the target's color depth 
    switch( lpTarget->bmiHeader.biBitCount ) 
    { 
        // 8bpp - need 256 entry color table 
        case 8: 
            if( lpSource->bmiHeader.biBitCount == 8 ) 
            { // Source is 8bpp too, copy color table 
                memcpy( lpTarget->bmiColors, lpSource->bmiColors, 256*sizeof(RGBQUAD) ); 
                return TRUE; 
            } 
            else 
            { // Source is != 8bpp, use halftone palette                 
                HPALETTE        hPal; 
                HDC            	hDC = GetDC( NULL ); 
                PALETTEENTRY    pe[256]; 
                UINT            i; 
 
                hPal = CreateHalftonePalette( hDC ); 
                ReleaseDC( NULL, hDC ); 
                GetPaletteEntries( hPal, 0, 256, pe ); 
                DeleteObject( hPal ); 
                for(i=0;i<256;i++) 
                { 
                    lpTarget->bmiColors[i].rgbRed = pe[i].peRed; 
                    lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen; 
                    lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue; 
                    lpTarget->bmiColors[i].rgbReserved = pe[i].peFlags; 
                } 
                return TRUE; 
            } 
        break; // end 8bpp 
 
        // 4bpp - need 16 entry color table 
        case 4: 
            if( lpSource->bmiHeader.biBitCount == 4 ) 
            { // Source is 4bpp too, copy color table 
                memcpy( lpTarget->bmiColors, lpSource->bmiColors, 16*sizeof(RGBQUAD) ); 
                return TRUE; 
            } 
            else 
            { // Source is != 4bpp, use system palette 
                HPALETTE        hPal; 
                PALETTEENTRY    pe[256]; 
                UINT            i; 
 
                hPal =(HPALETTE) GetStockObject( DEFAULT_PALETTE ); 
                GetPaletteEntries( hPal, 0, 16, pe ); 
                for(i=0;i<16;i++) 
                { 
                    lpTarget->bmiColors[i].rgbRed = pe[i].peRed; 
                    lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen; 
                    lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue; 
                    lpTarget->bmiColors[i].rgbReserved = pe[i].peFlags; 
                } 
                return TRUE; 
            } 
        break; // end 4bpp 
 
        // 1bpp - need 2 entry mono color table 
        case 1: 
            lpTarget->bmiColors[0].rgbRed = 0; 
            lpTarget->bmiColors[0].rgbGreen = 0; 
            lpTarget->bmiColors[0].rgbBlue = 0; 
            lpTarget->bmiColors[0].rgbReserved = 0; 
            lpTarget->bmiColors[1].rgbRed = 255; 
            lpTarget->bmiColors[1].rgbGreen = 255; 
            lpTarget->bmiColors[1].rgbBlue = 255; 
            lpTarget->bmiColors[1].rgbReserved = 0; 
        break; // end 1bpp 
 
        // no color table for the > 8bpp modes 
        case 32: 
        case 24: 
        case 16: 
        default: 
            return TRUE; 
        break; 
    } 
    return TRUE; 
} 
/* End CopyColorTable() *****************************************************/ 
HDIB WINAPI ConvertDIBFormat( HDIB hSrcDIB,  UINT nbpp) 
{ 
    LPBITMAPINFO    lpbmi = NULL,lpSrcDIB; 
    LPBYTE        	lpSourceBits, lpTargetBits, lpResult; 
    HDC            	hDC = NULL, hSourceDC, hTargetDC; 
    HBITMAP        	hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; 
    DWORD        	dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize; 
	HDIB			hResult; 
 //////if same bitcount ,then just copy  
	lpSrcDIB=(LPBITMAPINFO)::GlobalLock(hSrcDIB); 
	if(lpSrcDIB->bmiHeader.biBitCount==nbpp){ 
		GlobalUnlock(hSrcDIB); 
		return (HDIB)CopyHandle(hSrcDIB); 
	} 
   // Allocate and fill out a BITMAPINFO struct for the new DIB 
    // Allow enough room for a 256-entry color table, just in case 
    dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( 256 * sizeof( RGBQUAD ) ); 
    lpbmi =(LPBITMAPINFO) malloc( dwTargetHeaderSize ); 
    lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); 
    lpbmi->bmiHeader.biWidth = lpSrcDIB->bmiHeader.biWidth ; 
    lpbmi->bmiHeader.biHeight = lpSrcDIB->bmiHeader.biHeight; 
    lpbmi->bmiHeader.biPlanes = 1; 
    lpbmi->bmiHeader.biBitCount = nbpp; 
    lpbmi->bmiHeader.biCompression = BI_RGB; 
    lpbmi->bmiHeader.biSizeImage = 0; 
    lpbmi->bmiHeader.biXPelsPerMeter = 0; 
    lpbmi->bmiHeader.biYPelsPerMeter = 0; 
    lpbmi->bmiHeader.biClrUsed = 0; 
    lpbmi->bmiHeader.biClrImportant = 0; 
    // Fill in the color table 
    if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB ) ) 
    { 
        free( lpbmi ); 
		::GlobalUnlock(hSrcDIB); 
        return NULL; 
    } 
	///*************FIX******* 
	dwTargetHeaderSize=sizeof(BITMAPINFOHEADER)+DIBNumColors((LPSTR)lpbmi)*sizeof(RGBQUAD); 
	//// 
    // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
    hDC = GetDC( NULL ); 
    hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (void**)&lpTargetBits, NULL, 0 ); 
    hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (void**)&lpSourceBits, NULL, 0 ); 
    hSourceDC = CreateCompatibleDC( hDC ); 
    hTargetDC = CreateCompatibleDC( hDC ); 
 
    // Flip the bits on the source DIBSection to match the source DIB 
    dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine(&(lpSrcDIB->bmiHeader)); 
    dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine(&(lpbmi->bmiHeader)); 
    memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize ); 
 
    // Select DIBSections into DCs 
    hOldSourceBitmap =(HBITMAP) SelectObject( hSourceDC, hSourceBitmap ); 
    hOldTargetBitmap =(HBITMAP) SelectObject( hTargetDC, hTargetBitmap ); 
 
    // Set the color tables for the DIBSections 
    if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) 
        SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); 
    if( lpbmi->bmiHeader.biBitCount <= 8 ) 
        SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); 
 
    // If we are asking for a straight copy, do it 
    BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); 
     // Clean up and delete the DCs 
    SelectObject( hSourceDC, hOldSourceBitmap ); 
    SelectObject( hSourceDC, hOldTargetBitmap ); 
    DeleteDC( hSourceDC ); 
    DeleteDC( hTargetDC ); 
    ReleaseDC( NULL, hDC ); 
 
    // Flush the GDI batch, so we can play with the bits 
    GdiFlush(); 
 
    // Allocate enough memory for the new CF_DIB, and copy bits 
	hResult =(HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwTargetHeaderSize + dwTargetBitsSize); 
    if(hResult==NULL){ 
		::GlobalUnlock((HGLOBAL) hSrcDIB);	 
		return NULL; 
	} 
	lpResult = (LPBYTE)GlobalLock(hResult); 
    memcpy( lpResult, lpbmi, dwTargetHeaderSize ); 
    memcpy( FindDIBBits((LPSTR) lpResult ), lpTargetBits, dwTargetBitsSize ); 
 
    // final cleanup 
    DeleteObject( hTargetBitmap ); 
    DeleteObject( hSourceBitmap ); 
    free( lpbmi ); 
	::GlobalUnlock((HGLOBAL) hResult); 
	::GlobalUnlock((HGLOBAL) hSrcDIB); 
    return hResult; 
} 
/* End ConvertDIBFormat() ***************************************************/ 
/************************************************************************* 
 * 
 * CreateDIB() 
 * 
 * Parameters: 
 * 
 * DWORD dwWidth    - Width for new bitmap, in pixels 
 * DWORD dwHeight   - Height for new bitmap  
 * WORD  wBitCount  - Bit Count for new DIB (1, 4, 8, or 24) 
 * 
 * Return Value: 
 * 
 * HDIB             - Handle to new DIB 
 * 
 * Description: 
 * 
 * This function allocates memory for and initializes a new DIB by 
 * filling in the BITMAPINFOHEADER, allocating memory for the color 
 * table, and allocating memory for the bitmap bits.  As with all 
 * HDIBs, the header, colortable and bits are all in one contiguous 
 * memory block.  This function is similar to the CreateBitmap()  
 * Windows API. 
 * 
 * The colortable and bitmap bits are left uninitialized (zeroed) in the 
 * returned HDIB. 
 * 
 * 
 * History:   Date      Author              Reason 
 *            3/20/92   Mark Bader          Created 
 * 
 ************************************************************************/ 
HDIB WINAPI CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount) 
{ 
    BITMAPINFOHEADER    bi;             // bitmap header 
    LPBITMAPINFOHEADER  lpbi;           // pointer to BITMAPINFOHEADER 
    DWORD               dwLen;          // size of memory block 
    HDIB                hDIB; 
    DWORD               dwBytesPerLine; // Number of bytes per scanline 
 
 
    // Make sure bits per pixel is valid 
 
    if (wBitCount <= 1) 
        wBitCount = 1; 
    else if (wBitCount <= 4) 
        wBitCount = 4; 
    else if (wBitCount <= 8) 
        wBitCount = 8; 
    else if (wBitCount <= 24) 
        wBitCount = 24; 
    else 
        wBitCount = 4;  // set default value to 4 if parameter is bogus 
 
    // initialize BITMAPINFOHEADER 
 
    bi.biSize = sizeof(BITMAPINFOHEADER); 
    bi.biWidth = dwWidth;         // fill in width from parameter 
    bi.biHeight = dwHeight;       // fill in height from parameter 
    bi.biPlanes = 1;              // must be 1 
    bi.biBitCount = wBitCount;    // from parameter 
    bi.biCompression = BI_RGB;     
    bi.biSizeImage = 0;           // 0's here mean "default" 
    bi.biXPelsPerMeter = 0; 
    bi.biYPelsPerMeter = 0; 
    bi.biClrUsed = 0; 
    bi.biClrImportant = 0; 
 
    // calculate size of memory block required to store the DIB.  This 
    // block should be big enough to hold the BITMAPINFOHEADER, the color 
    // table, and the bits 
 
    dwBytesPerLine = WIDTHBYTES(wBitCount * dwWidth); 
    dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + (dwBytesPerLine * dwHeight); 
 
    // alloc memory block to store our bitmap 
 
    hDIB = (HDIB)GlobalAlloc(GHND, dwLen); 
 
    // major bummer if we couldn't get memory block 
 
    if (!hDIB) 
        return NULL; 
 
    // lock memory and get pointer to it 
 
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); 
 
    // use our bitmap info structure to fill in first part of 
    // our DIB with the BITMAPINFOHEADER 
 
    *lpbi = bi; 
 
    // Since we don't know what the colortable and bits should contain, 
    // just leave these blank.  Unlock the DIB and return the HDIB. 
 
    GlobalUnlock(hDIB); 
 
    //return handle to the DIB 
 
    return hDIB; 
}