www.pudn.com > XRayImg.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 
//  CopyHandle()        - Makes a copy of the given global memory block 
//                        in the DIB's color table 
// 
//  Functions imported by MYFILE.C 
// 
//  SaveDIBFile()       - Saves the specified dib in a file 
//  ReadDIBFile()       - Loads a DIB from a file 
// 
//  Functions developed by Fabio Angelini 
// 
//  CreateLogPalette()  - 
//  DestroyLogPalette() - 
// 
//  BitmapToDIB()       - This function creates a bitmap from a DIB 
//  DIBToBitmap()       - This function creates a DIB from a bitmap  
// 
//  DIBToMemBmpFile()   - 
//  MemBmpFileToDIB()   - 
// 
// This is a part of the Microsoft Foundation Classes C++ library. 
// Copyright (C) 1992-1997 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 "dibapi.h" 
#include  
#include  
#include  
 
#pragma warning(disable:4189) 
 
/* 
 * Dib Header Marker - used in writing DIBs to files 
 */ 
#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B') 
 
#ifdef _MAC 
#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x)) 
#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x))) 
void ByteSwapHeader(BITMAPFILEHEADER* bmiHeader); 
void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header); 
#endif 
 
 
/************************************************************************* 
 * 
 * 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 
 * 
 * BOOL bStretch    - determine whether to stretch  
 * 
 * Return Value: 
 * 
 * BOOL             - TRUE if DIB was drawn, FALSE otherwise 
 * 
 * Description: 
 * 
 ************************************************************************/ 
 
BOOL WINAPI PaintDIB(HDC     hDC, 
                     LPRECT  lpDCRect, 
                     HDIB    hDIB, 
                     LPRECT  lpDIBRect, 
                     CPalette* pPal, 
                     BOOL    bStretch,LPRECT lpClient ) 
{ 
   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; 
       
	  if( hPal ) hOldPal = ::SelectPalette(hDC, hPal, FALSE); 
      ::RealizePalette(hDC); 
   } 
    
   /* Microsoft version always uses ::SetStretchBltMode(hDC, COLORONCOLOR); */ 
   /* Make sure to use the stretching mode best for color pictures          */ 
   ::SetStretchBltMode(hDC, COLORONCOLOR);                                
    
	//center display if clientRect>scrollRect...  
    // 徐卫华添加 2005.8.29 
    long iDesLeft=lpDCRect->left,iDesTop=lpDCRect->top;	 
	if(lpClient!=NULL)  
	{		 
		if( RECTWIDTH(lpClient) > RECTWIDTH(lpDCRect) ) 
		{ 
			iDesLeft+=(long)( RECTWIDTH(lpClient) - RECTWIDTH(lpDCRect) )/2; 
		}	 
		if( RECTHEIGHT(lpClient) > RECTHEIGHT(lpDCRect) ) 
		{ 
			iDesTop+=(long)( RECTHEIGHT(lpClient) -RECTHEIGHT(lpDCRect) )/2; 
		} 
	} 
 
    /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */    
   if ( bStretch == FALSE )  
   { 
	  bSuccess = ::SetDIBitsToDevice(hDC,      // hDC 
		  /*lpDCRect->left*/iDesLeft,             // DestX 
		  /*lpDCRect->top*/iDesTop,              // 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*/iDesLeft,     // DestX 
		   /*lpDCRect->top*/iDesTop,       // 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,FALSE); 
      ::RealizePalette(hDC); 
   } 
    
   return bSuccess; 
} 
 
/************************************************************************* 
* 
* DrawDIB() 
* 
* 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: 
* 
************************************************************************/ 
                      
BOOL WINAPI DrawDIB(HDC     hDC, 
                    LPRECT  lpDCRect, 
                    HDIB    hDIB, 
                    LPRECT  lpDIBRect, 
                    CPalette* pPal,LPRECT lpClientRect) 
{ 
   /* Determine whether to stretch */ 
   if ( (RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect) ) && 
      (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect) ) ) 
   { 
      return PaintDIB(hDC,lpDCRect,hDIB,lpDIBRect,pPal,FALSE,lpClientRect); 
   } 
   else 
   { 
      return PaintDIB(hDC,lpDCRect,hDIB,lpDIBRect,pPal,TRUE,lpClientRect); 
   } 
} 
 
