1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/dib.cpp
3 // Purpose: implements wxDIB class
4 // Author: Vadim Zeitlin
6 // Created: 03.03.03 (replaces the old file with the same name)
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
28 #include "wx/string.h"
32 #include "wx/bitmap.h"
38 #if !defined(__MWERKS__) && !defined(__SALFORDC__)
42 #ifdef __GNUWIN32_OLD__
43 #include "wx/msw/gnuwin32/extra.h"
47 #include "wx/msw/dib.h"
49 // ============================================================================
51 // ============================================================================
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 bool wxDIB::Create(int width
, int height
, int depth
)
59 // we don't handle the palette yet
60 wxASSERT_MSG( depth
== 24 || depth
== 32,
61 _T("unsupported image depth in wxDIB::Create()") );
63 static const int infosize
= sizeof(BITMAPINFOHEADER
);
65 BITMAPINFO
*info
= (BITMAPINFO
*)malloc(infosize
);
66 wxCHECK_MSG( info
, NULL
, _T("malloc(BITMAPINFO) failed") );
68 memset(info
, 0, infosize
);
70 info
->bmiHeader
.biSize
= infosize
;
71 info
->bmiHeader
.biWidth
= width
;
73 // we use positive height here which corresponds to a DIB with normal, i.e.
74 // bottom to top, order -- normally using negative height (which means
75 // reversed for MS and hence natural for all the normal people top to
76 // bottom line scan order) could be used to avoid the need for the image
77 // reversal in Create(image) but this doesn't work under NT, only Win9x!
78 info
->bmiHeader
.biHeight
= height
;
80 info
->bmiHeader
.biPlanes
= 1;
81 info
->bmiHeader
.biBitCount
= depth
;
82 info
->bmiHeader
.biCompression
= BI_RGB
;
83 info
->bmiHeader
.biSizeImage
= GetLineSize(width
, depth
)*height
;
85 // No need to report an error here. If it fails, we just won't use a
86 // file mapping and CreateDIBSection will just allocate memory for us.
87 m_handle
= ::CreateDIBSection
89 0, // hdc (unused with DIB_RGB_COLORS)
90 info
, // bitmap description
91 DIB_RGB_COLORS
, // use RGB, not palette
92 &m_data
, // [out] DIB bits
93 NULL
, // don't use file mapping
94 0 // file mapping offset (not used here)
101 wxLogLastError(wxT("CreateDIBSection"));
113 // ----------------------------------------------------------------------------
114 // Loading/saving the DIBs
115 // ----------------------------------------------------------------------------
117 bool wxDIB::Load(const wxString
& filename
)
119 m_handle
= (HBITMAP
)::LoadImage
124 0, 0, // don't specify the size
125 LR_CREATEDIBSECTION
| LR_LOADFROMFILE
129 wxLogLastError(_T("LoadImage(LR_CREATEDIBSECTION | LR_LOADFROMFILE)"));
137 // ----------------------------------------------------------------------------
139 // ----------------------------------------------------------------------------
141 void wxDIB::DoGetObject() const
143 // only do something if we have a valid DIB but we don't [yet] have valid
145 if ( m_handle
&& !m_data
)
147 // although all the info we need is in BITMAP and so we don't really
148 // need DIBSECTION we still ask for it as modifying the bit values only
149 // works for the real DIBs and not for the bitmaps and it's better to
150 // check for this now rather than trying to find out why it doesn't
153 if ( !::GetObject(m_handle
, sizeof(ds
), &ds
) )
155 wxLogLastError(_T("GetObject(hDIB)"));
159 wxDIB
*self
= wxConstCast(this, wxDIB
);
161 self
->m_width
= ds
.dsBm
.bmWidth
;
162 self
->m_height
= ds
.dsBm
.bmHeight
;
163 self
->m_depth
= ds
.dsBm
.bmBitsPixel
;
164 self
->m_data
= ds
.dsBm
.bmBits
;
168 HBITMAP
wxDIB::CreateDDB(HDC hdc
) const
170 wxCHECK_MSG( m_handle
, 0, _T("wxDIB::CreateDDB(): invalid object") );
173 if ( !::GetObject(m_handle
, sizeof(ds
), &ds
) )
175 wxLogLastError(_T("GetObject(hDIB)"));
180 HBITMAP hbitmap
= ::CreateCompatibleBitmap
182 hdc
? hdc
: ScreenHDC(),
188 wxLogLastError(_T("CreateCompatibleBitmap()"));
194 SelectInHDC
select(hdcMem
, hbitmap
);
197 wxLogLastError(_T("SelectObjct(hBitmap)"));
207 (BITMAPINFO
*)&ds
.dsBmih
,
211 wxLogLastError(_T("SetDIBits"));
221 wxPalette
*wxDIB::CreatePalette() const
223 wxCHECK_MSG( m_handle
, NULL
, _T("wxDIB::CreatePalette(): invalid object") );
226 if ( !::GetObject(m_handle
, sizeof(ds
), &ds
) )
228 wxLogLastError(_T("GetObject(hDIB)"));
233 // how many colours are we going to have in the palette?
234 DWORD biClrUsed
= ds
.dsBmih
.biClrUsed
;
237 // biClrUsed field might not be set
238 biClrUsed
= 1 << ds
.dsBmih
.biBitCount
;
241 if ( biClrUsed
> 256 )
243 // only 8bpp bitmaps (and less) have palettes, so we surely don't
245 // NB: another possibility would be to return
246 // GetStockObject(DEFAULT_PALETTE) or even CreateHalftonePalette()?
250 // LOGPALETTE struct has only 1 element in palPalEntry array, we're
251 // going to have biClrUsed of them so add necessary space
252 LOGPALETTE
*pPalette
= (LOGPALETTE
*)
253 malloc(sizeof(LOGPALETTE
) + (biClrUsed
- 1)*sizeof(PALETTEENTRY
));
254 wxCHECK_MSG( pPalette
, NULL
, _T("out of memory") );
256 // initialize the palette header
257 pPalette
->palVersion
= 0x300; // magic number, not in docs but works
258 pPalette
->palNumEntries
= biClrUsed
;
260 // and the colour table (it starts right after the end of the header)
261 const RGBQUAD
*pRGB
= (RGBQUAD
*)((char *)&ds
.dsBmih
+ ds
.dsBmih
.biSize
);
262 for ( DWORD i
= 0; i
< biClrUsed
; i
++, pRGB
++ )
264 pPalette
->palPalEntry
[i
].peRed
= pRGB
->rgbRed
;
265 pPalette
->palPalEntry
[i
].peGreen
= pRGB
->rgbGreen
;
266 pPalette
->palPalEntry
[i
].peBlue
= pRGB
->rgbBlue
;
267 pPalette
->palPalEntry
[i
].peFlags
= 0;
270 HPALETTE hPalette
= ::CreatePalette(pPalette
);
276 wxLogLastError(_T("CreatePalette"));
281 wxPalette
*palette
= new wxPalette
;
282 palette
->SetHPALETTE((WXHPALETTE
)hPalette
);
287 #endif // wxUSE_PALETTE
289 // ----------------------------------------------------------------------------
291 // ----------------------------------------------------------------------------
295 bool wxDIB::Create(const wxImage
& image
)
297 wxCHECK_MSG( image
.Ok(), false, _T("invalid wxImage in wxDIB ctor") );
299 const int h
= image
.GetHeight();
300 const int w
= image
.GetWidth();
302 // if we have alpha channel, we need to create a 32bpp RGBA DIB, otherwise
303 // a 24bpp RGB is sufficient
304 const bool hasAlpha
= image
.HasAlpha();
305 const int bpp
= hasAlpha
? 32 : 24;
307 if ( !Create(w
, h
, bpp
) )
310 // DIBs are stored in bottom to top order (see also the comment above in
311 // Create()) so we need to copy bits line by line and starting from the end
312 const int srcBytesPerLine
= w
* 3;
313 const int dstBytesPerLine
= GetLineSize(w
, bpp
);
314 const unsigned char *src
= image
.GetData() + ((h
- 1) * srcBytesPerLine
);
315 const unsigned char *alpha
= hasAlpha
? image
.GetAlpha() + (h
- 1)*w
: NULL
;
316 unsigned char *dstLineStart
= (unsigned char *)m_data
;
317 for ( int y
= 0; y
< h
; y
++ )
320 unsigned char *dst
= dstLineStart
;
321 for ( int x
= 0; x
< w
; x
++ )
323 // also, the order of RGB is inversed for DIBs
334 // pass to the previous line in the image
335 src
-= 2*srcBytesPerLine
;
339 // and to the next one in the DIB
340 dstLineStart
+= dstBytesPerLine
;
346 #endif // wxUSE_IMAGE
348 // ============================================================================
349 // old DIB code, to be integrated in wxDIB class
350 // ============================================================================
353 * Routines for dealing with Device Independent Bitmaps.
355 * wxReadDIB() - Reads a DIB
356 * wxWriteDIB() - Writes a global handle in CF_DIB format
358 * wxPaletteSize() - Calculates the palette size in bytes
360 * wxDibNumColors() - Determines the number of colors in DIB
361 * wxDibFromBitmap() - Creates a DIB repr. the DDB passed in.
362 * lread() - Private routine to read more than 64k
363 * lwrite() - Private routine to write more than 64k
367 /* flags for _lseek */
373 #define MAXREAD 32768 /* Number of bytes to be read during */
374 /* each read operation. */
376 /* Header signatutes for various resources */
377 #define BFT_ICON 0x4349 /* 'IC' */
378 #define BFT_BITMAP 0x4d42 /* 'BM' */
379 #define BFT_CURSOR 0x5450 /* 'PT(' */
381 /* macro to determine if resource is a DIB */
382 #define ISDIB(bft) ((bft) == BFT_BITMAP)
384 /* Macro to align given value to the closest DWORD (unsigned long ) */
385 #define ALIGNULONG(i) ((i+3)/4*4)
387 /* Macro to determine to round off the given value to the closest byte */
388 #define WIDTHBYTES(i) ((i+31)/32*4)
390 #define PALVERSION 0x300
391 #define MAXPALETTE 256 /* max. # supported palette entries */
393 static DWORD
lread(int fh
, VOID FAR
*pv
, DWORD ul
);
394 static DWORD
lwrite(int fh
, VOID FAR
*pv
, DWORD ul
);
396 static bool wxWriteDIB (LPTSTR szFile
,HANDLE hdib
);
397 WORD
wxPaletteSize (VOID FAR
* pv
); // This is non-static as some apps use it externally
398 static WORD
wxDibNumColors (VOID FAR
* pv
);
399 static bool wxMakeBitmapAndPalette(HDC
,HANDLE
,HPALETTE
*,HBITMAP
*);
402 * FUNCTION : wxWriteDIB(LPSTR szFile,HANDLE hdib)
403 * PURPOSE : Write a global handle in CF_DIB format to a file.
404 * RETURNS : TRUE - if successful.
408 static bool wxWriteDIB(LPTSTR szFile
, HANDLE hdib
)
410 BITMAPFILEHEADER hdr
;
411 LPBITMAPINFOHEADER lpbi
;
418 fh
= OpenFile(wxConvertWX2MB(szFile
), &of
, OF_CREATE
| OF_READWRITE
);
422 lpbi
= (LPBITMAPINFOHEADER
) GlobalLock(hdib
);
424 /* Fill in the fields of the file header */
425 hdr
.bfType
= BFT_BITMAP
;
426 hdr
.bfSize
= GlobalSize(hdib
) + sizeof(BITMAPFILEHEADER
);
429 hdr
.bfOffBits
= (DWORD
) sizeof(BITMAPFILEHEADER
) + lpbi
->biSize
+
432 /* Write the file header */
433 _lwrite(fh
, (LPSTR
) &hdr
, sizeof(BITMAPFILEHEADER
));
435 /* Write the DIB header and the bits */
436 lwrite(fh
, (LPSTR
) lpbi
, GlobalSize(hdib
));
444 * FUNCTION : wxPaletteSize(VOID FAR * pv)
445 * PURPOSE : Calculates the palette size in bytes. If the info. block
446 * is of the BITMAPCOREHEADER type, the number of colors is
447 * multiplied by 3 to give the palette size, otherwise the
448 * number of colors is multiplied by 4.
449 * RETURNS : Palette size in number of bytes.
452 WORD
wxPaletteSize(VOID FAR
* pv
)
454 LPBITMAPINFOHEADER lpbi
;
457 lpbi
= (LPBITMAPINFOHEADER
) pv
;
458 NumColors
= wxDibNumColors(lpbi
);
460 if (lpbi
->biSize
== sizeof(BITMAPCOREHEADER
))
461 return (WORD
)(NumColors
* sizeof(RGBTRIPLE
));
463 return (WORD
)(NumColors
* sizeof(RGBQUAD
));
467 * FUNCTION : wxDibNumColors(VOID FAR * pv)
468 * PURPOSE : Determines the number of colors in the DIB by looking at
469 * the BitCount filed in the info block.
470 * RETURNS : The number of colors in the DIB. *
473 static WORD
wxDibNumColors(VOID FAR
*pv
)
476 BITMAPINFOHEADER
*lpbi
;
477 BITMAPCOREHEADER
*lpbc
;
479 lpbi
= ((BITMAPINFOHEADER
*) pv
);
480 lpbc
= ((BITMAPCOREHEADER
*) pv
);
482 /* With the BITMAPINFO format headers, the size of the palette
483 * is in biClrUsed, whereas in the BITMAPCORE - style headers, it
484 * is dependent on the bits per pixel ( = 2 raised to the power of
487 if (lpbi
->biSize
!= sizeof(BITMAPCOREHEADER
)) {
488 if (lpbi
->biClrUsed
!= 0)
489 return (WORD
) lpbi
->biClrUsed
;
490 bits
= lpbi
->biBitCount
;
493 bits
= lpbc
->bcBitCount
;
503 /* A 24 bitcount DIB has no color table */
509 * FUNCTION : lread(int fh, VOID FAR *pv, DWORD ul)
510 * PURPOSE : Reads data in steps of 32k till all the data has been read.
511 * RETURNS : 0 - If read did not proceed correctly.
512 * number of bytes read otherwise.
515 static DWORD
lread(int fh
, void far
*pv
, DWORD ul
)
518 #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__)
519 BYTE
*hp
= (BYTE
*) pv
;
521 BYTE huge
*hp
= (BYTE huge
*) pv
;
523 while (ul
> (DWORD
) MAXREAD
) {
524 if (_lread(fh
, (LPSTR
) hp
, (WORD
) MAXREAD
) != MAXREAD
)
529 if (_lread(fh
, (LPSTR
) hp
, (WXUINT
) ul
) != (WXUINT
) ul
)
535 * FUNCTION : lwrite(int fh, VOID FAR *pv, DWORD ul)
536 * PURPOSE : Writes data in steps of 32k till all the data is written.
537 * RETURNS : 0 - If write did not proceed correctly.
538 * number of bytes written otherwise.
541 static DWORD
lwrite(int fh
, VOID FAR
*pv
, DWORD ul
)
544 #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__)
545 BYTE
*hp
= (BYTE
*) pv
;
547 BYTE huge
*hp
= (BYTE huge
*) pv
;
549 while (ul
> MAXREAD
) {
550 if (_lwrite(fh
, (LPSTR
) hp
, (WORD
) MAXREAD
) != MAXREAD
)
555 if (_lwrite(fh
, (LPSTR
) hp
, (WXUINT
) ul
) != (WXUINT
) ul
)
561 * FUNCTION : wxReadDIB(hWnd)
562 * PURPOSE : Reads a DIB from a file, obtains a handle to its
563 * BITMAPINFO struct. and loads the DIB. Once the DIB
564 * is loaded, the function also creates a bitmap and
565 * palette out of the DIB for a device-dependent form.
566 * RETURNS : TRUE - DIB loaded and bitmap/palette created
567 * The DIBINIT structure pointed to by pInfo is
568 * filled with the appropriate handles.
572 bool wxReadDIB(LPTSTR lpFileName
, HBITMAP
*bitmap
, HPALETTE
*palette
)
575 LPBITMAPINFOHEADER lpbi
;
582 bool bCoreHead
= FALSE
;
585 /* Open the file and get a handle to it's BITMAPINFO */
587 fh
= OpenFile (wxConvertWX2MB(lpFileName
), &of
, OF_READ
);
589 wxLogError(_("Can't open file '%s'"), lpFileName
);
593 hDIB
= GlobalAlloc(GHND
, (DWORD
)(sizeof(BITMAPINFOHEADER
) +
594 256 * sizeof(RGBQUAD
)));
598 lpbi
= (LPBITMAPINFOHEADER
)GlobalLock(hDIB
);
600 /* read the BITMAPFILEHEADER */
601 if (sizeof (bf
) != _lread (fh
, (LPSTR
)&bf
, sizeof (bf
)))
604 if (bf
.bfType
!= 0x4d42) /* 'BM' */
607 if (sizeof(BITMAPCOREHEADER
) != _lread (fh
, (LPSTR
)lpbi
, sizeof(BITMAPCOREHEADER
)))
610 if (lpbi
->biSize
== sizeof(BITMAPCOREHEADER
))
612 lpbi
->biSize
= sizeof(BITMAPINFOHEADER
);
613 lpbi
->biBitCount
= ((LPBITMAPCOREHEADER
)lpbi
)->bcBitCount
;
614 lpbi
->biPlanes
= ((LPBITMAPCOREHEADER
)lpbi
)->bcPlanes
;
615 lpbi
->biHeight
= ((LPBITMAPCOREHEADER
)lpbi
)->bcHeight
;
616 lpbi
->biWidth
= ((LPBITMAPCOREHEADER
)lpbi
)->bcWidth
;
621 // get to the start of the header and read INFOHEADER
622 _llseek(fh
,sizeof(BITMAPFILEHEADER
),SEEK_SET
);
623 if (sizeof(BITMAPINFOHEADER
) != _lread (fh
, (LPSTR
)lpbi
, sizeof(BITMAPINFOHEADER
)))
627 nNumColors
= (WORD
)lpbi
->biClrUsed
;
628 if ( nNumColors
== 0 )
630 /* no color table for 24-bit, default size otherwise */
631 if (lpbi
->biBitCount
!= 24)
632 nNumColors
= 1 << lpbi
->biBitCount
; /* standard size table */
635 /* fill in some default values if they are zero */
636 if (lpbi
->biClrUsed
== 0)
637 lpbi
->biClrUsed
= nNumColors
;
639 if (lpbi
->biSizeImage
== 0)
641 lpbi
->biSizeImage
= ((((lpbi
->biWidth
* (DWORD
)lpbi
->biBitCount
) + 31) & ~31) >> 3)
645 /* get a proper-sized buffer for header, color table and bits */
647 hDIB
= GlobalReAlloc(hDIB
, lpbi
->biSize
+
648 nNumColors
* sizeof(RGBQUAD
) +
649 lpbi
->biSizeImage
, 0);
650 if (!hDIB
) /* can't resize buffer for loading */
653 lpbi
= (LPBITMAPINFOHEADER
)GlobalLock(hDIB
);
655 /* read the color table */
657 _lread(fh
, (LPSTR
)(lpbi
) + lpbi
->biSize
, nNumColors
* sizeof(RGBQUAD
));
662 RGBTRIPLE FAR
*pTriple
;
664 _lread(fh
, (LPSTR
)(lpbi
) + lpbi
->biSize
, nNumColors
* sizeof(RGBTRIPLE
));
666 pQuad
= (RGBQUAD FAR
*)((LPSTR
)lpbi
+ lpbi
->biSize
);
667 pTriple
= (RGBTRIPLE FAR
*) pQuad
;
668 for (i
= nNumColors
- 1; i
>= 0; i
--)
670 pQuad
[i
].rgbRed
= pTriple
[i
].rgbtRed
;
671 pQuad
[i
].rgbBlue
= pTriple
[i
].rgbtBlue
;
672 pQuad
[i
].rgbGreen
= pTriple
[i
].rgbtGreen
;
673 pQuad
[i
].rgbReserved
= 0;
677 /* offset to the bits from start of DIB header */
678 offBits
= (WORD
)(lpbi
->biSize
+ nNumColors
* sizeof(RGBQUAD
));
680 if (bf
.bfOffBits
!= 0L)
682 _llseek(fh
,bf
.bfOffBits
,SEEK_SET
);
685 if (lpbi
->biSizeImage
== lread(fh
, (LPSTR
)lpbi
+ offBits
, lpbi
->biSizeImage
))
690 if (!wxMakeBitmapAndPalette(hDC
, hDIB
, palette
,
716 * FUNCTION : wxMakeBitmapAndPalette
717 * PURPOSE : Given a DIB, creates a bitmap and corresponding palette
718 * to be used for a device-dependent representation of
720 * RETURNS : TRUE --> success. phPal and phBitmap are filled with
721 * appropriate handles. Caller is responsible
722 * for freeing objects.
723 * FALSE --> unable to create objects. both pointer are
727 static bool wxMakeBitmapAndPalette(HDC hDC
, HANDLE hDIB
,
728 HPALETTE
* phPal
, HBITMAP
* phBitmap
)
730 LPBITMAPINFOHEADER lpInfo
;
733 HPALETTE hPalette
, hOldPal
;
736 lpInfo
= (LPBITMAPINFOHEADER
) GlobalLock(hDIB
);
738 hPalette
= wxMakeDIBPalette(lpInfo
);
741 // Need to realize palette for converting DIB to bitmap.
742 hOldPal
= SelectPalette(hDC
, hPalette
, TRUE
);
745 lpBits
= (LPSTR
)lpInfo
+ (WORD
)lpInfo
->biSize
+
746 (WORD
)lpInfo
->biClrUsed
* sizeof(RGBQUAD
);
747 hBitmap
= CreateDIBitmap(hDC
, lpInfo
, CBM_INIT
, lpBits
,
748 (LPBITMAPINFO
)lpInfo
, DIB_RGB_COLORS
);
750 SelectPalette(hDC
, hOldPal
, TRUE
);
754 DeleteObject(hPalette
);
763 GlobalUnlock (hDIB
); // glt
769 * FUNCTION : wxMakeDIBPalette(lpInfo)
770 * PURPOSE : Given a BITMAPINFOHEADER, create a palette based on
772 * RETURNS : non-zero - handle of a corresponding palette
773 * zero - unable to create palette
776 HPALETTE
wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo
)
783 /* since biClrUsed field was filled during the loading of the DIB,
784 * we know it contains the number of colors in the color table.
786 if (lpInfo
->biClrUsed
)
788 npPal
= (LPLOGPALETTE
)malloc(sizeof(LOGPALETTE
) +
789 (WORD
)lpInfo
->biClrUsed
* sizeof(PALETTEENTRY
));
793 npPal
->palVersion
= 0x300;
794 npPal
->palNumEntries
= (WORD
)lpInfo
->biClrUsed
;
796 /* get pointer to the color table */
797 lpRGB
= (RGBQUAD FAR
*)((LPSTR
)lpInfo
+ lpInfo
->biSize
);
799 /* copy colors from the color table to the LogPalette structure */
800 for (i
= 0; (DWORD
)i
< lpInfo
->biClrUsed
; i
++, lpRGB
++)
802 npPal
->palPalEntry
[i
].peRed
= lpRGB
->rgbRed
;
803 npPal
->palPalEntry
[i
].peGreen
= lpRGB
->rgbGreen
;
804 npPal
->palPalEntry
[i
].peBlue
= lpRGB
->rgbBlue
;
805 npPal
->palPalEntry
[i
].peFlags
= 0;
808 hLogPal
= CreatePalette((LPLOGPALETTE
)npPal
);
814 /* 24-bit DIB with no color table. Return default palette. Another
815 * option would be to create a 256 color "rainbow" palette to provide
816 * some good color choices.
819 return((HPALETTE
) GetStockObject(DEFAULT_PALETTE
));
824 * Function: InitBitmapInfoHeader
826 * Purpose: Does a "standard" initialization of a BITMAPINFOHEADER,
827 * given the Width, Height, and Bits per Pixel for the
830 * By standard, I mean that all the relevant fields are set
831 * to the specified values. biSizeImage is computed, the
832 * biCompression field is set to "no compression," and all
833 * other fields are 0.
835 * Note that DIBs only allow BitsPixel values of 1, 4, 8, or
836 * 24. This routine makes sure that one of these values is
837 * used (whichever is most appropriate for the specified
840 * Parms: lpBmInfoHdr == Far pointer to a BITMAPINFOHEADER structure
842 * dwWidth == Width of DIB (not in Win 3.0 & 3.1, high
844 * dwHeight == Height of DIB (not in Win 3.0 & 3.1, high
846 * nBPP == Bits per Pixel for the DIB.
850 static void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr
,
855 // _fmemset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));
856 memset (lpBmInfoHdr
, 0, sizeof (BITMAPINFOHEADER
));
858 lpBmInfoHdr
->biSize
= sizeof (BITMAPINFOHEADER
);
859 lpBmInfoHdr
->biWidth
= dwWidth
;
860 lpBmInfoHdr
->biHeight
= dwHeight
;
861 lpBmInfoHdr
->biPlanes
= 1;
876 lpBmInfoHdr
->biBitCount
= nBPP
;
877 lpBmInfoHdr
->biSizeImage
= WIDTHBYTES (dwWidth
* nBPP
) * dwHeight
;
880 LPSTR
wxFindDIBBits (LPSTR lpbi
)
882 return (lpbi
+ *(LPDWORD
)lpbi
+ wxPaletteSize (lpbi
));
886 * Function: BitmapToDIB
888 * Purpose: Given a device dependent bitmap and a palette, returns
889 * a handle to global memory with a DIB spec in it. The
890 * DIB is rendered using the colors of the palette passed in.
892 * Parms: hBitmap == Handle to device dependent bitmap compatible
893 * with default screen display device.
894 * hPal == Palette to render the DDB with. If it's NULL,
895 * use the default palette.
898 HANDLE
wxBitmapToDIB (HBITMAP hBitmap
, HPALETTE hPal
)
901 BITMAPINFOHEADER bmInfoHdr
;
902 LPBITMAPINFOHEADER lpbmInfoHdr
;
906 HPALETTE hOldPal
= NULL
;
908 // Do some setup -- make sure the Bitmap passed in is valid,
909 // get info on the bitmap (like its height, width, etc.),
910 // then setup a BITMAPINFOHEADER.
915 if (!GetObject (hBitmap
, sizeof (Bitmap
), (LPSTR
) &Bitmap
))
918 InitBitmapInfoHeader (&bmInfoHdr
,
921 Bitmap
.bmPlanes
* Bitmap
.bmBitsPixel
);
923 // Now allocate memory for the DIB. Then, set the BITMAPINFOHEADER
924 // into this memory, and find out where the bitmap bits go.
926 hDIB
= GlobalAlloc (GHND
, sizeof (BITMAPINFOHEADER
) +
927 wxPaletteSize ((LPSTR
) &bmInfoHdr
) + bmInfoHdr
.biSizeImage
);
932 lpbmInfoHdr
= (LPBITMAPINFOHEADER
) GlobalLock (hDIB
);
934 *lpbmInfoHdr
= bmInfoHdr
;
935 lpBits
= wxFindDIBBits ((LPSTR
) lpbmInfoHdr
);
938 // Now, we need a DC to hold our bitmap. If the app passed us
939 // a palette, it should be selected into the DC.
941 hMemDC
= GetDC (NULL
);
945 hOldPal
= SelectPalette (hMemDC
, hPal
, FALSE
);
946 RealizePalette (hMemDC
);
949 // We're finally ready to get the DIB. Call the driver and let
950 // it party on our bitmap. It will fill in the color table,
951 // and bitmap bits of our global memory block.
953 if (!GetDIBits (hMemDC
, hBitmap
, 0, Bitmap
.bmHeight
, lpBits
,
954 (LPBITMAPINFO
) lpbmInfoHdr
, DIB_RGB_COLORS
))
963 // Finally, clean up and return.
966 SelectPalette (hMemDC
, hOldPal
, FALSE
);
968 ReleaseDC (NULL
, hMemDC
);
973 bool wxSaveBitmap(wxChar
*filename
, wxBitmap
*bitmap
, wxPalette
*palette
)
975 HPALETTE hPalette
= 0;
978 hPalette
= (HPALETTE
) palette
->GetHPALETTE();
979 #endif // wxUSE_PALETTE
981 HANDLE dibHandle
= wxBitmapToDIB((HBITMAP
) bitmap
->GetHBITMAP(), hPalette
);
984 bool success
= (wxWriteDIB(filename
, dibHandle
) != 0);
985 GlobalFree(dibHandle
);