1 /******************************************************************************* 
   5  *  DESCRIPTION : Routines for dealing with Device Independent Bitmaps.        * 
   9  *                ReadDIB()           - Reads a DIB                            * 
  11  *                WriteDIB()          - Writes a global handle in CF_DIB format* 
  14  *                PaletteSize()       - Calculates the palette size in bytes   * 
  17  *                DibNumColors()      - Determines the number of colors in DIB * 
  19  *                DibFromBitmap()     - Creates a DIB repr. the DDB passed in. * 
  22  *                lread()             - Private routine to read more than 64k  * 
  24  *                lwrite()            - Private routine to write more than 64k * 
  26  *******************************************************************************/ 
  28 // For compilers that support precompilation, includes "wx.h". 
  29 #include "wx/wxprec.h" 
  31 #if defined(__BORLANDC__) 
  38 #include "wx/bitmap.h" 
  45 #if !defined(__MWERKS__) && !defined(__SALFORDC__) 
  49 #include "wx/msw/dib.h" 
  53 #include "wx/msw/gnuwin32/extra.h" 
  58 /* flags for _lseek */ 
  64 #define MAXREAD  32768                           /* Number of bytes to be read during */ 
  65                                                  /* each read operation.                         */ 
  67 /* Header signatutes for various resources */ 
  68 #define BFT_ICON         0x4349  /* 'IC' */ 
  69 #define BFT_BITMAP 0x4d42        /* 'BM' */ 
  70 #define BFT_CURSOR 0x5450        /* 'PT' */ 
  72 /* macro to determine if resource is a DIB */ 
  73 #define ISDIB(bft) ((bft) == BFT_BITMAP) 
  75 /* Macro to align given value to the closest DWORD (unsigned long ) */ 
  76 #define ALIGNULONG(i)   ((i+3)/4*4) 
  78 /* Macro to determine to round off the given value to the closest byte */ 
  79 #define WIDTHBYTES(i)   ((i+31)/32*4) 
  81 #define PALVERSION              0x300 
  82 #define MAXPALETTE      256       /* max. # supported palette entries */ 
  84 DWORD PASCAL 
lread(int fh
, VOID FAR 
*pv
, DWORD ul
); 
  85 DWORD PASCAL 
lwrite(int fh
, VOID FAR 
*pv
, DWORD ul
); 
  87 BOOL             
WriteDIB (LPSTR szFile
,HANDLE hdib
); 
  88 WORD             
PaletteSize (VOID FAR 
* pv
); 
  89 WORD             
DibNumColors (VOID FAR 
* pv
); 
  90 // HANDLE                DibFromBitmap (HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal); 
  91 BOOL             PASCAL 
MakeBitmapAndPalette(HDC
,HANDLE
,HPALETTE 
*,HBITMAP 
*); 
  92 HPALETTE 
MakeDIBPalette(LPBITMAPINFOHEADER
); 
  93 BOOL             
ReadDIB(LPSTR lpFileName
, HBITMAP 
*bitmap
, HPALETTE 
*palette
); 
  95 /**************************************************************************** 
  97  *  FUNCTION   : WriteDIB(LPSTR szFile,HANDLE hdib)                         * 
  99  *  PURPOSE    : Write a global handle in CF_DIB format to a file.          * 
 101  *  RETURNS    : TRUE  - if successful.                                     * 
 102  *               FALSE - otherwise                                          * 
 104  ****************************************************************************/ 
 106 BOOL 
WriteDIB(LPSTR szFile
, HANDLE hdib
) 
 108         BITMAPFILEHEADER        hdr
; 
 109         LPBITMAPINFOHEADER  lpbi
; 
 116         fh 
= OpenFile(szFile
, &of
, OF_CREATE 
| OF_READWRITE
); 
 120 #ifdef __WINDOWS_386__ 
 121         lpbi 
= (LPBITMAPINFOHEADER
) MK_FP32(GlobalLock(hdib
)); 
 123         lpbi 
