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