]> git.saurik.com Git - wxWidgets.git/blob - src/msw/bitmap.cpp
6737631938fc25fd9f0113dcf43f97971fcba6a3
[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 for ( size_t cols = 0; cols < bytesPerLine; cols++ )
259 {
260 unsigned char val = *src++;
261 unsigned char reversed = 0;
262
263 for ( int bits = 0; bits < 8; bits++)
264 {
265 reversed <<= 1;
266 reversed |= (val & 0x01);
267 val >>= 1;
268 }
269 *dst++ = reversed;
270 }
271
272 if ( padding )
273 *dst++ = 0;
274 }
275 }
276 else
277 {
278 // bits should already be in Windows standard format
279 data = (char *)bits; // const_cast is harmless
280 }
281
282 HBITMAP hbmp = ::CreateBitmap(width, height, 1, depth, data);
283 if ( !hbmp )
284 {
285 wxLogLastError("CreateBitmap");
286 }
287
288 if ( data != bits )
289 {
290 free(data);
291 }
292
293 SetHBITMAP((WXHBITMAP)hbmp);
294 }
295
296 // GRG, Dic/99
297 wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
298 {
299 wxCHECK_MSG( Ok() &&
300 (rect.x >= 0) && (rect.y >= 0) &&
301 (rect.x+rect.width <= GetWidth()) &&
302 (rect.y+rect.height <= GetHeight()),
303 wxNullBitmap, wxT("Invalid bitmap or bitmap region") );
304
305 wxBitmap ret( rect.width, rect.height, GetDepth() );
306 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
307
308 // copy bitmap data
309 HDC dcSrc = ::CreateCompatibleDC(NULL);
310 HDC dcDst = ::CreateCompatibleDC(NULL);
311 SelectObject(dcSrc, (HBITMAP) GetHBITMAP());
312 SelectObject(dcDst, (HBITMAP) ret.GetHBITMAP());
313 BitBlt(dcDst, 0, 0, rect.width, rect.height, dcSrc, rect.x, rect.y, SRCCOPY);
314
315 // copy mask if there is one
316 if (GetMask())
317 {
318 HBITMAP hbmpMask = ::CreateBitmap(rect.width, rect.height, 1, 1, 0);
319
320 SelectObject(dcSrc, (HBITMAP) GetMask()->GetMaskBitmap());
321 SelectObject(dcDst, (HBITMAP) hbmpMask);
322 BitBlt(dcDst, 0, 0, rect.width, rect.height, dcSrc, rect.x, rect.y, SRCCOPY);
323
324 wxMask *mask = new wxMask((WXHBITMAP) hbmpMask);
325 ret.SetMask(mask);
326 }
327
328 SelectObject(dcDst, NULL);
329 SelectObject(dcSrc, NULL);
330 DeleteDC(dcDst);
331 DeleteDC(dcSrc);
332
333 return ret;
334 }
335
336 // Create from XPM data
337 wxBitmap::wxBitmap(char **data, wxControl *WXUNUSED(anItem))
338 {
339 Init();
340
341 (void)Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
342 }
343
344 wxBitmap::wxBitmap(int w, int h, int d)
345 {
346 Init();
347
348 (void)Create(w, h, d);
349 }
350
351 wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
352 {
353 Init();
354
355 (void)Create(data, type, width, height, depth);
356 }
357
358 wxBitmap::wxBitmap(const wxString& filename, long type)
359 {
360 Init();
361
362 LoadFile(filename, (int)type);
363 }
364
365 bool wxBitmap::Create(int w, int h, int d)
366 {
367 UnRef();
368
369 m_refData = new wxBitmapRefData;
370
371 GetBitmapData()->m_width = w;
372 GetBitmapData()->m_height = h;
373 GetBitmapData()->m_depth = d;
374
375 HBITMAP hbmp;
376
377 if ( d > 0 )
378 {
379 hbmp = ::CreateBitmap(w, h, 1, d, NULL);
380 if ( !hbmp )
381 {
382 wxLogLastError("CreateBitmap");
383 }
384 }
385 else
386 {
387 ScreenHDC dc;
388 hbmp = ::CreateCompatibleBitmap(dc, w, h);
389 if ( !hbmp )
390 {
391 wxLogLastError("CreateCompatibleBitmap");
392 }
393
394 GetBitmapData()->m_depth = wxDisplayDepth();
395 }
396
397 SetHBITMAP((WXHBITMAP)hbmp);
398
399 #if WXWIN_COMPATIBILITY_2
400 GetBitmapData()->m_ok = hbmp != 0;
401 #endif // WXWIN_COMPATIBILITY_2
402
403 return Ok();
404 }
405
406 bool wxBitmap::LoadFile(const wxString& filename, long type)
407 {
408 UnRef();
409
410 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
411
412 if ( handler )
413 {
414 m_refData = new wxBitmapRefData;
415
416 return handler->LoadFile(this, filename, type, -1, -1);
417 }
418 else
419 {
420 wxImage image;
421 if ( !image.LoadFile( filename, type ) || !image.Ok() )
422 return FALSE;
423
424 *this = image.ConvertToBitmap();
425
426 return TRUE;
427 }
428 }
429
430 bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
431 {
432 UnRef();
433
434 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
435
436 if ( !handler )
437 {
438 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for "
439 "type %d defined."), type);
440
441 return FALSE;
442 }
443
444 m_refData = new wxBitmapRefData;
445
446 return handler->Create(this, data, type, width, height, depth);
447 }
448
449 bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette)
450 {
451 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
452
453 if ( handler )
454 {
455 return handler->SaveFile(this, filename, type, palette);
456 }
457 else
458 {
459 // FIXME what about palette? shouldn't we use it?
460 wxImage image( *this );
461 if (!image.Ok())
462 return FALSE;
463
464 return image.SaveFile( filename, type );
465 }
466 }
467
468 // ----------------------------------------------------------------------------
469 // wxBitmap accessors
470 // ----------------------------------------------------------------------------
471
472 void wxBitmap::SetQuality(int q)
473 {
474 EnsureHasData();
475
476 GetBitmapData()->m_quality = q;
477 }
478
479 #if WXWIN_COMPATIBILITY_2
480 void wxBitmap::SetOk(bool isOk)
481 {
482 EnsureHasData();
483
484 GetBitmapData()->m_ok = isOk;
485 }
486 #endif // WXWIN_COMPATIBILITY_2
487
488 void wxBitmap::SetPalette(const wxPalette& palette)
489 {
490 EnsureHasData();
491
492 GetBitmapData()->m_bitmapPalette = palette;
493 }
494
495 void wxBitmap::SetMask(wxMask *mask)
496 {
497 EnsureHasData();
498
499 GetBitmapData()->m_bitmapMask = mask;
500 }
501
502 // Creates a bitmap that matches the device context, from
503 // an arbitray bitmap. At present, the original bitmap must have an
504 // associated palette. TODO: use a default palette if no palette exists.
505 // Contributed by Frederic Villeneuve <frederic.villeneuve@natinst.com>
506 wxBitmap wxBitmap::GetBitmapForDC(wxDC& dc) const
507 {
508 wxMemoryDC memDC;
509 wxBitmap tmpBitmap(this->GetWidth(), this->GetHeight(), dc.GetDepth());
510 HPALETTE hPal = (HPALETTE) NULL;
511 LPBITMAPINFO lpDib;
512 void *lpBits = (void*) NULL;
513
514 if( GetPalette() && GetPalette()->Ok() )
515 {
516 tmpBitmap.SetPalette(*GetPalette());
517 memDC.SelectObject(tmpBitmap);
518 memDC.SetPalette(*GetPalette());
519 hPal = (HPALETTE)GetPalette()->GetHPALETTE();
520 }
521 else
522 {
523 hPal = (HPALETTE) ::GetStockObject(DEFAULT_PALETTE);
524 wxPalette palette;
525 palette.SetHPALETTE( (WXHPALETTE)hPal );
526 tmpBitmap.SetPalette( palette );
527 memDC.SelectObject(tmpBitmap);
528 memDC.SetPalette( palette );
529 }
530
531 // set the height negative because in a DIB the order of the lines is
532 // reversed
533 if ( !wxCreateDIB(GetWidth(), -GetHeight(), GetDepth(), hPal, &lpDib) )
534 {
535 return wxNullBitmap;
536 }
537
538 lpBits = malloc(lpDib->bmiHeader.biSizeImage);
539
540 ::GetBitmapBits(GetHbitmap(), lpDib->bmiHeader.biSizeImage, lpBits);
541
542 ::SetDIBitsToDevice(GetHdcOf(memDC), 0, 0,
543 GetWidth(), GetHeight(),
544 0, 0, 0, GetHeight(),
545 lpBits, lpDib, DIB_RGB_COLORS);
546
547 free(lpBits);
548
549 wxFreeDIB(lpDib);
550
551 return tmpBitmap;
552 }
553
554 // ----------------------------------------------------------------------------
555 // wxMask
556 // ----------------------------------------------------------------------------
557
558 wxMask::wxMask()
559 {
560 m_maskBitmap = 0;
561 }
562
563 // Construct a mask from a bitmap and a colour indicating
564 // the transparent area
565 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
566 {
567 m_maskBitmap = 0;
568 Create(bitmap, colour);
569 }
570
571 // Construct a mask from a bitmap and a palette index indicating
572 // the transparent area
573 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
574 {
575 m_maskBitmap = 0;
576 Create(bitmap, paletteIndex);
577 }
578
579 // Construct a mask from a mono bitmap (copies the bitmap).
580 wxMask::wxMask(const wxBitmap& bitmap)
581 {
582 m_maskBitmap = 0;
583 Create(bitmap);
584 }
585
586 wxMask::~wxMask()
587 {
588 if ( m_maskBitmap )
589 ::DeleteObject((HBITMAP) m_maskBitmap);
590 }
591
592 // Create a mask from a mono bitmap (copies the bitmap).
593 bool wxMask::Create(const wxBitmap& bitmap)
594 {
595 if ( m_maskBitmap )
596 {
597 ::DeleteObject((HBITMAP) m_maskBitmap);
598 m_maskBitmap = 0;
599 }
600 if (!bitmap.Ok() || bitmap.GetDepth() != 1)
601 {
602 return FALSE;
603 }
604 m_maskBitmap = (WXHBITMAP) CreateBitmap(
605 bitmap.GetWidth(),
606 bitmap.GetHeight(),
607 1, 1, 0
608 );
609 HDC srcDC = CreateCompatibleDC(0);
610 SelectObject(srcDC, (HBITMAP) bitmap.GetHBITMAP());
611 HDC destDC = CreateCompatibleDC(0);
612 SelectObject(destDC, (HBITMAP) m_maskBitmap);
613 BitBlt(destDC, 0, 0, bitmap.GetWidth(), bitmap.GetHeight(), srcDC, 0, 0, SRCCOPY);
614 SelectObject(srcDC, 0);
615 DeleteDC(srcDC);
616 SelectObject(destDC, 0);
617 DeleteDC(destDC);
618 return TRUE;
619 }
620
621 // Create a mask from a bitmap and a palette index indicating
622 // the transparent area
623 bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
624 {
625 if ( m_maskBitmap )
626 {
627 ::DeleteObject((HBITMAP) m_maskBitmap);
628 m_maskBitmap = 0;
629 }
630 if (bitmap.Ok() && bitmap.GetPalette()->Ok())
631 {
632 unsigned char red, green, blue;
633 if (bitmap.GetPalette()->GetRGB(paletteIndex, &red, &green, &blue))
634 {
635 wxColour transparentColour(red, green, blue);
636 return Create(bitmap, transparentColour);
637 }
638 }
639 return FALSE;
640 }
641
642 // Create a mask from a bitmap and a colour indicating
643 // the transparent area
644 bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
645 {
646 if ( m_maskBitmap )
647 {
648 ::DeleteObject((HBITMAP) m_maskBitmap);
649 m_maskBitmap = 0;
650 }
651 if (!bitmap.Ok())
652 {
653 return FALSE;
654 }
655
656 // scan the bitmap for the transparent colour and set
657 // the corresponding pixels in the mask to BLACK and
658 // the rest to WHITE
659 COLORREF maskColour = RGB(colour.Red(), colour.Green(), colour.Blue());
660 m_maskBitmap = (WXHBITMAP) ::CreateBitmap(
661 bitmap.GetWidth(),
662 bitmap.GetHeight(),
663 1, 1, 0
664 );
665 HDC srcDC = ::CreateCompatibleDC(0);
666 ::SelectObject(srcDC, (HBITMAP) bitmap.GetHBITMAP());
667 HDC destDC = ::CreateCompatibleDC(0);
668 ::SelectObject(destDC, (HBITMAP) m_maskBitmap);
669
670 // this is not very efficient, but I can't think
671 // of a better way of doing it
672 for (int w = 0; w < bitmap.GetWidth(); w++)
673 {
674 for (int h = 0; h < bitmap.GetHeight(); h++)
675 {
676 COLORREF col = GetPixel(srcDC, w, h);
677 if (col == maskColour)
678 {
679 ::SetPixel(destDC, w, h, RGB(0, 0, 0));
680 }
681 else
682 {
683 ::SetPixel(destDC, w, h, RGB(255, 255, 255));
684 }
685 }
686 }
687 ::SelectObject(srcDC, 0);
688 ::DeleteDC(srcDC);
689 ::SelectObject(destDC, 0);
690 ::DeleteDC(destDC);
691 return TRUE;
692 }
693
694 // ----------------------------------------------------------------------------
695 // wxBitmapHandler
696 // ----------------------------------------------------------------------------
697
698 bool wxBitmapHandler::Create(wxGDIImage *image,
699 void *data,
700 long flags,
701 int width, int height, int depth)
702 {
703 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
704
705 return bitmap ? Create(bitmap, data, width, height, depth) : FALSE;
706 }
707
708 bool wxBitmapHandler::Load(wxGDIImage *image,
709 const wxString& name,
710 long flags,
711 int width, int height)
712 {
713 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
714
715 return bitmap ? LoadFile(bitmap, name, flags, width, height) : FALSE;
716 }
717
718 bool wxBitmapHandler::Save(wxGDIImage *image,
719 const wxString& name,
720 int type)
721 {
722 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
723
724 return bitmap ? SaveFile(bitmap, name, type) : FALSE;
725 }
726
727 bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap),
728 void *WXUNUSED(data),
729 long WXUNUSED(type),
730 int WXUNUSED(width),
731 int WXUNUSED(height),
732 int WXUNUSED(depth))
733 {
734 return FALSE;
735 }
736
737 bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap),
738 const wxString& WXUNUSED(name),
739 long WXUNUSED(type),
740 int WXUNUSED(desiredWidth),
741 int WXUNUSED(desiredHeight))
742 {
743 return FALSE;
744 }
745
746 bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap),
747 const wxString& WXUNUSED(name),
748 int WXUNUSED(type),
749 const wxPalette *WXUNUSED(palette))
750 {
751 return FALSE;
752 }
753
754 // ----------------------------------------------------------------------------
755 // DIB functions
756 // ----------------------------------------------------------------------------
757
758 bool wxCreateDIB(long xSize, long ySize, long bitsPerPixel,
759 HPALETTE hPal, LPBITMAPINFO* lpDIBHeader)
760 {
761 unsigned long i, headerSize;
762 LPBITMAPINFO lpDIBheader = NULL;
763 LPPALETTEENTRY lpPe = NULL;
764
765
766 // Allocate space for a DIB header
767 headerSize = (sizeof(BITMAPINFOHEADER) + (256 * sizeof(PALETTEENTRY)));
768 lpDIBheader = (BITMAPINFO *) malloc(headerSize);
769 lpPe = (PALETTEENTRY *)((BYTE*)lpDIBheader + sizeof(BITMAPINFOHEADER));
770
771 GetPaletteEntries(hPal, 0, 256, lpPe);
772
773 memset(lpDIBheader, 0x00, sizeof(BITMAPINFOHEADER));
774
775 // Fill in the static parts of the DIB header
776 lpDIBheader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
777 lpDIBheader->bmiHeader.biWidth = xSize;
778 lpDIBheader->bmiHeader.biHeight = ySize;
779 lpDIBheader->bmiHeader.biPlanes = 1;
780
781 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
782 lpDIBheader->bmiHeader.biBitCount = (WORD)(bitsPerPixel);
783 lpDIBheader->bmiHeader.biCompression = BI_RGB;
784 lpDIBheader->bmiHeader.biSizeImage = xSize * abs(ySize) * bitsPerPixel >> 3;
785 lpDIBheader->bmiHeader.biClrUsed = 256;
786
787
788 // Initialize the DIB palette
789 for (i = 0; i < 256; i++) {
790 lpDIBheader->bmiColors[i].rgbReserved = lpPe[i].peFlags;
791 lpDIBheader->bmiColors[i].rgbRed = lpPe[i].peRed;
792 lpDIBheader->bmiColors[i].rgbGreen = lpPe[i].peGreen;
793 lpDIBheader->bmiColors[i].rgbBlue = lpPe[i].peBlue;
794 }
795
796 *lpDIBHeader = lpDIBheader;
797
798 return TRUE;
799 }
800
801 void wxFreeDIB(LPBITMAPINFO lpDIBHeader)
802 {
803 free(lpDIBHeader);
804 }
805
806