]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dib.cpp
compilation fix for wxUSE_VALIDATORS==0
[wxWidgets.git] / src / msw / dib.cpp
CommitLineData
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>
6c9a19aa 9// License: wxWindows licence
53eff2a2
VZ
10///////////////////////////////////////////////////////////////////////////////
11
2b254edf
VZ
12/*
13 TODO: support for palettes is very incomplete, several functions simply
14 ignore them (we should select and realize the palette, if any, before
3692b948 15 caling GetDIBits() in the DC we use with it.
2b254edf
VZ
16 */
17
53eff2a2
VZ
18// ============================================================================
19// declarations
20// ============================================================================
21
22// ----------------------------------------------------------------------------
23// headers
24// ----------------------------------------------------------------------------
25
26// For compilers that support precompilation, includes "wx.h".
27#include "wx/wxprec.h"
28
29#ifdef __BORLANDC__
30 #pragma hdrstop
31#endif
32
33#ifndef WX_PRECOMP
34 #include "wx/string.h"
35 #include "wx/log.h"
36#endif //WX_PRECOMP
37
4676948b
JS
38#if wxUSE_WXDIB
39
1cfa5d8e
JS
40#include "wx/bitmap.h"
41#include "wx/intl.h"
2b254edf 42#include "wx/file.h"
1cfa5d8e
JS
43
44#include <stdio.h>
45#include <stdlib.h>
46
47#if !defined(__MWERKS__) && !defined(__SALFORDC__)
be69f971 48 #include <memory.h>
1cfa5d8e
JS
49#endif
50
51#ifdef __GNUWIN32_OLD__
52 #include "wx/msw/gnuwin32/extra.h"
53#endif
53eff2a2 54
1cfa5d8e 55#include "wx/image.h"
53eff2a2
VZ
56#include "wx/msw/dib.h"
57
be69f971
VZ
58#ifdef __WXWINCE__
59 #include <shellapi.h> // for SHLoadDIBitmap()
60#endif
61
22be0335
VZ
62// ----------------------------------------------------------------------------
63// private functions
64// ----------------------------------------------------------------------------
65
66// calculate the number of palette entries needed for the bitmap with this
67// number of bits per pixel
be69f971 68static inline WORD GetNumberOfColours(WORD bitsPerPixel)
22be0335
VZ
69{
70 // only 1, 4 and 8bpp bitmaps use palettes (well, they could be used with
71 // 24bpp ones too but we don't support this as I think it's quite uncommon)
72 return bitsPerPixel <= 8 ? 1 << bitsPerPixel : 0;
73}
74
3692b948
VZ
75// wrapper around ::GetObject() for DIB sections
76static inline bool GetDIBSection(HBITMAP hbmp, DIBSECTION *ds)
77{
78 // note that at least under Win9x (this doesn't seem to happen under Win2K
79 // but this doesn't mean anything, of course), GetObject() may return
80 // sizeof(DIBSECTION) for a bitmap which is *not* a DIB section and the way
81 // to check for it is by looking at the bits pointer
82 return ::GetObject(hbmp, sizeof(DIBSECTION), ds) == sizeof(DIBSECTION) &&
83 ds->dsBm.bmBits;
84}
85
53eff2a2
VZ
86// ============================================================================
87// implementation
88// ============================================================================
89
90// ----------------------------------------------------------------------------
91// wxDIB creation
92// ----------------------------------------------------------------------------
93
94bool wxDIB::Create(int width, int height, int depth)
95{
be69f971
VZ
96 // we don't support formats using palettes right now so we only create
97 // either 24bpp (RGB) or 32bpp (RGBA) bitmaps
98 wxASSERT_MSG( depth, _T("invalid image depth in wxDIB::Create()") );
99 if ( depth < 24 )
100 depth = 24;
53eff2a2 101
be69f971
VZ
102 // allocate memory for bitmap structures
103 static const int sizeHeader = sizeof(BITMAPINFOHEADER);
53eff2a2 104
be69f971 105 BITMAPINFO *info = (BITMAPINFO *)malloc(sizeHeader);
a1e71b10 106 wxCHECK_MSG( info, false, _T("malloc(BITMAPINFO) failed") );
53eff2a2 107
be69f971 108 memset(info, 0, sizeHeader);
53eff2a2 109
be69f971 110 info->bmiHeader.biSize = sizeHeader;
53eff2a2 111 info->bmiHeader.biWidth = width;
bbc1265c
VZ
112
113 // we use positive height here which corresponds to a DIB with normal, i.e.
114 // bottom to top, order -- normally using negative height (which means
115 // reversed for MS and hence natural for all the normal people top to
116 // bottom line scan order) could be used to avoid the need for the image
117 // reversal in Create(image) but this doesn't work under NT, only Win9x!
118 info->bmiHeader.biHeight = height;
119
53eff2a2
VZ
120 info->bmiHeader.biPlanes = 1;
121 info->bmiHeader.biBitCount = depth;
53eff2a2
VZ
122 info->bmiHeader.biSizeImage = GetLineSize(width, depth)*height;
123
53eff2a2
VZ
124 m_handle = ::CreateDIBSection
125 (
126 0, // hdc (unused with DIB_RGB_COLORS)
127 info, // bitmap description
128 DIB_RGB_COLORS, // use RGB, not palette
129 &m_data, // [out] DIB bits
130 NULL, // don't use file mapping
131 0 // file mapping offset (not used here)
132 );
133
134 free(info);
135
136 if ( !m_handle )
137 {
138 wxLogLastError(wxT("CreateDIBSection"));
139
140 return false;
141 }
142
143 m_width = width;
144 m_height = height;
145 m_depth = depth;
146
147 return true;
148}
149
2b254edf
VZ
150bool wxDIB::Create(const wxBitmap& bmp)
151{
152 wxCHECK_MSG( bmp.Ok(), false, _T("wxDIB::Create(): invalid bitmap") );
153
82ac3b0a
VZ
154 // this bitmap could already be a DIB section in which case we don't need
155 // to convert it to DIB
156 HBITMAP hbmp = GetHbitmapOf(bmp);
2b254edf 157
82ac3b0a 158 DIBSECTION ds;
3692b948 159 if ( GetDIBSection(hbmp, &ds) )
2b254edf 160 {
82ac3b0a
VZ
161 m_handle = hbmp;
162
163 // wxBitmap will free it, not we
164 m_ownsHandle = false;
2b254edf 165
82ac3b0a
VZ
166 // copy all the bitmap parameters too as we have them now anyhow
167 m_width = ds.dsBm.bmWidth;
168 m_height = ds.dsBm.bmHeight;
169 m_depth = ds.dsBm.bmBitsPixel;
170
171 m_data = ds.dsBm.bmBits;
172 }
173 else // no, it's a DDB -- convert it to DIB
174 {
175 const int w = bmp.GetWidth();
176 const int h = bmp.GetHeight();
177 int d = bmp.GetDepth();
be69f971 178 if ( d <= 0 )
82ac3b0a
VZ
179 d = wxDisplayDepth();
180
be69f971 181 if ( !Create(w, h, d) || !CopyFromDDB(hbmp) )
82ac3b0a 182 return false;
be69f971 183 }
82ac3b0a 184
be69f971
VZ
185 return true;
186}
3692b948 187
be69f971
VZ
188// Windows CE doesn't have GetDIBits() so use an alternative implementation
189// for it
190//
191// in fact I'm not sure if GetDIBits() is really much better than using
192// BitBlt() like this -- it should be faster but I didn't do any tests, if
193// anybody has time to do them and by chance finds that GetDIBits() is not
194// much faster than BitBlt(), we could always use the Win CE version here
195#ifdef __WXWINCE__
3692b948 196
be69f971
VZ
197bool wxDIB::CopyFromDDB(HBITMAP hbmp)
198{
199 MemoryHDC hdcSrc;
200 if ( !hdcSrc )
201 return false;
82ac3b0a 202
be69f971
VZ
203 SelectInHDC selectSrc(hdcSrc, hbmp);
204 if ( !selectSrc )
205 return false;
206
207 MemoryHDC hdcDst;
208 if ( !hdcDst )
209 return false;
210
211 SelectInHDC selectDst(hdcDst, m_handle);
212 if ( !selectDst )
213 return false;
214
215
216 if ( !::BitBlt(
217 hdcDst,
218 0, 0, m_width, m_height,
219 hdcSrc,
220 0, 0,
221 SRCCOPY
222 ) )
223 {
224 wxLogLastError(_T("BitBlt(DDB -> DIB)"));
225
226 return false;
227 }
228
229 return true;
230}
231
232#else // !__WXWINCE__
233
234bool wxDIB::CopyFromDDB(HBITMAP hbmp)
235{
236 DIBSECTION ds;
237 if ( !GetDIBSection(m_handle, &ds) )
238 {
239 // we're sure that our handle is a DIB section, so this should work
240 wxFAIL_MSG( _T("GetObject(DIBSECTION) unexpectedly failed") );
241
242 return false;
243 }
244
245 if ( !::GetDIBits
246 (
247 ScreenHDC(), // the DC to use
248 hbmp, // the source DDB
249 0, // first scan line
250 m_height, // number of lines to copy
251 ds.dsBm.bmBits, // pointer to the buffer
252 (BITMAPINFO *)&ds.dsBmih, // bitmap header
253 DIB_RGB_COLORS // and not DIB_PAL_COLORS
254 ) )
255 {
256 wxLogLastError(wxT("GetDIBits()"));
257
258 return false;
2b254edf
VZ
259 }
260
261 return true;
262}
263
be69f971
VZ
264#endif // __WXWINCE__/!__WXWINCE__
265
c11bf842
VZ
266// ----------------------------------------------------------------------------
267// Loading/saving the DIBs
268// ----------------------------------------------------------------------------
269
270bool wxDIB::Load(const wxString& filename)
271{
be69f971
VZ
272#ifdef __WXWINCE__
273 m_handle = SHLoadDIBitmap(filename);
274#else // !__WXWINCE__
c11bf842
VZ
275 m_handle = (HBITMAP)::LoadImage
276 (
277 wxGetInstance(),
278 filename,
279 IMAGE_BITMAP,
280 0, 0, // don't specify the size
281 LR_CREATEDIBSECTION | LR_LOADFROMFILE
282 );
be69f971
VZ
283#endif // __WXWINCE__
284
c11bf842
VZ
285 if ( !m_handle )
286 {
be69f971 287 wxLogLastError(_T("Loading DIB from file"));
c11bf842
VZ
288
289 return false;
290 }
291
292 return true;
293}
294
2b254edf
VZ
295bool wxDIB::Save(const wxString& filename)
296{
297 wxCHECK_MSG( m_handle, false, _T("wxDIB::Save(): invalid object") );
298
299 wxFile file(filename, wxFile::write);
300 bool ok = file.IsOpened();
301 if ( ok )
302 {
303 DIBSECTION ds;
3692b948 304 if ( !GetDIBSection(m_handle, &ds) )
2b254edf
VZ
305 {
306 wxLogLastError(_T("GetObject(hDIB)"));
307 }
308 else
309 {
310 BITMAPFILEHEADER bmpHdr;
311 wxZeroMemory(bmpHdr);
312
313 const size_t sizeHdr = ds.dsBmih.biSize;
314 const size_t sizeImage = ds.dsBmih.biSizeImage;
315
316 bmpHdr.bfType = 0x4d42; // 'BM' in little endian
317 bmpHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + ds.dsBmih.biSize;
318 bmpHdr.bfSize = bmpHdr.bfOffBits + sizeImage;
319
320 // first write the file header, then the bitmap header and finally the
321 // bitmap data itself
322 ok = file.Write(&bmpHdr, sizeof(bmpHdr)) == sizeof(bmpHdr) &&
323 file.Write(&ds.dsBmih, sizeHdr) == sizeHdr &&
324 file.Write(ds.dsBm.bmBits, sizeImage) == sizeImage;
325 }
326 }
327
328 if ( !ok )
329 {
330 wxLogError(_("Failed to save the bitmap image to file \"%s\"."),
331 filename.c_str());
332 }
333
334 return ok;
335}
336
53eff2a2
VZ
337// ----------------------------------------------------------------------------
338// wxDIB accessors
339// ----------------------------------------------------------------------------
340
341void wxDIB::DoGetObject() const
342{
343 // only do something if we have a valid DIB but we don't [yet] have valid
344 // data
345 if ( m_handle && !m_data )
346 {
347 // although all the info we need is in BITMAP and so we don't really
348 // need DIBSECTION we still ask for it as modifying the bit values only
349 // works for the real DIBs and not for the bitmaps and it's better to
350 // check for this now rather than trying to find out why it doesn't
351 // work later
352 DIBSECTION ds;
3692b948 353 if ( !GetDIBSection(m_handle, &ds) )
53eff2a2
VZ
354 {
355 wxLogLastError(_T("GetObject(hDIB)"));
53eff2a2
VZ
356 return;
357 }
358
359 wxDIB *self = wxConstCast(this, wxDIB);
360
361 self->m_width = ds.dsBm.bmWidth;
362 self->m_height = ds.dsBm.bmHeight;
363 self->m_depth = ds.dsBm.bmBitsPixel;
364 self->m_data = ds.dsBm.bmBits;
365 }
366}
367
22be0335
VZ
368// ----------------------------------------------------------------------------
369// DDB <-> DIB conversions
370// ----------------------------------------------------------------------------
371
be69f971
VZ
372#ifndef __WXWINCE__
373
c11bf842
VZ
374HBITMAP wxDIB::CreateDDB(HDC hdc) const
375{
376 wxCHECK_MSG( m_handle, 0, _T("wxDIB::CreateDDB(): invalid object") );
377
378 DIBSECTION ds;
3692b948 379 if ( !GetDIBSection(m_handle, &ds) )
c11bf842
VZ
380 {
381 wxLogLastError(_T("GetObject(hDIB)"));
382
383 return 0;
384 }
385
22be0335
VZ
386 return ConvertToBitmap((BITMAPINFO *)&ds.dsBmih, hdc, ds.dsBm.bmBits);
387}
388
389/* static */
390HBITMAP wxDIB::ConvertToBitmap(const BITMAPINFO *pbmi, HDC hdc, void *bits)
391{
392 wxCHECK_MSG( pbmi, 0, _T("invalid DIB in ConvertToBitmap") );
393
394 // here we get BITMAPINFO struct followed by the actual bitmap bits and
395 // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info
396 const BITMAPINFOHEADER *pbmih = &pbmi->bmiHeader;
397
398 // get the pointer to the start of the real image data if we have a plain
399 // DIB and not a DIB section (in the latter case the pointer must be passed
400 // to us by the caller)
401 if ( !bits )
c11bf842 402 {
22be0335 403 // we must skip over the colour table to get to the image data
a8beba72
VZ
404 //
405 // colour table either has the real colour data in which case its
406 // number of entries is given by biClrUsed or is used for masks to be
407 // used for extracting colour information from true colour bitmaps in
408 // which case it always have exactly 3 DWORDs
409 int numColors;
410 switch ( pbmih->biCompression )
22be0335 411 {
a8beba72
VZ
412 case BI_BITFIELDS:
413 numColors = 3;
414 break;
415
416 case BI_RGB:
417 // biClrUsed has the number of colors but it may be not initialized at
418 // all
419 numColors = pbmih->biClrUsed;
420 if ( !numColors )
421 {
be69f971 422 numColors = GetNumberOfColours(pbmih->biBitCount);
a8beba72
VZ
423 }
424 break;
425
426 default:
427 // no idea how it should be calculated for the other cases
428 numColors = 0;
22be0335
VZ
429 }
430
431 bits = (char *)pbmih + sizeof(*pbmih) + numColors*sizeof(RGBQUAD);
c11bf842 432 }
4b1f929c 433
22be0335
VZ
434 HBITMAP hbmp = ::CreateDIBitmap
435 (
4b1f929c
CE
436 hdc ? hdc // create bitmap compatible
437 : (HDC) ScreenHDC(), // with this DC
22be0335
VZ
438 pbmih, // used to get size &c
439 CBM_INIT, // initialize bitmap bits too
440 bits, // ... using this data
441 pbmi, // this is used for palette only
442 DIB_RGB_COLORS // direct or indexed palette?
443 );
444
445 if ( !hbmp )
c11bf842 446 {
22be0335 447 wxLogLastError(wxT("CreateDIBitmap"));
c11bf842
VZ
448 }
449
22be0335
VZ
450 return hbmp;
451}
452
453/* static */
454size_t wxDIB::ConvertFromBitmap(BITMAPINFO *pbi, HBITMAP hbmp)
455{
456 wxASSERT_MSG( hbmp, wxT("invalid bmp can't be converted to DIB") );
457
458 // prepare all the info we need
459 BITMAP bm;
460 if ( !::GetObject(hbmp, sizeof(bm), &bm) )
461 {
462 wxLogLastError(wxT("GetObject(bitmap)"));
463
464 return 0;
465 }
466
22be0335
VZ
467 // we need a BITMAPINFO anyhow and if we're not given a pointer to it we
468 // use this one
469 BITMAPINFO bi2;
470
2b254edf 471 const bool wantSizeOnly = pbi == NULL;
22be0335
VZ
472 if ( wantSizeOnly )
473 pbi = &bi2;
474
475 // just for convenience
476 const int h = bm.bmHeight;
477
478 // init the header
479 BITMAPINFOHEADER& bi = pbi->bmiHeader;
480 wxZeroMemory(bi);
481 bi.biSize = sizeof(BITMAPINFOHEADER);
482 bi.biWidth = bm.bmWidth;
483 bi.biHeight = h;
484 bi.biPlanes = 1;
2b254edf 485 bi.biBitCount = bm.bmBitsPixel;
22be0335
VZ
486
487 // memory we need for BITMAPINFO only
be69f971 488 DWORD dwLen = bi.biSize + GetNumberOfColours(bm.bmBitsPixel) * sizeof(RGBQUAD);
2b254edf
VZ
489
490 // get either just the image size or the image bits
491 if ( !::GetDIBits
492 (
493 ScreenHDC(), // the DC to use
494 hbmp, // the source DDB
495 0, // first scan line
496 h, // number of lines to copy
497 wantSizeOnly ? NULL // pointer to the buffer or
498 : (char *)pbi + dwLen, // NULL if we don't have it
499 pbi, // bitmap header
500 DIB_RGB_COLORS // or DIB_PAL_COLORS
501 ) )
c11bf842 502 {
2b254edf 503 wxLogLastError(wxT("GetDIBits()"));
c11bf842
VZ
504
505 return 0;
506 }
507
2b254edf
VZ
508 // return the total size
509 return dwLen + bi.biSizeImage;
510}
511
512/* static */
513HGLOBAL wxDIB::ConvertFromBitmap(HBITMAP hbmp)
514{
515 // first calculate the size needed
516 const size_t size = ConvertFromBitmap(NULL, hbmp);
517 if ( !size )
22be0335 518 {
2b254edf
VZ
519 // conversion to DDB failed?
520 return NULL;
521 }
22be0335 522
2b254edf
VZ
523 HGLOBAL hDIB = ::GlobalAlloc(GMEM_MOVEABLE, size);
524 if ( !hDIB )
525 {
526 // this is an error which does risk to happen especially under Win9x
527 // and which the user may understand so let him know about it
528 wxLogError(_("Failed to allocated %luKb of memory for bitmap data."),
529 (unsigned long)(size / 1024));
530
531 return NULL;
22be0335
VZ
532 }
533
3692b948 534 if ( !ConvertFromBitmap((BITMAPINFO *)(void *)GlobalPtr(hDIB), hbmp) )
2b254edf
VZ
535 {
536 // this really shouldn't happen... it worked the first time, why not
537 // now?
538 wxFAIL_MSG( _T("wxDIB::ConvertFromBitmap() unexpectedly failed") );
539
540 return NULL;
541 }
542
543 return hDIB;
c11bf842
VZ
544}
545
be69f971
VZ
546#endif // __WXWINCE__
547
22be0335
VZ
548// ----------------------------------------------------------------------------
549// palette support
550// ----------------------------------------------------------------------------
551
c11bf842
VZ
552#if wxUSE_PALETTE
553
554wxPalette *wxDIB::CreatePalette() const
555{
556 wxCHECK_MSG( m_handle, NULL, _T("wxDIB::CreatePalette(): invalid object") );
557
558 DIBSECTION ds;
3692b948 559 if ( !GetDIBSection(m_handle, &ds) )
c11bf842
VZ
560 {
561 wxLogLastError(_T("GetObject(hDIB)"));
562
563 return 0;
564 }
565
566 // how many colours are we going to have in the palette?
567 DWORD biClrUsed = ds.dsBmih.biClrUsed;
568 if ( !biClrUsed )
569 {
570 // biClrUsed field might not be set
be69f971 571 biClrUsed = GetNumberOfColours(ds.dsBmih.biBitCount);
c11bf842
VZ
572 }
573
2b254edf 574 if ( !biClrUsed )
c11bf842 575 {
2b254edf 576 // bitmaps of this depth don't have palettes at all
c11bf842
VZ
577 //
578 // NB: another possibility would be to return
579 // GetStockObject(DEFAULT_PALETTE) or even CreateHalftonePalette()?
580 return NULL;
581 }
582
583 // LOGPALETTE struct has only 1 element in palPalEntry array, we're
584 // going to have biClrUsed of them so add necessary space
585 LOGPALETTE *pPalette = (LOGPALETTE *)
586 malloc(sizeof(LOGPALETTE) + (biClrUsed - 1)*sizeof(PALETTEENTRY));
587 wxCHECK_MSG( pPalette, NULL, _T("out of memory") );
588
589 // initialize the palette header
590 pPalette->palVersion = 0x300; // magic number, not in docs but works
591 pPalette->palNumEntries = biClrUsed;
592
593 // and the colour table (it starts right after the end of the header)
594 const RGBQUAD *pRGB = (RGBQUAD *)((char *)&ds.dsBmih + ds.dsBmih.biSize);
595 for ( DWORD i = 0; i < biClrUsed; i++, pRGB++ )
596 {
597 pPalette->palPalEntry[i].peRed = pRGB->rgbRed;
598 pPalette->palPalEntry[i].peGreen = pRGB->rgbGreen;
599 pPalette->palPalEntry[i].peBlue = pRGB->rgbBlue;
600 pPalette->palPalEntry[i].peFlags = 0;
601 }
602
603 HPALETTE hPalette = ::CreatePalette(pPalette);
604
605 free(pPalette);
606
607 if ( !hPalette )
608 {
609 wxLogLastError(_T("CreatePalette"));
610
611 return NULL;
612 }
613
614 wxPalette *palette = new wxPalette;
615 palette->SetHPALETTE((WXHPALETTE)hPalette);
616
617 return palette;
618}
619
620#endif // wxUSE_PALETTE
621
53eff2a2
VZ
622// ----------------------------------------------------------------------------
623// wxImage support
624// ----------------------------------------------------------------------------
625
626#if wxUSE_IMAGE
627
628bool wxDIB::Create(const wxImage& image)
629{
630 wxCHECK_MSG( image.Ok(), false, _T("invalid wxImage in wxDIB ctor") );
631
632 const int h = image.GetHeight();
633 const int w = image.GetWidth();
634
635 // if we have alpha channel, we need to create a 32bpp RGBA DIB, otherwise
636 // a 24bpp RGB is sufficient
637 const bool hasAlpha = image.HasAlpha();
638 const int bpp = hasAlpha ? 32 : 24;
639
640 if ( !Create(w, h, bpp) )
641 return false;
642
bbc1265c
VZ
643 // DIBs are stored in bottom to top order (see also the comment above in
644 // Create()) so we need to copy bits line by line and starting from the end
53eff2a2
VZ
645 const int srcBytesPerLine = w * 3;
646 const int dstBytesPerLine = GetLineSize(w, bpp);
647 const unsigned char *src = image.GetData() + ((h - 1) * srcBytesPerLine);
648 const unsigned char *alpha = hasAlpha ? image.GetAlpha() + (h - 1)*w : NULL;
649 unsigned char *dstLineStart = (unsigned char *)m_data;
650 for ( int y = 0; y < h; y++ )
651 {
652 // copy one DIB line
653 unsigned char *dst = dstLineStart;
654 for ( int x = 0; x < w; x++ )
655 {
656 // also, the order of RGB is inversed for DIBs
657 *dst++ = src[2];
658 *dst++ = src[1];
659 *dst++ = src[0];
660
661 src += 3;
662
663 if ( alpha )
664 *dst++ = *alpha++;
665 }
666
667 // pass to the previous line in the image
668 src -= 2*srcBytesPerLine;
669 if ( alpha )
670 alpha -= 2*w;
671
672 // and to the next one in the DIB
673 dstLineStart += dstBytesPerLine;
674 }
675
676 return true;
677}
678
be69f971
VZ
679wxImage wxDIB::ConvertToImage() const
680{
681 wxCHECK_MSG( IsOk(), wxNullImage,
682 wxT("can't convert invalid DIB to wxImage") );
683
684 // create the wxImage object
685 const int w = GetWidth();
686 const int h = GetHeight();
687 wxImage image(w, h, false /* don't bother clearing memory */);
688 if ( !image.Ok() )
689 {
690 wxFAIL_MSG( wxT("could not allocate data for image") );
691 return wxNullImage;
692 }
693
694 const int bpp = GetDepth();
695 if ( bpp == 32 )
696 {
697 image.SetAlpha();
698 }
699
700 // this is the same loop as in Create() just above but with copy direction
701 // reversed
702 const int dstBytesPerLine = w * 3;
703 const int srcBytesPerLine = GetLineSize(w, bpp);
704 unsigned char *dst = image.GetData() + ((h - 1) * dstBytesPerLine);
705 unsigned char *alpha = image.HasAlpha() ? image.GetAlpha() + (h - 1)*w
706 : NULL;
707 const unsigned char *srcLineStart = (unsigned char *)GetData();
708 for ( int y = 0; y < h; y++ )
709 {
710 // copy one DIB line
711 const unsigned char *src = srcLineStart;
712 for ( int x = 0; x < w; x++ )
713 {
714 dst[2] = *src++;
715 dst[1] = *src++;
716 dst[0] = *src++;
717
718 dst += 3;
719
720 if ( alpha )
721 *alpha++ = *src++;
722 }
723
724 // pass to the previous line in the image
725 dst -= 2*dstBytesPerLine;
726 if ( alpha )
727 alpha -= 2*w;
728
729 // and to the next one in the DIB
730 srcLineStart += srcBytesPerLine;
731 }
732
733 return image;
734}
735
53eff2a2
VZ
736#endif // wxUSE_IMAGE
737
be69f971
VZ
738#endif // wxUSE_WXDIB
739