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