/************************************************************************* 
* 
* 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); 
   } 
   else 
   { 
      CWindowDC dcScreen(NULL); 
       
      if ( dcScreen.GetDeviceCaps(RASTERCAPS) & RC_PALETTE ) 
      { 
         /* create the palette and get handle to it */ 
         bResult = pPal->CreateHalftonePalette(&dcScreen); 
      } 
      else 
      { 
         pPal->DeleteObject(); 
         bResult = TRUE; 
      } 
   } 
    
   ::GlobalUnlock((HGLOBAL) hDIB); 
    
   return bResult; 
} 
 
/************************************************************************* 
* 
* FindDIBBits()	得到dib位图中真正的数据部分指针 
* 
* 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()		dib文件中调色板数量计算 
* 
* 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; 
   } 
}                      
 
/************************************************************************* 
* 
* BitmapToDIB() 
* 
* Parameter: 
* 
* HBITMAP - handle to a Bitmap that the DIB is to be  
*            created from 
* HPALETTE - palette to use in creation of DIB 
* 
* Return Value: 
* 
* HDIB - handle of the DIB created from the Bitmap, NULL 
*        on error 
* 
* Description: 
* 
* Returns an HDIB created from an HBITMAP. 
* This function creates a DIB from a bitmap using the  
* specified palette. 
************************************************************************/ 
 
