]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dib.cpp
added wxListView class: this is going to be a wxListCtrl with human (inter)face
[wxWidgets.git] / src / msw / dib.cpp
CommitLineData
d80207c3
KB
1/*******************************************************************************
2 * *
3 * MODULE : DIB.CC *
4 * *
5 * DESCRIPTION : Routines for dealing with Device Independent Bitmaps. *
6 * *
7 * FUNCTIONS : *
8 * *
9 * wxReadDIB() - Reads a DIB *
10 * *
11 * WriteDIB() - Writes a global handle in CF_DIB format*
12 * to a file. *
13 * *
14 * wxPaletteSize() - 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 *******************************************************************************/
2bda0e17
KB
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
2432b92d 36#include "wx/bitmap.h"
531dfa44
VZ
37#include "wx/log.h"
38#include "wx/intl.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
c42404a5
VZ
51#ifdef __GNUWIN32_OLD__
52 #include "wx/msw/gnuwin32/extra.h"
65fd5cb0 53#endif
2bda0e17
KB
54
55#ifndef SEEK_CUR
d80207c3 56/* flags for _lseek */
a58a12e9
VZ
57#define SEEK_CUR 1
58#define SEEK_END 2
59#define SEEK_SET 0
2bda0e17
KB
60#endif
61
d80207c3
KB
62#define MAXREAD 32768 /* Number of bytes to be read during */
63 /* each read operation. */
2bda0e17 64
d80207c3
KB
65/* Header signatutes for various resources */
66#define BFT_ICON 0x4349 /* 'IC' */
67#define BFT_BITMAP 0x4d42 /* 'BM' */
68#define BFT_CURSOR 0x5450 /* 'PT(' */
2bda0e17 69
d80207c3
KB
70/* macro to determine if resource is a DIB */
71#define ISDIB(bft) ((bft) == BFT_BITMAP)
2bda0e17 72
d80207c3
KB
73/* Macro to align given value to the closest DWORD (unsigned long ) */
74#define ALIGNULONG(i) ((i+3)/4*4)
2bda0e17 75
d80207c3
KB
76/* Macro to determine to round off the given value to the closest byte */
77#define WIDTHBYTES(i) ((i+31)/32*4)
2bda0e17 78
d80207c3
KB
79#define PALVERSION 0x300
80#define MAXPALETTE 256 /* max. # supported palette entries */
2bda0e17 81
d80207c3 82static DWORD PASCAL lread(int fh, VOID FAR *pv, DWORD ul);
73974df1
VZ
83static DWORD PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul);
84
d80207c3
KB
85static BOOL WriteDIB (LPTSTR szFile,HANDLE hdib);
86WORD wxPaletteSize (VOID FAR * pv); // This is non-static as some apps use it externally
87static WORD DibNumColors (VOID FAR * pv);
88// HANDLE DibFromBitmap (HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal);
73974df1 89static BOOL PASCAL MakeBitmapAndPalette(HDC,HANDLE,HPALETTE *,HBITMAP *);
2bda0e17 90
d80207c3
KB
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
102static BOOL WriteDIB(LPTSTR szFile, HANDLE hdib)
2bda0e17 103{
d80207c3
KB
104 BITMAPFILEHEADER hdr;
105 LPBITMAPINFOHEADER lpbi;
106 int fh;
107 OFSTRUCT of;
2bda0e17 108
d80207c3
KB
109 if (!hdib)
110 return FALSE;
111
112 fh = OpenFile(wxConvertWX2MB(szFile), &of, OF_CREATE | OF_READWRITE);
113 if (fh == -1)
114 return FALSE;
2bda0e17
KB
115
116#ifdef __WINDOWS_386__
d80207c3 117 lpbi = (LPBITMAPINFOHEADER) MK_FP32(GlobalLock(hdib));
2bda0e17 118#else
d80207c3 119 lpbi = (LPBITMAPINFOHEADER) GlobalLock(hdib);
2bda0e17 120#endif
d80207c3
KB
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 wxPaletteSize(lpbi);
2bda0e17 128
d80207c3
KB
129 /* Write the file header */
130 _lwrite(fh, (LPSTR) &hdr, sizeof(BITMAPFILEHEADER));
2bda0e17 131
d80207c3
KB
132 /* Write the DIB header and the bits */
133 lwrite(fh, (LPSTR) lpbi, GlobalSize(hdib));
2bda0e17 134
d80207c3
KB
135 GlobalUnlock(hdib);
136 _lclose(fh);
137 return TRUE;
2bda0e17
KB
138}
139
d80207c3
KB
140/****************************************************************************
141 * *
142 * FUNCTION : wxPaletteSize(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
153WORD wxPaletteSize(VOID FAR * pv)
2bda0e17 154{
d80207c3
KB
155 LPBITMAPINFOHEADER lpbi;
156 WORD NumColors;
2bda0e17 157
d80207c3
KB
158 lpbi = (LPBITMAPINFOHEADER) pv;
159 NumColors = DibNumColors(lpbi);
2bda0e17 160
d80207c3
KB
161 if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
162 return (WORD)(NumColors * sizeof(RGBTRIPLE));
163 else
164 return (WORD)(NumColors * sizeof(RGBQUAD));
2bda0e17
KB
165}
166
d80207c3
KB
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
178static WORD DibNumColors(VOID FAR *pv)
2bda0e17 179{
d80207c3
KB
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 }
2bda0e17
KB
211}
212
d80207c3
KB
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
2bda0e17 224#if NOTHING
d80207c3 225static HANDLE DibFromBitmap(HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal)
2bda0e17 226{
d80207c3
KB
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 + wxPaletteSize(&bi);
259
260 hdc = GetDC((HWND) 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 }
2bda0e17
KB
271
272#ifdef __WINDOWS_386__
d80207c3 273 lpbi = (BITMAPINFOHEADER FAR *) MK_FP32(GlobalLock(hdib));
2bda0e17 274#else
d80207c3 275 lpbi = (BITMAPINFOHEADER FAR *) GlobalLock(hdib);
2bda0e17
KB
276#endif
277
d80207c3 278 *lpbi = bi;
2bda0e17 279
d80207c3
KB
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);
716cd410 285
d80207c3
KB
286 bi = *lpbi;
287 GlobalUnlock(hdib);
2bda0e17 288
d80207c3
KB
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 + wxPaletteSize(&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 */
2bda0e17 313#ifdef __WINDOWS_386__
a58a12e9 314 lpbi = (BITMAPINFOHEADER FAR *) MK_FP32(GlobalLock(hdib));
2bda0e17 315#else
a58a12e9 316 lpbi = (BITMAPINFOHEADER FAR *) GlobalLock(hdib);
2bda0e17
KB
317#endif
318
d80207c3
KB
319 if (GetDIBits(hdc,
320 hbm,
321 0,
322 (WORD) bi.biHeight,
323 (LPSTR) lpbi + (WORD) lpbi->biSize + wxPaletteSize(lpbi),
324 (LPBITMAPINFO) lpbi, DIB_RGB_COLORS) == 0) {
325 GlobalUnlock(hdib);
326 hdib = NULL;
327 SelectPalette(hdc, hpal, FALSE);
328 ReleaseDC((HWND) NULL, hdc);
329 return NULL;
330 }
a58a12e9
VZ
331
332 bi = *lpbi;
333 GlobalUnlock(hdib);
d80207c3 334
a58a12e9
VZ
335 SelectPalette(hdc, hpal, FALSE);
336 ReleaseDC(NULL, hdc);
337 return hdib;
2bda0e17
KB
338}
339#endif
340
d80207c3
KB
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
353static DWORD PASCAL lread(int fh, void far *pv, DWORD ul)
354{
355 DWORD ulT = ul;
356#if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__) || defined(__WXWINE__)
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, (WXUINT) ul) != (WXUINT) ul)
368 return 0;
369 return ulT;
370}
2bda0e17 371
d80207c3
KB
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
383static DWORD PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul)
2bda0e17 384{
d80207c3 385 DWORD ulT = ul;
c455ab93 386#if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__) || defined(__WXWINE__)
d80207c3 387 BYTE *hp = (BYTE *) pv;
2bda0e17 388#else
d80207c3 389 BYTE huge *hp = (BYTE huge *) pv;
2bda0e17 390#endif
d80207c3
KB
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, (WXUINT) ul) != (WXUINT) ul)
398 return 0;
399 return ulT;
2bda0e17
KB
400}
401
d80207c3
KB
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 ****************************************************************************/
417BOOL wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette)
2bda0e17 418{
d80207c3 419 int fh;
2bda0e17 420 LPBITMAPINFOHEADER lpbi;
d80207c3
KB
421 OFSTRUCT of;
422 BITMAPFILEHEADER bf;
423 WORD nNumColors;
2bda0e17 424 BOOL result = FALSE;
2bda0e17
KB
425 WORD offBits;
426 HDC hDC;
427 BOOL bCoreHead = FALSE;
428 HANDLE hDIB = 0;
429
d80207c3
KB
430 /* Open the file and get a handle to it's BITMAPINFO */
431
432 fh = OpenFile (wxConvertWX2MB(lpFileName), &of, OF_READ);
433 if (fh == -1) {
a58a12e9
VZ
434 wxLogError(_("Can't open file '%s'"), lpFileName);
435 return (0);
d80207c3 436 }
40c7a5fc 437
d80207c3
KB
438 hDIB = GlobalAlloc(GHND, (DWORD)(sizeof(BITMAPINFOHEADER) +
439 256 * sizeof(RGBQUAD)));
2bda0e17 440 if (!hDIB)
a58a12e9 441 return(0);
2bda0e17
KB
442
443#ifdef __WINDOWS_386__
444 lpbi = (LPBITMAPINFOHEADER)MK_FP32(GlobalLock(hDIB));
445#else
446 lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
447#endif
448
d80207c3
KB
449 /* read the BITMAPFILEHEADER */
450 if (sizeof (bf) != _lread (fh, (LPSTR)&bf, sizeof (bf)))
a58a12e9 451 goto ErrExit;
2bda0e17 452
d80207c3 453 if (bf.bfType != 0x4d42) /* 'BM' */
a58a12e9 454 goto ErrExit;
2bda0e17 455
d80207c3 456 if (sizeof(BITMAPCOREHEADER) != _lread (fh, (LPSTR)lpbi, sizeof(BITMAPCOREHEADER)))
a58a12e9 457 goto ErrExit;
2bda0e17 458
d80207c3
KB
459 if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
460 {
a58a12e9
VZ
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;
d80207c3
KB
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)))
a58a12e9 473 goto ErrExit;
d80207c3 474 }
2bda0e17 475
fd3f686c 476 nNumColors = (WORD)lpbi->biClrUsed;
d80207c3
KB
477 if ( nNumColors == 0 )
478 {
479 /* no color table for 24-bit, default size otherwise */
a58a12e9 480 if (lpbi->biBitCount != 24)
d80207c3
KB
481 nNumColors = 1 << lpbi->biBitCount; /* standard size table */
482 }
2bda0e17 483
d80207c3 484 /* fill in some default values if they are zero */
2bda0e17 485 if (lpbi->biClrUsed == 0)
a58a12e9 486 lpbi->biClrUsed = nNumColors;
2bda0e17 487
d80207c3
KB
488 if (lpbi->biSizeImage == 0)
489 {
a58a12e9 490 lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3)
d80207c3
KB
491 * lpbi->biHeight;
492 }
2bda0e17 493
d80207c3 494 /* get a proper-sized buffer for header, color table and bits */
2bda0e17 495 GlobalUnlock(hDIB);
d80207c3
KB
496 hDIB = GlobalReAlloc(hDIB, lpbi->biSize +
497 nNumColors * sizeof(RGBQUAD) +
498 lpbi->biSizeImage, 0);
499 if (!hDIB) /* can't resize buffer for loading */
a58a12e9 500 goto ErrExit2;
2bda0e17
KB
501
502#ifdef __WINDOWS_386__
503 lpbi = (LPBITMAPINFOHEADER)MK_FP32(GlobalLock(hDIB));
504#else
505 lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
506#endif
507
d80207c3 508 /* read the color table */
2bda0e17 509 if (!bCoreHead)
d80207c3
KB
510 _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));
511 else
512 {
a58a12e9
VZ
513 signed int i;
514 RGBQUAD FAR *pQuad;
515 RGBTRIPLE FAR *pTriple;
d80207c3
KB
516
517 _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBTRIPLE));
518
a58a12e9
VZ
519 pQuad = (RGBQUAD FAR *)((LPSTR)lpbi + lpbi->biSize);
520 pTriple = (RGBTRIPLE FAR *) pQuad;
d80207c3
KB
521 for (i = nNumColors - 1; i >= 0; i--)
522 {
a58a12e9
VZ
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 }
d80207c3 528 }
2bda0e17 529
d80207c3 530 /* offset to the bits from start of DIB header */
33ac7e6f 531 offBits = (WORD)(lpbi->biSize + nNumColors * sizeof(RGBQUAD));
2bda0e17
KB
532
533 if (bf.bfOffBits != 0L)
d80207c3
KB
534 {
535 _llseek(fh,bf.bfOffBits,SEEK_SET);
536 }
2bda0e17 537
d80207c3 538 if (lpbi->biSizeImage == lread(fh, (LPSTR)lpbi + offBits, lpbi->biSizeImage))
2bda0e17 539 {
a58a12e9 540 GlobalUnlock(hDIB);
d80207c3 541
a58a12e9 542 hDC = GetDC(NULL);
d80207c3
KB
543 if (!MakeBitmapAndPalette(hDC, hDIB, palette,
544 bitmap))
a58a12e9
VZ
545 {
546 ReleaseDC(NULL,hDC);
547 goto ErrExit2;
548 }
549 else
550 {
551 ReleaseDC(NULL,hDC);
2bda0e17 552 GlobalFree(hDIB);
a58a12e9
VZ
553 result = TRUE;
554 }
2bda0e17
KB
555 }
556 else
557 {
558ErrExit:
a58a12e9 559 GlobalUnlock(hDIB);
2bda0e17 560ErrExit2:
a58a12e9 561 GlobalFree(hDIB);
2bda0e17 562 }
d80207c3
KB
563
564 _lclose(fh);
2bda0e17
KB
565 return(result);
566}
567
d80207c3
KB
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 ****************************************************************************/
583static BOOL PASCAL MakeBitmapAndPalette(HDC hDC, HANDLE hDIB,
584 HPALETTE * phPal, HBITMAP * phBitmap)
2bda0e17
KB
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
ef3ab009 598 hPalette = wxMakeDIBPalette(lpInfo);
fd3f686c 599 if ( hPalette )
2bda0e17 600 {
a58a12e9
VZ
601 // Need to realize palette for converting DIB to bitmap.
602 hOldPal = SelectPalette(hDC, hPalette, TRUE);
603 RealizePalette(hDC);
604
605 lpBits = (LPSTR)lpInfo + (WORD)lpInfo->biSize +
606 (WORD)lpInfo->biClrUsed * sizeof(RGBQUAD);
607 hBitmap = CreateDIBitmap(hDC, lpInfo, CBM_INIT, lpBits,
608 (LPBITMAPINFO)lpInfo, DIB_RGB_COLORS);
609
610 SelectPalette(hDC, hOldPal, TRUE);
611 RealizePalette(hDC);
612
613 if (!hBitmap)
614 DeleteObject(hPalette);
615 else
616 {
617 *phBitmap = hBitmap;
618 *phPal = hPalette;
619 result = TRUE;
620 }
2bda0e17 621 }
8d1e5dbf
GT
622
623 GlobalUnlock (hDIB); // glt
d80207c3 624
2bda0e17
KB
625 return(result);
626}
627
d80207c3
KB
628/****************************************************************************
629 * *
630 * FUNCTION : wxMakeDIBPalette(lpInfo) *
631 * *
632 * PURPOSE : Given a BITMAPINFOHEADER, create a palette based on
633 * the color table.
634 *
635 * *
636 * RETURNS : non-zero - handle of a corresponding palette
637 * zero - unable to create palette
638 * *
639 ****************************************************************************/
640HPALETTE wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo)
2bda0e17 641{
c455ab93 642#ifdef __WXWINE__
d80207c3 643 return (FALSE);
c455ab93 644#else
48c12cb1 645 LPLOGPALETTE npPal;
2bda0e17 646 RGBQUAD far *lpRGB;
40c7a5fc 647 HPALETTE hLogPal;
2bda0e17
KB
648 WORD i;
649
d80207c3
KB
650 /* since biClrUsed field was filled during the loading of the DIB,
651 ** we know it contains the number of colors in the color table.
652 */
2bda0e17
KB
653 if (lpInfo->biClrUsed)
654 {
655/*
a58a12e9
VZ
656 npPal = (NPLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) +
657 (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY));
2bda0e17 658*/
a58a12e9
VZ
659 npPal = (LPLOGPALETTE)malloc(sizeof(LOGPALETTE) +
660 (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY));
2bda0e17 661 if (!npPal)
a58a12e9 662 return(FALSE);
2bda0e17 663
a58a12e9
VZ
664 npPal->palVersion = 0x300;
665 npPal->palNumEntries = (WORD)lpInfo->biClrUsed;
2bda0e17 666
d80207c3 667 /* get pointer to the color table */
a58a12e9 668 lpRGB = (RGBQUAD FAR *)((LPSTR)lpInfo + lpInfo->biSize);
2bda0e17 669
d80207c3 670 /* copy colors from the color table to the LogPalette structure */
3897b707 671 for (i = 0; (DWORD)i < lpInfo->biClrUsed; i++, lpRGB++)
a58a12e9
VZ
672 {
673 npPal->palPalEntry[i].peRed = lpRGB->rgbRed;
674 npPal->palPalEntry[i].peGreen = lpRGB->rgbGreen;
675 npPal->palPalEntry[i].peBlue = lpRGB->rgbBlue;
676 npPal->palPalEntry[i].peFlags = 0;
677 }
2bda0e17 678
a58a12e9
VZ
679 hLogPal = CreatePalette((LPLOGPALETTE)npPal);
680// LocalFree((HANDLE)npPal);
2bda0e17 681 free(npPal);
d80207c3 682
a58a12e9 683 return(hLogPal);
2bda0e17
KB
684 }
685
d80207c3
KB
686 /* 24-bit DIB with no color table. return default palette. Another
687 ** option would be to create a 256 color "rainbow" palette to provide
688 ** some good color choices.
689 */
2bda0e17 690 else
a58a12e9 691 return((HPALETTE) GetStockObject(DEFAULT_PALETTE));
c455ab93 692#endif
d80207c3 693
2bda0e17
KB
694}
695
d80207c3 696bool wxLoadIntoBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette **pal)
2bda0e17 697{
d80207c3
KB
698 HBITMAP hBitmap;
699 HPALETTE hPalette;
2bda0e17 700
d80207c3 701 bool success = (wxReadDIB(filename, &hBitmap, &hPalette) != 0);
2bda0e17 702
d80207c3
KB
703 if (!success)
704 {
705 DeleteObject(hPalette);
706 return FALSE;
707 }
708
709 if (hPalette)
710 {
711 if (pal)
2bda0e17 712 {
d80207c3
KB
713 *pal = new wxPalette;
714 (*pal)->SetHPALETTE((WXHPALETTE) hPalette);
2bda0e17 715 }
d80207c3
KB
716 else
717 DeleteObject(hPalette);
718 }
719 else if (pal)
720 *pal = NULL;
2bda0e17 721
d80207c3
KB
722 if (hBitmap)
723 {
724 BITMAP bm;
725 GetObject(hBitmap, sizeof(bm), (LPSTR)&bm);
2bda0e17 726
d80207c3
KB
727 bitmap->SetHBITMAP((WXHBITMAP) hBitmap);
728 bitmap->SetWidth(bm.bmWidth);
729 bitmap->SetHeight(bm.bmHeight);
730 bitmap->SetDepth(bm.bmPlanes * bm.bmBitsPixel);
0d0512bd 731#if WXWIN_COMPATIBILITY_2
d80207c3 732 bitmap->SetOk(TRUE);
0d0512bd 733#endif // WXWIN_COMPATIBILITY_2
d80207c3
KB
734 return TRUE;
735 }
736 else return FALSE;
2bda0e17
KB
737}
738
d80207c3 739wxBitmap *wxLoadBitmap(wxChar *filename, wxPalette **pal)
2bda0e17 740{
d80207c3
KB
741 wxBitmap *bitmap = new wxBitmap;
742 if (wxLoadIntoBitmap(filename, bitmap, pal))
743 return bitmap;
744 else
745 {
746 delete bitmap;
747 return NULL;
748 }
2bda0e17
KB
749}
750
751//---------------------------------------------------------------------
752//
d80207c3
KB
753// Function: InitBitmapInfoHeader
754//
755// Purpose: Does a "standard" initialization of a BITMAPINFOHEADER,
756// given the Width, Height, and Bits per Pixel for the
757// DIB.
2bda0e17 758//
d80207c3
KB
759// By standard, I mean that all the relevant fields are set
760// to the specified values. biSizeImage is computed, the
761// biCompression field is set to "no compression," and all
762// other fields are 0.
2bda0e17 763//
d80207c3
KB
764// Note that DIBs only allow BitsPixel values of 1, 4, 8, or
765// 24. This routine makes sure that one of these values is
766// used (whichever is most appropriate for the specified
767// nBPP).
768//
769// Parms: lpBmInfoHdr == Far pointer to a BITMAPINFOHEADER structure
2bda0e17 770// to be filled in.
d80207c3 771// dwWidth == Width of DIB (not in Win 3.0 & 3.1, high
2bda0e17 772// word MUST be 0).
d80207c3 773// dwHeight == Height of DIB (not in Win 3.0 & 3.1, high
2bda0e17 774// word MUST be 0).
d80207c3 775// nBPP == Bits per Pixel for the DIB.
2bda0e17
KB
776//
777// History: Date Reason
778// 11/07/91 Created
40c7a5fc 779//
2bda0e17 780//---------------------------------------------------------------------
d80207c3
KB
781
782static void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr,
783 DWORD dwWidth,
784 DWORD dwHeight,
785 int nBPP)
2bda0e17
KB
786{
787// _fmemset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));
788 memset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));
789
790 lpBmInfoHdr->biSize = sizeof (BITMAPINFOHEADER);
791 lpBmInfoHdr->biWidth = dwWidth;
792 lpBmInfoHdr->biHeight = dwHeight;
793 lpBmInfoHdr->biPlanes = 1;
794
795 if (nBPP <= 1)
796 nBPP = 1;
797 else if (nBPP <= 4)
798 nBPP = 4;
799 else if (nBPP <= 8)
800 nBPP = 8;
801/* Doesn't work
802 else if (nBPP <= 16)
803 nBPP = 16;
804*/
805 else
806 nBPP = 24;
807
808 lpBmInfoHdr->biBitCount = nBPP;
809 lpBmInfoHdr->biSizeImage = WIDTHBYTES (dwWidth * nBPP) * dwHeight;
810}
811
d80207c3
KB
812
813
814
ef3ab009 815LPSTR wxFindDIBBits (LPSTR lpbi)
2bda0e17 816{
448af9a4 817 return (lpbi + *(LPDWORD)lpbi + wxPaletteSize (lpbi));
2bda0e17
KB
818}
819
820//---------------------------------------------------------------------
d80207c3 821//
2bda0e17
KB
822// Function: BitmapToDIB
823//
824// Purpose: Given a device dependent bitmap and a palette, returns
825// a handle to global memory with a DIB spec in it. The
826// DIB is rendered using the colors of the palette passed in.
827//
828// Stolen almost verbatim from ShowDIB.
829//
830// Parms: hBitmap == Handle to device dependent bitmap compatible
831// with default screen display device.
832// hPal == Palette to render the DDB with. If it's NULL,
833// use the default palette.
834//
835// History: Date Reason
836// 6/01/91 Created
40c7a5fc 837//
2bda0e17 838//---------------------------------------------------------------------
d80207c3
KB
839
840HANDLE wxBitmapToDIB (HBITMAP hBitmap, HPALETTE hPal)
2bda0e17 841{
d80207c3
KB
842 BITMAP Bitmap;
843 BITMAPINFOHEADER bmInfoHdr;
844 LPBITMAPINFOHEADER lpbmInfoHdr;
845 LPSTR lpBits;
846 HDC hMemDC;
847 HANDLE hDIB;
848 HPALETTE hOldPal = NULL;
849
850 // Do some setup -- make sure the Bitmap passed in is valid,
851 // get info on the bitmap (like its height, width, etc.),
852 // then setup a BITMAPINFOHEADER.
2bda0e17
KB
853
854 if (!hBitmap)
855 return NULL;
856
857 if (!GetObject (hBitmap, sizeof (Bitmap), (LPSTR) &Bitmap))
858 return NULL;
859
40c7a5fc
RD
860 InitBitmapInfoHeader (&bmInfoHdr,
861 Bitmap.bmWidth,
862 Bitmap.bmHeight,
2bda0e17
KB
863 Bitmap.bmPlanes * Bitmap.bmBitsPixel);
864
865
d80207c3
KB
866 // Now allocate memory for the DIB. Then, set the BITMAPINFOHEADER
867 // into this memory, and find out where the bitmap bits go.
2bda0e17 868
d80207c3
KB
869 hDIB = GlobalAlloc (GHND, sizeof (BITMAPINFOHEADER) +
870 wxPaletteSize ((LPSTR) &bmInfoHdr) + bmInfoHdr.biSizeImage);
2bda0e17 871
d80207c3
KB
872 if (!hDIB)
873 return NULL;
2bda0e17
KB
874
875#ifdef __WINDOWS_386__
d80207c3 876 lpbmInfoHdr = (LPBITMAPINFOHEADER) MK_FP32(GlobalLock (hDIB));
2bda0e17 877#else
d80207c3 878 lpbmInfoHdr = (LPBITMAPINFOHEADER) GlobalLock (hDIB);
2bda0e17
KB
879#endif
880
d80207c3
KB
881 *lpbmInfoHdr = bmInfoHdr;
882 lpBits = wxFindDIBBits ((LPSTR) lpbmInfoHdr);
2bda0e17 883
2bda0e17 884
d80207c3
KB
885 // Now, we need a DC to hold our bitmap. If the app passed us
886 // a palette, it should be selected into the DC.
887
888 hMemDC = GetDC (NULL);
2bda0e17 889
d80207c3
KB
890 if (hPal)
891 {
892 hOldPal = SelectPalette (hMemDC, hPal, FALSE);
893 RealizePalette (hMemDC);
894 }
895
896
897
898 // We're finally ready to get the DIB. Call the driver and let
899 // it party on our bitmap. It will fill in the color table,
900 // and bitmap bits of our global memory block.
901
902 if (!GetDIBits (hMemDC,
40c7a5fc
RD
903 hBitmap,
904 0,
905 Bitmap.bmHeight,
906 lpBits,
907 (LPBITMAPINFO) lpbmInfoHdr,
2bda0e17 908 DIB_RGB_COLORS))
d80207c3
KB
909 {
910 GlobalUnlock (hDIB);
911 GlobalFree (hDIB);
912 hDIB = NULL;
913 }
914 else
915 GlobalUnlock (hDIB);
916
917
918 // Finally, clean up and return.
2bda0e17
KB
919
920 if (hOldPal)
d80207c3 921 SelectPalette (hMemDC, hOldPal, FALSE);
2bda0e17
KB
922
923 ReleaseDC (NULL, hMemDC);
d80207c3 924
2bda0e17
KB
925 return hDIB;
926}
927
d80207c3 928bool wxSaveBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette *colourmap)
2bda0e17 929{
d80207c3
KB
930 HPALETTE hPalette = 0;
931 if (colourmap)
932 hPalette = (HPALETTE) colourmap->GetHPALETTE();
933
934 HANDLE dibHandle = wxBitmapToDIB((HBITMAP) bitmap->GetHBITMAP(), hPalette);
935 if (dibHandle)
936 {
937 bool success = (WriteDIB(filename, dibHandle) != 0);
938 GlobalFree(dibHandle);
939 return success;
940 }
941 else return FALSE;
2bda0e17
KB
942}
943