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