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