]>
Commit | Line | Data |
---|---|---|
53eff2a2 VZ |
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 | ||
d80207c3 KB |
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 | *******************************************************************************/ | |
2bda0e17 KB |
214 | |
215 | // For compilers that support precompilation, includes "wx.h". | |
2bda0e17 KB |
216 | #include "wx/wxprec.h" |
217 | ||
218 | #if defined(__BORLANDC__) | |
219 | #pragma hdrstop | |
220 | #endif | |
221 | ||
222 | #ifndef WX_PRECOMP | |
2432b92d | 223 | #include "wx/bitmap.h" |
531dfa44 VZ |
224 | #include "wx/log.h" |
225 | #include "wx/intl.h" | |
2bda0e17 KB |
226 | #endif |
227 | ||
228 | #include <windows.h> | |
229 | #include <stdio.h> | |
230 | #include <stdlib.h> | |
ce3ed50d JS |
231 | |
232 | #if !defined(__MWERKS__) && !defined(__SALFORDC__) | |
2bda0e17 | 233 | #include <memory.h> |
17dff81c | 234 | #endif |
2bda0e17 KB |
235 | |
236 | #include "wx/msw/dib.h" | |
237 | ||
c42404a5 VZ |
238 | #ifdef __GNUWIN32_OLD__ |
239 | #include "wx/msw/gnuwin32/extra.h" | |
65fd5cb0 | 240 | #endif |
2bda0e17 KB |
241 | |
242 | #ifndef SEEK_CUR | |
d80207c3 | 243 | /* flags for _lseek */ |
a58a12e9 VZ |
244 | #define SEEK_CUR 1 |
245 | #define SEEK_END 2 | |
246 | #define SEEK_SET 0 | |
2bda0e17 KB |
247 | #endif |
248 | ||
d80207c3 KB |
249 | #define MAXREAD 32768 /* Number of bytes to be read during */ |
250 | /* each read operation. */ | |
2bda0e17 | 251 | |
d80207c3 KB |
252 | /* Header signatutes for various resources */ |
253 | #define BFT_ICON 0x4349 /* 'IC' */ | |
254 | #define BFT_BITMAP 0x4d42 /* 'BM' */ | |
255 | #define BFT_CURSOR 0x5450 /* 'PT(' */ | |
2bda0e17 | 256 | |
d80207c3 KB |
257 | /* macro to determine if resource is a DIB */ |
258 | #define ISDIB(bft) ((bft) == BFT_BITMAP) | |
2bda0e17 | 259 | |
d80207c3 KB |
260 | /* Macro to align given value to the closest DWORD (unsigned long ) */ |
261 | #define ALIGNULONG(i) ((i+3)/4*4) | |
2bda0e17 | 262 | |
d80207c3 KB |
263 | /* Macro to determine to round off the given value to the closest byte */ |
264 | #define WIDTHBYTES(i) ((i+31)/32*4) | |
2bda0e17 | 265 | |
d80207c3 KB |
266 | #define PALVERSION 0x300 |
267 | #define MAXPALETTE 256 /* max. # supported palette entries */ | |
2bda0e17 | 268 | |
d80207c3 | 269 | static DWORD PASCAL lread(int fh, VOID FAR *pv, DWORD ul); |
73974df1 VZ |
270 | static DWORD PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul); |
271 | ||
d80207c3 KB |
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); | |
73974df1 | 276 | static BOOL PASCAL MakeBitmapAndPalette(HDC,HANDLE,HPALETTE *,HBITMAP *); |
2bda0e17 | 277 | |
d80207c3 KB |
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) | |
2bda0e17 | 290 | { |
d80207c3 KB |
291 | BITMAPFILEHEADER hdr; |
292 | LPBITMAPINFOHEADER lpbi; | |
293 | int fh; | |
294 | OFSTRUCT of; | |
2bda0e17 | 295 | |
d80207c3 KB |
296 | if (!hdib) |
297 | return FALSE; | |
298 | ||
299 | fh = OpenFile(wxConvertWX2MB(szFile), &of, OF_CREATE | OF_READWRITE); | |
300 | if (fh == -1) | |
301 | return FALSE; | |
2bda0e17 KB |
302 | |
303 | #ifdef __WINDOWS_386__ | |
d80207c3 | 304 | lpbi = (LPBITMAPINFOHEADER) MK_FP32(GlobalLock(hdib)); |
2bda0e17 | 305 | #else |
d80207c3 | 306 | lpbi = (LPBITMAPINFOHEADER) GlobalLock(hdib); |
2bda0e17 | 307 | #endif |
d80207c3 KB |
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); | |
2bda0e17 | 315 | |
d80207c3 KB |
316 | /* Write the file header */ |
317 | _lwrite(fh, (LPSTR) &hdr, sizeof(BITMAPFILEHEADER)); | |
2bda0e17 | 318 | |
d80207c3 KB |
319 | /* Write the DIB header and the bits */ |
320 | lwrite(fh, (LPSTR) lpbi, GlobalSize(hdib)); | |
2bda0e17 | 321 | |
d80207c3 KB |
322 | GlobalUnlock(hdib); |
323 | _lclose(fh); | |
324 | return TRUE; | |
2bda0e17 KB |
325 | } |
326 | ||
d80207c3 KB |
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) | |
2bda0e17 | 341 | { |
d80207c3 KB |
342 | LPBITMAPINFOHEADER lpbi; |
343 | WORD NumColors; | |
2bda0e17 | 344 | |
d80207c3 KB |
345 | lpbi = (LPBITMAPINFOHEADER) pv; |
346 | NumColors = DibNumColors(lpbi); | |
2bda0e17 | 347 | |
d80207c3 KB |
348 | if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) |
349 | return (WORD)(NumColors * sizeof(RGBTRIPLE)); | |
350 | else | |
351 | return (WORD)(NumColors * sizeof(RGBQUAD)); | |
2bda0e17 KB |
352 | } |
353 | ||
d80207c3 KB |
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) | |
2bda0e17 | 366 | { |
d80207c3 KB |
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 | } | |
2bda0e17 KB |
398 | } |
399 | ||
d80207c3 KB |
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 | ||
2bda0e17 | 411 | #if NOTHING |
d80207c3 | 412 | static HANDLE DibFromBitmap(HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal) |
2bda0e17 | 413 | { |
d80207c3 KB |
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 | } | |
2bda0e17 KB |
458 | |
459 | #ifdef __WINDOWS_386__ | |
d80207c3 | 460 | lpbi = (BITMAPINFOHEADER FAR *) MK_FP32(GlobalLock(hdib)); |
2bda0e17 | 461 | #else |
d80207c3 | 462 | lpbi = (BITMAPINFOHEADER FAR *) GlobalLock(hdib); |
2bda0e17 KB |
463 | #endif |
464 | ||
d80207c3 | 465 | *lpbi = bi; |
2bda0e17 | 466 | |
d80207c3 KB |
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); | |
716cd410 | 472 | |
d80207c3 KB |
473 | bi = *lpbi; |
474 | GlobalUnlock(hdib); | |
2bda0e17 | 475 | |
d80207c3 KB |
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 | */ | |
2bda0e17 | 500 | #ifdef __WINDOWS_386__ |
a58a12e9 | 501 | lpbi = (BITMAPINFOHEADER FAR *) MK_FP32(GlobalLock(hdib)); |
2bda0e17 | 502 | #else |
a58a12e9 | 503 | lpbi = (BITMAPINFOHEADER FAR *) GlobalLock(hdib); |
2bda0e17 KB |
504 | #endif |
505 | ||
d80207c3 KB |
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 | } | |
a58a12e9 VZ |
518 | |
519 | bi = *lpbi; | |
520 | GlobalUnlock(hdib); | |
d80207c3 | 521 | |
a58a12e9 VZ |
522 | SelectPalette(hdc, hpal, FALSE); |
523 | ReleaseDC(NULL, hdc); | |
524 | return hdib; | |
2bda0e17 KB |
525 | } |
526 | #endif | |
527 | ||
d80207c3 KB |
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; | |
b4da152e | 543 | #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__) |
d80207c3 KB |
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 | } | |
2bda0e17 | 558 | |
d80207c3 KB |
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) | |
2bda0e17 | 571 | { |
d80207c3 | 572 | DWORD ulT = ul; |
b4da152e | 573 | #if defined(WINNT) || defined(__WIN32__) || defined(__WIN32__) |
d80207c3 | 574 | BYTE *hp = (BYTE *) pv; |
2bda0e17 | 575 | #else |
d80207c3 | 576 | BYTE huge *hp = (BYTE huge *) pv; |
2bda0e17 | 577 | #endif |
d80207c3 KB |
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; | |
2bda0e17 KB |
587 | } |
588 | ||
d80207c3 KB |
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) | |
2bda0e17 | 605 | { |
d80207c3 | 606 | int fh; |
2bda0e17 | 607 | LPBITMAPINFOHEADER lpbi; |
d80207c3 KB |
608 | OFSTRUCT of; |
609 | BITMAPFILEHEADER bf; | |
610 | WORD nNumColors; | |
2bda0e17 | 611 | BOOL result = FALSE; |
2bda0e17 KB |
612 | WORD offBits; |
613 | HDC hDC; | |
614 | BOOL bCoreHead = FALSE; | |
615 | HANDLE hDIB = 0; | |
616 | ||
d80207c3 KB |
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) { | |
a58a12e9 VZ |
621 | wxLogError(_("Can't open file '%s'"), lpFileName); |
622 | return (0); | |
d80207c3 | 623 | } |
40c7a5fc | 624 | |
d80207c3 KB |
625 | hDIB = GlobalAlloc(GHND, (DWORD)(sizeof(BITMAPINFOHEADER) + |
626 | 256 * sizeof(RGBQUAD))); | |
2bda0e17 | 627 | if (!hDIB) |
a58a12e9 | 628 | return(0); |
2bda0e17 KB |
629 | |
630 | #ifdef __WINDOWS_386__ | |
631 | lpbi = (LPBITMAPINFOHEADER)MK_FP32(GlobalLock(hDIB)); | |
632 | #else | |
633 | lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); | |
634 | #endif | |
635 | ||
d80207c3 KB |
636 | /* read the BITMAPFILEHEADER */ |
637 | if (sizeof (bf) != _lread (fh, (LPSTR)&bf, sizeof (bf))) | |
a58a12e9 | 638 | goto ErrExit; |
2bda0e17 | 639 | |
d80207c3 | 640 | if (bf.bfType != 0x4d42) /* 'BM' */ |
a58a12e9 | 641 | goto ErrExit; |
2bda0e17 | 642 | |
d80207c3 | 643 | if (sizeof(BITMAPCOREHEADER) != _lread (fh, (LPSTR)lpbi, sizeof(BITMAPCOREHEADER))) |
a58a12e9 | 644 | goto ErrExit; |
2bda0e17 | 645 | |
d80207c3 KB |
646 | if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) |
647 | { | |
a58a12e9 VZ |
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; | |
d80207c3 KB |
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))) | |
a58a12e9 | 660 | goto ErrExit; |
d80207c3 | 661 | } |
2bda0e17 | 662 | |
fd3f686c | 663 | nNumColors = (WORD)lpbi->biClrUsed; |
d80207c3 KB |
664 | if ( nNumColors == 0 ) |
665 | { | |
666 | /* no color table for 24-bit, default size otherwise */ | |
a58a12e9 | 667 | if (lpbi->biBitCount != 24) |
d80207c3 KB |
668 | nNumColors = 1 << lpbi->biBitCount; /* standard size table */ |
669 | } | |
2bda0e17 | 670 | |
d80207c3 | 671 | /* fill in some default values if they are zero */ |
2bda0e17 | 672 | if (lpbi->biClrUsed == 0) |
a58a12e9 | 673 | lpbi->biClrUsed = nNumColors; |
2bda0e17 | 674 | |
d80207c3 KB |
675 | if (lpbi->biSizeImage == 0) |
676 | { | |
a58a12e9 | 677 | lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) |
d80207c3 KB |
678 | * lpbi->biHeight; |
679 | } | |
2bda0e17 | 680 | |
d80207c3 | 681 | /* get a proper-sized buffer for header, color table and bits */ |
2bda0e17 | 682 | GlobalUnlock(hDIB); |
d80207c3 KB |
683 | hDIB = GlobalReAlloc(hDIB, lpbi->biSize + |
684 | nNumColors * sizeof(RGBQUAD) + | |
685 | lpbi->biSizeImage, 0); | |
686 | if (!hDIB) /* can't resize buffer for loading */ | |
a58a12e9 | 687 | goto ErrExit2; |
2bda0e17 KB |
688 | |
689 | #ifdef __WINDOWS_386__ | |
690 | lpbi = (LPBITMAPINFOHEADER)MK_FP32(GlobalLock(hDIB)); | |
691 | #else | |
692 | lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); | |
693 | #endif | |
694 | ||
d80207c3 | 695 | /* read the color table */ |
2bda0e17 | 696 | if (!bCoreHead) |
d80207c3 KB |
697 | _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD)); |
698 | else | |
699 | { | |
a58a12e9 VZ |
700 | signed int i; |
701 | RGBQUAD FAR *pQuad; | |
702 | RGBTRIPLE FAR *pTriple; | |
d80207c3 KB |
703 | |
704 | _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBTRIPLE)); | |
705 | ||
a58a12e9 VZ |
706 | pQuad = (RGBQUAD FAR *)((LPSTR)lpbi + lpbi->biSize); |
707 | pTriple = (RGBTRIPLE FAR *) pQuad; | |
d80207c3 KB |
708 | for (i = nNumColors - 1; i >= 0; i--) |
709 | { | |
a58a12e9 VZ |
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 | } | |
d80207c3 | 715 | } |
2bda0e17 | 716 | |
d80207c3 | 717 | /* offset to the bits from start of DIB header */ |
33ac7e6f | 718 | offBits = (WORD)(lpbi->biSize + nNumColors * sizeof(RGBQUAD)); |
2bda0e17 KB |
719 | |
720 | if (bf.bfOffBits != 0L) | |
d80207c3 KB |
721 | { |
722 | _llseek(fh,bf.bfOffBits,SEEK_SET); | |
723 | } | |
2bda0e17 | 724 | |
d80207c3 | 725 | if (lpbi->biSizeImage == lread(fh, (LPSTR)lpbi + offBits, lpbi->biSizeImage)) |
2bda0e17 | 726 | { |
a58a12e9 | 727 | GlobalUnlock(hDIB); |
d80207c3 | 728 | |
a58a12e9 | 729 | hDC = GetDC(NULL); |
d80207c3 KB |
730 | if (!MakeBitmapAndPalette(hDC, hDIB, palette, |
731 | bitmap)) | |
a58a12e9 VZ |
732 | { |
733 | ReleaseDC(NULL,hDC); | |
734 | goto ErrExit2; | |
735 | } | |
736 | else | |
737 | { | |
738 | ReleaseDC(NULL,hDC); | |
2bda0e17 | 739 | GlobalFree(hDIB); |
a58a12e9 VZ |
740 | result = TRUE; |
741 | } | |
2bda0e17 KB |
742 | } |
743 | else | |
744 | { | |
745 | ErrExit: | |
a58a12e9 | 746 | GlobalUnlock(hDIB); |
2bda0e17 | 747 | ErrExit2: |
a58a12e9 | 748 | GlobalFree(hDIB); |
2bda0e17 | 749 | } |
d80207c3 KB |
750 | |
751 | _lclose(fh); | |
2bda0e17 KB |
752 | return(result); |
753 | } | |
754 | ||
d80207c3 KB |
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) | |
2bda0e17 KB |
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 | ||
ef3ab009 | 785 | hPalette = wxMakeDIBPalette(lpInfo); |
fd3f686c | 786 | if ( hPalette ) |
2bda0e17 | 787 | { |
a58a12e9 VZ |
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 | } | |
2bda0e17 | 808 | } |
8d1e5dbf GT |
809 | |
810 | GlobalUnlock (hDIB); // glt | |
d80207c3 | 811 | |
2bda0e17 KB |
812 | return(result); |
813 | } | |
814 | ||
d80207c3 KB |
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) | |
2bda0e17 | 828 | { |
48c12cb1 | 829 | LPLOGPALETTE npPal; |
2bda0e17 | 830 | RGBQUAD far *lpRGB; |
40c7a5fc | 831 | HPALETTE hLogPal; |
2bda0e17 KB |
832 | WORD i; |
833 | ||
d80207c3 KB |
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 | */ | |
2bda0e17 KB |
837 | if (lpInfo->biClrUsed) |
838 | { | |
839 | /* | |
a58a12e9 VZ |
840 | npPal = (NPLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) + |
841 | (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY)); | |
2bda0e17 | 842 | */ |
a58a12e9 VZ |
843 | npPal = (LPLOGPALETTE)malloc(sizeof(LOGPALETTE) + |
844 | (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY)); | |
2bda0e17 | 845 | if (!npPal) |
f7f50f49 | 846 | return NULL; |
2bda0e17 | 847 | |
a58a12e9 VZ |
848 | npPal->palVersion = 0x300; |
849 | npPal->palNumEntries = (WORD)lpInfo->biClrUsed; | |
2bda0e17 | 850 | |
d80207c3 | 851 | /* get pointer to the color table */ |
a58a12e9 | 852 | lpRGB = (RGBQUAD FAR *)((LPSTR)lpInfo + lpInfo->biSize); |
2bda0e17 | 853 | |
d80207c3 | 854 | /* copy colors from the color table to the LogPalette structure */ |
3897b707 | 855 | for (i = 0; (DWORD)i < lpInfo->biClrUsed; i++, lpRGB++) |
a58a12e9 VZ |
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 | } | |
2bda0e17 | 862 | |
a58a12e9 VZ |
863 | hLogPal = CreatePalette((LPLOGPALETTE)npPal); |
864 | // LocalFree((HANDLE)npPal); | |
2bda0e17 | 865 | free(npPal); |
d80207c3 | 866 | |
a58a12e9 | 867 | return(hLogPal); |
2bda0e17 KB |
868 | } |
869 | ||
d80207c3 KB |
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 | */ | |
2bda0e17 | 874 | else |
a58a12e9 | 875 | return((HPALETTE) GetStockObject(DEFAULT_PALETTE)); |
2bda0e17 KB |
876 | } |
877 | ||
d80207c3 | 878 | bool wxLoadIntoBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette **pal) |
2bda0e17 | 879 | { |
7527fdd8 GT |
880 | HBITMAP hBitmap = NULL; |
881 | HPALETTE hPalette = NULL; | |
2bda0e17 | 882 | |
d80207c3 | 883 | bool success = (wxReadDIB(filename, &hBitmap, &hPalette) != 0); |
2bda0e17 | 884 | |
d80207c3 KB |
885 | if (!success) |
886 | { | |
7527fdd8 GT |
887 | if (hPalette) |
888 | DeleteObject(hPalette); | |
d80207c3 KB |
889 | return FALSE; |
890 | } | |
891 | ||
892 | if (hPalette) | |
893 | { | |
d275c7eb | 894 | #if wxUSE_PALETTE |
d80207c3 | 895 | if (pal) |
2bda0e17 | 896 | { |
d80207c3 KB |
897 | *pal = new wxPalette; |
898 | (*pal)->SetHPALETTE((WXHPALETTE) hPalette); | |
2bda0e17 | 899 | } |
d80207c3 | 900 | else |
d275c7eb | 901 | #endif // wxUSE_PALETTE |
d80207c3 KB |
902 | DeleteObject(hPalette); |
903 | } | |
904 | else if (pal) | |
905 | *pal = NULL; | |
2bda0e17 | 906 | |
d80207c3 KB |
907 | if (hBitmap) |
908 | { | |
909 | BITMAP bm; | |
910 | GetObject(hBitmap, sizeof(bm), (LPSTR)&bm); | |
2bda0e17 | 911 | |
d80207c3 KB |
912 | bitmap->SetHBITMAP((WXHBITMAP) hBitmap); |
913 | bitmap->SetWidth(bm.bmWidth); | |
914 | bitmap->SetHeight(bm.bmHeight); | |
915 | bitmap->SetDepth(bm.bmPlanes * bm.bmBitsPixel); | |
0d0512bd | 916 | #if WXWIN_COMPATIBILITY_2 |
d80207c3 | 917 | bitmap->SetOk(TRUE); |
0d0512bd | 918 | #endif // WXWIN_COMPATIBILITY_2 |
d80207c3 KB |
919 | return TRUE; |
920 | } | |
921 | else return FALSE; | |
2bda0e17 KB |
922 | } |
923 | ||
d80207c3 | 924 | wxBitmap *wxLoadBitmap(wxChar *filename, wxPalette **pal) |
2bda0e17 | 925 | { |
d80207c3 KB |
926 | wxBitmap *bitmap = new wxBitmap; |
927 | if (wxLoadIntoBitmap(filename, bitmap, pal)) | |
928 | return bitmap; | |
929 | else | |
930 | { | |
931 | delete bitmap; | |
932 | return NULL; | |
933 | } | |
2bda0e17 KB |
934 | } |
935 | ||
936 | //--------------------------------------------------------------------- | |
937 | // | |
d80207c3 KB |
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. | |
2bda0e17 | 943 | // |
d80207c3 KB |
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. | |
2bda0e17 | 948 | // |
d80207c3 KB |
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 | |
2bda0e17 | 955 | // to be filled in. |
d80207c3 | 956 | // dwWidth == Width of DIB (not in Win 3.0 & 3.1, high |
2bda0e17 | 957 | // word MUST be 0). |
d80207c3 | 958 | // dwHeight == Height of DIB (not in Win 3.0 & 3.1, high |
2bda0e17 | 959 | // word MUST be 0). |
d80207c3 | 960 | // nBPP == Bits per Pixel for the DIB. |
2bda0e17 KB |
961 | // |
962 | // History: Date Reason | |
963 | // 11/07/91 Created | |
40c7a5fc | 964 | // |
2bda0e17 | 965 | //--------------------------------------------------------------------- |
d80207c3 KB |
966 | |
967 | static void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr, | |
968 | DWORD dwWidth, | |
969 | DWORD dwHeight, | |
970 | int nBPP) | |
2bda0e17 KB |
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 | ||
d80207c3 KB |
997 | |
998 | ||
999 | ||
ef3ab009 | 1000 | LPSTR wxFindDIBBits (LPSTR lpbi) |
2bda0e17 | 1001 | { |
448af9a4 | 1002 | return (lpbi + *(LPDWORD)lpbi + wxPaletteSize (lpbi)); |
2bda0e17 KB |
1003 | } |
1004 | ||
1005 | //--------------------------------------------------------------------- | |
d80207c3 | 1006 | // |
2bda0e17 KB |
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 | |
40c7a5fc | 1022 | // |
2bda0e17 | 1023 | //--------------------------------------------------------------------- |
d80207c3 KB |
1024 | |
1025 | HANDLE wxBitmapToDIB (HBITMAP hBitmap, HPALETTE hPal) | |
2bda0e17 | 1026 | { |
d80207c3 KB |
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. | |
2bda0e17 KB |
1038 | |
1039 | if (!hBitmap) | |
1040 | return NULL; | |
1041 | ||
1042 | if (!GetObject (hBitmap, sizeof (Bitmap), (LPSTR) &Bitmap)) | |
1043 | return NULL; | |
1044 | ||
40c7a5fc RD |
1045 | InitBitmapInfoHeader (&bmInfoHdr, |
1046 | Bitmap.bmWidth, | |
1047 | Bitmap.bmHeight, | |
2bda0e17 KB |
1048 | Bitmap.bmPlanes * Bitmap.bmBitsPixel); |
1049 | ||
1050 | ||
d80207c3 KB |
1051 | // Now allocate memory for the DIB. Then, set the BITMAPINFOHEADER |
1052 | // into this memory, and find out where the bitmap bits go. | |
2bda0e17 | 1053 | |
d80207c3 KB |
1054 | hDIB = GlobalAlloc (GHND, sizeof (BITMAPINFOHEADER) + |
1055 | wxPaletteSize ((LPSTR) &bmInfoHdr) + bmInfoHdr.biSizeImage); | |
2bda0e17 | 1056 | |
d80207c3 KB |
1057 | if (!hDIB) |
1058 | return NULL; | |
2bda0e17 KB |
1059 | |
1060 | #ifdef __WINDOWS_386__ | |
d80207c3 | 1061 | lpbmInfoHdr = (LPBITMAPINFOHEADER) MK_FP32(GlobalLock (hDIB)); |
2bda0e17 | 1062 | #else |
d80207c3 | 1063 | lpbmInfoHdr = (LPBITMAPINFOHEADER) GlobalLock (hDIB); |
2bda0e17 KB |
1064 | #endif |
1065 | ||
d80207c3 KB |
1066 | *lpbmInfoHdr = bmInfoHdr; |
1067 | lpBits = wxFindDIBBits ((LPSTR) lpbmInfoHdr); | |
2bda0e17 | 1068 | |
2bda0e17 | 1069 | |
d80207c3 KB |
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); | |
2bda0e17 | 1074 | |
d80207c3 KB |
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, | |
40c7a5fc RD |
1088 | hBitmap, |
1089 | 0, | |
1090 | Bitmap.bmHeight, | |
1091 | lpBits, | |
1092 | (LPBITMAPINFO) lpbmInfoHdr, | |
2bda0e17 | 1093 | DIB_RGB_COLORS)) |
d80207c3 KB |
1094 | { |
1095 | GlobalUnlock (hDIB); | |
1096 | GlobalFree (hDIB); | |
1097 | hDIB = NULL; | |
1098 | } | |
1099 | else | |
1100 | GlobalUnlock (hDIB); | |
1101 | ||
1102 | ||
1103 | // Finally, clean up and return. | |
2bda0e17 KB |
1104 | |
1105 | if (hOldPal) | |
d80207c3 | 1106 | SelectPalette (hMemDC, hOldPal, FALSE); |
2bda0e17 KB |
1107 | |
1108 | ReleaseDC (NULL, hMemDC); | |
d80207c3 | 1109 | |
2bda0e17 KB |
1110 | return hDIB; |
1111 | } | |
1112 | ||
d80207c3 | 1113 | bool wxSaveBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette *colourmap) |
2bda0e17 | 1114 | { |
d80207c3 | 1115 | HPALETTE hPalette = 0; |
d275c7eb | 1116 | #if wxUSE_PALETTE |
d80207c3 KB |
1117 | if (colourmap) |
1118 | hPalette = (HPALETTE) colourmap->GetHPALETTE(); | |
d275c7eb | 1119 | #endif // wxUSE_PALETTE |
d80207c3 KB |
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; | |
2bda0e17 KB |
1129 | } |
1130 |