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 // calculate the number of palette entries needed for the bitmap with this
54 // number of bits per pixel
55 static WORD
wxGetNumOfBitmapColors(WORD bitsPerPixel
)
57 // only 1, 4 and 8bpp bitmaps use palettes (well, they could be used with
58 // 24bpp ones too but we don't support this as I think it's quite uncommon)
59 return bitsPerPixel
<= 8 ? 1 << bitsPerPixel
: 0;
62 // ============================================================================
64 // ============================================================================
66 // ----------------------------------------------------------------------------
68 // ----------------------------------------------------------------------------
70 bool wxDIB::Create(int width
, int height
, int depth
)
72 // we don't handle the palette yet
73 wxASSERT_MSG( depth
== 24 || depth
== 32,
74 _T("unsupported image depth in wxDIB::Create()") );
76 static const int infosize
= sizeof(BITMAPINFOHEADER
);
78 BITMAPINFO
*info
= (BITMAPINFO
*)malloc(infosize
);
79 wxCHECK_MSG( info
, NULL
, _T("malloc(BITMAPINFO) failed") );
81 memset(info
, 0, infosize
);
83 info
->bmiHeader
.biSize
= infosize
;
84 info
->bmiHeader
.biWidth
= width
;
86 // we use positive height here which corresponds to a DIB with normal, i.e.
87 // bottom to top, order -- normally using negative height (which means
88 // reversed for MS and hence natural for all the normal people top to
89 // bottom line scan order) could be used to avoid the need for the image
90 // reversal in Create(image) but this doesn't work under NT, only Win9x!
91 info
->bmiHeader
.biHeight
= height
;
93 info
->bmiHeader
.biPlanes
= 1;
94 info
->bmiHeader
.biBitCount
= depth
;
95 info
->bmiHeader
.biSizeImage
= GetLineSize(width
, depth
)*height
;
97 m_handle
= ::CreateDIBSection
99 0, // hdc (unused with DIB_RGB_COLORS)
100 info
, // bitmap description
101 DIB_RGB_COLORS
, // use RGB, not palette
102 &m_data
, // [out] DIB bits
103 NULL
, // don't use file mapping
104 0 // file mapping offset (not used here)
111 wxLogLastError(wxT("CreateDIBSection"));
123 // ----------------------------------------------------------------------------
124 // Loading/saving the DIBs
125 // ----------------------------------------------------------------------------
127 bool wxDIB::Load(const wxString
& filename
)
129 m_handle
= (HBITMAP
)::LoadImage
134 0, 0, // don't specify the size
135 LR_CREATEDIBSECTION
| LR_LOADFROMFILE
139 wxLogLastError(_T("LoadImage(LR_CREATEDIBSECTION | LR_LOADFROMFILE)"));
147 // ----------------------------------------------------------------------------
149 // ----------------------------------------------------------------------------
151 void wxDIB::DoGetObject() const
153 // only do something if we have a valid DIB but we don't [yet] have valid
155 if ( m_handle
&& !m_data
)
157 // although all the info we need is in BITMAP and so we don't really
158 // need DIBSECTION we still ask for it as modifying the bit values only
159 // works for the real DIBs and not for the bitmaps and it's better to
160 // check for this now rather than trying to find out why it doesn't
163 if ( !::GetObject(m_handle
, sizeof(ds
), &ds
) )
165 wxLogLastError(_T("GetObject(hDIB)"));
169 wxDIB
*self
= wxConstCast(this, wxDIB
);
171 self
->m_width
= ds
.dsBm
.bmWidth
;
172 self
->m_height
= ds
.dsBm
.bmHeight
;
173 self
->m_depth
= ds
.dsBm
.bmBitsPixel
;
174 self
->m_data
= ds
.dsBm
.bmBits
;
178 // ----------------------------------------------------------------------------
179 // DDB <-> DIB conversions
180 // ----------------------------------------------------------------------------
182 HBITMAP
wxDIB::CreateDDB(HDC hdc
) const
184 wxCHECK_MSG( m_handle
, 0, _T("wxDIB::CreateDDB(): invalid object") );
187 if ( !::GetObject(m_handle
, sizeof(ds
), &ds
) )
189 wxLogLastError(_T("GetObject(hDIB)"));
194 return ConvertToBitmap((BITMAPINFO
*)&ds
.dsBmih
, hdc
, ds
.dsBm
.bmBits
);
198 HBITMAP
wxDIB::ConvertToBitmap(const BITMAPINFO
*pbmi
, HDC hdc
, void *bits
)
200 wxCHECK_MSG( pbmi
, 0, _T("invalid DIB in ConvertToBitmap") );
202 // here we get BITMAPINFO struct followed by the actual bitmap bits and
203 // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info
204 const BITMAPINFOHEADER
*pbmih
= &pbmi
->bmiHeader
;
206 // get the pointer to the start of the real image data if we have a plain
207 // DIB and not a DIB section (in the latter case the pointer must be passed
208 // to us by the caller)
211 // we must skip over the colour table to get to the image data
213 // biClrUsed has the number of colors but it may be not initialized at
215 int numColors
= pbmih
->biClrUsed
;
218 numColors
= wxGetNumOfBitmapColors(pbmih
->biBitCount
);
221 bits
= (char *)pbmih
+ sizeof(*pbmih
) + numColors
*sizeof(RGBQUAD
);
224 HBITMAP hbmp
= ::CreateDIBitmap
226 hdc
? hdc
// create bitmap compatible
227 : ScreenHDC(), // with this DC
228 pbmih
, // used to get size &c
229 CBM_INIT
, // initialize bitmap bits too
230 bits
, // ... using this data
231 pbmi
, // this is used for palette only
232 DIB_RGB_COLORS
// direct or indexed palette?
237 wxLogLastError(wxT("CreateDIBitmap"));
244 size_t wxDIB::ConvertFromBitmap(BITMAPINFO
*pbi
, HBITMAP hbmp
)
246 wxASSERT_MSG( hbmp
, wxT("invalid bmp can't be converted to DIB") );
248 // prepare all the info we need
250 if ( !::GetObject(hbmp
, sizeof(bm
), &bm
) )
252 wxLogLastError(wxT("GetObject(bitmap)"));
257 // calculate the number of bits per pixel and the number of items in
258 // bmiColors array (whose meaning depends on the bitmap format)
259 WORD biBits
= bm
.bmPlanes
* bm
.bmBitsPixel
;
260 WORD biColors
= wxGetNumOfBitmapColors(biBits
);
262 // we need a BITMAPINFO anyhow and if we're not given a pointer to it we
266 bool wantSizeOnly
= pbi
== NULL
;
270 // just for convenience
271 const int h
= bm
.bmHeight
;
274 BITMAPINFOHEADER
& bi
= pbi
->bmiHeader
;
276 bi
.biSize
= sizeof(BITMAPINFOHEADER
);
277 bi
.biWidth
= bm
.bmWidth
;
280 bi
.biBitCount
= biBits
;
282 // memory we need for BITMAPINFO only
283 DWORD dwLen
= bi
.biSize
+ biColors
* sizeof(RGBQUAD
);
285 // first get the image size
287 if ( !::GetDIBits(hdc
, hbmp
, 0, h
, NULL
, pbi
, DIB_RGB_COLORS
) )
289 wxLogLastError(wxT("GetDIBits(NULL)"));
296 // and now copy the bits
297 void *image
= (char *)pbi
+ dwLen
;
298 if ( !::GetDIBits(hdc
, hbmp
, 0, h
, image
, pbi
, DIB_RGB_COLORS
) )
300 wxLogLastError(wxT("GetDIBits"));
306 // return the total size
307 return dwLen
+ bi
.biSizeImage
;
310 // ----------------------------------------------------------------------------
312 // ----------------------------------------------------------------------------
316 wxPalette
*wxDIB::CreatePalette() const
318 wxCHECK_MSG( m_handle
, NULL
, _T("wxDIB::CreatePalette(): invalid object") );
321 if ( !::GetObject(m_handle
, sizeof(ds
), &ds
) )
323 wxLogLastError(_T("GetObject(hDIB)"));
328 // how many colours are we going to have in the palette?
329 DWORD biClrUsed
= ds
.dsBmih
.biClrUsed
;
332 // biClrUsed field might not be set
333 biClrUsed
= 1 << ds
.dsBmih
.biBitCount
;
336 if ( biClrUsed
> 256 )
338 // only 8bpp bitmaps (and less) have palettes, so we surely don't
340 // NB: another possibility would be to return
341 // GetStockObject(DEFAULT_PALETTE) or even CreateHalftonePalette()?
345 // LOGPALETTE struct has only 1 element in palPalEntry array, we're
346 // going to have biClrUsed of them so add necessary space
347 LOGPALETTE
*pPalette
= (LOGPALETTE
*)
348 malloc(sizeof(LOGPALETTE
) + (biClrUsed
- 1)*sizeof(PALETTEENTRY
));
349 wxCHECK_MSG( pPalette
, NULL
, _T("out of memory") );
351 // initialize the palette header
352 pPalette
->palVersion
= 0x300; // magic number, not in docs but works
353 pPalette
->palNumEntries
= biClrUsed
;
355 // and the colour table (it starts right after the end of the header)
356 const RGBQUAD
*pRGB
= (RGBQUAD
*)((char *)&ds
.dsBmih
+ ds
.dsBmih
.biSize
);
357 for ( DWORD i
= 0; i
< biClrUsed
; i
++, pRGB
++ )
359 pPalette
->palPalEntry
[i
].peRed
= pRGB
->rgbRed
;
360 pPalette
->palPalEntry
[i
].peGreen
= pRGB
->rgbGreen
;
361 pPalette
->palPalEntry
[i
].peBlue
= pRGB
->rgbBlue
;
362 pPalette
->palPalEntry
[i
].peFlags
= 0;
365 HPALETTE hPalette
= ::CreatePalette(pPalette
);
371 wxLogLastError(_T("CreatePalette"));
376 wxPalette
*palette
= new wxPalette
;
377 palette
->SetHPALETTE((WXHPALETTE
)hPalette
);
382 #endif // wxUSE_PALETTE
384 // ----------------------------------------------------------------------------
386 // ----------------------------------------------------------------------------
390 bool wxDIB::Create(const wxImage
& image
)
392 wxCHECK_MSG( image
.Ok(), false, _T("invalid wxImage in wxDIB ctor") );
394 const int h
= image
.GetHeight();
395 const int w
= image
.GetWidth();
397 // if we have alpha channel, we need to create a 32bpp RGBA DIB, otherwise
398 // a 24bpp RGB is sufficient
399 const bool hasAlpha
= image
.HasAlpha();
400 const int bpp
= hasAlpha
? 32 : 24;
402 if ( !Create(w
, h
, bpp
) )
405 // DIBs are stored in bottom to top order (see also the comment above in
406 // Create()) so we need to copy bits line by line and starting from the end
407 const int srcBytesPerLine
= w
* 3;
408 const int dstBytesPerLine
= GetLineSize(w
, bpp
);
409 const unsigned char *src
= image
.GetData() + ((h
- 1) * srcBytesPerLine
);
410 const unsigned char *alpha
= hasAlpha
? image
.GetAlpha() + (h
- 1)*w
: NULL
;
411 unsigned char *dstLineStart
= (unsigned char *)m_data
;
412 for ( int y
= 0; y
< h
; y
++ )
415 unsigned char *dst
= dstLineStart
;
416 for ( int x
= 0; x
< w
; x
++ )
418 // also, the order of RGB is inversed for DIBs
429 // pass to the previous line in the image
430 src
-= 2*srcBytesPerLine
;
434 // and to the next one in the DIB
435 dstLineStart
+= dstBytesPerLine
;
441 #endif // wxUSE_IMAGE
443 // ============================================================================
444 // old DIB code, to be integrated in wxDIB class
445 // ============================================================================
448 * Routines for dealing with Device Independent Bitmaps.
450 * wxReadDIB() - Reads a DIB
451 * wxWriteDIB() - Writes a global handle in CF_DIB format
453 * wxPaletteSize() - Calculates the palette size in bytes
455 * wxDibNumColors() - Determines the number of colors in DIB
456 * wxDibFromBitmap() - Creates a DIB repr. the DDB passed in.
457 * lread() - Private routine to read more than 64k
458 * lwrite() - Private routine to write more than 64k
462 /* flags for _lseek */
468 #define MAXREAD 32768 /* Number of bytes to be read during */
469 /* each read operation. */
471 /* Header signatutes for various resources */
472 #define BFT_ICON 0x4349 /* 'IC' */
473 #define BFT_BITMAP 0x4d42 /* 'BM' */
474 #define BFT_CURSOR 0x5450 /* 'PT(' */
476 /* macro to determine if resource is a DIB */
477 #define ISDIB(bft) ((bft) == BFT_BITMAP)
479 /* Macro to align given value to the closest DWORD (unsigned long ) */
480 #define ALIGNULONG(i) ((i+3)/4*4)
482 /* Macro to determine to round off the given value to the closest byte */
483 #define WIDTHBYTES(i) ((i+31)/32*4)
485 #define PALVERSION 0x300
486 #define MAXPALETTE 256 /* max. # supported palette entries */
488 static DWORD
lread(int fh
, VOID FAR
*pv
, DWORD ul
);
489 static DWORD
lwrite(int fh
, VOID FAR
*pv
, DWORD ul
);
491 static bool wxWriteDIB (LPTSTR szFile
,HANDLE hdib
);
492 WORD
wxPaletteSize (VOID FAR
* pv
); // This is non-static as some apps use it externally
493 static WORD
wxDibNumColors (VOID FAR
* pv
);
494 static bool wxMakeBitmapAndPalette(HDC
,HANDLE
,HPALETTE
*,HBITMAP
*);
497 * FUNCTION : wxWriteDIB(LPSTR szFile,HANDLE hdib)
498 * PURPOSE : Write a global handle in CF_DIB format to a file.
499 * RETURNS : TRUE - if successful.
503 static bool wxWriteDIB(LPTSTR szFile
, HANDLE hdib
)
505 BITMAPFILEHEADER hdr
;
506 LPBITMAPINFOHEADER lpbi
;
513 fh
= OpenFile(wxConvertWX2MB(szFile
), &of
, OF_CREATE
| OF_READWRITE
);
517 lpbi
= (LPBITMAPINFOHEADER
) GlobalLock(hdib
);
519 /* Fill in the fields of the file header */
520 hdr
.bfType
= BFT_BITMAP
;
521 hdr
.bfSize
= GlobalSize(hdib
) + sizeof(BITMAPFILEHEADER
);
524 hdr
.bfOffBits
= (DWORD
) sizeof(BITMAPFILEHEADER
) + lpbi
->biSize
+
527 /* Write the file header */
528 _lwrite(fh
, (LPSTR
) &hdr
, sizeof(BITMAPFILEHEADER
));
530 /* Write the DIB header and the bits */
531 lwrite(fh
, (LPSTR
) lpbi
, GlobalSize(hdib
));
539 * FUNCTION : wxPaletteSize(VOID FAR * pv)
540 * PURPOSE : Calculates the palette size in bytes. If the info. block
541 * is of the BITMAPCOREHEADER type, the number of colors is
542 * multiplied by 3 to give the palette size, otherwise the
543 * number of colors is multiplied by 4.
544 * RETURNS : Palette size in number of bytes.
547 WORD
wxPaletteSize(VOID FAR
* pv
)
549 LPBITMAPINFOHEADER lpbi
;
552 lpbi
= (LPBITMAPINFOHEADER
) pv
;
553 NumColors
= wxDibNumColors(lpbi
);
555 if (lpbi
->biSize
== sizeof(BITMAPCOREHEADER
))
556 return (WORD
)(NumColors
* sizeof(RGBTRIPLE
));
558 return (WORD
)(NumColors
* sizeof(RGBQUAD
));
562 * FUNCTION : wxDibNumColors(VOID FAR * pv)
563 * PURPOSE : Determines the number of colors in the DIB by looking at
564 * the BitCount filed in the info block.
565 * RETURNS : The number of colors in the DIB. *
568 static WORD
wxDibNumColors(VOID FAR
*pv
)
571 BITMAPINFOHEADER
*lpbi
;
572 BITMAPCOREHEADER
*lpbc
;
574 lpbi
= ((BITMAPINFOHEADER
*) pv
);
575 lpbc
= ((BITMAPCOREHEADER
*) pv
);
577 /* With the BITMAPINFO format headers, the size of the palette
578 * is in biClrUsed, whereas in the BITMAPCORE - style headers, it
579 * is dependent on the bits per pixel ( = 2 raised to the power of
582 if (lpbi
->biSize
!= sizeof(BITMAPCOREHEADER
)) {
583 if (lpbi
->biClrUsed
!= 0)
584 return (WORD
) lpbi
->biClrUsed
;
585 bits
= lpbi
->biBitCount
;
588 bits
= lpbc
->bcBitCount
;
598 /* A 24 bitcount DIB has no color table */
604 * FUNCTION : lread(int fh, VOID FAR *pv, DWORD ul)
605 * PURPOSE : Reads data in steps of 32k till all the data has been read.
606 * RETURNS : 0 - If read did not proceed correctly.
607 * number of bytes read otherwise.
610 static DWORD
lread(int fh
, void far
*pv
, DWORD ul
)
613 #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__)
614 BYTE
*hp
= (BYTE
*) pv
;
616 BYTE huge
*hp
= (BYTE huge
*) pv
;
618 while (ul
> (DWORD
) MAXREAD
) {
619 if (_lread(fh
, (LPSTR
) hp
, (WORD
) MAXREAD
) != MAXREAD
)
624 if (_lread(fh
, (LPSTR
) hp
, (WXUINT
) ul
) != (WXUINT
) ul
)
630 * FUNCTION : lwrite(int fh, VOID FAR *pv, DWORD ul)
631 * PURPOSE : Writes data in steps of 32k till all the data is written.
632 * RETURNS : 0 - If write did not proceed correctly.
633 * number of bytes written otherwise.
636 static DWORD
lwrite(int fh
, VOID FAR
*pv
, DWORD ul
)
639 #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__)
640 BYTE
*hp
= (BYTE
*) pv
;
642 BYTE huge
*hp
= (BYTE huge
*) pv
;
644 while (ul
> MAXREAD
) {
645 if (_lwrite(fh
, (LPSTR
) hp
, (WORD
) MAXREAD
) != MAXREAD
)
650 if (_lwrite(fh
, (LPSTR
) hp
, (WXUINT
) ul
) != (WXUINT
) ul
)
656 * FUNCTION : wxReadDIB(hWnd)
657 * PURPOSE : Reads a DIB from a file, obtains a handle to its
658 * BITMAPINFO struct. and loads the DIB. Once the DIB
659 * is loaded, the function also creates a bitmap and
660 * palette out of the DIB for a device-dependent form.
661 * RETURNS : TRUE - DIB loaded and bitmap/palette created
662 * The DIBINIT structure pointed to by pInfo is
663 * filled with the appropriate handles.
667 bool wxReadDIB(LPTSTR lpFileName
, HBITMAP
*bitmap
, HPALETTE
*palette
)
670 LPBITMAPINFOHEADER lpbi
;
677 bool bCoreHead
= FALSE
;
680 /* Open the file and get a handle to it's BITMAPINFO */
682 fh
= OpenFile (wxConvertWX2MB(lpFileName
), &of
, OF_READ
);
684 wxLogError(_("Can't open file '%s'"), lpFileName
);
688 hDIB
= GlobalAlloc(GHND
, (DWORD
)(sizeof(BITMAPINFOHEADER
) +
689 256 * sizeof(RGBQUAD
)));
693 lpbi
= (LPBITMAPINFOHEADER
)GlobalLock(hDIB
);
695 /* read the BITMAPFILEHEADER */
696 if (sizeof (bf
) != _lread (fh
, (LPSTR
)&bf
, sizeof (bf
)))
699 if (bf
.bfType
!= 0x4d42) /* 'BM' */
702 if (sizeof(BITMAPCOREHEADER
) != _lread (fh
, (LPSTR
)lpbi
, sizeof(BITMAPCOREHEADER
)))
705 if (lpbi
->biSize
== sizeof(BITMAPCOREHEADER
))
707 lpbi
->biSize
= sizeof(BITMAPINFOHEADER
);
708 lpbi
->biBitCount
= ((LPBITMAPCOREHEADER
)lpbi
)->bcBitCount
;
709 lpbi
->biPlanes
= ((LPBITMAPCOREHEADER
)lpbi
)->bcPlanes
;
710 lpbi
->biHeight
= ((LPBITMAPCOREHEADER
)lpbi
)->bcHeight
;
711 lpbi
->biWidth
= ((LPBITMAPCOREHEADER
)lpbi
)->bcWidth
;
716 // get to the start of the header and read INFOHEADER
717 _llseek(fh
,sizeof(BITMAPFILEHEADER
),SEEK_SET
);
718 if (sizeof(BITMAPINFOHEADER
) != _lread (fh
, (LPSTR
)lpbi
, sizeof(BITMAPINFOHEADER
)))
722 nNumColors
= (WORD
)lpbi
->biClrUsed
;
723 if ( nNumColors
== 0 )
725 /* no color table for 24-bit, default size otherwise */
726 if (lpbi
->biBitCount
!= 24)
727 nNumColors
= 1 << lpbi
->biBitCount
; /* standard size table */
730 /* fill in some default values if they are zero */
731 if (lpbi
->biClrUsed
== 0)
732 lpbi
->biClrUsed
= nNumColors
;
734 if (lpbi
->biSizeImage
== 0)
736 lpbi
->biSizeImage
= ((((lpbi
->biWidth
* (DWORD
)lpbi
->biBitCount
) + 31) & ~31) >> 3)
740 /* get a proper-sized buffer for header, color table and bits */
742 hDIB
= GlobalReAlloc(hDIB
, lpbi
->biSize
+
743 nNumColors
* sizeof(RGBQUAD
) +
744 lpbi
->biSizeImage
, 0);
745 if (!hDIB
) /* can't resize buffer for loading */
748 lpbi
= (LPBITMAPINFOHEADER
)GlobalLock(hDIB
);
750 /* read the color table */
752 _lread(fh
, (LPSTR
)(lpbi
) + lpbi
->biSize
, nNumColors
* sizeof(RGBQUAD
));
757 RGBTRIPLE FAR
*pTriple
;
759 _lread(fh
, (LPSTR
)(lpbi
) + lpbi
->biSize
, nNumColors
* sizeof(RGBTRIPLE
));
761 pQuad
= (RGBQUAD FAR
*)((LPSTR
)lpbi
+ lpbi
->biSize
);
762 pTriple
= (RGBTRIPLE FAR
*) pQuad
;
763 for (i
= nNumColors
- 1; i
>= 0; i
--)
765 pQuad
[i
].rgbRed
= pTriple
[i
].rgbtRed
;
766 pQuad
[i
].rgbBlue
= pTriple
[i
].rgbtBlue
;
767 pQuad
[i
].rgbGreen
= pTriple
[i
].rgbtGreen
;
768 pQuad
[i
].rgbReserved
= 0;
772 /* offset to the bits from start of DIB header */
773 offBits
= (WORD
)(lpbi
->biSize
+ nNumColors
* sizeof(RGBQUAD
));
775 if (bf
.bfOffBits
!= 0L)
777 _llseek(fh
,bf
.bfOffBits
,SEEK_SET
);
780 if (lpbi
->biSizeImage
== lread(fh
, (LPSTR
)lpbi
+ offBits
, lpbi
->biSizeImage
))
785 if (!wxMakeBitmapAndPalette(hDC
, hDIB
, palette
,
811 * FUNCTION : wxMakeBitmapAndPalette
812 * PURPOSE : Given a DIB, creates a bitmap and corresponding palette
813 * to be used for a device-dependent representation of
815 * RETURNS : TRUE --> success. phPal and phBitmap are filled with
816 * appropriate handles. Caller is responsible
817 * for freeing objects.
818 * FALSE --> unable to create objects. both pointer are
822 static bool wxMakeBitmapAndPalette(HDC hDC
, HANDLE hDIB
,
823 HPALETTE
* phPal
, HBITMAP
* phBitmap
)
825 LPBITMAPINFOHEADER lpInfo
;
828 HPALETTE hPalette
, hOldPal
;
831 lpInfo
= (LPBITMAPINFOHEADER
) GlobalLock(hDIB
);
833 hPalette
= wxMakeDIBPalette(lpInfo
);
836 // Need to realize palette for converting DIB to bitmap.
837 hOldPal
= SelectPalette(hDC
, hPalette
, TRUE
);
840 lpBits
= (LPSTR
)lpInfo
+ (WORD
)lpInfo
->biSize
+
841 (WORD
)lpInfo
->biClrUsed
* sizeof(RGBQUAD
);
842 hBitmap
= CreateDIBitmap(hDC
, lpInfo
, CBM_INIT
, lpBits
,
843 (LPBITMAPINFO
)lpInfo
, DIB_RGB_COLORS
);
845 SelectPalette(hDC
, hOldPal
, TRUE
);
849 DeleteObject(hPalette
);
858 GlobalUnlock (hDIB
); // glt
864 * FUNCTION : wxMakeDIBPalette(lpInfo)
865 * PURPOSE : Given a BITMAPINFOHEADER, create a palette based on
867 * RETURNS : non-zero - handle of a corresponding palette
868 * zero - unable to create palette
871 HPALETTE
wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo
)
878 /* since biClrUsed field was filled during the loading of the DIB,
879 * we know it contains the number of colors in the color table.
881 if (lpInfo
->biClrUsed
)
883 npPal
= (LPLOGPALETTE
)malloc(sizeof(LOGPALETTE
) +
884 (WORD
)lpInfo
->biClrUsed
* sizeof(PALETTEENTRY
));
888 npPal
->palVersion
= 0x300;
889 npPal
->palNumEntries
= (WORD
)lpInfo
->biClrUsed
;
891 /* get pointer to the color table */
892 lpRGB
= (RGBQUAD FAR
*)((LPSTR
)lpInfo
+ lpInfo
->biSize
);
894 /* copy colors from the color table to the LogPalette structure */
895 for (i
= 0; (DWORD
)i
< lpInfo
->biClrUsed
; i
++, lpRGB
++)
897 npPal
->palPalEntry
[i
].peRed
= lpRGB
->rgbRed
;
898 npPal
->palPalEntry
[i
].peGreen
= lpRGB
->rgbGreen
;
899 npPal
->palPalEntry
[i
].peBlue
= lpRGB
->rgbBlue
;
900 npPal
->palPalEntry
[i
].peFlags
= 0;
903 hLogPal
= CreatePalette((LPLOGPALETTE
)npPal
);
909 /* 24-bit DIB with no color table. Return default palette. Another
910 * option would be to create a 256 color "rainbow" palette to provide
911 * some good color choices.
914 return((HPALETTE
) GetStockObject(DEFAULT_PALETTE
));
919 * Function: InitBitmapInfoHeader
921 * Purpose: Does a "standard" initialization of a BITMAPINFOHEADER,
922 * given the Width, Height, and Bits per Pixel for the
925 * By standard, I mean that all the relevant fields are set
926 * to the specified values. biSizeImage is computed, the
927 * biCompression field is set to "no compression," and all
928 * other fields are 0.
930 * Note that DIBs only allow BitsPixel values of 1, 4, 8, or
931 * 24. This routine makes sure that one of these values is
932 * used (whichever is most appropriate for the specified
935 * Parms: lpBmInfoHdr == Far pointer to a BITMAPINFOHEADER structure
937 * dwWidth == Width of DIB (not in Win 3.0 & 3.1, high
939 * dwHeight == Height of DIB (not in Win 3.0 & 3.1, high
941 * nBPP == Bits per Pixel for the DIB.
945 static void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr
,
950 // _fmemset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));
951 memset (lpBmInfoHdr
, 0, sizeof (BITMAPINFOHEADER
));
953 lpBmInfoHdr
->biSize
= sizeof (BITMAPINFOHEADER
);
954 lpBmInfoHdr
->biWidth
= dwWidth
;
955 lpBmInfoHdr
->biHeight
= dwHeight
;
956 lpBmInfoHdr
->biPlanes
= 1;
971 lpBmInfoHdr
->biBitCount
= nBPP
;
972 lpBmInfoHdr
->biSizeImage
= WIDTHBYTES (dwWidth
* nBPP
) * dwHeight
;
975 LPSTR
wxFindDIBBits (LPSTR lpbi
)
977 return (lpbi
+ *(LPDWORD
)lpbi
+ wxPaletteSize (lpbi
));
981 * Function: BitmapToDIB
983 * Purpose: Given a device dependent bitmap and a palette, returns
984 * a handle to global memory with a DIB spec in it. The
985 * DIB is rendered using the colors of the palette passed in.
987 * Parms: hBitmap == Handle to device dependent bitmap compatible
988 * with default screen display device.
989 * hPal == Palette to render the DDB with. If it's NULL,
990 * use the default palette.
993 HANDLE
wxBitmapToDIB (HBITMAP hBitmap
, HPALETTE hPal
)
996 BITMAPINFOHEADER bmInfoHdr
;
997 LPBITMAPINFOHEADER lpbmInfoHdr
;
1001 HPALETTE hOldPal
= NULL
;
1003 // Do some setup -- make sure the Bitmap passed in is valid,
1004 // get info on the bitmap (like its height, width, etc.),
1005 // then setup a BITMAPINFOHEADER.
1010 if (!GetObject (hBitmap
, sizeof (Bitmap
), (LPSTR
) &Bitmap
))
1013 InitBitmapInfoHeader (&bmInfoHdr
,
1016 Bitmap
.bmPlanes
* Bitmap
.bmBitsPixel
);
1018 // Now allocate memory for the DIB. Then, set the BITMAPINFOHEADER
1019 // into this memory, and find out where the bitmap bits go.
1021 hDIB
= GlobalAlloc (GHND
, sizeof (BITMAPINFOHEADER
) +
1022 wxPaletteSize ((LPSTR
) &bmInfoHdr
) + bmInfoHdr
.biSizeImage
);
1027 lpbmInfoHdr
= (LPBITMAPINFOHEADER
) GlobalLock (hDIB
);
1029 *lpbmInfoHdr
= bmInfoHdr
;
1030 lpBits
= wxFindDIBBits ((LPSTR
) lpbmInfoHdr
);
1033 // Now, we need a DC to hold our bitmap. If the app passed us
1034 // a palette, it should be selected into the DC.
1036 hMemDC
= GetDC (NULL
);
1040 hOldPal
= SelectPalette (hMemDC
, hPal
, FALSE
);
1041 RealizePalette (hMemDC
);
1044 // We're finally ready to get the DIB. Call the driver and let
1045 // it party on our bitmap. It will fill in the color table,
1046 // and bitmap bits of our global memory block.
1048 if (!GetDIBits (hMemDC
, hBitmap
, 0, Bitmap
.bmHeight
, lpBits
,
1049 (LPBITMAPINFO
) lpbmInfoHdr
, DIB_RGB_COLORS
))
1051 GlobalUnlock (hDIB
);
1056 GlobalUnlock (hDIB
);
1058 // Finally, clean up and return.
1061 SelectPalette (hMemDC
, hOldPal
, FALSE
);
1063 ReleaseDC (NULL
, hMemDC
);
1068 bool wxSaveBitmap(wxChar
*filename
, wxBitmap
*bitmap
, wxPalette
*palette
)
1070 HPALETTE hPalette
= 0;
1073 hPalette
= (HPALETTE
) palette
->GetHPALETTE();
1074 #endif // wxUSE_PALETTE
1076 HANDLE dibHandle
= wxBitmapToDIB((HBITMAP
) bitmap
->GetHBITMAP(), hPalette
);
1079 bool success
= (wxWriteDIB(filename
, dibHandle
) != 0);
1080 GlobalFree(dibHandle
);