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