= (LPBITMAPINFOHEADER
) GlobalLock(hdib
); 
 125     /* Fill in the fields of the file header */ 
 126         hdr
.bfType 
= BFT_BITMAP
; 
 127         hdr
.bfSize 
= GlobalSize(hdib
) + sizeof(BITMAPFILEHEADER
); 
 130         hdr
.bfOffBits 
= (DWORD
) sizeof(BITMAPFILEHEADER
) + lpbi
->biSize 
+ 
 133     /* Write the file header */ 
 134         _lwrite(fh
, (LPSTR
) &hdr
, sizeof(BITMAPFILEHEADER
)); 
 136     /* Write the DIB header and the bits */ 
 137         lwrite(fh
, (LPSTR
) lpbi
, GlobalSize(hdib
)); 
 144 /**************************************************************************** 
 146  *  FUNCTION   :  PaletteSize(VOID FAR * pv)                                * 
 148  *  PURPOSE    :  Calculates the palette size in bytes. If the info. block  * 
 149  *                is of the BITMAPCOREHEADER type, the number of colors is  * 
 150  *                multiplied by 3 to give the palette size, otherwise the   * 
 151  *                number of colors is multiplied by 4.                                                          * 
 153  *  RETURNS    :  Palette size in number of bytes.                          * 
 155  ****************************************************************************/ 
 157 WORD 
PaletteSize(VOID FAR 
* pv
) 
 159         LPBITMAPINFOHEADER lpbi
; 
 162         lpbi 
= (LPBITMAPINFOHEADER
) pv
; 
 163         NumColors 
= DibNumColors(lpbi
); 
 165         if (lpbi
->biSize 
== sizeof(BITMAPCOREHEADER
)) 
 166                 return NumColors 
* sizeof(RGBTRIPLE
); 
 168                 return NumColors 
* sizeof(RGBQUAD
); 
 171 /**************************************************************************** 
 173  *  FUNCTION   : DibNumColors(VOID FAR * pv)                                * 
 175  *  PURPOSE    : Determines the number of colors in the DIB by looking at   * 
 176  *               the BitCount filed in the info block.                      * 
 178  *  RETURNS    : The number of colors in the DIB.                           * 
 180  ****************************************************************************/ 
 182 WORD 
DibNumColors(VOID FAR 
*pv
) 
 185         BITMAPINFOHEADER        
*lpbi
; 
 186         BITMAPCOREHEADER        
*lpbc
; 
 188         lpbi 
= ((BITMAPINFOHEADER
*) pv
); 
 189         lpbc 
= ((BITMAPCOREHEADER
*) pv
); 
 191     /*  With the BITMAPINFO format headers, the size of the palette 
 192      *  is in biClrUsed, whereas in the BITMAPCORE - style headers, it 
 193      *  is dependent on the bits per pixel ( = 2 raised to the power of 
 196         if (lpbi
->biSize 
!= sizeof(BITMAPCOREHEADER
)) { 
 197                 if (lpbi
->biClrUsed 
!= 0) 
 198                         return (WORD
) lpbi
->biClrUsed
; 
 199                 bits 
= lpbi
->biBitCount
; 
 202                 bits 
= lpbc
->bcBitCount
; 
 212                 /* A 24 bitcount DIB has no color table */ 
 217 /**************************************************************************** 
 219  *  FUNCTION   : DibFromBitmap()                                            * 
 221  *  PURPOSE    : Will create a global memory block in DIB format that       * 
 222  *               represents the Device-dependent bitmap (DDB) passed in.    * 
 224  *  RETURNS    : A handle to the DIB                                        * 
 226  ****************************************************************************/ 
 229 HANDLE 
DibFromBitmap(HBITMAP hbm
, DWORD biStyle
, WORD biBits
, HPALETTE hpal
) 
 233         BITMAPINFOHEADER FAR 
