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