]> git.saurik.com Git - wxWidgets.git/blob - src/msw/bitmap.cpp
1. small fix in wxDirDialog: SHBrowseForFolder() doesn't like '/'s
[wxWidgets.git] / src / msw / bitmap.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: bitmap.cpp
3 // Purpose: wxBitmap
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "bitmap.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include <stdio.h>
33
34 #include "wx/list.h"
35 #include "wx/utils.h"
36 #include "wx/app.h"
37 #include "wx/palette.h"
38 #include "wx/dcmemory.h"
39 #include "wx/bitmap.h"
40 #include "wx/icon.h"
41 #endif
42
43 #include "wx/msw/private.h"
44 #include "wx/log.h"
45
46 #include "wx/msw/dib.h"
47 #include "wx/image.h"
48
49 // ----------------------------------------------------------------------------
50 // macros
51 // ----------------------------------------------------------------------------
52
53 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
54 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
55
56 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
57
58 // ============================================================================
59 // implementation
60 // ============================================================================
61
62 // ----------------------------------------------------------------------------
63 // wxBitmapRefData
64 // ----------------------------------------------------------------------------
65
66 wxBitmapRefData::wxBitmapRefData()
67 {
68 m_quality = 0;
69 m_selectedInto = NULL;
70 m_numColors = 0;
71 m_bitmapMask = NULL;
72 m_hBitmap = (WXHBITMAP) NULL;
73 }
74
75 void wxBitmapRefData::Free()
76 {
77 wxASSERT_MSG( !m_selectedInto,
78 wxT("deleting bitmap still selected into wxMemoryDC") );
79
80 if ( m_hBitmap)
81 {
82 if ( !::DeleteObject((HBITMAP)m_hBitmap) )
83 {
84 wxLogLastError("DeleteObject(hbitmap)");
85 }
86 }
87
88 delete m_bitmapMask;
89 m_bitmapMask = NULL;
90 }
91
92 // ----------------------------------------------------------------------------
93 // wxBitmap creation
94 // ----------------------------------------------------------------------------
95
96 // this function should be called from all wxBitmap ctors
97 void wxBitmap::Init()
98 {
99 // m_refData = NULL; done in the base class ctor
100
101 if ( wxTheBitmapList )
102 wxTheBitmapList->AddBitmap(this);
103 }
104
105 #ifdef __WIN32__
106
107 bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon)
108 {
109 // it may be either HICON or HCURSOR
110 HICON hicon = (HICON)icon.GetHandle();
111
112 ICONINFO iconInfo;
113 if ( !::GetIconInfo(hicon, &iconInfo) )
114 {
115 wxLogLastError("GetIconInfo");
116
117 return FALSE;
118 }
119
120 wxBitmapRefData *refData = new wxBitmapRefData;
121 m_refData = refData;
122
123 int w = icon.GetWidth(),
124 h = icon.GetHeight();
125
126 refData->m_width = w;
127 refData->m_height = h;
128 refData->m_depth = wxDisplayDepth();
129
130 refData->m_hBitmap = (WXHBITMAP)iconInfo.hbmColor;
131
132 // the mask returned by GetIconInfo() is inversed compared to the usual
133 // wxWin convention
134 HBITMAP hbmpMask = ::CreateBitmap(w, h, 1, 1, 0);
135
136 // the icons mask is opposite to the usual wxWin convention
137 HDC dcSrc = ::CreateCompatibleDC(NULL);
138 HDC dcDst = ::CreateCompatibleDC(NULL);
139 (void)SelectObject(dcSrc, iconInfo.hbmMask);
140 (void)SelectObject(dcDst, hbmpMask);
141
142 HBRUSH brush = ::CreateSolidBrush(RGB(255, 255, 255));
143 RECT rect = { 0, 0, w, h };
144 FillRect(dcDst, &rect, brush);
145
146 BitBlt(dcDst, 0, 0, w, h, dcSrc, 0, 0, SRCINVERT);
147
148 SelectObject(dcDst, NULL);
149 SelectObject(dcSrc, NULL);
150 DeleteDC(dcDst);
151 DeleteDC(dcSrc);
152
153 refData->m_bitmapMask = new wxMask((WXHBITMAP)hbmpMask);
154
155 #if WXWIN_COMPATIBILITY_2
156 refData->m_ok = TRUE;
157 #endif // WXWIN_COMPATIBILITY_2
158
159 return TRUE;
160 }
161
162 #endif // Win32
163
164 bool wxBitmap::CopyFromCursor(const wxCursor& cursor)
165 {
166 UnRef();
167
168 if ( !cursor.Ok() )
169 return FALSE;
170
171 #ifdef __WIN16__
172 wxFAIL_MSG( _T("don't know how to convert cursor to bitmap") );
173
174 return FALSE;
175 #else
176 return CopyFromIconOrCursor(cursor);
177 #endif // Win16
178 }
179
180 bool wxBitmap::CopyFromIcon(const wxIcon& icon)
181 {
182 UnRef();
183
184 if ( !icon.Ok() )
185 return FALSE;
186
187 // GetIconInfo() doesn't exist under Win16 and I don't know any other way
188 // to create a bitmap from icon there - but using this way we won't have
189 // the mask (FIXME)
190 #ifdef __WIN16__
191 int width = icon.GetWidth(),
192 height = icon.GetHeight();
193
194 // copy the icon to the bitmap
195 ScreenHDC hdcScreen;
196 HDC hdc = ::CreateCompatibleDC(hdcScreen);
197 HBITMAP hbitmap = ::CreateCompatibleBitmap(hdcScreen, width, height);
198 HBITMAP hbmpOld = (HBITMAP)::SelectObject(hdc, hbitmap);
199
200 ::DrawIcon(hdc, 0, 0, GetHiconOf(icon));
201
202 ::SelectObject(hdc, hbmpOld);
203 ::DeleteDC(hdc);
204
205 wxBitmapRefData *refData = new wxBitmapRefData;
206 m_refData = refData;
207
208 refData->m_width = width;
209 refData->m_height = height;
210 refData->m_depth = wxDisplayDepth();
211
212 refData->m_hBitmap = (WXHBITMAP)hbitmap;
213
214 #if WXWIN_COMPATIBILITY_2
215 refData->m_ok = TRUE;
216 #endif // WXWIN_COMPATIBILITY_2
217
218 return TRUE;
219 #else // Win32
220 return CopyFromIconOrCursor(icon);
221 #endif // Win16/Win32
222 }
223
224 wxBitmap::~wxBitmap()
225 {
226 if (wxTheBitmapList)
227 wxTheBitmapList->DeleteObject(this);
228 }
229
230 wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
231 {
232 Init();
233
234 wxBitmapRefData *refData = new wxBitmapRefData;
235 m_refData = refData;
236
237 refData->m_width = width;
238 refData->m_height = height;
239 refData->m_depth = depth;
240 refData->m_numColors = 0;
241 refData->m_selectedInto = NULL;
242
243 char *data;
244 if ( depth == 1 )
245 {
246 // we assume that it is in XBM format which is not quite the same as
247 // the format CreateBitmap() wants because the order of bytes in the
248 // line is inversed!
249 static const size_t bytesPerLine = (width + 7) / 8;
250 static const size_t padding = bytesPerLine % 2;
251 static const size_t len = height * ( padding + bytesPerLine );
252 data = (char *)malloc(len);
253 const char *src = bits;
254 char *dst = data;
255
256 for ( int rows = 0; rows < height; rows++ )
257 {
258 // note that offset cannot be size_t due to >= 0 test!
259 for ( int offset = bytesPerLine - 1; offset >= 0; offset-- )
260 {
261 *dst++ = *(src + offset);
262 }
263
264 if ( padding )
265 *dst++ = 0;
266
267 src += bytesPerLine;
268 }
269 }
270 else
271 {
272 // bits should already be in Windows standard format
273 data = (char *)bits; // const_cast is harmless
274 }
275
276 HBITMAP hbmp = ::CreateBitmap(width, height, 1, depth, data);
277 if ( !hbmp )
278 {
279 wxLogLastError("CreateBitmap");
280 }
281
282 if ( data != bits )
283 {
284 free(data);
285 }
286
287 SetHBITMAP((WXHBITMAP)hbmp);
288 }
289
290 // GRG, Dic/99
291 wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
292 {
293 wxCHECK_MSG( Ok() &&
294 (rect.x >= 0) && (rect.y >= 0) &&
295 (rect.x+rect.width <= GetWidth()) &&
296 (rect.y+rect.height <= GetHeight()),
297 wxNullBitmap, wxT("Invalid bitmap or bitmap region") );
298
299 wxBitmap ret( rect.width, rect.height, GetDepth() );
300 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
301
302 // copy bitmap data
303 HDC dcSrc = ::CreateCompatibleDC(NULL);
304 HDC dcDst = ::CreateCompatibleDC(NULL);
305 SelectObject(dcSrc, (HBITMAP) GetHBITMAP());
306 SelectObject(dcDst, (HBITMAP) ret.GetHBITMAP());
307 BitBlt(dcDst, 0, 0, rect.width, rect.height, dcSrc, rect.x, rect.y, SRCCOPY);
308
309 // copy mask if there is one
310 if (GetMask())
311 {
312 HBITMAP hbmpMask = ::CreateBitmap(rect.width, rect.height, 1, 1, 0);
313
314 SelectObject(dcSrc, (HBITMAP) GetMask()->GetMaskBitmap());
315 SelectObject(dcDst, (HBITMAP) hbmpMask);
316 BitBlt(dcDst, 0, 0, rect.width, rect.height, dcSrc, rect.x, rect.y, SRCCOPY);
317
318 wxMask *mask = new wxMask((WXHBITMAP) hbmpMask);
319 ret.SetMask(mask);
320 }
321
322 SelectObject(dcDst, NULL);
323 SelectObject(dcSrc, NULL);
324 DeleteDC(dcDst);
325 DeleteDC(dcSrc);
326
327 return ret;
328 }
329
330 // Create from XPM data
331 wxBitmap::wxBitmap(char **data, wxControl *WXUNUSED(anItem))
332 {
333 Init();
334
335 (void)Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
336 }
337
338 wxBitmap::wxBitmap(int w, int h, int d)
339 {
340 Init();
341
342 (void)Create(w, h, d);
343 }
344
345 wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
346 {
347 Init();
348
349 (void)Create(data, type, width, height, depth);
350 }
351
352 wxBitmap::wxBitmap(const wxString& filename, long type)
353 {
354 Init();
355
356 LoadFile(filename, (int)type);
357 }
358
359 bool wxBitmap::Create(int w, int h, int d)
360 {
361 UnRef();
362
363 m_refData = new wxBitmapRefData;
364
365 GetBitmapData()->m_width = w;
366 GetBitmapData()->m_height = h;
367 GetBitmapData()->m_depth = d;
368
369 HBITMAP hbmp;
370
371 if ( d > 0 )
372 {
373 hbmp = ::CreateBitmap(w, h, 1, d, NULL);
374 if ( !hbmp )
375 {
376 wxLogLastError("CreateBitmap");
377 }
378 }
379 else
380 {
381 ScreenHDC dc;
382 hbmp = ::CreateCompatibleBitmap(dc, w, h);
383 if ( !hbmp )
384 {
385 wxLogLastError("CreateCompatibleBitmap");
386 }
387
388 GetBitmapData()->m_depth = wxDisplayDepth();
389 }
390
391 SetHBITMAP((WXHBITMAP)hbmp);
392
393 #if WXWIN_COMPATIBILITY_2
394 GetBitmapData()->m_ok = hbmp != 0;
395 #endif // WXWIN_COMPATIBILITY_2
396
397 return Ok();
398 }
399
400 bool wxBitmap::LoadFile(const wxString& filename, long type)
401 {
402 UnRef();
403
404 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
405
406 if ( handler )
407 {
408 m_refData = new wxBitmapRefData;
409
410 return handler->LoadFile(this, filename, type, -1, -1);
411 }
412 else
413 {
414 wxImage image;
415 if ( !image.LoadFile( filename, type ) || !image.Ok() )
416 return FALSE;
417
418 *this = image.ConvertToBitmap();
419
420 return TRUE;
421 }
422 }
423
424 bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
425 {
426 UnRef();
427
428 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
429
430 if ( !handler )
431 {
432 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for "
433 "type %d defined."), type);
434
435 return FALSE;
436 }
437
438 m_refData = new wxBitmapRefData;
439
440 return handler->Create(this, data, type, width, height, depth);
441 }
442
443 bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette)
444 {
445 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
446
447 if ( handler )
448 {
449 return handler->SaveFile(this, filename, type, palette);
450 }
451 else
452 {
453 // FIXME what about palette? shouldn't we use it?
454 wxImage image( *this );
455 if (!image.Ok())
456 return FALSE;
457
458 return image.SaveFile( filename, type );
459 }
460 }
461
462 // ----------------------------------------------------------------------------
463 // wxBitmap accessors
464 // ----------------------------------------------------------------------------
465
466 void wxBitmap::SetQuality(int q)
467 {
468 EnsureHasData();
469
470 GetBitmapData()->m_quality = q;
471 }
472
473 #if WXWIN_COMPATIBILITY_2
474 void wxBitmap::SetOk(bool isOk)
475 {
476 EnsureHasData();
477
478 GetBitmapData()->m_ok = isOk;
479 }
480 #endif // WXWIN_COMPATIBILITY_2
481
482 void wxBitmap::SetPalette(const wxPalette& palette)
483 {
484 EnsureHasData();
485
486 GetBitmapData()->m_bitmapPalette = palette;
487 }
488
489 void wxBitmap::SetMask(wxMask *mask)
490 {
491 EnsureHasData();
492
493 GetBitmapData()->m_bitmapMask = mask;
494 }
495
496 // Creates a bitmap that matches the device context, from
497 // an arbitray bitmap. At present, the original bitmap must have an
498 // associated palette. TODO: use a default palette if no palette exists.
499 // Contributed by Frederic Villeneuve <frederic.villeneuve@natinst.com>
500 wxBitmap wxBitmap::GetBitmapForDC(wxDC& dc) const
501 {
502 wxMemoryDC memDC;
503 wxBitmap tmpBitmap(this->GetWidth(), this->GetHeight(), dc.GetDepth());
504 HPALETTE hPal = (HPALETTE) NULL;
505 LPBITMAPINFO lpDib;
506 void *lpBits = (void*) NULL;
507
508 if( GetPalette() && GetPalette()->Ok() )
509 {
510 tmpBitmap.SetPalette(*GetPalette());
511 memDC.SelectObject(tmpBitmap);
512 memDC.SetPalette(*GetPalette());
513 hPal = (HPALETTE)GetPalette()->GetHPALETTE();
514 }
515 else
516 {
517 hPal = (HPALETTE) ::GetStockObject(DEFAULT_PALETTE);
518 wxPalette palette;
519 palette.SetHPALETTE( (WXHPALETTE)hPal );
520 tmpBitmap.SetPalette( palette );
521 memDC.SelectObject(tmpBitmap);
522 memDC.SetPalette( palette );
523 }
524
525 // set the height negative because in a DIB the order of the lines is
526 // reversed
527 if ( !wxCreateDIB(GetWidth(), -GetHeight(), GetDepth(), hPal, &lpDib) )
528 {
529 return wxNullBitmap;
530 }
531
532 lpBits = malloc(lpDib->bmiHeader.biSizeImage);
533
534 ::GetBitmapBits(GetHbitmap(), lpDib->bmiHeader.biSizeImage, lpBits);
535
536 ::SetDIBitsToDevice(GetHdcOf(memDC), 0, 0,
537 GetWidth(), GetHeight(),
538 0, 0, 0, GetHeight(),
539 lpBits, lpDib, DIB_RGB_COLORS);
540
541 free(lpBits);
542
543 wxFreeDIB(lpDib);
544
545 return tmpBitmap;
546 }
547
548 // ----------------------------------------------------------------------------
549 // wxMask
550 // ----------------------------------------------------------------------------
551
552 wxMask::wxMask()
553 {
554 m_maskBitmap = 0;
555 }
556
557 // Construct a mask from a bitmap and a colour indicating
558 // the transparent area
559 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
560 {
561 m_maskBitmap = 0;
562 Create(bitmap, colour);
563 }
564
565 // Construct a mask from a bitmap and a palette index indicating
566 // the transparent area
567 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
568 {
569 m_maskBitmap = 0;
570 Create(bitmap, paletteIndex);
571 }
572
573 // Construct a mask from a mono bitmap (copies the bitmap).
574 wxMask::wxMask(const wxBitmap& bitmap)
575 {
576 m_maskBitmap = 0;
577 Create(bitmap);
578 }
579
580 wxMask::~wxMask()
581 {
582 if ( m_maskBitmap )
583 ::DeleteObject((HBITMAP) m_maskBitmap);
584 }
585
586 // Create a mask from a mono bitmap (copies the bitmap).
587 bool wxMask::Create(const wxBitmap& bitmap)
588 {
589 if ( m_maskBitmap )
590 {
591 ::DeleteObject((HBITMAP) m_maskBitmap);
592 m_maskBitmap = 0;
593 }
594 if (!bitmap.Ok() || bitmap.GetDepth() != 1)
595 {
596 return FALSE;
597 }
598 m_maskBitmap = (WXHBITMAP) CreateBitmap(
599 bitmap.GetWidth(),
600 bitmap.GetHeight(),
601 1, 1, 0
602 );
603 HDC srcDC = CreateCompatibleDC(0);
604 SelectObject(srcDC, (HBITMAP) bitmap.GetHBITMAP());
605 HDC destDC = CreateCompatibleDC(0);
606 SelectObject(destDC, (HBITMAP) m_maskBitmap);
607 BitBlt(destDC, 0, 0, bitmap.GetWidth(), bitmap.GetHeight(), srcDC, 0, 0, SRCCOPY);
608 SelectObject(srcDC, 0);
609 DeleteDC(srcDC);
610 SelectObject(destDC, 0);
611 DeleteDC(destDC);
612 return TRUE;
613 }
614
615 // Create a mask from a bitmap and a palette index indicating
616 // the transparent area
617 bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
618 {
619 if ( m_maskBitmap )
620 {
621 ::DeleteObject((HBITMAP) m_maskBitmap);
622 m_maskBitmap = 0;
623 }
624 if (bitmap.Ok() && bitmap.GetPalette()->Ok())
625 {
626 unsigned char red, green, blue;
627 if (bitmap.GetPalette()->GetRGB(paletteIndex, &red, &green, &blue))
628 {
629 wxColour transparentColour(red, green, blue);
630 return Create(bitmap, transparentColour);
631 }
632 }
633 return FALSE;
634 }
635
636 // Create a mask from a bitmap and a colour indicating
637 // the transparent area
638 bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
639 {
640 if ( m_maskBitmap )
641 {
642 ::DeleteObject((HBITMAP) m_maskBitmap);
643 m_maskBitmap = 0;
644 }
645 if (!bitmap.Ok())
646 {
647 return FALSE;
648 }
649
650 // scan the bitmap for the transparent colour and set
651 // the corresponding pixels in the mask to BLACK and
652 // the rest to WHITE
653 COLORREF maskColour = RGB(colour.Red(), colour.Green(), colour.Blue());
654 m_maskBitmap = (WXHBITMAP) ::CreateBitmap(
655 bitmap.GetWidth(),
656 bitmap.GetHeight(),
657 1, 1, 0
658 );
659 HDC srcDC = ::CreateCompatibleDC(0);
660 ::SelectObject(srcDC, (HBITMAP) bitmap.GetHBITMAP());
661 HDC destDC = ::CreateCompatibleDC(0);
662 ::SelectObject(destDC, (HBITMAP) m_maskBitmap);
663
664 // this is not very efficient, but I can't think
665 // of a better way of doing it
666 for (int w = 0; w < bitmap.GetWidth(); w++)
667 {
668 for (int h = 0; h < bitmap.GetHeight(); h++)
669 {
670 COLORREF col = GetPixel(srcDC, w, h);
671 if (col == maskColour)
672 {
673 ::SetPixel(destDC, w, h, RGB(0, 0, 0));
674 }
675 else
676 {
677 ::SetPixel(destDC, w, h, RGB(255, 255, 255));
678 }
679 }
680 }
681 ::SelectObject(srcDC, 0);
682 ::DeleteDC(srcDC);
683 ::SelectObject(destDC, 0);
684 ::DeleteDC(destDC);
685 return TRUE;
686 }
687
688 // ----------------------------------------------------------------------------
689 // wxBitmapHandler
690 // ----------------------------------------------------------------------------
691
692 bool wxBitmapHandler::Create(wxGDIImage *image,
693 void *data,
694 long flags,
695 int width, int height, int depth)
696 {
697 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
698
699 return bitmap ? Create(bitmap, data, width, height, depth) : FALSE;
700 }
701
702 bool wxBitmapHandler::Load(wxGDIImage *image,
703 const wxString& name,
704 long flags,
705 int width, int height)
706 {
707 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
708
709 return bitmap ? LoadFile(bitmap, name, flags, width, height) : FALSE;
710 }
711
712 bool wxBitmapHandler::Save(wxGDIImage *image,
713 const wxString& name,
714 int type)
715 {
716 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
717
718 return bitmap ? SaveFile(bitmap, name, type) : FALSE;
719 }
720
721 bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap),
722 void *WXUNUSED(data),
723 long WXUNUSED(type),
724 int WXUNUSED(width),
725 int WXUNUSED(height),
726 int WXUNUSED(depth))
727 {
728 return FALSE;
729 }
730
731 bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap),
732 const wxString& WXUNUSED(name),
733 long WXUNUSED(type),
734 int WXUNUSED(desiredWidth),
735 int WXUNUSED(desiredHeight))
736 {
737 return FALSE;
738 }
739
740 bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap),
741 const wxString& WXUNUSED(name),
742 int WXUNUSED(type),
743 const wxPalette *WXUNUSED(palette))
744 {
745 return FALSE;
746 }
747
748 // ----------------------------------------------------------------------------
749 // DIB functions
750 // ----------------------------------------------------------------------------
751
752 bool wxCreateDIB(long xSize, long ySize, long bitsPerPixel,
753 HPALETTE hPal, LPBITMAPINFO* lpDIBHeader)
754 {
755 unsigned long i, headerSize;
756 LPBITMAPINFO lpDIBheader = NULL;
757 LPPALETTEENTRY lpPe = NULL;
758
759
760 // Allocate space for a DIB header
761 headerSize = (sizeof(BITMAPINFOHEADER) + (256 * sizeof(PALETTEENTRY)));
762 lpDIBheader = (BITMAPINFO *) malloc(headerSize);
763 lpPe = (PALETTEENTRY *)((BYTE*)lpDIBheader + sizeof(BITMAPINFOHEADER));
764
765 GetPaletteEntries(hPal, 0, 256, lpPe);
766
767 memset(lpDIBheader, 0x00, sizeof(BITMAPINFOHEADER));
768
769 // Fill in the static parts of the DIB header
770 lpDIBheader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
771 lpDIBheader->bmiHeader.biWidth = xSize;
772 lpDIBheader->bmiHeader.biHeight = ySize;
773 lpDIBheader->bmiHeader.biPlanes = 1;
774
775 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
776 lpDIBheader->bmiHeader.biBitCount = (WORD)(bitsPerPixel);
777 lpDIBheader->bmiHeader.biCompression = BI_RGB;
778 lpDIBheader->bmiHeader.biSizeImage = xSize * abs(ySize) * bitsPerPixel >> 3;
779 lpDIBheader->bmiHeader.biClrUsed = 256;
780
781
782 // Initialize the DIB palette
783 for (i = 0; i < 256; i++) {
784 lpDIBheader->bmiColors[i].rgbReserved = lpPe[i].peFlags;
785 lpDIBheader->bmiColors[i].rgbRed = lpPe[i].peRed;
786 lpDIBheader->bmiColors[i].rgbGreen = lpPe[i].peGreen;
787 lpDIBheader->bmiColors[i].rgbBlue = lpPe[i].peBlue;
788 }
789
790 *lpDIBHeader = lpDIBheader;
791
792 return TRUE;
793 }
794
795 void wxFreeDIB(LPBITMAPINFO lpDIBHeader)
796 {
797 free(lpDIBHeader);
798 }
799
800