*lpbi
; 
 243                 hpal 
= GetStockObject(DEFAULT_PALETTE
); 
 245         GetObject(hbm
, sizeof (bm
), (LPSTR
) &bm
); 
 248                 biBits 
= bm
.bmPlanes 
* bm
.bmBitsPixel
; 
 250         bi
.biSize 
= sizeof(BITMAPINFOHEADER
); 
 251         bi
.biWidth 
= bm
.bmWidth
; 
 252         bi
.biHeight 
= bm
.bmHeight
; 
 254         bi
.biBitCount 
= biBits
; 
 255         bi
.biCompression 
= biStyle
; 
 257         bi
.biXPelsPerMeter 
= 0; 
 258         bi
.biYPelsPerMeter 
= 0; 
 260         bi
.biClrImportant 
= 0; 
 262         dwLen 
= bi
.biSize 
+ PaletteSize(&bi
); 
 264         hdc 
= GetDC((HWND
) NULL
); 
 265         hpal 
= SelectPalette(hdc
, hpal
, FALSE
); 
 268         hdib 
= GlobalAlloc(GHND
, dwLen
); 
 271                 SelectPalette(hdc
, hpal
, FALSE
); 
 272                 ReleaseDC(NULL
, hdc
); 
 276 #ifdef __WINDOWS_386__ 
 277         lpbi 
= (BITMAPINFOHEADER FAR 
*) MK_FP32(GlobalLock(hdib
)); 
 279         lpbi 
