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