HDIB WINAPI BitmapToDIB(HBITMAP hBitmap, HPALETTE hPal) 
{ 
   ASSERT(hBitmap); 
    
   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 
   UINT wLineLen; 
   DWORD dwSize; 
   DWORD wColSize; 
    
   // 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), &bm)) 
   { 
      return NULL; 
   } 
    
   // if no palette is specified, use default palette 
   if (hPal == NULL) 
      hPal = (HPALETTE)::GetStockObject(DEFAULT_PALETTE); 
    
   // calculate bits per pixel 
   biBits = (WORD) (bm.bmPlanes * bm.bmBitsPixel); 
    
   wLineLen = ( bm.bmWidth * biBits + 31 ) / 32 * 4; 
   wColSize = sizeof(RGBQUAD) * (( biBits <= 8 ) ?  
      1 << biBits : 0 ); 
   dwSize = sizeof( BITMAPINFOHEADER ) + wColSize + 
      (DWORD)(UINT)wLineLen * (DWORD)(UINT)bm.bmHeight; 
    
   // 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 = dwSize - sizeof(BITMAPINFOHEADER) - wColSize; 
   bi.biXPelsPerMeter = 0; 
   bi.biYPelsPerMeter = 0; 
   bi.biClrUsed = ( biBits <= 8 ) ? 1 << biBits : 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((HGLOBAL)hDib); 
   if (!lpbi) 
   { 
      // clean up and return NULL 
      ::SelectPalette(hDC, hPal, TRUE); 
      ::RealizePalette(hDC); 
      ::ReleaseDC(NULL, hDC); 
       
      return NULL; 
   } 
    
   // 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, (WORD)bi.biHeight, NULL,  
      (LPBITMAPINFO)lpbi, DIB_RGB_COLORS); 
    
   // get the info. returned by GetDIBits and unlock  
   // memory block 
   bi = *lpbi; 
   bi.biClrUsed = ( biBits <= 8 ) ? 1 << biBits : 0; 
   ::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; 
   h = (HDIB)::GlobalReAlloc(hDib, dwLen, 0); 
   if ( h ) 
   { 
      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((HGLOBAL)hDib); 
   if (!lpbi) 
   { 
      // clean up and return NULL 
      ::GlobalFree(hDib); 
      hDib = NULL; 
       
      ::SelectPalette(hDC, hPal, TRUE); 
      ::RealizePalette(hDC); 
      ::ReleaseDC(NULL, hDC); 
       
      return NULL; 
   } 
    
   // call GetDIBits with a NON-NULL lpBits param, and  
   // actualy get the bits this time 
   if (::GetDIBits(hDC, hBitmap, 0, (WORD)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; 
} 
 
/************************************************************************* 
* 
* DIBToBitmap() 
* 
* Parameters: 
* HDIB - handle to a DIB that the Bitmap (DDB) is to be  
*        created from 
* 
* HPALETTE - palette to use in creation of bitmap (DDB) 
* 
* Return Value: 
* 
* HBITMAP - handle of the Bitmap created from the DIB, 
*           NULL on error 
* Description: 
* 
* Returns an HBITMAP created from an HDIB. 
* This function creates a bitmap from a DIB using the  
* specified palette. If no palette is specified, one is  
* created, used for the conversion, and then deleted. 
* 
* 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. 
* 
* if your application requires a monochrome HBITMAP  
* returned for a monochrome DIB, use the function SetDIBits(). 
************************************************************************/ 
 
HBITMAP WINAPI DIBToBitmap(HDIB hDib, HPALETTE hPal) 
{ 
   ASSERT(hDib); 
    
   LPVOID lpDIBHdr = NULL;  // pointer to DIB header 
   LPVOID lpDIBBits = NULL; // pointer to DIB bits 
   HBITMAP hBitmap = NULL;  // handle to DDB 
   HDC hDC = NULL;          // handle to DC 
   HPALETTE hOldPal = NULL; // handle to a palette 
   BOOL bPalCreated = FALSE; 
    
   // if invalid handle, return NULL 
   if (!hDib) 
   { 
      return NULL; 
   } 
    
   // lock memory block and get a pointer to it 
   lpDIBHdr = ::GlobalLock((HGLOBAL)hDib); 
   if (!lpDIBHdr) 
   { 
      return NULL; 
   } 
    
   // get a pointer to the DIB bits 
   lpDIBBits = ::FindDIBBits((LPSTR) lpDIBHdr); 
   if (!lpDIBBits) 
      return NULL; 
    
   // get a DC 
   hDC = ::GetDC(NULL); 
   if (!hDC) 
   { 
      // clean up and return NULL 
      ::GlobalUnlock(hDib); 
       
      return NULL; 
   } 
    
   // select and realize palette 
   if (!hPal) 
   { 
      CPalette    DibPal;  
      CreateDIBPalette(hDib,&DibPal); 
      hPal = (HPALETTE) DibPal.Detach(); 
      bPalCreated = TRUE; 
   } 
   hOldPal = ::SelectPalette(hDC, hPal, FALSE); 
   ::RealizePalette(hDC); 
    
   // create bitmap from DIB info. and bits 
   hBitmap = ::CreateDIBitmap(hDC, (LPBITMAPINFOHEADER)lpDIBHdr,  
      CBM_INIT, lpDIBBits, (LPBITMAPINFO)lpDIBHdr,  
      DIB_RGB_COLORS); 
   if (!hBitmap) 
   { 
      if (hOldPal) 
         ::SelectPalette(hDC, hOldPal, FALSE); 
      ::DeleteObject(hPal); 
      return NULL; 
   } 
    
   // restore previous palette 
   if (hOldPal) 
      ::SelectPalette(hDC, hOldPal, FALSE); 
    
   // if we created the palette then we clean it up 
   if (bPalCreated && hPal) 
      ::DeleteObject(hPal); 
    
   // clean up 
   ::ReleaseDC(NULL, hDC); 
   ::GlobalUnlock(hDib); 
    
   // return handle to the bitmap 
   return hBitmap; 
} 
 
/************************************************************************* 
* 
* 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 | GMEM_DDESHARE, dwLen); 
    
   if (hCopy != NULL) 
   { 
      void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); 
      void* lp     = ::GlobalLock((HGLOBAL) h); 
      memcpy(lpCopy, lp, dwLen); 
      ::GlobalUnlock(hCopy); 
      ::GlobalUnlock(h); 
   } 
    
   return hCopy; 
} 
 
 
LOGPALETTE* WINAPI CreateLogPalette( HPALETTE  hPal ) 
{ 
   if ( hPal ) 
   { 
      UINT NumEntries = ::GetPaletteEntries( hPal, 0, 0, NULL ); 
      UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * NumEntries); 
      LOGPALETTE *pLP = (LOGPALETTE *) malloc(nSize); 
       
      pLP->palVersion = PALVERSION; 
      pLP->palNumEntries = (USHORT) ::GetPaletteEntries( hPal, 0, NumEntries, pLP->palPalEntry ); 
      return pLP; 
   } 
   return NULL; 
} 
 
void WINAPI DestroyLogPalette( LOGPALETTE* pLP ) 
{ 
   if ( pLP != NULL ) 
      free(pLP); 
} 
 
 
/************************************************************************* 
* 
* SaveDIBFile() 
* 
* 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 SaveDIBFile(HDIB hDib, CFile& file) 
{ 
   BITMAPFILEHEADER bmfHdr; // Header for Bitmap file 
   LPBITMAPINFOHEADER lpBI;   // Pointer to DIB info structure 
   DWORD dwDIBSize; 
    
   if (hDib == NULL) 
      return FALSE; 
    
      /* 
      * Get a pointer to the DIB memory, the first of which contains 
      * a BITMAPINFO structure 
   */ 
   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) 
   } 
    
   /* 
   * Fill in the fields of the file header 
   */ 
    
   /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */ 
   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. 
    
   dwDIBSize = *(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 
       
      dwDIBSize += 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; 
       
      dwDIBSize += 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 = dwDIBSize + sizeof(BITMAPFILEHEADER); 
   bmfHdr.bfReserved1 = 0; 
   bmfHdr.bfReserved2 = 0; 
    
   /* 
   * Now, calculate the offset the actual bitmap bits will be in 
   * the file -- It's the Bitmap file header plus the DIB header, 
   * plus the size of the color table. 
   */ 
   bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize 
      + PaletteSize((LPSTR)lpBI); 
#ifdef _MAC 
   ByteSwapHeader(&bmfHdr); 
    
   // First swap the size field 
   *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI)); 
    
   // Now swap the rest of the structure (we don't save < Win30 files) 
   ByteSwapInfo((LPSTR)lpBI, TRUE); 
