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