]> git.saurik.com Git - wxWidgets.git/blob - src/msw/dib.cpp
Copyright corrections
[wxWidgets.git] / src / msw / dib.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/dib.cpp
3 // Purpose: implements wxDIB class
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 03.03.03 (replaces the old file with the same name)
7 // RCS-ID: $Id$
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/string.h"
29 #include "wx/log.h"
30 #endif //WX_PRECOMP
31
32 #include "wx/bitmap.h"
33 #include "wx/intl.h"
34
35 #include <stdio.h>
36 #include <stdlib.h>
37
38 #if !defined(__MWERKS__) && !defined(__SALFORDC__)
39 #include <memory.h>
40 #endif
41
42 #ifdef __GNUWIN32_OLD__
43 #include "wx/msw/gnuwin32/extra.h"
44 #endif
45
46 #include "wx/image.h"
47 #include "wx/msw/dib.h"
48
49 // ============================================================================
50 // implementation
51 // ============================================================================
52
53 // ----------------------------------------------------------------------------
54 // wxDIB creation
55 // ----------------------------------------------------------------------------
56
57 bool wxDIB::Create(int width, int height, int depth)
58 {
59 // we don't handle the palette yet
60 wxASSERT_MSG( depth == 24 || depth == 32,
61 _T("unsupported image depth in wxDIB::Create()") );
62
63 static const int infosize = sizeof(BITMAPINFOHEADER);
64
65 BITMAPINFO *info = (BITMAPINFO *)malloc(infosize);
66 wxCHECK_MSG( info, NULL, _T("malloc(BITMAPINFO) failed") );
67
68 memset(info, 0, infosize);
69
70 info->bmiHeader.biSize = infosize;
71 info->bmiHeader.biWidth = width;
72 info->bmiHeader.biHeight = -height;
73 info->bmiHeader.biPlanes = 1;
74 info->bmiHeader.biBitCount = depth;
75 info->bmiHeader.biCompression = BI_RGB;
76 info->bmiHeader.biSizeImage = GetLineSize(width, depth)*height;
77
78 // No need to report an error here. If it fails, we just won't use a
79 // file mapping and CreateDIBSection will just allocate memory for us.
80 m_handle = ::CreateDIBSection
81 (
82 0, // hdc (unused with DIB_RGB_COLORS)
83 info, // bitmap description
84 DIB_RGB_COLORS, // use RGB, not palette
85 &m_data, // [out] DIB bits
86 NULL, // don't use file mapping
87 0 // file mapping offset (not used here)
88 );
89
90 free(info);
91
92 if ( !m_handle )
93 {
94 wxLogLastError(wxT("CreateDIBSection"));
95
96 return false;
97 }
98
99 m_width = width;
100 m_height = height;
101 m_depth = depth;
102
103 return true;
104 }
105
106 // ----------------------------------------------------------------------------
107 // wxDIB accessors
108 // ----------------------------------------------------------------------------
109
110 void wxDIB::DoGetObject() const
111 {
112 // only do something if we have a valid DIB but we don't [yet] have valid
113 // data
114 if ( m_handle && !m_data )
115 {
116 // although all the info we need is in BITMAP and so we don't really
117 // need DIBSECTION we still ask for it as modifying the bit values only
118 // works for the real DIBs and not for the bitmaps and it's better to
119 // check for this now rather than trying to find out why it doesn't
120 // work later
121 DIBSECTION ds;
122 if ( !::GetObject(m_handle, sizeof(ds), &ds) )
123 {
124 wxLogLastError(_T("GetObject(hDIB)"));
125
126 return;
127 }
128
129 wxDIB *self = wxConstCast(this, wxDIB);
130
131 self->m_width = ds.dsBm.bmWidth;
132 self->m_height = ds.dsBm.bmHeight;
133 self->m_depth = ds.dsBm.bmBitsPixel;
134 self->m_data = ds.dsBm.bmBits;
135 }
136 }
137
138 // ----------------------------------------------------------------------------
139 // wxImage support
140 // ----------------------------------------------------------------------------
141
142 #if wxUSE_IMAGE
143
144 bool wxDIB::Create(const wxImage& image)
145 {
146 wxCHECK_MSG( image.Ok(), false, _T("invalid wxImage in wxDIB ctor") );
147
148 const int h = image.GetHeight();
149 const int w = image.GetWidth();
150
151 // if we have alpha channel, we need to create a 32bpp RGBA DIB, otherwise
152 // a 24bpp RGB is sufficient
153 const bool hasAlpha = image.HasAlpha();
154 const int bpp = hasAlpha ? 32 : 24;
155
156 if ( !Create(w, h, bpp) )
157 return false;
158
159 // DIBs are stored in bottom to top order so we need to copy bits line by
160 // line and starting from the end
161 const int srcBytesPerLine = w * 3;
162 const int dstBytesPerLine = GetLineSize(w, bpp);
163 const unsigned char *src = image.GetData() + ((h - 1) * srcBytesPerLine);
164 const unsigned char *alpha = hasAlpha ? image.GetAlpha() + (h - 1)*w : NULL;
165 unsigned char *dstLineStart = (unsigned char *)m_data;
166 for ( int y = 0; y < h; y++ )
167 {
168 // copy one DIB line
169 unsigned char *dst = dstLineStart;
170 for ( int x = 0; x < w; x++ )
171 {
172 // also, the order of RGB is inversed for DIBs
173 *dst++ = src[2];
174 *dst++ = src[1];
175 *dst++ = src[0];
176
177 src += 3;
178
179 if ( alpha )
180 *dst++ = *alpha++;
181 }
182
183 // pass to the previous line in the image
184 src -= 2*srcBytesPerLine;
185 if ( alpha )
186 alpha -= 2*w;
187
188 // and to the next one in the DIB
189 dstLineStart += dstBytesPerLine;
190 }
191
192 return true;
193 }
194
195 #endif // wxUSE_IMAGE
196
197 // ============================================================================
198 // old DIB code, to be integrated in wxDIB class
199 // ============================================================================
200
201 /*
202 * Routines for dealing with Device Independent Bitmaps.
203 *
204 * wxReadDIB() - Reads a DIB
205 * wxWriteDIB() - Writes a global handle in CF_DIB format
206 * to a file.
207 * wxPaletteSize() - Calculates the palette size in bytes
208 * of given DIB
209 * wxDibNumColors() - Determines the number of colors in DIB
210 * wxDibFromBitmap() - Creates a DIB repr. the DDB passed in.
211 * lread() - Private routine to read more than 64k
212 * lwrite() - Private routine to write more than 64k
213 */
214
215 #ifndef SEEK_CUR
216 /* flags for _lseek */
217 #define SEEK_CUR 1
218 #define SEEK_END 2
219 #define SEEK_SET 0
220 #endif
221
222 #define MAXREAD 32768 /* Number of bytes to be read during */
223 /* each read operation. */
224
225 /* Header signatutes for various resources */
226 #define BFT_ICON 0x4349 /* 'IC' */
227 #define BFT_BITMAP 0x4d42 /* 'BM' */
228 #define BFT_CURSOR 0x5450 /* 'PT(' */
229
230 /* macro to determine if resource is a DIB */
231 #define ISDIB(bft) ((bft) == BFT_BITMAP)
232
233 /* Macro to align given value to the closest DWORD (unsigned long ) */
234 #define ALIGNULONG(i) ((i+3)/4*4)
235
236 /* Macro to determine to round off the given value to the closest byte */
237 #define WIDTHBYTES(i) ((i+31)/32*4)
238
239 #define PALVERSION 0x300
240 #define MAXPALETTE 256 /* max. # supported palette entries */
241
242 static DWORD lread(int fh, VOID FAR *pv, DWORD ul);
243 static DWORD lwrite(int fh, VOID FAR *pv, DWORD ul);
244
245 static bool wxWriteDIB (LPTSTR szFile,HANDLE hdib);
246 WORD wxPaletteSize (VOID FAR * pv); // This is non-static as some apps use it externally
247 static WORD wxDibNumColors (VOID FAR * pv);
248 static bool wxMakeBitmapAndPalette(HDC,HANDLE,HPALETTE *,HBITMAP *);
249
250 /*
251 * FUNCTION : wxWriteDIB(LPSTR szFile,HANDLE hdib)
252 * PURPOSE : Write a global handle in CF_DIB format to a file.
253 * RETURNS : TRUE - if successful.
254 * FALSE - otherwise
255 */
256
257 static bool wxWriteDIB(LPTSTR szFile, HANDLE hdib)
258 {
259 BITMAPFILEHEADER hdr;
260 LPBITMAPINFOHEADER lpbi;
261 int fh;
262 OFSTRUCT of;
263
264 if (!hdib)
265 return FALSE;
266
267 fh = OpenFile(wxConvertWX2MB(szFile), &of, OF_CREATE | OF_READWRITE);
268 if (fh == -1)
269 return FALSE;
270
271 lpbi = (LPBITMAPINFOHEADER) GlobalLock(hdib);
272
273 /* Fill in the fields of the file header */
274 hdr.bfType = BFT_BITMAP;
275 hdr.bfSize = GlobalSize(hdib) + sizeof(BITMAPFILEHEADER);
276 hdr.bfReserved1 = 0;
277 hdr.bfReserved2 = 0;
278 hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + lpbi->biSize +
279 wxPaletteSize(lpbi);
280
281 /* Write the file header */
282 _lwrite(fh, (LPSTR) &hdr, sizeof(BITMAPFILEHEADER));
283
284 /* Write the DIB header and the bits */
285 lwrite(fh, (LPSTR) lpbi, GlobalSize(hdib));
286
287 GlobalUnlock(hdib);
288 _lclose(fh);
289 return TRUE;
290 }
291
292 /*
293 * FUNCTION : wxPaletteSize(VOID FAR * pv)
294 * PURPOSE : Calculates the palette size in bytes. If the info. block
295 * is of the BITMAPCOREHEADER type, the number of colors is
296 * multiplied by 3 to give the palette size, otherwise the
297 * number of colors is multiplied by 4.
298 * RETURNS : Palette size in number of bytes.
299 */
300
301 WORD wxPaletteSize(VOID FAR * pv)
302 {
303 LPBITMAPINFOHEADER lpbi;
304 WORD NumColors;
305
306 lpbi = (LPBITMAPINFOHEADER) pv;
307 NumColors = wxDibNumColors(lpbi);
308
309 if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
310 return (WORD)(NumColors * sizeof(RGBTRIPLE));
311 else
312 return (WORD)(NumColors * sizeof(RGBQUAD));
313 }
314
315 /*
316 * FUNCTION : wxDibNumColors(VOID FAR * pv)
317 * PURPOSE : Determines the number of colors in the DIB by looking at
318 * the BitCount filed in the info block.
319 * RETURNS : The number of colors in the DIB. *
320 */
321
322 static WORD wxDibNumColors(VOID FAR *pv)
323 {
324 int bits;
325 BITMAPINFOHEADER *lpbi;
326 BITMAPCOREHEADER *lpbc;
327
328 lpbi = ((BITMAPINFOHEADER*) pv);
329 lpbc = ((BITMAPCOREHEADER*) pv);
330
331 /* With the BITMAPINFO format headers, the size of the palette
332 * is in biClrUsed, whereas in the BITMAPCORE - style headers, it
333 * is dependent on the bits per pixel ( = 2 raised to the power of
334 * bits/pixel).
335 */
336 if (lpbi->biSize != sizeof(BITMAPCOREHEADER)) {
337 if (lpbi->biClrUsed != 0)
338 return (WORD) lpbi->biClrUsed;
339 bits = lpbi->biBitCount;
340 }
341 else
342 bits = lpbc->bcBitCount;
343
344 switch (bits) {
345 case 1:
346 return 2;
347 case 4:
348 return 16;
349 case 8:
350 return 256;
351 default:
352 /* A 24 bitcount DIB has no color table */
353 return 0;
354 }
355 }
356
357 /*
358 * FUNCTION : lread(int fh, VOID FAR *pv, DWORD ul)
359 * PURPOSE : Reads data in steps of 32k till all the data has been read.
360 * RETURNS : 0 - If read did not proceed correctly.
361 * number of bytes read otherwise.
362 */
363
364 static DWORD lread(int fh, void far *pv, DWORD ul)
365 {
366 DWORD ulT = ul;
367 #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__)
368 BYTE *hp = (BYTE *) pv;
369 #else
370 BYTE huge *hp = (BYTE huge *) pv;
371 #endif
372 while (ul > (DWORD) MAXREAD) {
373 if (_lread(fh, (LPSTR) hp, (WORD) MAXREAD) != MAXREAD)
374 return 0;
375 ul -= MAXREAD;
376 hp += MAXREAD;
377 }
378 if (_lread(fh, (LPSTR) hp, (WXUINT) ul) != (WXUINT) ul)
379 return 0;
380 return ulT;
381 }
382
383 /*
384 * FUNCTION : lwrite(int fh, VOID FAR *pv, DWORD ul)
385 * PURPOSE : Writes data in steps of 32k till all the data is written.
386 * RETURNS : 0 - If write did not proceed correctly.
387 * number of bytes written otherwise.
388 */
389
390 static DWORD lwrite(int fh, VOID FAR *pv, DWORD ul)
391 {
392 DWORD ulT = ul;
393 #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__)
394 BYTE *hp = (BYTE *) pv;
395 #else
396 BYTE huge *hp = (BYTE huge *) pv;
397 #endif
398 while (ul > MAXREAD) {
399 if (_lwrite(fh, (LPSTR) hp, (WORD) MAXREAD) != MAXREAD)
400 return 0;
401 ul -= MAXREAD;
402 hp += MAXREAD;
403 }
404 if (_lwrite(fh, (LPSTR) hp, (WXUINT) ul) != (WXUINT) ul)
405 return 0;
406 return ulT;
407 }
408
409 /*
410 * FUNCTION : wxReadDIB(hWnd)
411 * PURPOSE : Reads a DIB from a file, obtains a handle to its
412 * BITMAPINFO struct. and loads the DIB. Once the DIB
413 * is loaded, the function also creates a bitmap and
414 * palette out of the DIB for a device-dependent form.
415 * RETURNS : TRUE - DIB loaded and bitmap/palette created
416 * The DIBINIT structure pointed to by pInfo is
417 * filled with the appropriate handles.
418 * FALSE - otherwise
419 */
420
421 bool wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette)
422 {
423 int fh;
424 LPBITMAPINFOHEADER lpbi;
425 OFSTRUCT of;
426 BITMAPFILEHEADER bf;
427 WORD nNumColors;
428 bool result = FALSE;
429 WORD offBits;
430 HDC hDC;
431 bool bCoreHead = FALSE;
432 HANDLE hDIB = 0;
433
434 /* Open the file and get a handle to it's BITMAPINFO */
435
436 fh = OpenFile (wxConvertWX2MB(lpFileName), &of, OF_READ);
437 if (fh == -1) {
438 wxLogError(_("Can't open file '%s'"), lpFileName);
439 return (0);
440 }
441
442 hDIB = GlobalAlloc(GHND, (DWORD)(sizeof(BITMAPINFOHEADER) +
443 256 * sizeof(RGBQUAD)));
444 if (!hDIB)
445 return(0);
446
447 lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
448
449 /* read the BITMAPFILEHEADER */
450 if (sizeof (bf) != _lread (fh, (LPSTR)&bf, sizeof (bf)))
451 goto ErrExit;
452
453 if (bf.bfType != 0x4d42) /* 'BM' */
454 goto ErrExit;
455
456 if (sizeof(BITMAPCOREHEADER) != _lread (fh, (LPSTR)lpbi, sizeof(BITMAPCOREHEADER)))
457 goto ErrExit;
458
459 if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
460 {
461 lpbi->biSize = sizeof(BITMAPINFOHEADER);
462 lpbi->biBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
463 lpbi->biPlanes = ((LPBITMAPCOREHEADER)lpbi)->bcPlanes;
464 lpbi->biHeight = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
465 lpbi->biWidth = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
466 bCoreHead = TRUE;
467 }
468 else
469 {
470 // get to the start of the header and read INFOHEADER
471 _llseek(fh,sizeof(BITMAPFILEHEADER),SEEK_SET);
472 if (sizeof(BITMAPINFOHEADER) != _lread (fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))
473 goto ErrExit;
474 }
475
476 nNumColors = (WORD)lpbi->biClrUsed;
477 if ( nNumColors == 0 )
478 {
479 /* no color table for 24-bit, default size otherwise */
480 if (lpbi->biBitCount != 24)
481 nNumColors = 1 << lpbi->biBitCount; /* standard size table */
482 }
483
484 /* fill in some default values if they are zero */
485 if (lpbi->biClrUsed == 0)
486 lpbi->biClrUsed = nNumColors;
487
488 if (lpbi->biSizeImage == 0)
489 {
490 lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3)
491 * lpbi->biHeight;
492 }
493
494 /* get a proper-sized buffer for header, color table and bits */
495 GlobalUnlock(hDIB);
496 hDIB = GlobalReAlloc(hDIB, lpbi->biSize +
497 nNumColors * sizeof(RGBQUAD) +
498 lpbi->biSizeImage, 0);
499 if (!hDIB) /* can't resize buffer for loading */
500 goto ErrExit2;
501
502 lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
503
504 /* read the color table */
505 if (!bCoreHead)
506 _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));
507 else
508 {
509 signed int i;
510 RGBQUAD FAR *pQuad;
511 RGBTRIPLE FAR *pTriple;
512
513 _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBTRIPLE));
514
515 pQuad = (RGBQUAD FAR *)((LPSTR)lpbi + lpbi->biSize);
516 pTriple = (RGBTRIPLE FAR *) pQuad;
517 for (i = nNumColors - 1; i >= 0; i--)
518 {
519 pQuad[i].rgbRed = pTriple[i].rgbtRed;
520 pQuad[i].rgbBlue = pTriple[i].rgbtBlue;
521 pQuad[i].rgbGreen = pTriple[i].rgbtGreen;
522 pQuad[i].rgbReserved = 0;
523 }
524 }
525
526 /* offset to the bits from start of DIB header */
527 offBits = (WORD)(lpbi->biSize + nNumColors * sizeof(RGBQUAD));
528
529 if (bf.bfOffBits != 0L)
530 {
531 _llseek(fh,bf.bfOffBits,SEEK_SET);
532 }
533
534 if (lpbi->biSizeImage == lread(fh, (LPSTR)lpbi + offBits, lpbi->biSizeImage))
535 {
536 GlobalUnlock(hDIB);
537
538 hDC = GetDC(NULL);
539 if (!wxMakeBitmapAndPalette(hDC, hDIB, palette,
540 bitmap))
541 {
542 ReleaseDC(NULL,hDC);
543 goto ErrExit2;
544 }
545 else
546 {
547 ReleaseDC(NULL,hDC);
548 GlobalFree(hDIB);
549 result = TRUE;
550 }
551 }
552 else
553 {
554 ErrExit:
555 GlobalUnlock(hDIB);
556 ErrExit2:
557 GlobalFree(hDIB);
558 }
559
560 _lclose(fh);
561 return(result);
562 }
563
564 /*
565 * FUNCTION : wxMakeBitmapAndPalette
566 * PURPOSE : Given a DIB, creates a bitmap and corresponding palette
567 * to be used for a device-dependent representation of
568 * of the image.
569 * RETURNS : TRUE --> success. phPal and phBitmap are filled with
570 * appropriate handles. Caller is responsible
571 * for freeing objects.
572 * FALSE --> unable to create objects. both pointer are
573 * not valid
574 */
575
576 static bool wxMakeBitmapAndPalette(HDC hDC, HANDLE hDIB,
577 HPALETTE * phPal, HBITMAP * phBitmap)
578 {
579 LPBITMAPINFOHEADER lpInfo;
580 bool result = FALSE;
581 HBITMAP hBitmap;
582 HPALETTE hPalette, hOldPal;
583 LPSTR lpBits;
584
585 lpInfo = (LPBITMAPINFOHEADER) GlobalLock(hDIB);
586
587 hPalette = wxMakeDIBPalette(lpInfo);
588 if ( hPalette )
589 {
590 // Need to realize palette for converting DIB to bitmap.
591 hOldPal = SelectPalette(hDC, hPalette, TRUE);
592 RealizePalette(hDC);
593
594 lpBits = (LPSTR)lpInfo + (WORD)lpInfo->biSize +
595 (WORD)lpInfo->biClrUsed * sizeof(RGBQUAD);
596 hBitmap = CreateDIBitmap(hDC, lpInfo, CBM_INIT, lpBits,
597 (LPBITMAPINFO)lpInfo, DIB_RGB_COLORS);
598
599 SelectPalette(hDC, hOldPal, TRUE);
600 RealizePalette(hDC);
601
602 if (!hBitmap)
603 DeleteObject(hPalette);
604 else
605 {
606 *phBitmap = hBitmap;
607 *phPal = hPalette;
608 result = TRUE;
609 }
610 }
611
612 GlobalUnlock (hDIB); // glt
613
614 return(result);
615 }
616
617 /*
618 * FUNCTION : wxMakeDIBPalette(lpInfo)
619 * PURPOSE : Given a BITMAPINFOHEADER, create a palette based on
620 * the color table.
621 * RETURNS : non-zero - handle of a corresponding palette
622 * zero - unable to create palette
623 */
624
625 HPALETTE wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo)
626 {
627 LPLOGPALETTE npPal;
628 RGBQUAD far *lpRGB;
629 HPALETTE hLogPal;
630 WORD i;
631
632 /* since biClrUsed field was filled during the loading of the DIB,
633 * we know it contains the number of colors in the color table.
634 */
635 if (lpInfo->biClrUsed)
636 {
637 npPal = (LPLOGPALETTE)malloc(sizeof(LOGPALETTE) +
638 (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY));
639 if (!npPal)
640 return NULL;
641
642 npPal->palVersion = 0x300;
643 npPal->palNumEntries = (WORD)lpInfo->biClrUsed;
644
645 /* get pointer to the color table */
646 lpRGB = (RGBQUAD FAR *)((LPSTR)lpInfo + lpInfo->biSize);
647
648 /* copy colors from the color table to the LogPalette structure */
649 for (i = 0; (DWORD)i < lpInfo->biClrUsed; i++, lpRGB++)
650 {
651 npPal->palPalEntry[i].peRed = lpRGB->rgbRed;
652 npPal->palPalEntry[i].peGreen = lpRGB->rgbGreen;
653 npPal->palPalEntry[i].peBlue = lpRGB->rgbBlue;
654 npPal->palPalEntry[i].peFlags = 0;
655 }
656
657 hLogPal = CreatePalette((LPLOGPALETTE)npPal);
658 free(npPal);
659
660 return(hLogPal);
661 }
662
663 /* 24-bit DIB with no color table. Return default palette. Another
664 * option would be to create a 256 color "rainbow" palette to provide
665 * some good color choices.
666 */
667 else
668 return((HPALETTE) GetStockObject(DEFAULT_PALETTE));
669 }
670
671 bool wxLoadIntoBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette **pal)
672 {
673 HBITMAP hBitmap = NULL;
674 HPALETTE hPalette = NULL;
675
676 bool success = (wxReadDIB(filename, &hBitmap, &hPalette) != 0);
677
678 if (!success)
679 {
680 if (hPalette)
681 DeleteObject(hPalette);
682 return FALSE;
683 }
684
685 if (hPalette)
686 {
687 #if wxUSE_PALETTE
688 if (pal)
689 {
690 *pal = new wxPalette;
691 (*pal)->SetHPALETTE((WXHPALETTE) hPalette);
692 }
693 else
694 #endif // wxUSE_PALETTE
695 DeleteObject(hPalette);
696 }
697 else if (pal)
698 *pal = NULL;
699
700 if (hBitmap)
701 {
702 BITMAP bm;
703 GetObject(hBitmap, sizeof(bm), (LPSTR)&bm);
704
705 bitmap->SetHBITMAP((WXHBITMAP) hBitmap);
706 bitmap->SetWidth(bm.bmWidth);
707 bitmap->SetHeight(bm.bmHeight);
708 bitmap->SetDepth(bm.bmPlanes * bm.bmBitsPixel);
709 #if WXWIN_COMPATIBILITY_2
710 bitmap->SetOk(TRUE);
711 #endif // WXWIN_COMPATIBILITY_2
712 return TRUE;
713 }
714 else return FALSE;
715 }
716
717 wxBitmap *wxLoadBitmap(wxChar *filename, wxPalette **pal)
718 {
719 wxBitmap *bitmap = new wxBitmap;
720 if (wxLoadIntoBitmap(filename, bitmap, pal))
721 return bitmap;
722 else
723 {
724 delete bitmap;
725 return NULL;
726 }
727 }
728
729 /*
730 *
731 * Function: InitBitmapInfoHeader
732 *
733 * Purpose: Does a "standard" initialization of a BITMAPINFOHEADER,
734 * given the Width, Height, and Bits per Pixel for the
735 * DIB.
736 *
737 * By standard, I mean that all the relevant fields are set
738 * to the specified values. biSizeImage is computed, the
739 * biCompression field is set to "no compression," and all
740 * other fields are 0.
741 *
742 * Note that DIBs only allow BitsPixel values of 1, 4, 8, or
743 * 24. This routine makes sure that one of these values is
744 * used (whichever is most appropriate for the specified
745 * nBPP).
746 *
747 * Parms: lpBmInfoHdr == Far pointer to a BITMAPINFOHEADER structure
748 * to be filled in.
749 * dwWidth == Width of DIB (not in Win 3.0 & 3.1, high
750 * word MUST be 0).
751 * dwHeight == Height of DIB (not in Win 3.0 & 3.1, high
752 * word MUST be 0).
753 * nBPP == Bits per Pixel for the DIB.
754 *
755 */
756
757 static void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr,
758 DWORD dwWidth,
759 DWORD dwHeight,
760 int nBPP)
761 {
762 // _fmemset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));
763 memset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));
764
765 lpBmInfoHdr->biSize = sizeof (BITMAPINFOHEADER);
766 lpBmInfoHdr->biWidth = dwWidth;
767 lpBmInfoHdr->biHeight = dwHeight;
768 lpBmInfoHdr->biPlanes = 1;
769
770 if (nBPP <= 1)
771 nBPP = 1;
772 else if (nBPP <= 4)
773 nBPP = 4;
774 else if (nBPP <= 8)
775 nBPP = 8;
776 /* Doesn't work
777 else if (nBPP <= 16)
778 nBPP = 16;
779 */
780 else
781 nBPP = 24;
782
783 lpBmInfoHdr->biBitCount = nBPP;
784 lpBmInfoHdr->biSizeImage = WIDTHBYTES (dwWidth * nBPP) * dwHeight;
785 }
786
787 LPSTR wxFindDIBBits (LPSTR lpbi)
788 {
789 return (lpbi + *(LPDWORD)lpbi + wxPaletteSize (lpbi));
790 }
791
792 /*
793 * Function: BitmapToDIB
794 *
795 * Purpose: Given a device dependent bitmap and a palette, returns
796 * a handle to global memory with a DIB spec in it. The
797 * DIB is rendered using the colors of the palette passed in.
798 *
799 * Parms: hBitmap == Handle to device dependent bitmap compatible
800 * with default screen display device.
801 * hPal == Palette to render the DDB with. If it's NULL,
802 * use the default palette.
803 */
804
805 HANDLE wxBitmapToDIB (HBITMAP hBitmap, HPALETTE hPal)
806 {
807 BITMAP Bitmap;
808 BITMAPINFOHEADER bmInfoHdr;
809 LPBITMAPINFOHEADER lpbmInfoHdr;
810 LPSTR lpBits;
811 HDC hMemDC;
812 HANDLE hDIB;
813 HPALETTE hOldPal = NULL;
814
815 // Do some setup -- make sure the Bitmap passed in is valid,
816 // get info on the bitmap (like its height, width, etc.),
817 // then setup a BITMAPINFOHEADER.
818
819 if (!hBitmap)
820 return NULL;
821
822 if (!GetObject (hBitmap, sizeof (Bitmap), (LPSTR) &Bitmap))
823 return NULL;
824
825 InitBitmapInfoHeader (&bmInfoHdr,
826 Bitmap.bmWidth,
827 Bitmap.bmHeight,
828 Bitmap.bmPlanes * Bitmap.bmBitsPixel);
829
830 // Now allocate memory for the DIB. Then, set the BITMAPINFOHEADER
831 // into this memory, and find out where the bitmap bits go.
832
833 hDIB = GlobalAlloc (GHND, sizeof (BITMAPINFOHEADER) +
834 wxPaletteSize ((LPSTR) &bmInfoHdr) + bmInfoHdr.biSizeImage);
835
836 if (!hDIB)
837 return NULL;
838
839 lpbmInfoHdr = (LPBITMAPINFOHEADER) GlobalLock (hDIB);
840
841 *lpbmInfoHdr = bmInfoHdr;
842 lpBits = wxFindDIBBits ((LPSTR) lpbmInfoHdr);
843
844
845 // Now, we need a DC to hold our bitmap. If the app passed us
846 // a palette, it should be selected into the DC.
847
848 hMemDC = GetDC (NULL);
849
850 if (hPal)
851 {
852 hOldPal = SelectPalette (hMemDC, hPal, FALSE);
853 RealizePalette (hMemDC);
854 }
855
856 // We're finally ready to get the DIB. Call the driver and let
857 // it party on our bitmap. It will fill in the color table,
858 // and bitmap bits of our global memory block.
859
860 if (!GetDIBits (hMemDC, hBitmap, 0, Bitmap.bmHeight, lpBits,
861 (LPBITMAPINFO) lpbmInfoHdr, DIB_RGB_COLORS))
862 {
863 GlobalUnlock (hDIB);
864 GlobalFree (hDIB);
865 hDIB = NULL;
866 }
867 else
868 GlobalUnlock (hDIB);
869
870 // Finally, clean up and return.
871
872 if (hOldPal)
873 SelectPalette (hMemDC, hOldPal, FALSE);
874
875 ReleaseDC (NULL, hMemDC);
876
877 return hDIB;
878 }
879
880 bool wxSaveBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette *palette)
881 {
882 HPALETTE hPalette = 0;
883 #if wxUSE_PALETTE
884 if (palette)
885 hPalette = (HPALETTE) palette->GetHPALETTE();
886 #endif // wxUSE_PALETTE
887
888 HANDLE dibHandle = wxBitmapToDIB((HBITMAP) bitmap->GetHBITMAP(), hPalette);
889 if (dibHandle)
890 {
891 bool success = (wxWriteDIB(filename, dibHandle) != 0);
892 GlobalFree(dibHandle);
893 return success;
894 }
895 else return FALSE;
896 }
897