#endif 
    
   TRY 
   { 
      // Write the file header 
      file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); 
      // 
      // Write the DIB header and the bits 
      // 
      file.WriteHuge(lpBI, dwDIBSize); 
   } 
   CATCH (CFileException, e) 
   { 
#ifdef _MAC 
      // Swap everything back 
      *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI)); 
      ByteSwapInfo((LPSTR)lpBI, TRUE); 
#endif 
      ::GlobalUnlock((HGLOBAL) hDib); 
      THROW_LAST(); 
   } 
   END_CATCH 
       
#ifdef _MAC 
      // Swap everything back 
      *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI)); 
   ByteSwapInfo((LPSTR)lpBI, TRUE); 
#endif 
    
   ::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(CFile& file) 
{ 
   BITMAPFILEHEADER bmfHeader; 
   DWORD dwBitsSize; 
   HDIB hDIB; 
   LPSTR pDIB; 
    
   /* 
   * get length of DIB in bytes for use when reading 
   */ 
    
   dwBitsSize = file.GetLength() - file.GetPosition(); 
    
   /* 
   * Go read the DIB file header and check if it's valid. 
   */ 
   if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) 
      return NULL; 
    
#ifdef _MAC 
   ByteSwapHeader(&bmfHeader); 
#endif 
   if (bmfHeader.bfType != DIB_HEADER_MARKER) 
      return NULL; 
    
      /* 
      * Allocate memory for DIB 
   */ 
   hDIB = (HDIB) ::GlobalAlloc(GHND, dwBitsSize); 
   if (hDIB == 0) 
   { 
      return NULL; 
   } 
   pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
    
   /* 
   * Go read the bits. 
   */ 
   if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != 
      dwBitsSize - sizeof(BITMAPFILEHEADER) ) 
   { 
      ::GlobalUnlock((HGLOBAL) hDIB); 
      ::GlobalFree((HGLOBAL) hDIB); 
      return NULL; 
   } 
#ifdef _MAC 
   // First swap the size field 
   *((LPDWORD)pDIB) = SWAPLONG(*((LPDWORD)pDIB)); 
    
   // Now swap the rest of the structure 
   ByteSwapInfo(pDIB, IS_WIN30_DIB(pDIB)); 
#endif 
   ::GlobalUnlock((HGLOBAL) hDIB); 
   return hDIB; 
} 
 
