]> git.saurik.com Git - wxWidgets.git/blob - src/msw/dib.cpp
got rid of more duplicated code for working with DIBs
[wxWidgets.git] / src / msw / dib.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/dib.cpp
3 // Purpose: implements wxDIB class
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 03.03.03 (replaces the old file with the same name)
7 // RCS-ID: $Id$
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/string.h"
29 #include "wx/log.h"
30 #endif //WX_PRECOMP
31
32 #include "wx/bitmap.h"
33 #include "wx/intl.h"
34
35 #include <stdio.h>
36 #include <stdlib.h>
37
38 #if !defined(__MWERKS__) && !defined(__SALFORDC__)
39 #include <memory.h>
40 #endif
41
42 #ifdef __GNUWIN32_OLD__
43 #include "wx/msw/gnuwin32/extra.h"
44 #endif
45
46 #include "wx/image.h"
47 #include "wx/msw/dib.h"
48
49 // ----------------------------------------------------------------------------
50 // private functions
51 // ----------------------------------------------------------------------------
52
53 // calculate the number of palette entries needed for the bitmap with this
54 // number of bits per pixel
55 static WORD wxGetNumOfBitmapColors(WORD bitsPerPixel)
56 {
57 // only 1, 4 and 8bpp bitmaps use palettes (well, they could be used with
58 // 24bpp ones too but we don't support this as I think it's quite uncommon)
59 return bitsPerPixel <= 8 ? 1 << bitsPerPixel : 0;
60 }
61
62 // ============================================================================
63 // implementation
64 // ============================================================================
65
66 // ----------------------------------------------------------------------------
67 // wxDIB creation
68 // ----------------------------------------------------------------------------
69
70 bool wxDIB::Create(int width, int height, int depth)
71 {
72 // we don't handle the palette yet
73 wxASSERT_MSG( depth == 24 || depth == 32,
74 _T("unsupported image depth in wxDIB::Create()") );
75
76 static const int infosize = sizeof(BITMAPINFOHEADER);
77
78 BITMAPINFO *info = (BITMAPINFO *)malloc(infosize);
79 wxCHECK_MSG( info, NULL, _T("malloc(BITMAPINFO) failed") );
80
81 memset(info, 0, infosize);
82
83 info->bmiHeader.biSize = infosize;
84 info->bmiHeader.biWidth = width;
85
86 // we use positive height here which corresponds to a DIB with normal, i.e.
87 // bottom to top, order -- normally using negative height (which means
88 // reversed for MS and hence natural for all the normal people top to
89 // bottom line scan order) could be used to avoid the need for the image
90 // reversal in Create(image) but this doesn't work under NT, only Win9x!
91 info->bmiHeader.biHeight = height;
92
93 info->bmiHeader.biPlanes = 1;
94 info->bmiHeader.biBitCount = depth;
95 info->bmiHeader.biSizeImage = GetLineSize(width, depth)*height;
96
97 m_handle = ::CreateDIBSection
98 (
99 0, // hdc (unused with DIB_RGB_COLORS)
100 info, // bitmap description
101 DIB_RGB_COLORS, // use RGB, not palette
102 &m_data, // [out] DIB bits
103 NULL, // don't use file mapping
104 0 // file mapping offset (not used here)
105 );
106
107 free(info);
108
109 if ( !m_handle )
110 {
111 wxLogLastError(wxT("CreateDIBSection"));
112
113 return false;
114 }
115
116 m_width = width;
117 m_height = height;
118 m_depth = depth;
119
120 return true;
121 }
122
123 // ----------------------------------------------------------------------------
124 // Loading/saving the DIBs
125 // ----------------------------------------------------------------------------
126
127 bool wxDIB::Load(const wxString& filename)
128 {
129 m_handle = (HBITMAP)::LoadImage
130 (
131 wxGetInstance(),
132 filename,
133 IMAGE_BITMAP,
134 0, 0, // don't specify the size
135 LR_CREATEDIBSECTION | LR_LOADFROMFILE
136 );
137 if ( !m_handle )
138 {
139 wxLogLastError(_T("LoadImage(LR_CREATEDIBSECTION | LR_LOADFROMFILE)"));
140
141 return false;
142 }
143
144 return true;
145 }
146
147 // ----------------------------------------------------------------------------
148 // wxDIB accessors
149 // ----------------------------------------------------------------------------
150
151 void wxDIB::DoGetObject() const
152 {
153 // only do something if we have a valid DIB but we don't [yet] have valid
154 // data
155 if ( m_handle && !m_data )
156 {
157 // although all the info we need is in BITMAP and so we don't really
158 // need DIBSECTION we still ask for it as modifying the bit values only
159 // works for the real DIBs and not for the bitmaps and it's better to
160 // check for this now rather than trying to find out why it doesn't
161 // work later
162 DIBSECTION ds;
163 if ( !::GetObject(m_handle, sizeof(ds), &ds) )
164 {
165 wxLogLastError(_T("GetObject(hDIB)"));
166 return;
167 }
168
169 wxDIB *self = wxConstCast(this, wxDIB);
170
171 self->m_width = ds.dsBm.bmWidth;
172 self->m_height = ds.dsBm.bmHeight;
173 self->m_depth = ds.dsBm.bmBitsPixel;
174 self->m_data = ds.dsBm.bmBits;
175 }
176 }
177
178 // ----------------------------------------------------------------------------
179 // DDB <-> DIB conversions
180 // ----------------------------------------------------------------------------
181
182 HBITMAP wxDIB::CreateDDB(HDC hdc) const
183 {
184 wxCHECK_MSG( m_handle, 0, _T("wxDIB::CreateDDB(): invalid object") );
185
186 DIBSECTION ds;
187 if ( !::GetObject(m_handle, sizeof(ds), &ds) )
188 {
189 wxLogLastError(_T("GetObject(hDIB)"));
190
191 return 0;
192 }
193
194 return ConvertToBitmap((BITMAPINFO *)&ds.dsBmih, hdc, ds.dsBm.bmBits);
195 }
196
197 /* static */
198 HBITMAP wxDIB::ConvertToBitmap(const BITMAPINFO *pbmi, HDC hdc, void *bits)
199 {
200 wxCHECK_MSG( pbmi, 0, _T("invalid DIB in ConvertToBitmap") );
201
202 // here we get BITMAPINFO struct followed by the actual bitmap bits and
203 // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info
204 const BITMAPINFOHEADER *pbmih = &pbmi->bmiHeader;
205
206 // get the pointer to the start of the real image data if we have a plain
207 // DIB and not a DIB section (in the latter case the pointer must be passed
208 // to us by the caller)
209 if ( !bits )
210 {
211 // we must skip over the colour table to get to the image data
212
213 // biClrUsed has the number of colors but it may be not initialized at
214 // all
215 int numColors = pbmih->biClrUsed;
216 if ( !numColors )
217 {
218 numColors = wxGetNumOfBitmapColors(pbmih->biBitCount);
219 }
220
221 bits = (char *)pbmih + sizeof(*pbmih) + numColors*sizeof(RGBQUAD);
222 }
223
224 HBITMAP hbmp = ::CreateDIBitmap
225 (
226 hdc ? hdc // create bitmap compatible
227 : ScreenHDC(), // with this DC
228 pbmih, // used to get size &c
229 CBM_INIT, // initialize bitmap bits too
230 bits, // ... using this data
231 pbmi, // this is used for palette only
232 DIB_RGB_COLORS // direct or indexed palette?
233 );
234
235 if ( !hbmp )
236 {
237 wxLogLastError(wxT("CreateDIBitmap"));
238 }
239
240 return hbmp;
241 }
242
243 /* static */
244 size_t wxDIB::ConvertFromBitmap(BITMAPINFO *pbi, HBITMAP hbmp)
245 {
246 wxASSERT_MSG( hbmp, wxT("invalid bmp can't be converted to DIB") );
247
248 // prepare all the info we need
249 BITMAP bm;
250 if ( !::GetObject(hbmp, sizeof(bm), &bm) )
251 {
252 wxLogLastError(wxT("GetObject(bitmap)"));
253
254 return 0;
255 }
256
257 // calculate the number of bits per pixel and the number of items in
258 // bmiColors array (whose meaning depends on the bitmap format)
259 WORD biBits = bm.bmPlanes * bm.bmBitsPixel;
260 WORD biColors = wxGetNumOfBitmapColors(biBits);
261
262 // we need a BITMAPINFO anyhow and if we're not given a pointer to it we
263 // use this one
264 BITMAPINFO bi2;
265
266 bool wantSizeOnly = pbi == NULL;
267 if ( wantSizeOnly )
268 pbi = &bi2;
269
270 // just for convenience
271 const int h = bm.bmHeight;
272
273 // init the header
274 BITMAPINFOHEADER& bi = pbi->bmiHeader;
275 wxZeroMemory(bi);
276 bi.biSize = sizeof(BITMAPINFOHEADER);
277 bi.biWidth = bm.bmWidth;
278 bi.biHeight = h;
279 bi.biPlanes = 1;
280 bi.biBitCount = biBits;
281
282 // memory we need for BITMAPINFO only
283 DWORD dwLen = bi.biSize + biColors * sizeof(RGBQUAD);
284
285 // first get the image size
286 ScreenHDC hdc;
287 if ( !::GetDIBits(hdc, hbmp, 0, h, NULL, pbi, DIB_RGB_COLORS) )
288 {
289 wxLogLastError(wxT("GetDIBits(NULL)"));
290
291 return 0;
292 }
293
294 if ( !wantSizeOnly )
295 {
296 // and now copy the bits
297 void *image = (char *)pbi + dwLen;
298 if ( !::GetDIBits(hdc, hbmp, 0, h, image, pbi, DIB_RGB_COLORS) )
299 {
300 wxLogLastError(wxT("GetDIBits"));
301
302 return 0;
303 }
304 }
305
306 // return the total size
307 return dwLen + bi.biSizeImage;
308 }
309
310 // ----------------------------------------------------------------------------
311 // palette support
312 // ----------------------------------------------------------------------------
313
314 #if wxUSE_PALETTE
315
316 wxPalette *wxDIB::CreatePalette() const
317 {
318 wxCHECK_MSG( m_handle, NULL, _T("wxDIB::CreatePalette(): invalid object") );
319
320 DIBSECTION ds;
321 if ( !::GetObject(m_handle, sizeof(ds), &ds) )
322 {
323 wxLogLastError(_T("GetObject(hDIB)"));
324
325 return 0;
326 }
327
328 // how many colours are we going to have in the palette?
329 DWORD biClrUsed = ds.dsBmih.biClrUsed;
330 if ( !biClrUsed )
331 {
332 // biClrUsed field might not be set
333 biClrUsed = 1 << ds.dsBmih.biBitCount;
334 }
335
336 if ( biClrUsed > 256 )
337 {
338 // only 8bpp bitmaps (and less) have palettes, so we surely don't
339 //
340 // NB: another possibility would be to return
341 // GetStockObject(DEFAULT_PALETTE) or even CreateHalftonePalette()?
342 return NULL;
343 }
344
345 // LOGPALETTE struct has only 1 element in palPalEntry array, we're
346 // going to have biClrUsed of them so add necessary space
347 LOGPALETTE *pPalette = (LOGPALETTE *)
348 malloc(sizeof(LOGPALETTE) + (biClrUsed - 1)*sizeof(PALETTEENTRY));
349 wxCHECK_MSG( pPalette, NULL, _T("out of memory") );
350
351 // initialize the palette header
352 pPalette->palVersion = 0x300; // magic number, not in docs but works
353 pPalette->palNumEntries = biClrUsed;
354
355 // and the colour table (it starts right after the end of the header)
356 const RGBQUAD *pRGB = (RGBQUAD *)((char *)&ds.dsBmih + ds.dsBmih.biSize);
357 for ( DWORD i = 0; i < biClrUsed; i++, pRGB++ )
358 {
359 pPalette->palPalEntry[i].peRed = pRGB->rgbRed;
360 pPalette->palPalEntry[i].peGreen = pRGB->rgbGreen;
361 pPalette->palPalEntry[i].peBlue = pRGB->rgbBlue;
362 pPalette->palPalEntry[i].peFlags = 0;
363 }
364
365 HPALETTE hPalette = ::CreatePalette(pPalette);
366
367 free(pPalette);
368
369 if ( !hPalette )
370 {
371 wxLogLastError(_T("CreatePalette"));
372
373 return NULL;
374 }
375
376 wxPalette *palette = new wxPalette;
377 palette->SetHPALETTE((WXHPALETTE)hPalette);
378
379 return palette;
380 }
381
382 #endif // wxUSE_PALETTE
383
384 // ----------------------------------------------------------------------------
385 // wxImage support
386 // ----------------------------------------------------------------------------
387
388 #if wxUSE_IMAGE
389
390 bool wxDIB::Create(const wxImage& image)
391 {
392 wxCHECK_MSG( image.Ok(), false, _T("invalid wxImage in wxDIB ctor") );
393
394 const int h = image.GetHeight();
395 const int w = image.GetWidth();
396
397 // if we have alpha channel, we need to create a 32bpp RGBA DIB, otherwise
398 // a 24bpp RGB is sufficient
399 const bool hasAlpha = image.HasAlpha();
400 const int bpp = hasAlpha ? 32 : 24;
401
402 if ( !Create(w, h, bpp) )
403 return false;
404
405 // DIBs are stored in bottom to top order (see also the comment above in
406 // Create()) so we need to copy bits line by line and starting from the end
407 const int srcBytesPerLine = w * 3;
408 const int dstBytesPerLine = GetLineSize(w, bpp);
409 const unsigned char *src = image.GetData() + ((h - 1) * srcBytesPerLine);
410 const unsigned char *alpha = hasAlpha ? image.GetAlpha() + (h - 1)*w : NULL;
411 unsigned char *dstLineStart = (unsigned char *)m_data;
412 for ( int y = 0; y < h; y++ )
413 {
414 // copy one DIB line
415 unsigned char *dst = dstLineStart;
416 for ( int x = 0; x < w; x++ )
417 {
418 // also, the order of RGB is inversed for DIBs
419 *dst++ = src[2];
420 *dst++ = src[1];
421 *dst++ = src[0];
422
423 src += 3;
424
425 if ( alpha )
426 *dst++ = *alpha++;
427 }
428
429 // pass to the previous line in the image
430 src -= 2*srcBytesPerLine;
431 if ( alpha )
432 alpha -= 2*w;
433
434 // and to the next one in the DIB
435 dstLineStart += dstBytesPerLine;
436 }
437
438 return true;
439 }
440
441 #endif // wxUSE_IMAGE
442
443 // ============================================================================
444 // old DIB code, to be integrated in wxDIB class
445 // ============================================================================
446
447 /*
448 * Routines for dealing with Device Independent Bitmaps.
449 *
450 * wxReadDIB() - Reads a DIB
451 * wxWriteDIB() - Writes a global handle in CF_DIB format
452 * to a file.
453 * wxPaletteSize() - Calculates the palette size in bytes
454 * of given DIB
455 * wxDibNumColors() - Determines the number of colors in DIB
456 * wxDibFromBitmap() - Creates a DIB repr. the DDB passed in.
457 * lread() - Private routine to read more than 64k
458 * lwrite() - Private routine to write more than 64k
459 */
460
461 #ifndef SEEK_CUR
462 /* flags for _lseek */
463 #define SEEK_CUR 1
464 #define SEEK_END 2
465 #define SEEK_SET 0
466 #endif
467
468 #define MAXREAD 32768 /* Number of bytes to be read during */
469 /* each read operation. */
470
471 /* Header signatutes for various resources */
472 #define BFT_ICON 0x4349 /* 'IC' */
473 #define BFT_BITMAP 0x4d42 /* 'BM' */
474 #define BFT_CURSOR 0x5450 /* 'PT(' */
475
476 /* macro to determine if resource is a DIB */
477 #define ISDIB(bft) ((bft) == BFT_BITMAP)
478
479 /* Macro to align given value to the closest DWORD (unsigned long ) */
480 #define ALIGNULONG(i) ((i+3)/4*4)
481
482 /* Macro to determine to round off the given value to the closest byte */
483 #define WIDTHBYTES(i) ((i+31)/32*4)
484
485 #define PALVERSION 0x300
486 #define MAXPALETTE 256 /* max. # supported palette entries */
487
488 static DWORD lread(int fh, VOID FAR *pv, DWORD ul);
489 static DWORD lwrite(int fh, VOID FAR *pv, DWORD ul);
490
491 static bool wxWriteDIB (LPTSTR szFile,HANDLE hdib);
492 WORD wxPaletteSize (VOID FAR * pv); // This is non-static as some apps use it externally
493 static WORD wxDibNumColors (VOID FAR * pv);
494 static bool wxMakeBitmapAndPalette(HDC,HANDLE,HPALETTE *,HBITMAP *);
495
496 /*
497 * FUNCTION : wxWriteDIB(LPSTR szFile,HANDLE hdib)
498 * PURPOSE : Write a global handle in CF_DIB format to a file.
499 * RETURNS : TRUE - if successful.
500 * FALSE - otherwise
501 */
502
503 static bool wxWriteDIB(LPTSTR szFile, HANDLE hdib)
504 {
505 BITMAPFILEHEADER hdr;
506 LPBITMAPINFOHEADER lpbi;
507 int fh;
508 OFSTRUCT of;
509
510 if (!hdib)
511 return FALSE;
512
513 fh = OpenFile(wxConvertWX2MB(szFile), &of, OF_CREATE | OF_READWRITE);
514 if (fh == -1)
515 return FALSE;
516
517 lpbi = (LPBITMAPINFOHEADER) GlobalLock(hdib);
518
519 /* Fill in the fields of the file header */
520 hdr.bfType = BFT_BITMAP;
521 hdr.bfSize = GlobalSize(hdib) + sizeof(BITMAPFILEHEADER);
522 hdr.bfReserved1 = 0;
523 hdr.bfReserved2 = 0;
524 hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + lpbi->biSize +
525 wxPaletteSize(lpbi);
526
527 /* Write the file header */
528 _lwrite(fh, (LPSTR) &hdr, sizeof(BITMAPFILEHEADER));
529
530 /* Write the DIB header and the bits */
531 lwrite(fh, (LPSTR) lpbi, GlobalSize(hdib));
532
533 GlobalUnlock(hdib);
534 _lclose(fh);
535 return TRUE;
536 }
537
538 /*
539 * FUNCTION : wxPaletteSize(VOID FAR * pv)
540 * PURPOSE : Calculates the palette size in bytes. If the info. block
541 * is of the BITMAPCOREHEADER type, the number of colors is
542 * multiplied by 3 to give the palette size, otherwise the
543 * number of colors is multiplied by 4.
544 * RETURNS : Palette size in number of bytes.
545 */
546
547 WORD wxPaletteSize(VOID FAR * pv)
548 {
549 LPBITMAPINFOHEADER lpbi;
550 WORD NumColors;
551
552 lpbi = (LPBITMAPINFOHEADER) pv;
553 NumColors = wxDibNumColors(lpbi);
554
555 if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
556 return (WORD)(NumColors * sizeof(RGBTRIPLE));
557 else
558 return (WORD)(NumColors * sizeof(RGBQUAD));
559 }
560
561 /*
562 * FUNCTION : wxDibNumColors(VOID FAR * pv)
563 * PURPOSE : Determines the number of colors in the DIB by looking at
564 * the BitCount filed in the info block.
565 * RETURNS : The number of colors in the DIB. *
566 */
567
568 static WORD wxDibNumColors(VOID FAR *pv)
569 {
570 int bits;
571 BITMAPINFOHEADER *lpbi;
572 BITMAPCOREHEADER *lpbc;
573
574 lpbi = ((BITMAPINFOHEADER*) pv);
575 lpbc = ((BITMAPCOREHEADER*) pv);
576
577 /* With the BITMAPINFO format headers, the size of the palette
578 * is in biClrUsed, whereas in the BITMAPCORE - style headers, it
579 * is dependent on the bits per pixel ( = 2 raised to the power of
580 * bits/pixel).
581 */
582 if (lpbi->biSize != sizeof(BITMAPCOREHEADER)) {
583 if (lpbi->biClrUsed != 0)
584 return (WORD) lpbi->biClrUsed;
585 bits = lpbi->biBitCount;
586 }
587 else
588 bits = lpbc->bcBitCount;
589
590 switch (bits) {
591 case 1:
592 return 2;
593 case 4:
594 return 16;
595 case 8:
596 return 256;
597 default:
598 /* A 24 bitcount DIB has no color table */
599 return 0;
600 }
601 }
602
603 /*
604 * FUNCTION : lread(int fh, VOID FAR *pv, DWORD ul)
605 * PURPOSE : Reads data in steps of 32k till all the data has been read.
606 * RETURNS : 0 - If read did not proceed correctly.
607 * number of bytes read otherwise.
608 */
609
610 static DWORD lread(int fh, void far *pv, DWORD ul)
611 {
612 DWORD ulT = ul;
613 #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__)
614 BYTE *hp = (BYTE *) pv;
615 #else
616 BYTE huge *hp = (BYTE huge *) pv;
617 #endif
618 while (ul > (DWORD) MAXREAD) {
619 if (_lread(fh, (LPSTR) hp, (WORD) MAXREAD) != MAXREAD)
620 return 0;
621 ul -= MAXREAD;
622 hp += MAXREAD;
623 }
624 if (_lread(fh, (LPSTR) hp, (WXUINT) ul) != (WXUINT) ul)
625 return 0;
626 return ulT;
627 }
628
629 /*
630 * FUNCTION : lwrite(int fh, VOID FAR *pv, DWORD ul)
631 * PURPOSE : Writes data in steps of 32k till all the data is written.
632 * RETURNS : 0 - If write did not proceed correctly.
633 * number of bytes written otherwise.
634 */
635
636 static DWORD lwrite(int fh, VOID FAR *pv, DWORD ul)
637 {
638 DWORD ulT = ul;
639 #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__)
640 BYTE *hp = (BYTE *) pv;
641 #else
642 BYTE huge *hp = (BYTE huge *) pv;
643 #endif
644 while (ul > MAXREAD) {
645 if (_lwrite(fh, (LPSTR) hp, (WORD) MAXREAD) != MAXREAD)
646 return 0;
647 ul -= MAXREAD;
648 hp += MAXREAD;
649 }
650 if (_lwrite(fh, (LPSTR) hp, (WXUINT) ul) != (WXUINT) ul)
651 return 0;
652 return ulT;
653 }
654
655 /*
656 * FUNCTION : wxReadDIB(hWnd)
657 * PURPOSE : Reads a DIB from a file, obtains a handle to its
658 * BITMAPINFO struct. and loads the DIB. Once the DIB
659 * is loaded, the function also creates a bitmap and
660 * palette out of the DIB for a device-dependent form.
661 * RETURNS : TRUE - DIB loaded and bitmap/palette created
662 * The DIBINIT structure pointed to by pInfo is
663 * filled with the appropriate handles.
664 * FALSE - otherwise
665 */
666
667 bool wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette)
668 {
669 int fh;
670 LPBITMAPINFOHEADER lpbi;
671 OFSTRUCT of;
672 BITMAPFILEHEADER bf;
673 WORD nNumColors;
674 bool result = FALSE;
675 WORD offBits;
676 HDC hDC;
677 bool bCoreHead = FALSE;
678 HANDLE hDIB = 0;
679
680 /* Open the file and get a handle to it's BITMAPINFO */
681
682 fh = OpenFile (wxConvertWX2MB(lpFileName), &of, OF_READ);
683 if (fh == -1) {
684 wxLogError(_("Can't open file '%s'"), lpFileName);
685 return (0);
686 }
687
688 hDIB = GlobalAlloc(GHND, (DWORD)(sizeof(BITMAPINFOHEADER) +
689 256 * sizeof(RGBQUAD)));
690 if (!hDIB)
691 return(0);
692
693 lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
694
695 /* read the BITMAPFILEHEADER */
696 if (sizeof (bf) != _lread (fh, (LPSTR)&bf, sizeof (bf)))
697 goto ErrExit;
698
699 if (bf.bfType != 0x4d42) /* 'BM' */
700 goto ErrExit;
701
702 if (sizeof(BITMAPCOREHEADER) != _lread (fh, (LPSTR)lpbi, sizeof(BITMAPCOREHEADER)))
703 goto ErrExit;
704
705 if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
706 {
707 lpbi->biSize = sizeof(BITMAPINFOHEADER);
708 lpbi->biBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
709 lpbi->biPlanes = ((LPBITMAPCOREHEADER)lpbi)->bcPlanes;
710 lpbi->biHeight = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
711 lpbi->biWidth = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
712 bCoreHead = TRUE;
713 }
714 else
715 {
716 // get to the start of the header and read INFOHEADER
717 _llseek(fh,sizeof(BITMAPFILEHEADER),SEEK_SET);
718 if (sizeof(BITMAPINFOHEADER) != _lread (fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))
719 goto ErrExit;
720 }
721
722 nNumColors = (WORD)lpbi->biClrUsed;
723 if ( nNumColors == 0 )
724 {
725 /* no color table for 24-bit, default size otherwise */
726 if (lpbi->biBitCount != 24)
727 nNumColors = 1 << lpbi->biBitCount; /* standard size table */
728 }
729
730 /* fill in some default values if they are zero */
731 if (lpbi->biClrUsed == 0)
732 lpbi->biClrUsed = nNumColors;
733
734 if (lpbi->biSizeImage == 0)
735 {
736 lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3)
737 * lpbi->biHeight;
738 }
739
740 /* get a proper-sized buffer for header, color table and bits */
741 GlobalUnlock(hDIB);
742 hDIB = GlobalReAlloc(hDIB, lpbi->biSize +
743 nNumColors * sizeof(RGBQUAD) +
744 lpbi->biSizeImage, 0);
745 if (!hDIB) /* can't resize buffer for loading */
746 goto ErrExit2;
747
748 lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
749
750 /* read the color table */
751 if (!bCoreHead)
752 _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));
753 else
754 {
755 signed int i;
756 RGBQUAD FAR *pQuad;
757 RGBTRIPLE FAR *pTriple;
758
759 _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBTRIPLE));
760
761 pQuad = (RGBQUAD FAR *)((LPSTR)lpbi + lpbi->biSize);
762 pTriple = (RGBTRIPLE FAR *) pQuad;
763 for (i = nNumColors - 1; i >= 0; i--)
764 {
765 pQuad[i].rgbRed = pTriple[i].rgbtRed;
766 pQuad[i].rgbBlue = pTriple[i].rgbtBlue;
767 pQuad[i].rgbGreen = pTriple[i].rgbtGreen;
768 pQuad[i].rgbReserved = 0;
769 }
770 }
771
772 /* offset to the bits from start of DIB header */
773 offBits = (WORD)(lpbi->biSize + nNumColors * sizeof(RGBQUAD));
774
775 if (bf.bfOffBits != 0L)
776 {
777 _llseek(fh,bf.bfOffBits,SEEK_SET);
778 }
779
780 if (lpbi->biSizeImage == lread(fh, (LPSTR)lpbi + offBits, lpbi->biSizeImage))
781 {
782 GlobalUnlock(hDIB);
783
784 hDC = GetDC(NULL);
785 if (!wxMakeBitmapAndPalette(hDC, hDIB, palette,
786 bitmap))
787 {
788 ReleaseDC(NULL,hDC);
789 goto ErrExit2;
790 }
791 else
792 {
793 ReleaseDC(NULL,hDC);
794 GlobalFree(hDIB);
795 result = TRUE;
796 }
797 }
798 else
799 {
800 ErrExit:
801 GlobalUnlock(hDIB);
802 ErrExit2:
803 GlobalFree(hDIB);
804 }
805
806 _lclose(fh);
807 return(result);
808 }
809
810 /*
811 * FUNCTION : wxMakeBitmapAndPalette
812 * PURPOSE : Given a DIB, creates a bitmap and corresponding palette
813 * to be used for a device-dependent representation of
814 * of the image.
815 * RETURNS : TRUE --> success. phPal and phBitmap are filled with
816 * appropriate handles. Caller is responsible
817 * for freeing objects.
818 * FALSE --> unable to create objects. both pointer are
819 * not valid
820 */
821
822 static bool wxMakeBitmapAndPalette(HDC hDC, HANDLE hDIB,
823 HPALETTE * phPal, HBITMAP * phBitmap)
824 {
825 LPBITMAPINFOHEADER lpInfo;
826 bool result = FALSE;
827 HBITMAP hBitmap;
828 HPALETTE hPalette, hOldPal;
829 LPSTR lpBits;
830
831 lpInfo = (LPBITMAPINFOHEADER) GlobalLock(hDIB);
832
833 hPalette = wxMakeDIBPalette(lpInfo);
834 if ( hPalette )
835 {
836 // Need to realize palette for converting DIB to bitmap.
837 hOldPal = SelectPalette(hDC, hPalette, TRUE);
838 RealizePalette(hDC);
839
840 lpBits = (LPSTR)lpInfo + (WORD)lpInfo->biSize +
841 (WORD)lpInfo->biClrUsed * sizeof(RGBQUAD);
842 hBitmap = CreateDIBitmap(hDC, lpInfo, CBM_INIT, lpBits,
843 (LPBITMAPINFO)lpInfo, DIB_RGB_COLORS);
844
845 SelectPalette(hDC, hOldPal, TRUE);
846 RealizePalette(hDC);
847
848 if (!hBitmap)
849 DeleteObject(hPalette);
850 else
851 {
852 *phBitmap = hBitmap;
853 *phPal = hPalette;
854 result = TRUE;
855 }
856 }
857
858 GlobalUnlock (hDIB); // glt
859
860 return(result);
861 }
862
863 /*
864 * FUNCTION : wxMakeDIBPalette(lpInfo)
865 * PURPOSE : Given a BITMAPINFOHEADER, create a palette based on
866 * the color table.
867 * RETURNS : non-zero - handle of a corresponding palette
868 * zero - unable to create palette
869 */
870
871 HPALETTE wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo)
872 {
873 LPLOGPALETTE npPal;
874 RGBQUAD far *lpRGB;
875 HPALETTE hLogPal;
876 WORD i;
877
878 /* since biClrUsed field was filled during the loading of the DIB,
879 * we know it contains the number of colors in the color table.
880 */
881 if (lpInfo->biClrUsed)
882 {
883 npPal = (LPLOGPALETTE)malloc(sizeof(LOGPALETTE) +
884 (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY));
885 if (!npPal)
886 return NULL;
887
888 npPal->palVersion = 0x300;
889 npPal->palNumEntries = (WORD)lpInfo->biClrUsed;
890
891 /* get pointer to the color table */
892 lpRGB = (RGBQUAD FAR *)((LPSTR)lpInfo + lpInfo->biSize);
893
894 /* copy colors from the color table to the LogPalette structure */
895 for (i = 0; (DWORD)i < lpInfo->biClrUsed; i++, lpRGB++)
896 {
897 npPal->palPalEntry[i].peRed = lpRGB->rgbRed;
898 npPal->palPalEntry[i].peGreen = lpRGB->rgbGreen;
899 npPal->palPalEntry[i].peBlue = lpRGB->rgbBlue;
900 npPal->palPalEntry[i].peFlags = 0;
901 }
902
903 hLogPal = CreatePalette((LPLOGPALETTE)npPal);
904 free(npPal);
905
906 return(hLogPal);
907 }
908
909 /* 24-bit DIB with no color table. Return default palette. Another
910 * option would be to create a 256 color "rainbow" palette to provide
911 * some good color choices.
912 */
913 else
914 return((HPALETTE) GetStockObject(DEFAULT_PALETTE));
915 }
916
917 /*
918 *
919 * Function: InitBitmapInfoHeader
920 *
921 * Purpose: Does a "standard" initialization of a BITMAPINFOHEADER,
922 * given the Width, Height, and Bits per Pixel for the
923 * DIB.
924 *
925 * By standard, I mean that all the relevant fields are set
926 * to the specified values. biSizeImage is computed, the
927 * biCompression field is set to "no compression," and all
928 * other fields are 0.
929 *
930 * Note that DIBs only allow BitsPixel values of 1, 4, 8, or
931 * 24. This routine makes sure that one of these values is
932 * used (whichever is most appropriate for the specified
933 * nBPP).
934 *
935 * Parms: lpBmInfoHdr == Far pointer to a BITMAPINFOHEADER structure
936 * to be filled in.
937 * dwWidth == Width of DIB (not in Win 3.0 & 3.1, high
938 * word MUST be 0).
939 * dwHeight == Height of DIB (not in Win 3.0 & 3.1, high
940 * word MUST be 0).
941 * nBPP == Bits per Pixel for the DIB.
942 *
943 */
944
945 static void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr,
946 DWORD dwWidth,
947 DWORD dwHeight,
948 int nBPP)
949 {
950 // _fmemset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));
951 memset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));
952
953 lpBmInfoHdr->biSize = sizeof (BITMAPINFOHEADER);
954 lpBmInfoHdr->biWidth = dwWidth;
955 lpBmInfoHdr->biHeight = dwHeight;
956 lpBmInfoHdr->biPlanes = 1;
957
958 if (nBPP <= 1)
959 nBPP = 1;
960 else if (nBPP <= 4)
961 nBPP = 4;
962 else if (nBPP <= 8)
963 nBPP = 8;
964 /* Doesn't work
965 else if (nBPP <= 16)
966 nBPP = 16;
967 */
968 else
969 nBPP = 24;
970
971 lpBmInfoHdr->biBitCount = nBPP;
972 lpBmInfoHdr->biSizeImage = WIDTHBYTES (dwWidth * nBPP) * dwHeight;
973 }
974
975 LPSTR wxFindDIBBits (LPSTR lpbi)
976 {
977 return (lpbi + *(LPDWORD)lpbi + wxPaletteSize (lpbi));
978 }
979
980 /*
981 * Function: BitmapToDIB
982 *
983 * Purpose: Given a device dependent bitmap and a palette, returns
984 * a handle to global memory with a DIB spec in it. The
985 * DIB is rendered using the colors of the palette passed in.
986 *
987 * Parms: hBitmap == Handle to device dependent bitmap compatible
988 * with default screen display device.
989 * hPal == Palette to render the DDB with. If it's NULL,
990 * use the default palette.
991 */
992
993 HANDLE wxBitmapToDIB (HBITMAP hBitmap, HPALETTE hPal)
994 {
995 BITMAP Bitmap;
996 BITMAPINFOHEADER bmInfoHdr;
997 LPBITMAPINFOHEADER lpbmInfoHdr;
998 LPSTR lpBits;
999 HDC hMemDC;
1000 HANDLE hDIB;
1001 HPALETTE hOldPal = NULL;
1002
1003 // Do some setup -- make sure the Bitmap passed in is valid,
1004 // get info on the bitmap (like its height, width, etc.),
1005 // then setup a BITMAPINFOHEADER.
1006
1007 if (!hBitmap)
1008 return NULL;
1009
1010 if (!GetObject (hBitmap, sizeof (Bitmap), (LPSTR) &Bitmap))
1011 return NULL;
1012
1013 InitBitmapInfoHeader (&bmInfoHdr,
1014 Bitmap.bmWidth,
1015 Bitmap.bmHeight,
1016 Bitmap.bmPlanes * Bitmap.bmBitsPixel);
1017
1018 // Now allocate memory for the DIB. Then, set the BITMAPINFOHEADER
1019 // into this memory, and find out where the bitmap bits go.
1020
1021 hDIB = GlobalAlloc (GHND, sizeof (BITMAPINFOHEADER) +
1022 wxPaletteSize ((LPSTR) &bmInfoHdr) + bmInfoHdr.biSizeImage);
1023
1024 if (!hDIB)
1025 return NULL;
1026
1027 lpbmInfoHdr = (LPBITMAPINFOHEADER) GlobalLock (hDIB);
1028
1029 *lpbmInfoHdr = bmInfoHdr;
1030 lpBits = wxFindDIBBits ((LPSTR) lpbmInfoHdr);
1031
1032
1033 // Now, we need a DC to hold our bitmap. If the app passed us
1034 // a palette, it should be selected into the DC.
1035
1036 hMemDC = GetDC (NULL);
1037
1038 if (hPal)
1039 {
1040 hOldPal = SelectPalette (hMemDC, hPal, FALSE);
1041 RealizePalette (hMemDC);
1042 }
1043
1044 // We're finally ready to get the DIB. Call the driver and let
1045 // it party on our bitmap. It will fill in the color table,
1046 // and bitmap bits of our global memory block.
1047
1048 if (!GetDIBits (hMemDC, hBitmap, 0, Bitmap.bmHeight, lpBits,
1049 (LPBITMAPINFO) lpbmInfoHdr, DIB_RGB_COLORS))
1050 {
1051 GlobalUnlock (hDIB);
1052 GlobalFree (hDIB);
1053 hDIB = NULL;
1054 }
1055 else
1056 GlobalUnlock (hDIB);
1057
1058 // Finally, clean up and return.
1059
1060 if (hOldPal)
1061 SelectPalette (hMemDC, hOldPal, FALSE);
1062
1063 ReleaseDC (NULL, hMemDC);
1064
1065 return hDIB;
1066 }
1067
1068 bool wxSaveBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette *palette)
1069 {
1070 HPALETTE hPalette = 0;
1071 #if wxUSE_PALETTE
1072 if (palette)
1073 hPalette = (HPALETTE) palette->GetHPALETTE();
1074 #endif // wxUSE_PALETTE
1075
1076 HANDLE dibHandle = wxBitmapToDIB((HBITMAP) bitmap->GetHBITMAP(), hPalette);
1077 if (dibHandle)
1078 {
1079 bool success = (wxWriteDIB(filename, dibHandle) != 0);
1080 GlobalFree(dibHandle);
1081 return success;
1082 }
1083 else return FALSE;
1084 }
1085