= (BITMAPINFOHEADER FAR 
*) GlobalLock(hdib
); 
 284     /*  call GetDIBits with a NULL lpBits param, so it will calculate the 
 285      *  biSizeImage field for us 
 287         GetDIBits(hdc
, hbm
, 0, (WORD
) bi
.biHeight
, 
 288                  NULL
, (LPBITMAPINFO
) lpbi
, DIB_RGB_COLORS
); 
 293     /* If the driver did not fill in the biSizeImage field, make one up */ 
 294         if (bi
.biSizeImage 
== 0) { 
 295                 bi
.biSizeImage 
= WIDTHBYTES((DWORD
)bm
.bmWidth 
* biBits
) * bm
.bmHeight
; 
 297                 if (biStyle 
!= BI_RGB
) 
 298                         bi
.biSizeImage 
= (bi
.biSizeImage 
* 3) / 2; 
 301     /*  realloc the buffer big enough to hold all the bits */ 
 302         dwLen 
= bi
.biSize 
+ PaletteSize(&bi
) + bi
.biSizeImage
; 
 303         if (h 
= GlobalReAlloc(hdib
, dwLen
, 0)) 
 309                 SelectPalette(hdc
, hpal
, FALSE
); 
 310                 ReleaseDC(NULL
, hdc
); 
 314     /*  call GetDIBits with a NON-NULL lpBits param, and actualy get the 
 317 #ifdef __WINDOWS_386__ 
 318         lpbi 
= (BITMAPINFOHEADER FAR 
*) MK_FP32(GlobalLock(hdib
)); 
 320         lpbi 
= (BITMAPINFOHEADER FAR 
*) GlobalLock(hdib
); 
 327                  (LPSTR
) lpbi 
+ (WORD
) lpbi
->biSize 
+ PaletteSize(lpbi
), 
 328                  (LPBITMAPINFO
) lpbi
, DIB_RGB_COLORS
) == 0) { 
 331                 SelectPalette(hdc
, hpal
, FALSE
); 
 332                 ReleaseDC((HWND
) NULL
, hdc
); 
 339         SelectPalette(hdc
, hpal
, FALSE
); 
 340         ReleaseDC(NULL
, hdc
); 
 345  /************* PRIVATE ROUTINES TO READ/WRITE MORE THAN 64K ***************/ 
 346 /**************************************************************************** 
 348  *  FUNCTION   : lread(int fh, VOID FAR *pv, DWORD ul)                      * 
 350  *  PURPOSE    : Reads data in steps of 32k till all the data has been read.* 
 352  *  RETURNS    : 0 - If read did not proceed correctly.                     * 
 353  *               number of bytes read otherwise.                            * 
 355  ****************************************************************************/ 
 357 DWORD PASCAL 
lread(int fh
, void far 
*pv
, DWORD ul
) 
 360 #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__) 
 361         BYTE 
*hp 
= (BYTE 
*) pv
; 
 363         BYTE huge 
*hp 
= (BYTE huge 
*) pv
; 
 365         while (ul 
> (DWORD
) MAXREAD
) { 
 366                 if (_lread(fh
, (LPSTR
) hp
, (WORD
) MAXREAD
) != MAXREAD
) 
 371         if (_lread(fh
, (LPSTR
) hp
, (WORD
) ul
) != (WORD
) ul
) 
 376 /**************************************************************************** 
 378  *  FUNCTION   : lwrite(int fh, VOID FAR *pv, DWORD ul)                     * 
 380  *  PURPOSE    : Writes data in steps of 32k till all the data is written.  * 
 382  *  RETURNS    : 0 - If write did not proceed correctly.                    * 
 383  *               number of bytes written otherwise.                         * 
 385  ****************************************************************************/ 
 387 DWORD PASCAL 
lwrite(int fh
, VOID FAR 
*pv
, DWORD ul
) 
 390 #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__) 
 391         BYTE 
*hp 
= (BYTE 
*) pv
; 
 393         BYTE huge 
*hp 
= (BYTE huge 
*) pv
; 
 395         while (ul 
> MAXREAD
) { 
 396                 if (_lwrite(fh
, (LPSTR
) hp
, (WORD
) MAXREAD
) != MAXREAD
) 
 401         if (_lwrite(fh
, (LPSTR
) hp
, (WORD
) ul
) != (WORD
) ul
) 
 406 /**************************************************************************** 
 408  *  FUNCTION   : ReadDIB(hWnd) 
 410  *  PURPOSE    : Reads a DIB from a file, obtains a handle to its 
 411  *               BITMAPINFO struct. and loads the DIB.  Once the DIB 
 412  *               is loaded, the function also creates a bitmap and 
 413  *               palette out of the DIB for a device-dependent form. 
 415  *  RETURNS    : TRUE  - DIB loaded and bitmap/palette created 
 416  *                       The DIBINIT structure pointed to by pInfo is 
 417  *                       filled with the appropriate handles. 
 420  ****************************************************************************/ 
 421 BOOL 
ReadDIB(LPSTR lpFileName
, HBITMAP 
*bitmap
, HPALETTE 
*palette
) 
 424     LPBITMAPINFOHEADER lpbi
; 
 432     BOOL bCoreHead 
= FALSE
; 
 435     /* Open the file and get a handle to it's BITMAPINFO */ 
 437     fh 
= OpenFile (lpFileName
, &of
, OF_READ
); 
 439         wsprintf(str
,"Can't open file '%s'", lpFileName
); 
 440         MessageBox(NULL
, str
, "Error", MB_ICONSTOP 
| MB_OK
); 
 444     hDIB 
= GlobalAlloc(GHND
, (DWORD
)(sizeof(BITMAPINFOHEADER
) + 
 445                                         256 * sizeof(RGBQUAD
))); 
 449 #ifdef __WINDOWS_386__ 
 450     lpbi 
= (LPBITMAPINFOHEADER
)MK_FP32(GlobalLock(hDIB
)); 
 452     lpbi 
= (LPBITMAPINFOHEADER
)GlobalLock(hDIB
); 
 455     /* read the BITMAPFILEHEADER */ 
 456     if (sizeof (bf
) != _lread (fh
, (LPSTR
)&bf
, sizeof (bf
))) 
 459     if (bf
.bfType 
!= 0x4d42)    /* 'BM' */ 
 462     if (sizeof(BITMAPCOREHEADER
) != _lread (fh
, (LPSTR
)lpbi
, sizeof(BITMAPCOREHEADER
))) 
 465     if (lpbi
->biSize 
== sizeof(BITMAPCOREHEADER
)) 
 467         lpbi
->biSize 
= sizeof(BITMAPINFOHEADER
); 
 468         lpbi
->biBitCount 
= ((LPBITMAPCOREHEADER
)lpbi
)->bcBitCount
; 
 469         lpbi
->biPlanes 
= ((LPBITMAPCOREHEADER
)lpbi
)->bcPlanes
; 
 470         lpbi
->biHeight 
= ((LPBITMAPCOREHEADER
)lpbi
)->bcHeight
; 
 471         lpbi
->biWidth 
= ((LPBITMAPCOREHEADER
)lpbi
)->bcWidth
; 
 476         // get to the start of the header and read INFOHEADER 
 477         _llseek(fh
,sizeof(BITMAPFILEHEADER
),SEEK_SET
); 
 478         if (sizeof(BITMAPINFOHEADER
) != _lread (fh
, (LPSTR
)lpbi
, sizeof(BITMAPINFOHEADER
))) 
 482     nNumColors 
= (WORD
)lpbi
->biClrUsed
; 
 483     if ( nNumColors 
== 0 ) 
 485         /* no color table for 24-bit, default size otherwise */ 
 486         if (lpbi
->biBitCount 
!= 24) 
 487             nNumColors 
= 1 << lpbi
->biBitCount
; /* standard size table */ 
 490     /*  fill in some default values if they are zero */ 
 491     if (lpbi
->biClrUsed 
== 0) 
 492         lpbi
->biClrUsed 
= nNumColors
; 
 494     if (lpbi
->biSizeImage 
== 0) 
 496         lpbi
->biSizeImage 
= ((((lpbi
->biWidth 
* (DWORD
)lpbi
->biBitCount
) + 31) & ~31) >> 3) 
 500     /* get a proper-sized buffer for header, color table and bits */ 
 502     hDIB 
= GlobalReAlloc(hDIB
, lpbi
->biSize 
+ 
 503                                         nNumColors 
* sizeof(RGBQUAD
) + 
 504                                         lpbi
->biSizeImage
, 0); 
 505     if (!hDIB
)  /* can't resize buffer for loading */ 
 508 #ifdef __WINDOWS_386__ 
 509     lpbi 
= (LPBITMAPINFOHEADER
)MK_FP32(GlobalLock(hDIB
)); 
 511     lpbi 
= (LPBITMAPINFOHEADER
)GlobalLock(hDIB
); 
 514     /* read the color table */ 
 516         _lread(fh
, (LPSTR
)(lpbi
) + lpbi
->biSize
, nNumColors 
* sizeof(RGBQUAD
)); 
 521         RGBTRIPLE FAR 
*pTriple
; 
 523         _lread(fh
, (LPSTR
)(lpbi
) + lpbi
->biSize
, nNumColors 
* sizeof(RGBTRIPLE
)); 
 525         pQuad 
= (RGBQUAD FAR 
*)((LPSTR
)lpbi 
+ lpbi
->biSize
); 
 526         pTriple 
= (RGBTRIPLE FAR 
*) pQuad
; 
 527         for (i 
= nNumColors 
- 1; i 
>= 0; i
--) 
 529             pQuad
[i
].rgbRed 
= pTriple
[i
].rgbtRed
; 
 530             pQuad
[i
].rgbBlue 
= pTriple
[i
].rgbtBlue
; 
 531             pQuad
[i
].rgbGreen 
= pTriple
[i
].rgbtGreen
; 
 532             pQuad
[i
].rgbReserved 
= 0; 
 536     /* offset to the bits from start of DIB header */ 
 537     offBits 
= (WORD
)lpbi
->biSize 
+ nNumColors 
* sizeof(RGBQUAD
); 
 539     if (bf
.bfOffBits 
!= 0L) 
 541         _llseek(fh
,bf
.bfOffBits
,SEEK_SET
); 
 544     if (lpbi
->biSizeImage 
== lread(fh
, (LPSTR
)lpbi 
+ offBits
, lpbi
->biSizeImage
)) 
 549         if (!MakeBitmapAndPalette(hDC
, hDIB
, palette
, 
 574 /**************************************************************************** 
 576  *  FUNCTION   : MakeBitmapAndPalette 
 578  *  PURPOSE    : Given a DIB, creates a bitmap and corresponding palette 
 579  *               to be used for a device-dependent representation of 
 582  *  RETURNS    : TRUE  --> success. phPal and phBitmap are filled with 
 583  *                         appropriate handles.  Caller is responsible 
 584  *                         for freeing objects. 
 585  *               FALSE --> unable to create objects.  both pointer are 
 588  ****************************************************************************/ 
 589 BOOL PASCAL 
MakeBitmapAndPalette(HDC hDC
, HANDLE hDIB
, 
 590                         HPALETTE 
* phPal
, HBITMAP 
* phBitmap
) 
 592     LPBITMAPINFOHEADER lpInfo
; 
 595     HPALETTE hPalette
, hOldPal
; 
 598 #ifdef __WINDOWS_386__ 
 599     lpInfo 
= (LPBITMAPINFOHEADER
) MK_FP32(GlobalLock(hDIB
)); 
 601     lpInfo 
= (LPBITMAPINFOHEADER
) GlobalLock(hDIB
); 
 604     hPalette 
= MakeDIBPalette(lpInfo
); 
 607         // Need to realize palette for converting DIB to bitmap. 
 608         hOldPal 
= SelectPalette(hDC
, hPalette
, TRUE
); 
 611         lpBits 
= (LPSTR
)lpInfo 
+ (WORD
)lpInfo
->biSize 
+ 
 612                 (WORD
)lpInfo
->biClrUsed 
* sizeof(RGBQUAD
); 
 613         hBitmap 
= CreateDIBitmap(hDC
, lpInfo
, CBM_INIT
, lpBits
, 
 614                                 (LPBITMAPINFO
)lpInfo
, DIB_RGB_COLORS
); 
 616         SelectPalette(hDC
, hOldPal
, TRUE
); 
 620             DeleteObject(hPalette
); 
 631 /**************************************************************************** 
 633  *  FUNCTION   : MakeDIBPalette(lpInfo)                                     * 
 635  *  PURPOSE    : Given a BITMAPINFOHEADER, create a palette based on 
 639  *  RETURNS    : non-zero - handle of a corresponding palette 
 640  *               zero - unable to create palette 
 642  ****************************************************************************/ 
 643 HPALETTE 
MakeDIBPalette(LPBITMAPINFOHEADER lpInfo
) 
 650     /* since biClrUsed field was filled during the loading of the DIB, 
 651     ** we know it contains the number of colors in the color table. 
 653     if (lpInfo
->biClrUsed
) 
 656         npPal = (NPLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) + 
 657                                 (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY)); 
 659         npPal 
= (NPLOGPALETTE
)malloc(sizeof(LOGPALETTE
) + 
 660                                 (WORD
)lpInfo
->biClrUsed 
* sizeof(PALETTEENTRY
)); 
 665         npPal
->palVersion 
= 0x300; 
 666         npPal
->palNumEntries 
= (WORD
)lpInfo
->biClrUsed
; 
 668         /* get pointer to the color table */ 
 669         lpRGB 
= (RGBQUAD FAR 
*)((LPSTR
)lpInfo 
+ lpInfo
->biSize
); 
 671         /* copy colors from the color table to the LogPalette structure */ 
 672         for (i 
= 0; i 
< lpInfo
->biClrUsed
; i
++, lpRGB
++) 
 674             npPal
->palPalEntry
[i
].peRed 
= lpRGB
->rgbRed
; 
 675             npPal
->palPalEntry
[i
].peGreen 
= lpRGB
->rgbGreen
; 
 676             npPal
->palPalEntry
[i
].peBlue 
= lpRGB
->rgbBlue
; 
 677             npPal
->palPalEntry
[i
].peFlags 
= 0; 
 680         hLogPal 
= CreatePalette((LPLOGPALETTE
)npPal
); 
 681 //      LocalFree((HANDLE)npPal); 
 687     /* 24-bit DIB with no color table.  return default palette.  Another 
 688     ** option would be to create a 256 color "rainbow" palette to provide 
 689     ** some good color choices. 
 692         return((HPALETTE
) GetStockObject(DEFAULT_PALETTE
)); 
 695 bool wxLoadIntoBitmap(char *filename
, wxBitmap 
*bitmap
, wxPalette 
**pal
) 
 700   bool success 
= (ReadDIB(filename
, &hBitmap
, &hPalette
) != 0); 
 704     DeleteObject(hPalette
); 
 712       *pal 
= new wxPalette
; 
 713       (*pal
)->SetHPALETTE((WXHPALETTE
) hPalette
); 
 716       DeleteObject(hPalette
); 
 724     GetObject(hBitmap
, sizeof(bm
), (LPSTR
)&bm
); 
 726     bitmap
->SetHBITMAP((WXHBITMAP
) hBitmap
); 
 727     bitmap
->SetWidth(bm
.bmWidth
); 
 728     bitmap
->SetHeight(bm
.bmHeight
); 
 729     bitmap
->SetDepth(bm
.bmPlanes 
* bm
.bmBitsPixel
); 
 736 wxBitmap 
*wxLoadBitmap(char *filename
, wxPalette 
**pal
) 
 738   wxBitmap 
*bitmap 
= new wxBitmap
; 
 739   if (wxLoadIntoBitmap(filename
, bitmap
, pal
)) 
 748 //--------------------------------------------------------------------- 
 750 // Function:   InitBitmapInfoHeader 
 752 // Purpose:    Does a "standard" initialization of a BITMAPINFOHEADER, 
 753 //             given the Width, Height, and Bits per Pixel for the 
 756 //             By standard, I mean that all the relevant fields are set 
 757 //             to the specified values.  biSizeImage is computed, the 
 758 //             biCompression field is set to "no compression," and all 
 759 //             other fields are 0. 
 761 //             Note that DIBs only allow BitsPixel values of 1, 4, 8, or 
 762 //             24.  This routine makes sure that one of these values is 
 763 //             used (whichever is most appropriate for the specified 
 766 // Parms:      lpBmInfoHdr == Far pointer to a BITMAPINFOHEADER structure 
 768 //             dwWidth     == Width of DIB (not in Win 3.0 & 3.1, high 
 770 //             dwHeight    == Height of DIB (not in Win 3.0 & 3.1, high 
 772 //             nBPP        == Bits per Pixel for the DIB. 
 774 // History:   Date      Reason 
 777 //--------------------------------------------------------------------- 
 779 void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr
, 
 784 //   _fmemset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER)); 
 785    memset (lpBmInfoHdr
, 0, sizeof (BITMAPINFOHEADER
)); 
 787    lpBmInfoHdr
->biSize      
= sizeof (BITMAPINFOHEADER
); 
 788    lpBmInfoHdr
->biWidth     
= dwWidth
; 
 789    lpBmInfoHdr
->biHeight    
= dwHeight
; 
 790    lpBmInfoHdr
->biPlanes    
= 1; 
 805    lpBmInfoHdr
->biBitCount  
= nBPP
; 
 806    lpBmInfoHdr
->biSizeImage 
= WIDTHBYTES (dwWidth 
* nBPP
) * dwHeight
; 
 812 LPSTR 
FindDIBBits (LPSTR lpbi
) 
 814    return (lpbi 
+ *(LPDWORD
)lpbi 
+ PaletteSize (lpbi
)); 
 817 //--------------------------------------------------------------------- 
 819 // Function:   BitmapToDIB 
 821 // Purpose:    Given a device dependent bitmap and a palette, returns 
 822 //             a handle to global memory with a DIB spec in it.  The 
 823 //             DIB is rendered using the colors of the palette passed in. 
 825 //             Stolen almost verbatim from ShowDIB. 
 827 // Parms:      hBitmap == Handle to device dependent bitmap compatible 
 828 //                        with default screen display device. 
 829 //             hPal    == Palette to render the DDB with.  If it's NULL, 
 830 //                        use the default palette. 
 832 // History:   Date      Reason 
 835 //--------------------------------------------------------------------- 
 837 HANDLE 
BitmapToDIB (HBITMAP hBitmap
, HPALETTE hPal
) 
 840    BITMAPINFOHEADER   bmInfoHdr
; 
 841    LPBITMAPINFOHEADER lpbmInfoHdr
; 
 845    HPALETTE           hOldPal 
= NULL
; 
 847       // Do some setup -- make sure the Bitmap passed in is valid, 
 848       //  get info on the bitmap (like its height, width, etc.), 
 849       //  then setup a BITMAPINFOHEADER. 
 854    if (!GetObject (hBitmap
, sizeof (Bitmap
), (LPSTR
) &Bitmap
)) 
 857    InitBitmapInfoHeader (&bmInfoHdr
, 
 860                          Bitmap
.bmPlanes 
* Bitmap
.bmBitsPixel
); 
 863       // Now allocate memory for the DIB.  Then, set the BITMAPINFOHEADER 
 864       //  into this memory, and find out where the bitmap bits go. 
 866    hDIB 
= GlobalAlloc (GHND
, sizeof (BITMAPINFOHEADER
) + 
 867              PaletteSize ((LPSTR
) &bmInfoHdr
) + bmInfoHdr
.biSizeImage
); 
 872 #ifdef __WINDOWS_386__ 
 873    lpbmInfoHdr  
= (LPBITMAPINFOHEADER
) MK_FP32(GlobalLock (hDIB
)); 
 875    lpbmInfoHdr  
= (LPBITMAPINFOHEADER
) GlobalLock (hDIB
); 
 878    *lpbmInfoHdr 
= bmInfoHdr
; 
 879    lpBits       
= FindDIBBits ((LPSTR
) lpbmInfoHdr
); 
 882       // Now, we need a DC to hold our bitmap.  If the app passed us 
 883       //  a palette, it should be selected into the DC. 
 885    hMemDC       
= GetDC (NULL
); 
 889       hOldPal 
= SelectPalette (hMemDC
, hPal
, FALSE
); 
 890       RealizePalette (hMemDC
); 
 895       // We're finally ready to get the DIB.  Call the driver and let 
 896       //  it party on our bitmap.  It will fill in the color table, 
 897       //  and bitmap bits of our global memory block. 
 899    if (!GetDIBits (hMemDC
, 
 904                    (LPBITMAPINFO
) lpbmInfoHdr
, 
 915       // Finally, clean up and return. 
 918       SelectPalette (hMemDC
, hOldPal
, FALSE
); 
 920    ReleaseDC (NULL
, hMemDC
); 
 925 bool wxSaveBitmap(char *filename
, wxBitmap 
*bitmap
, wxPalette 
*colourmap
) 
 927   HPALETTE hPalette 
= 0; 
 929     hPalette 
= (HPALETTE
) colourmap
->GetHPALETTE(); 
 931   HANDLE dibHandle 
= BitmapToDIB((HBITMAP
) bitmap
->GetHBITMAP(), hPalette
); 
 934     bool success 
= (WriteDIB(filename
, dibHandle
) != 0); 
 935     GlobalFree(dibHandle
);