#ifdef _MAC 
void ByteSwapHeader(BITMAPFILEHEADER* bmfHeader) 
{ 
   bmfHeader->bfType = SWAPWORD(bmfHeader->bfType); 
   bmfHeader->bfSize = SWAPLONG(bmfHeader->bfSize); 
   bmfHeader->bfOffBits = SWAPLONG(bmfHeader->bfOffBits); 
} 
 
 
void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header) 
{ 
   // Note this doesn't swap the bcSize/biSize field.  It assumes that the 
   // size field was swapped during read or while setting the fWin30Header 
   // flag. 
    
   if (fWin30Header) 
   { 
      LPBITMAPINFOHEADER lpBMIH = &(LPBITMAPINFO(lpHeader)->bmiHeader); 
       
      //lpBMIH->biSize = SWAPLONG(lpBMIH->biSize); 
      lpBMIH->biWidth = SWAPLONG(lpBMIH->biWidth); 
      lpBMIH->biHeight = SWAPLONG(lpBMIH->biHeight); 
      lpBMIH->biPlanes = SWAPWORD(lpBMIH->biPlanes); 
      lpBMIH->biBitCount = SWAPWORD(lpBMIH->biBitCount); 
      lpBMIH->biCompression = SWAPLONG(lpBMIH->biCompression); 
      lpBMIH->biSizeImage = SWAPLONG(lpBMIH->biSizeImage); 
      lpBMIH->biXPelsPerMeter = SWAPLONG(lpBMIH->biXPelsPerMeter); 
      lpBMIH->biYPelsPerMeter = SWAPLONG(lpBMIH->biYPelsPerMeter); 
      lpBMIH->biClrUsed = SWAPLONG(lpBMIH->biClrUsed); 
      lpBMIH->biClrImportant = SWAPLONG(lpBMIH->biClrImportant); 
   } 
   else 
   { 
      LPBITMAPCOREHEADER lpBMCH = &(LPBITMAPCOREINFO(lpHeader)->bmciHeader); 
       
      lpBMCH->bcWidth = SWAPWORD(lpBMCH->bcWidth); 
      lpBMCH->bcHeight = SWAPWORD(lpBMCH->bcHeight); 
      lpBMCH->bcPlanes = SWAPWORD(lpBMCH->bcPlanes); 
      lpBMCH->bcBitCount = SWAPWORD(lpBMCH->bcBitCount); 
   } 
} 
 
#endif 
 
/************************************************************************* 
* 
* DIBToMemBmpFile() 
* 
* Parameter: 
* 
* HDIB - handle to a DIB that the Memory Bitmap File (MBF) is to be  
*        created from 
* 
* Return Value: 
* 
* HMEMBMPFILE - Handle to new global memory block rapresenting an 
*               image of a bitmap file, NULL on error 
* 
* Description: 
* 
************************************************************************/ 
                 
HMEMBMPFILE WINAPI DIBToMemBmpFile(HDIB hDib)  
{ 
   CSharedFile file; 
   try 
   { 
      if ( SaveDIBFile( hDib, file ) == 0 ) 
         return NULL; 
   } 
   catch (CFileException* e) 
   { 
      e->Delete(); 
      return 0; 
   } 
    
   return (HMEMBMPFILE) file.Detach(); 
} 
 
/************************************************************************* 
* 
* MemBmpFileToDIB() 
* 
* Parameter: 
* 
* HMEMBMPFILE - handle to Memory Bitmap File (MBF) that the DIB is to be  
*               created from 
* 
* Return Value: 
* 
* HDIB - Handle to new global memory block, NULL on error 
* 
* Description: 
* 
************************************************************************/ 
 
HDIB WINAPI MemBmpFileToDIB(HMEMBMPFILE hMemBmpFile) 
{ 
   CSharedFile file; 
   file.SetHandle(hMemBmpFile, FALSE); 
   HDIB hDib = ReadDIBFile(file); 
   file.Detach(); 
   return hDib; 
} 
 
/************************************************************************* 
* 
* WindowToDIB() 
* 
* Parameter: 
* 
* CWnd*    - ... 
* 
* Return Value: 
* 
* HDIB - Handle to new global memory block, NULL on error 
* 
* Description: 
* 
************************************************************************/ 
 
HDIB WINAPI WindowToDIB(CWnd *pWnd, CRect* pScreenRect) 
{ 
   CBitmap 	   bitmap; 
   CWindowDC	dc(pWnd); 
   CDC 		   memDC; 
   CRect		   rect; 
    
   memDC.CreateCompatibleDC(&dc);  
    
   if ( pScreenRect == NULL ) 
      pWnd->GetWindowRect(rect); 
   else 
      rect = *pScreenRect; 
    
   bitmap.CreateCompatibleBitmap(&dc, rect.Width(),rect.Height() ); 
    
   CBitmap* pOldBitmap = memDC.SelectObject(&bitmap); 
   memDC.BitBlt(0, 0, rect.Width(),rect.Height(), &dc, rect.left, rect.top, SRCCOPY);  
    
   // Create logical palette if device support a palette 
   CPalette pal; 
   if ( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE ) 
   { 
      UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * MAXPALCOLORS); 
      LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize]; 
      pLP->palVersion = PALVERSION; 
       
      pLP->palNumEntries = (USHORT) GetSystemPaletteEntries( dc, 0, MAXPALCOLORS-1, pLP->palPalEntry ); 
       
      // Create the palette 
      pal.CreatePalette( pLP ); 
       
      delete[] pLP; 
   } 
    
   memDC.SelectObject(pOldBitmap); 
    
   HDIB hDib = BitmapToDIB( bitmap, pal ); 
    
   return hDib; 
}