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 license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
28 #include "wx/string.h"
34 #include "wx/msw/dib.h"
36 // ============================================================================
38 // ============================================================================
40 // ----------------------------------------------------------------------------
42 // ----------------------------------------------------------------------------
44 bool wxDIB::Create(int width
, int height
, int depth
)
46 // we don't handle the palette yet
47 wxASSERT_MSG( depth
== 24 || depth
== 32,
48 _T("unsupported image depth in wxDIB::Create()") );
50 static const int infosize
= sizeof(BITMAPINFOHEADER
);
52 BITMAPINFO
*info
= (BITMAPINFO
*)malloc(infosize
);
53 wxCHECK_MSG( info
, NULL
, _T("malloc(BITMAPINFO) failed") );
55 memset(info
, 0, infosize
);
57 info
->bmiHeader
.biSize
= infosize
;
58 info
->bmiHeader
.biWidth
= width
;
59 info
->bmiHeader
.biHeight
= -height
;
60 info
->bmiHeader
.biPlanes
= 1;
61 info
->bmiHeader
.biBitCount
= depth
;
62 info
->bmiHeader
.biCompression
= BI_RGB
;
63 info
->bmiHeader
.biSizeImage
= GetLineSize(width
, depth
)*height
;
65 // No need to report an error here. If it fails, we just won't use a
66 // file mapping and CreateDIBSection will just allocate memory for us.
67 m_handle
= ::CreateDIBSection
69 0, // hdc (unused with DIB_RGB_COLORS)
70 info
, // bitmap description
71 DIB_RGB_COLORS
, // use RGB, not palette
72 &m_data
, // [out] DIB bits
73 NULL
, // don't use file mapping
74 0 // file mapping offset (not used here)
81 wxLogLastError(wxT("CreateDIBSection"));
93 // ----------------------------------------------------------------------------
95 // ----------------------------------------------------------------------------
97 void wxDIB::DoGetObject() const
99 // only do something if we have a valid DIB but we don't [yet] have valid
101 if ( m_handle
&& !m_data
)
103 // although all the info we need is in BITMAP and so we don't really
104 // need DIBSECTION we still ask for it as modifying the bit values only
105 // works for the real DIBs and not for the bitmaps and it's better to
106 // check for this now rather than trying to find out why it doesn't
109 if ( !::GetObject(m_handle
, sizeof(ds
), &ds
) )
111 wxLogLastError(_T("GetObject(hDIB)"));
116 wxDIB
*self
= wxConstCast(this, wxDIB
);
118 self
->m_width
= ds
.dsBm
.bmWidth
;
119 self
->m_height
= ds
.dsBm
.bmHeight
;
120 self
->m_depth
= ds
.dsBm
.bmBitsPixel
;
121 self
->m_data
= ds
.dsBm
.bmBits
;
125 // ----------------------------------------------------------------------------
127 // ----------------------------------------------------------------------------
131 bool wxDIB::Create(const wxImage
& image
)
133 wxCHECK_MSG( image
.Ok(), false, _T("invalid wxImage in wxDIB ctor") );
135 const int h
= image
.GetHeight();
136 const int w
= image
.GetWidth();
138 // if we have alpha channel, we need to create a 32bpp RGBA DIB, otherwise
139 // a 24bpp RGB is sufficient
140 const bool hasAlpha
= image
.HasAlpha();
141 const int bpp
= hasAlpha
? 32 : 24;
143 if ( !Create(w
, h
, bpp
) )
146 // DIBs are stored in bottom to top order so we need to copy bits line by
147 // line and starting from the end
148 const int srcBytesPerLine
= w
* 3;
149 const int dstBytesPerLine
= GetLineSize(w
, bpp
);
150 const unsigned char *src
= image
.GetData() + ((h
- 1) * srcBytesPerLine
);
151 const unsigned char *alpha
= hasAlpha
? image
.GetAlpha() + (h
- 1)*w
: NULL
;
152 unsigned char *dstLineStart
= (unsigned char *)m_data
;
153 for ( int y
= 0; y
< h
; y
++ )
156 unsigned char *dst
= dstLineStart
;
157 for ( int x
= 0; x
< w
; x
++ )
159 // also, the order of RGB is inversed for DIBs
170 // pass to the previous line in the image
171 src
-= 2*srcBytesPerLine
;
175 // and to the next one in the DIB
176 dstLineStart
+= dstBytesPerLine
;
182 #endif // wxUSE_IMAGE
184 // ============================================================================
185 // old DIB code, to be integrated in wxDIB class
186 // ============================================================================
188 /*******************************************************************************
192 * DESCRIPTION : Routines for dealing with Device Independent Bitmaps. *
196 * wxReadDIB() - Reads a DIB *
198 * WriteDIB() - Writes a global handle in CF_DIB format*
201 * wxPaletteSize() - Calculates the palette size in bytes *
204 * DibNumColors() - Determines the number of colors in DIB *
206 * DibFromBitmap() - Creates a DIB repr. the DDB passed in. *
209 * lread() - Private routine to read more than 64k *
211 * lwrite() - Private routine to write more than 64k *
213 *******************************************************************************/
215 // For compilers that support precompilation, includes "wx.h".
216 #include "wx/wxprec.h"
218 #if defined(__BORLANDC__)
223 #include "wx/bitmap.h"
232 #if !defined(__MWERKS__) && !defined(__SALFORDC__)
236 #include "wx/msw/dib.h"
238 #ifdef __GNUWIN32_OLD__
239 #include "wx/msw/gnuwin32/extra.h"
243 /* flags for _lseek */
249 #define MAXREAD 32768 /* Number of bytes to be read during */
250 /* each read operation. */
252 /* Header signatutes for various resources */
253 #define BFT_ICON 0x4349 /* 'IC' */
254 #define BFT_BITMAP 0x4d42 /* 'BM' */
255 #define BFT_CURSOR 0x5450 /* 'PT(' */
257 /* macro to determine if resource is a DIB */
258 #define ISDIB(bft) ((bft) == BFT_BITMAP)
260 /* Macro to align given value to the closest DWORD (unsigned long ) */
261 #define ALIGNULONG(i) ((i+3)/4*4)
263 /* Macro to determine to round off the given value to the closest byte */
264 #define WIDTHBYTES(i) ((i+31)/32*4)
266 #define PALVERSION 0x300
267 #define MAXPALETTE 256 /* max. # supported palette entries */
269 static DWORD PASCAL
lread(int fh
, VOID FAR
*pv
, DWORD ul
);
270 static DWORD PASCAL
lwrite(int fh
, VOID FAR
*pv
, DWORD ul
);
272 static BOOL
WriteDIB (LPTSTR szFile
,HANDLE hdib
);
273 WORD
wxPaletteSize (VOID FAR
* pv
); // This is non-static as some apps use it externally
274 static WORD
DibNumColors (VOID FAR
* pv
);
275 // HANDLE DibFromBitmap (HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal);
276 static BOOL PASCAL
MakeBitmapAndPalette(HDC
,HANDLE
,HPALETTE
*,HBITMAP
*);
278 /****************************************************************************
280 * FUNCTION : WriteDIB(LPSTR szFile,HANDLE hdib) *
282 * PURPOSE : Write a global handle in CF_DIB format to a file. *
284 * RETURNS : TRUE - if successful. *
285 * FALSE - otherwise *
287 ****************************************************************************/
289 static BOOL
WriteDIB(LPTSTR szFile
, HANDLE hdib
)
291 BITMAPFILEHEADER hdr
;
292 LPBITMAPINFOHEADER lpbi
;
299 fh
= OpenFile(wxConvertWX2MB(szFile
), &of
, OF_CREATE
| OF_READWRITE
);
303 #ifdef __WINDOWS_386__
304 lpbi
= (LPBITMAPINFOHEADER
) MK_FP32(GlobalLock(hdib
));
306 lpbi
= (LPBITMAPINFOHEADER
) GlobalLock(hdib
);
308 /* Fill in the fields of the file header */
309 hdr
.bfType
= BFT_BITMAP
;
310 hdr
.bfSize
= GlobalSize(hdib
) + sizeof(BITMAPFILEHEADER
);
313 hdr
.bfOffBits
= (DWORD
) sizeof(BITMAPFILEHEADER
) + lpbi
->biSize
+
316 /* Write the file header */
317 _lwrite(fh
, (LPSTR
) &hdr
, sizeof(BITMAPFILEHEADER
));
319 /* Write the DIB header and the bits */
320 lwrite(fh
, (LPSTR
) lpbi
, GlobalSize(hdib
));
327 /****************************************************************************
329 * FUNCTION : wxPaletteSize(VOID FAR * pv) *
331 * PURPOSE : Calculates the palette size in bytes. If the info. block *
332 * is of the BITMAPCOREHEADER type, the number of colors is *
333 * multiplied by 3 to give the palette size, otherwise the *
334 * number of colors is multiplied by 4. *
336 * RETURNS : Palette size in number of bytes. *
338 ****************************************************************************/
340 WORD
wxPaletteSize(VOID FAR
* pv
)
342 LPBITMAPINFOHEADER lpbi
;
345 lpbi
= (LPBITMAPINFOHEADER
) pv
;
346 NumColors
= DibNumColors(lpbi
);
348 if (lpbi
->biSize
== sizeof(BITMAPCOREHEADER
))
349 return (WORD
)(NumColors
* sizeof(RGBTRIPLE
));
351 return (WORD
)(NumColors
* sizeof(RGBQUAD
));
354 /****************************************************************************
356 * FUNCTION : DibNumColors(VOID FAR * pv) *
358 * PURPOSE : Determines the number of colors in the DIB by looking at *
359 * the BitCount filed in the info block. *
361 * RETURNS : The number of colors in the DIB. *
363 ****************************************************************************/
365 static WORD
DibNumColors(VOID FAR
*pv
)
368 BITMAPINFOHEADER
*lpbi
;
369 BITMAPCOREHEADER
*lpbc
;
371 lpbi
= ((BITMAPINFOHEADER
*) pv
);
372 lpbc
= ((BITMAPCOREHEADER
*) pv
);
374 /* With the BITMAPINFO format headers, the size of the palette
375 * is in biClrUsed, whereas in the BITMAPCORE - style headers, it
376 * is dependent on the bits per pixel ( = 2 raised to the power of
379 if (lpbi
->biSize
!= sizeof(BITMAPCOREHEADER
)) {
380 if (lpbi
->biClrUsed
!= 0)
381 return (WORD
) lpbi
->biClrUsed
;
382 bits
= lpbi
->biBitCount
;
385 bits
= lpbc
->bcBitCount
;
395 /* A 24 bitcount DIB has no color table */
400 /****************************************************************************
402 * FUNCTION : DibFromBitmap() *
404 * PURPOSE : Will create a global memory block in DIB format that *
405 * represents the Device-dependent bitmap (DDB) passed in. *
407 * RETURNS : A handle to the DIB *
409 ****************************************************************************/
412 static HANDLE
DibFromBitmap(HBITMAP hbm
, DWORD biStyle
, WORD biBits
, HPALETTE hpal
)
416 BITMAPINFOHEADER FAR
*lpbi
;
426 hpal
= GetStockObject(DEFAULT_PALETTE
);
428 GetObject(hbm
, sizeof (bm
), (LPSTR
) &bm
);
431 biBits
= bm
.bmPlanes
* bm
.bmBitsPixel
;
433 bi
.biSize
= sizeof(BITMAPINFOHEADER
);
434 bi
.biWidth
= bm
.bmWidth
;
435 bi
.biHeight
= bm
.bmHeight
;
437 bi
.biBitCount
= biBits
;
438 bi
.biCompression
= biStyle
;
440 bi
.biXPelsPerMeter
= 0;
441 bi
.biYPelsPerMeter
= 0;
443 bi
.biClrImportant
= 0;
445 dwLen
= bi
.biSize
+ wxPaletteSize(&bi
);
447 hdc
= GetDC((HWND
) NULL
);
448 hpal
= SelectPalette(hdc
, hpal
, FALSE
);
451 hdib
= GlobalAlloc(GHND
, dwLen
);
454 SelectPalette(hdc
, hpal
, FALSE
);
455 ReleaseDC(NULL
, hdc
);
459 #ifdef __WINDOWS_386__
460 lpbi
= (BITMAPINFOHEADER FAR
*) MK_FP32(GlobalLock(hdib
));
462 lpbi
= (BITMAPINFOHEADER FAR
*) GlobalLock(hdib
);
467 /* call GetDIBits with a NULL lpBits param, so it will calculate the
468 * biSizeImage field for us
470 GetDIBits(hdc
, hbm
, 0, (WORD
) bi
.biHeight
,
471 NULL
, (LPBITMAPINFO
) lpbi
, DIB_RGB_COLORS
);
476 /* If the driver did not fill in the biSizeImage field, make one up */
477 if (bi
.biSizeImage
== 0) {
478 bi
.biSizeImage
= WIDTHBYTES((DWORD
)bm
.bmWidth
* biBits
) * bm
.bmHeight
;
480 if (biStyle
!= BI_RGB
)
481 bi
.biSizeImage
= (bi
.biSizeImage
* 3) / 2;
484 /* realloc the buffer big enough to hold all the bits */
485 dwLen
= bi
.biSize
+ wxPaletteSize(&bi
) + bi
.biSizeImage
;
486 if (h
= GlobalReAlloc(hdib
, dwLen
, 0))
492 SelectPalette(hdc
, hpal
, FALSE
);
493 ReleaseDC(NULL
, hdc
);
497 /* call GetDIBits with a NON-NULL lpBits param, and actualy get the
500 #ifdef __WINDOWS_386__
501 lpbi
= (BITMAPINFOHEADER FAR
*) MK_FP32(GlobalLock(hdib
));
503 lpbi
= (BITMAPINFOHEADER FAR
*) GlobalLock(hdib
);
510 (LPSTR
) lpbi
+ (WORD
) lpbi
->biSize
+ wxPaletteSize(lpbi
),
511 (LPBITMAPINFO
) lpbi
, DIB_RGB_COLORS
) == 0) {
514 SelectPalette(hdc
, hpal
, FALSE
);
515 ReleaseDC((HWND
) NULL
, hdc
);
522 SelectPalette(hdc
, hpal
, FALSE
);
523 ReleaseDC(NULL
, hdc
);
528 /************* PRIVATE ROUTINES TO READ/WRITE MORE THAN 64K ***************/
529 /****************************************************************************
531 * FUNCTION : lread(int fh, VOID FAR *pv, DWORD ul) *
533 * PURPOSE : Reads data in steps of 32k till all the data has been read.*
535 * RETURNS : 0 - If read did not proceed correctly. *
536 * number of bytes read otherwise. *
538 ****************************************************************************/
540 static DWORD PASCAL
lread(int fh
, void far
*pv
, DWORD ul
)
543 #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__)
544 BYTE
*hp
= (BYTE
*) pv
;
546 BYTE huge
*hp
= (BYTE huge
*) pv
;
548 while (ul
> (DWORD
) MAXREAD
) {
549 if (_lread(fh
, (LPSTR
) hp
, (WORD
) MAXREAD
) != MAXREAD
)
554 if (_lread(fh
, (LPSTR
) hp
, (WXUINT
) ul
) != (WXUINT
) ul
)
559 /****************************************************************************
561 * FUNCTION : lwrite(int fh, VOID FAR *pv, DWORD ul) *
563 * PURPOSE : Writes data in steps of 32k till all the data is written. *
565 * RETURNS : 0 - If write did not proceed correctly. *
566 * number of bytes written otherwise. *
568 ****************************************************************************/
570 static DWORD PASCAL
lwrite(int fh
, VOID FAR
*pv
, DWORD ul
)
573 #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__)
574 BYTE
*hp
= (BYTE
*) pv
;
576 BYTE huge
*hp
= (BYTE huge
*) pv
;
578 while (ul
> MAXREAD
) {
579 if (_lwrite(fh
, (LPSTR
) hp
, (WORD
) MAXREAD
) != MAXREAD
)
584 if (_lwrite(fh
, (LPSTR
) hp
, (WXUINT
) ul
) != (WXUINT
) ul
)
589 /****************************************************************************
591 * FUNCTION : ReadDIB(hWnd)
593 * PURPOSE : Reads a DIB from a file, obtains a handle to its
594 * BITMAPINFO struct. and loads the DIB. Once the DIB
595 * is loaded, the function also creates a bitmap and
596 * palette out of the DIB for a device-dependent form.
598 * RETURNS : TRUE - DIB loaded and bitmap/palette created
599 * The DIBINIT structure pointed to by pInfo is
600 * filled with the appropriate handles.
603 ****************************************************************************/
604 BOOL
wxReadDIB(LPTSTR lpFileName
, HBITMAP
*bitmap
, HPALETTE
*palette
)
607 LPBITMAPINFOHEADER lpbi
;
614 BOOL bCoreHead
= FALSE
;
617 /* Open the file and get a handle to it's BITMAPINFO */
619 fh
= OpenFile (wxConvertWX2MB(lpFileName
), &of
, OF_READ
);
621 wxLogError(_("Can't open file '%s'"), lpFileName
);
625 hDIB
= GlobalAlloc(GHND
, (DWORD
)(sizeof(BITMAPINFOHEADER
) +
626 256 * sizeof(RGBQUAD
)));
630 #ifdef __WINDOWS_386__
631 lpbi
= (LPBITMAPINFOHEADER
)MK_FP32(GlobalLock(hDIB
));
633 lpbi
= (LPBITMAPINFOHEADER
)GlobalLock(hDIB
);
636 /* read the BITMAPFILEHEADER */
637 if (sizeof (bf
) != _lread (fh
, (LPSTR
)&bf
, sizeof (bf
)))
640 if (bf
.bfType
!= 0x4d42) /* 'BM' */
643 if (sizeof(BITMAPCOREHEADER
) != _lread (fh
, (LPSTR
)lpbi
, sizeof(BITMAPCOREHEADER
)))
646 if (lpbi
->biSize
== sizeof(BITMAPCOREHEADER
))
648 lpbi
->biSize
= sizeof(BITMAPINFOHEADER
);
649 lpbi
->biBitCount
= ((LPBITMAPCOREHEADER
)lpbi
)->bcBitCount
;
650 lpbi
->biPlanes
= ((LPBITMAPCOREHEADER
)lpbi
)->bcPlanes
;
651 lpbi
->biHeight
= ((LPBITMAPCOREHEADER
)lpbi
)->bcHeight
;
652 lpbi
->biWidth
= ((LPBITMAPCOREHEADER
)lpbi
)->bcWidth
;
657 // get to the start of the header and read INFOHEADER
658 _llseek(fh
,sizeof(BITMAPFILEHEADER
),SEEK_SET
);
659 if (sizeof(BITMAPINFOHEADER
) != _lread (fh
, (LPSTR
)lpbi
, sizeof(BITMAPINFOHEADER
)))
663 nNumColors
= (WORD
)lpbi
->biClrUsed
;
664 if ( nNumColors
== 0 )
666 /* no color table for 24-bit, default size otherwise */
667 if (lpbi
->biBitCount
!= 24)
668 nNumColors
= 1 << lpbi
->biBitCount
; /* standard size table */
671 /* fill in some default values if they are zero */
672 if (lpbi
->biClrUsed
== 0)
673 lpbi
->biClrUsed
= nNumColors
;
675 if (lpbi
->biSizeImage
== 0)
677 lpbi
->biSizeImage
= ((((lpbi
->biWidth
* (DWORD
)lpbi
->biBitCount
) + 31) & ~31) >> 3)
681 /* get a proper-sized buffer for header, color table and bits */
683 hDIB
= GlobalReAlloc(hDIB
, lpbi
->biSize
+
684 nNumColors
* sizeof(RGBQUAD
) +
685 lpbi
->biSizeImage
, 0);
686 if (!hDIB
) /* can't resize buffer for loading */
689 #ifdef __WINDOWS_386__
690 lpbi
= (LPBITMAPINFOHEADER
)MK_FP32(GlobalLock(hDIB
));
692 lpbi
= (LPBITMAPINFOHEADER
)GlobalLock(hDIB
);
695 /* read the color table */
697 _lread(fh
, (LPSTR
)(lpbi
) + lpbi
->biSize
, nNumColors
* sizeof(RGBQUAD
));
702 RGBTRIPLE FAR
*pTriple
;
704 _lread(fh
, (LPSTR
)(lpbi
) + lpbi
->biSize
, nNumColors
* sizeof(RGBTRIPLE
));
706 pQuad
= (RGBQUAD FAR
*)((LPSTR
)lpbi
+ lpbi
->biSize
);
707 pTriple
= (RGBTRIPLE FAR
*) pQuad
;
708 for (i
= nNumColors
- 1; i
>= 0; i
--)
710 pQuad
[i
].rgbRed
= pTriple
[i
].rgbtRed
;
711 pQuad
[i
].rgbBlue
= pTriple
[i
].rgbtBlue
;
712 pQuad
[i
].rgbGreen
= pTriple
[i
].rgbtGreen
;
713 pQuad
[i
].rgbReserved
= 0;
717 /* offset to the bits from start of DIB header */
718 offBits
= (WORD
)(lpbi
->biSize
+ nNumColors
* sizeof(RGBQUAD
));
720 if (bf
.bfOffBits
!= 0L)
722 _llseek(fh
,bf
.bfOffBits
,SEEK_SET
);
725 if (lpbi
->biSizeImage
== lread(fh
, (LPSTR
)lpbi
+ offBits
, lpbi
->biSizeImage
))
730 if (!MakeBitmapAndPalette(hDC
, hDIB
, palette
,
755 /****************************************************************************
757 * FUNCTION : MakeBitmapAndPalette
759 * PURPOSE : Given a DIB, creates a bitmap and corresponding palette
760 * to be used for a device-dependent representation of
763 * RETURNS : TRUE --> success. phPal and phBitmap are filled with
764 * appropriate handles. Caller is responsible
765 * for freeing objects.
766 * FALSE --> unable to create objects. both pointer are
769 ****************************************************************************/
770 static BOOL PASCAL
MakeBitmapAndPalette(HDC hDC
, HANDLE hDIB
,
771 HPALETTE
* phPal
, HBITMAP
* phBitmap
)
773 LPBITMAPINFOHEADER lpInfo
;
776 HPALETTE hPalette
, hOldPal
;
779 #ifdef __WINDOWS_386__
780 lpInfo
= (LPBITMAPINFOHEADER
) MK_FP32(GlobalLock(hDIB
));
782 lpInfo
= (LPBITMAPINFOHEADER
) GlobalLock(hDIB
);
785 hPalette
= wxMakeDIBPalette(lpInfo
);
788 // Need to realize palette for converting DIB to bitmap.
789 hOldPal
= SelectPalette(hDC
, hPalette
, TRUE
);
792 lpBits
= (LPSTR
)lpInfo
+ (WORD
)lpInfo
->biSize
+
793 (WORD
)lpInfo
->biClrUsed
* sizeof(RGBQUAD
);
794 hBitmap
= CreateDIBitmap(hDC
, lpInfo
, CBM_INIT
, lpBits
,
795 (LPBITMAPINFO
)lpInfo
, DIB_RGB_COLORS
);
797 SelectPalette(hDC
, hOldPal
, TRUE
);
801 DeleteObject(hPalette
);
810 GlobalUnlock (hDIB
); // glt
815 /****************************************************************************
817 * FUNCTION : wxMakeDIBPalette(lpInfo) *
819 * PURPOSE : Given a BITMAPINFOHEADER, create a palette based on
823 * RETURNS : non-zero - handle of a corresponding palette
824 * zero - unable to create palette
826 ****************************************************************************/
827 HPALETTE
wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo
)
834 /* since biClrUsed field was filled during the loading of the DIB,
835 ** we know it contains the number of colors in the color table.
837 if (lpInfo
->biClrUsed
)
840 npPal = (NPLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) +
841 (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY));
843 npPal
= (LPLOGPALETTE
)malloc(sizeof(LOGPALETTE
) +
844 (WORD
)lpInfo
->biClrUsed
* sizeof(PALETTEENTRY
));
848 npPal
->palVersion
= 0x300;
849 npPal
->palNumEntries
= (WORD
)lpInfo
->biClrUsed
;
851 /* get pointer to the color table */
852 lpRGB
= (RGBQUAD FAR
*)((LPSTR
)lpInfo
+ lpInfo
->biSize
);
854 /* copy colors from the color table to the LogPalette structure */
855 for (i
= 0; (DWORD
)i
< lpInfo
->biClrUsed
; i
++, lpRGB
++)
857 npPal
->palPalEntry
[i
].peRed
= lpRGB
->rgbRed
;
858 npPal
->palPalEntry
[i
].peGreen
= lpRGB
->rgbGreen
;
859 npPal
->palPalEntry
[i
].peBlue
= lpRGB
->rgbBlue
;
860 npPal
->palPalEntry
[i
].peFlags
= 0;
863 hLogPal
= CreatePalette((LPLOGPALETTE
)npPal
);
864 // LocalFree((HANDLE)npPal);
870 /* 24-bit DIB with no color table. return default palette. Another
871 ** option would be to create a 256 color "rainbow" palette to provide
872 ** some good color choices.
875 return((HPALETTE
) GetStockObject(DEFAULT_PALETTE
));
878 bool wxLoadIntoBitmap(wxChar
*filename
, wxBitmap
*bitmap
, wxPalette
**pal
)
880 HBITMAP hBitmap
= NULL
;
881 HPALETTE hPalette
= NULL
;
883 bool success
= (wxReadDIB(filename
, &hBitmap
, &hPalette
) != 0);
888 DeleteObject(hPalette
);
897 *pal
= new wxPalette
;
898 (*pal
)->SetHPALETTE((WXHPALETTE
) hPalette
);
901 #endif // wxUSE_PALETTE
902 DeleteObject(hPalette
);
910 GetObject(hBitmap
, sizeof(bm
), (LPSTR
)&bm
);
912 bitmap
->SetHBITMAP((WXHBITMAP
) hBitmap
);
913 bitmap
->SetWidth(bm
.bmWidth
);
914 bitmap
->SetHeight(bm
.bmHeight
);
915 bitmap
->SetDepth(bm
.bmPlanes
* bm
.bmBitsPixel
);
916 #if WXWIN_COMPATIBILITY_2
918 #endif // WXWIN_COMPATIBILITY_2
924 wxBitmap
*wxLoadBitmap(wxChar
*filename
, wxPalette
**pal
)
926 wxBitmap
*bitmap
= new wxBitmap
;
927 if (wxLoadIntoBitmap(filename
, bitmap
, pal
))
936 //---------------------------------------------------------------------
938 // Function: InitBitmapInfoHeader
940 // Purpose: Does a "standard" initialization of a BITMAPINFOHEADER,
941 // given the Width, Height, and Bits per Pixel for the
944 // By standard, I mean that all the relevant fields are set
945 // to the specified values. biSizeImage is computed, the
946 // biCompression field is set to "no compression," and all
947 // other fields are 0.
949 // Note that DIBs only allow BitsPixel values of 1, 4, 8, or
950 // 24. This routine makes sure that one of these values is
951 // used (whichever is most appropriate for the specified
954 // Parms: lpBmInfoHdr == Far pointer to a BITMAPINFOHEADER structure
956 // dwWidth == Width of DIB (not in Win 3.0 & 3.1, high
958 // dwHeight == Height of DIB (not in Win 3.0 & 3.1, high
960 // nBPP == Bits per Pixel for the DIB.
962 // History: Date Reason
965 //---------------------------------------------------------------------
967 static void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr
,
972 // _fmemset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));
973 memset (lpBmInfoHdr
, 0, sizeof (BITMAPINFOHEADER
));
975 lpBmInfoHdr
->biSize
= sizeof (BITMAPINFOHEADER
);
976 lpBmInfoHdr
->biWidth
= dwWidth
;
977 lpBmInfoHdr
->biHeight
= dwHeight
;
978 lpBmInfoHdr
->biPlanes
= 1;
993 lpBmInfoHdr
->biBitCount
= nBPP
;
994 lpBmInfoHdr
->biSizeImage
= WIDTHBYTES (dwWidth
* nBPP
) * dwHeight
;
1000 LPSTR
wxFindDIBBits (LPSTR lpbi
)
1002 return (lpbi
+ *(LPDWORD
)lpbi
+ wxPaletteSize (lpbi
));
1005 //---------------------------------------------------------------------
1007 // Function: BitmapToDIB
1009 // Purpose: Given a device dependent bitmap and a palette, returns
1010 // a handle to global memory with a DIB spec in it. The
1011 // DIB is rendered using the colors of the palette passed in.
1013 // Stolen almost verbatim from ShowDIB.
1015 // Parms: hBitmap == Handle to device dependent bitmap compatible
1016 // with default screen display device.
1017 // hPal == Palette to render the DDB with. If it's NULL,
1018 // use the default palette.
1020 // History: Date Reason
1023 //---------------------------------------------------------------------
1025 HANDLE
wxBitmapToDIB (HBITMAP hBitmap
, HPALETTE hPal
)
1028 BITMAPINFOHEADER bmInfoHdr
;
1029 LPBITMAPINFOHEADER lpbmInfoHdr
;
1033 HPALETTE hOldPal
= NULL
;
1035 // Do some setup -- make sure the Bitmap passed in is valid,
1036 // get info on the bitmap (like its height, width, etc.),
1037 // then setup a BITMAPINFOHEADER.
1042 if (!GetObject (hBitmap
, sizeof (Bitmap
), (LPSTR
) &Bitmap
))
1045 InitBitmapInfoHeader (&bmInfoHdr
,
1048 Bitmap
.bmPlanes
* Bitmap
.bmBitsPixel
);
1051 // Now allocate memory for the DIB. Then, set the BITMAPINFOHEADER
1052 // into this memory, and find out where the bitmap bits go.
1054 hDIB
= GlobalAlloc (GHND
, sizeof (BITMAPINFOHEADER
) +
1055 wxPaletteSize ((LPSTR
) &bmInfoHdr
) + bmInfoHdr
.biSizeImage
);
1060 #ifdef __WINDOWS_386__
1061 lpbmInfoHdr
= (LPBITMAPINFOHEADER
) MK_FP32(GlobalLock (hDIB
));
1063 lpbmInfoHdr
= (LPBITMAPINFOHEADER
) GlobalLock (hDIB
);
1066 *lpbmInfoHdr
= bmInfoHdr
;
1067 lpBits
= wxFindDIBBits ((LPSTR
) lpbmInfoHdr
);
1070 // Now, we need a DC to hold our bitmap. If the app passed us
1071 // a palette, it should be selected into the DC.
1073 hMemDC
= GetDC (NULL
);
1077 hOldPal
= SelectPalette (hMemDC
, hPal
, FALSE
);
1078 RealizePalette (hMemDC
);
1083 // We're finally ready to get the DIB. Call the driver and let
1084 // it party on our bitmap. It will fill in the color table,
1085 // and bitmap bits of our global memory block.
1087 if (!GetDIBits (hMemDC
,
1092 (LPBITMAPINFO
) lpbmInfoHdr
,
1095 GlobalUnlock (hDIB
);
1100 GlobalUnlock (hDIB
);
1103 // Finally, clean up and return.
1106 SelectPalette (hMemDC
, hOldPal
, FALSE
);
1108 ReleaseDC (NULL
, hMemDC
);
1113 bool wxSaveBitmap(wxChar
*filename
, wxBitmap
*bitmap
, wxPalette
*colourmap
)
1115 HPALETTE hPalette
= 0;
1118 hPalette
= (HPALETTE
) colourmap
->GetHPALETTE();
1119 #endif // wxUSE_PALETTE
1121 HANDLE dibHandle
= wxBitmapToDIB((HBITMAP
) bitmap
->GetHBITMAP(), hPalette
);
1124 bool success
= (WriteDIB(filename
, dibHandle
) != 0);
1125 GlobalFree(dibHandle
);