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