Implemented simplistic ConvertToImage()
[wxWidgets.git] / src / cocoa / bitmap.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/bitmap.cpp
3 // Purpose:     wxBitmap
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2003/07/19
7 // RCS-ID:      $Id$
8 // Copyright:   (c) 2003 David Elliott
9 // Licence:     wxWidgets licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13 #ifndef WX_PRECOMP
14     #include "wx/log.h"
15     #include "wx/utils.h"
16     #include "wx/palette.h"
17     #include "wx/icon.h"
18     #include "wx/colour.h"
19 #endif //WX_PRECOMP
20 #include "wx/bitmap.h"
21 #include "wx/image.h"
22 #include "wx/xpmdecod.h"
23 #include "wx/rawbmp.h"
24
25 #include "wx/cocoa/autorelease.h"
26 #include "wx/cocoa/string.h"
27
28 #import <AppKit/NSBitmapImageRep.h>
29 #import <AppKit/NSGraphics.h>
30 #import <AppKit/NSImage.h>
31 #import <AppKit/NSColor.h>
32
33 // ========================================================================
34 // wxBitmapRefData
35 // ========================================================================
36 class wxBitmapRefData: public wxGDIRefData
37 {
38     friend class wxBitmap;
39 public:
40     wxBitmapRefData();
41     wxBitmapRefData( const wxBitmapRefData& data );
42     virtual ~wxBitmapRefData();
43
44 protected:
45     int                 m_width;
46     int                 m_height;
47     int                 m_depth;
48     bool                m_ok;
49     int                 m_numColors;
50     wxPalette           m_bitmapPalette;
51     int                 m_quality;
52     WX_NSBitmapImageRep m_cocoaNSBitmapImageRep;
53     wxMask             *m_bitmapMask; // Optional mask
54 };
55
56 #define M_BITMAPDATA ((wxBitmapRefData *)m_refData)
57
58 wxBitmapRefData::wxBitmapRefData()
59 {
60     m_ok = FALSE;
61     m_width = 0;
62     m_height = 0;
63     m_depth = 0;
64     m_quality = 0;
65     m_numColors = 0;
66     m_cocoaNSBitmapImageRep = nil;
67     m_bitmapMask = NULL;
68 }
69
70 wxBitmapRefData::wxBitmapRefData( const wxBitmapRefData& data)
71 {
72     m_width = data.m_width;
73     m_height = data.m_height;
74     m_depth = data.m_depth;
75     m_ok = data.m_ok;
76     m_numColors = data.m_numColors;
77     m_bitmapPalette = data.m_bitmapPalette;
78     m_quality = data.m_quality;
79     m_cocoaNSBitmapImageRep = [data.m_cocoaNSBitmapImageRep copyWithZone:nil];
80     m_bitmapMask = data.m_bitmapMask?new wxMask(*data.m_bitmapMask):NULL;
81 }
82
83 wxBitmapRefData::~wxBitmapRefData()
84 {
85     [m_cocoaNSBitmapImageRep release];
86     m_cocoaNSBitmapImageRep = NULL;
87
88     delete m_bitmapMask;
89     m_bitmapMask = NULL;
90 }
91
92 // ========================================================================
93 // wxBitmap
94 // ========================================================================
95 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
96
97 wxBitmap::wxBitmap()
98 {
99     m_refData = NULL;
100 }
101
102 wxBitmap::~wxBitmap()
103 {
104 }
105
106 wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits)
107 {
108     m_refData = new wxBitmapRefData;
109
110     M_BITMAPDATA->m_width = the_width ;
111     M_BITMAPDATA->m_height = the_height ;
112     M_BITMAPDATA->m_depth = no_bits ;
113     M_BITMAPDATA->m_numColors = 0;
114
115     /* TODO: create the bitmap from data */
116 }
117
118 wxBitmap::wxBitmap(int w, int h, int d)
119 {
120     (void)Create(w, h, d);
121 }
122
123 wxBitmap::wxBitmap(void *data, wxBitmapType type, int width, int height, int depth)
124 {
125     (void) Create(data, type, width, height, depth);
126 }
127
128 wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
129 {
130     LoadFile(filename, type);
131 }
132
133 wxObjectRefData *wxBitmap::CreateRefData() const
134 {
135     return new wxBitmapRefData;
136 }
137
138 wxObjectRefData *wxBitmap::CloneRefData(const wxObjectRefData *data) const
139 {
140     return new wxBitmapRefData(*(wxBitmapRefData*)data);
141 }
142
143 WX_NSBitmapImageRep wxBitmap::GetNSBitmapImageRep()
144 {
145     if(!M_BITMAPDATA)
146         return NULL;
147     return M_BITMAPDATA->m_cocoaNSBitmapImageRep;
148 }
149
150 WX_NSImage wxBitmap::GetNSImage(bool useMask) const
151 {
152     if(!Ok())
153         return nil;
154     NSImage *nsimage = [[[NSImage alloc]
155             initWithSize:NSMakeSize(GetWidth(), GetHeight())] autorelease];
156     if(!nsimage)
157         return nil;
158     [nsimage addRepresentation: M_BITMAPDATA->m_cocoaNSBitmapImageRep];
159     if(useMask && GetMask())
160     {
161         // Show before/after to prove that the bitmap itself is not changed
162         // even though we just composited onto the NSImage
163         wxLogTrace(wxTRACE_COCOA,wxT("Before: bpp=%d"),[M_BITMAPDATA->m_cocoaNSBitmapImageRep bitsPerPixel]);
164         NSImage *maskImage = [[NSImage alloc]
165                 initWithSize:NSMakeSize(GetWidth(), GetHeight())];
166         [maskImage addRepresentation: GetMask()->GetNSBitmapImageRep()];
167         [nsimage lockFocus];
168         [maskImage compositeToPoint:NSZeroPoint operation:NSCompositeDestinationIn];
169         [nsimage unlockFocus];
170         [maskImage release];
171         wxLogTrace(wxTRACE_COCOA,wxT("After: bpp=%d"),[M_BITMAPDATA->m_cocoaNSBitmapImageRep bitsPerPixel]);
172     }
173     return nsimage;
174 }
175
176 void wxBitmap::SetNSBitmapImageRep(WX_NSBitmapImageRep bitmapImageRep)
177 {
178     if(!M_BITMAPDATA)
179         return;
180     // NOTE: No checking is done to make sure width/height agree
181     [bitmapImageRep retain];
182     [M_BITMAPDATA->m_cocoaNSBitmapImageRep release];
183     M_BITMAPDATA->m_cocoaNSBitmapImageRep = bitmapImageRep;
184 }
185
186 void wxBitmap::SetWidth(int w)
187 {
188     if (!M_BITMAPDATA)
189         m_refData = new wxBitmapRefData;
190
191     M_BITMAPDATA->m_width = w;
192 }
193
194 void wxBitmap::SetHeight(int h)
195 {
196     if (!M_BITMAPDATA)
197         m_refData = new wxBitmapRefData;
198
199     M_BITMAPDATA->m_height = h;
200 }
201
202 void wxBitmap::SetDepth(int d)
203 {
204     if (!M_BITMAPDATA)
205         m_refData = new wxBitmapRefData;
206
207     M_BITMAPDATA->m_depth = d;
208 }
209
210 void wxBitmap::SetQuality(int q)
211 {
212     if (!M_BITMAPDATA)
213         m_refData = new wxBitmapRefData;
214
215     M_BITMAPDATA->m_quality = q;
216 }
217
218 void wxBitmap::SetOk(bool isOk)
219 {
220     if (!M_BITMAPDATA)
221         m_refData = new wxBitmapRefData;
222
223     M_BITMAPDATA->m_ok = isOk;
224 }
225
226 void wxBitmap::SetPalette(const wxPalette& palette)
227 {
228     if (!M_BITMAPDATA)
229         m_refData = new wxBitmapRefData;
230
231     M_BITMAPDATA->m_bitmapPalette = palette ;
232 }
233
234 void wxBitmap::SetMask(wxMask *mask)
235 {
236     if (!M_BITMAPDATA)
237         m_refData = new wxBitmapRefData;
238
239     M_BITMAPDATA->m_bitmapMask = mask ;
240 }
241
242 bool wxBitmap::Ok() const
243 {
244     return m_refData && M_BITMAPDATA->m_ok;
245 }
246
247 wxPalette* wxBitmap::GetPalette() const
248 {
249     if(!m_refData)
250         return NULL;
251     return &M_BITMAPDATA->m_bitmapPalette;
252 }
253
254 wxMask* wxBitmap::GetMask() const
255 {
256     if(!m_refData)
257         return NULL;
258     return M_BITMAPDATA->m_bitmapMask;
259 }
260
261 int wxBitmap::GetDepth() const
262 {
263     if(!m_refData)
264         return 0;
265     return M_BITMAPDATA->m_depth;
266 }
267
268 int wxBitmap::GetWidth() const
269 {
270     if(!m_refData)
271         return 0;
272     return M_BITMAPDATA->m_width;
273 }
274
275 int wxBitmap::GetHeight() const
276 {
277     if(!m_refData)
278         return 0;
279     return M_BITMAPDATA->m_height;
280 }
281
282 bool wxBitmap::Create(int w, int h, int d)
283 {
284     UnRef();
285
286     m_refData = new wxBitmapRefData;
287
288     M_BITMAPDATA->m_width = w;
289     M_BITMAPDATA->m_height = h;
290     M_BITMAPDATA->m_depth = d;
291
292     /* TODO: create new bitmap */
293     M_BITMAPDATA->m_cocoaNSBitmapImageRep = [[NSBitmapImageRep alloc]
294             initWithBitmapDataPlanes: NULL
295             pixelsWide: w
296             pixelsHigh: h
297             bitsPerSample: 8
298             samplesPerPixel: 3
299             hasAlpha: NO
300             isPlanar: NO
301             colorSpaceName: NSCalibratedRGBColorSpace
302             bytesPerRow: 0
303             bitsPerPixel: 0];
304
305     wxLogTrace(wxTRACE_COCOA,wxT("M_BITMAPDATA=%p NSBitmapImageRep bitmapData=%p"), M_BITMAPDATA, [M_BITMAPDATA->m_cocoaNSBitmapImageRep bitmapData]);
306     M_BITMAPDATA->m_ok = true;
307     M_BITMAPDATA->m_numColors = 0;
308     M_BITMAPDATA->m_quality = 0;
309     M_BITMAPDATA->m_bitmapMask = NULL;
310
311     return M_BITMAPDATA->m_ok;
312 }
313
314 bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type)
315 {
316     wxAutoNSAutoreleasePool pool;
317     UnRef();
318
319     m_refData = new wxBitmapRefData;
320
321     NSBitmapImageRep *imageRep = [NSBitmapImageRep
322         imageRepWithContentsOfFile:wxNSStringWithWxString(filename)];
323
324     if(imageRep)
325     {
326         M_BITMAPDATA->m_width = [imageRep pixelsWide];
327         M_BITMAPDATA->m_height = [imageRep pixelsHigh];
328         M_BITMAPDATA->m_depth = 24; // FIXME
329         M_BITMAPDATA->m_ok = true;
330         M_BITMAPDATA->m_numColors = 0;
331         M_BITMAPDATA->m_quality = 0;
332         M_BITMAPDATA->m_cocoaNSBitmapImageRep = [imageRep retain];
333         M_BITMAPDATA->m_bitmapMask = NULL;
334         return true;
335     }
336     wxImage image;
337     if(!image.LoadFile(filename,type))
338         return false;
339     if(!image.Ok())
340         return false;
341     *this = wxBitmap(image);
342     return true;
343 }
344
345 bool wxBitmap::Create(void *data, wxBitmapType type, int width, int height, int depth)
346 {
347     UnRef();
348
349     m_refData = new wxBitmapRefData;
350
351     return false;
352 }
353
354 bool wxBitmap::SaveFile(const wxString& filename, wxBitmapType type, const wxPalette *palette) const
355 {
356     return false;
357 }
358
359 bool wxBitmap::CopyFromIcon(const wxIcon& icon)
360 {
361     UnRef();
362     if(!icon.GetNSImage());
363     [icon.GetNSImage() lockFocus];
364     NSRect imageRect;
365     imageRect.origin.x = imageRect.origin.y = 0.0;
366     imageRect.size = [icon.GetNSImage() size];
367     NSBitmapImageRep *newBitmapRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:imageRect];
368     [icon.GetNSImage() unlockFocus];
369     if(!newBitmapRep)
370         return false;
371     m_refData = new wxBitmapRefData;
372     M_BITMAPDATA->m_cocoaNSBitmapImageRep = newBitmapRep;
373     M_BITMAPDATA->m_width = [newBitmapRep pixelsWide];
374     M_BITMAPDATA->m_height = [newBitmapRep pixelsHigh];
375     M_BITMAPDATA->m_depth = [newBitmapRep bitsPerSample]*[newBitmapRep samplesPerPixel];
376     M_BITMAPDATA->m_ok = true;
377     M_BITMAPDATA->m_numColors = 0;
378     M_BITMAPDATA->m_quality = 0;
379     M_BITMAPDATA->m_bitmapMask = NULL;
380     return true;
381 }
382
383 wxBitmap wxBitmap::GetSubBitmap(wxRect const&) const
384 {
385     return wxNullBitmap;
386 }
387
388 wxImage wxBitmap::ConvertToImage() const
389 {
390     wxAutoNSAutoreleasePool pool;
391     if(!Ok())
392         return /*wxImage(5,5)*/wxNullImage;
393     NSImage *nsimage = GetNSImage(false /* don't use mask */);
394     wxImage newImage(M_BITMAPDATA->m_width,M_BITMAPDATA->m_height);
395     [nsimage lockFocus];
396     for(int i=0; i < M_BITMAPDATA->m_width; i++)
397     {
398         // Don't let the pool get too big as you'll notice we're creating
399         // two autoreleased NSColor objects with every iteration.
400         wxAutoNSAutoreleasePool loopPool;
401         for(int j=0; j < M_BITMAPDATA->m_height; j++)
402         {
403             NSColor *pixelColor = NSReadPixel(NSMakePoint(i,M_BITMAPDATA->m_height - j - 1));
404             NSColor *color = [pixelColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
405             newImage.SetRGB(i,j,int([color redComponent]*255.0), int([color greenComponent]*255.0), int([color blueComponent]*255.0));
406         }
407     }
408     [nsimage unlockFocus];
409     return newImage;
410 }
411
412 bool wxBitmap::CreateFromXpm(const char **xpm)
413 {
414 #if wxUSE_IMAGE && wxUSE_XPM
415     UnRef();
416
417     wxCHECK_MSG( xpm, false, wxT("invalid XPM data") )
418
419     wxXPMDecoder decoder;
420     wxImage img = decoder.ReadData(xpm);
421     wxCHECK_MSG( img.Ok(), false, wxT("invalid XPM data") )
422
423     *this = wxBitmap(img);
424     return true;
425 #else
426     return false;
427 #endif
428 }
429
430 bool wxBitmap::CreateFromImage(const wxImage& image, int depth)
431 {
432     UnRef();
433
434     wxCHECK_MSG(image.Ok(), false, wxT("invalid image"));
435     wxCHECK_MSG(depth == -1 || depth == 1, false, wxT("invalid bitmap depth"));
436
437     m_refData = new wxBitmapRefData();
438
439     M_BITMAPDATA->m_width = image.GetWidth();
440     M_BITMAPDATA->m_height = image.GetHeight();
441     NSBitmapImageRep *bitmapImage = [[NSBitmapImageRep alloc]
442             initWithBitmapDataPlanes: NULL
443             pixelsWide: image.GetWidth()
444             pixelsHigh: image.GetHeight()
445             bitsPerSample: 8
446             samplesPerPixel: 3
447             hasAlpha: NO
448             isPlanar: NO
449             colorSpaceName: NSCalibratedRGBColorSpace
450             bytesPerRow: 0
451             bitsPerPixel: 0];
452
453     const int numBytes = image.GetWidth()*image.GetHeight()*3;
454     memcpy([bitmapImage bitmapData], image.GetData(), numBytes);
455     // TODO: Alpha and convert to desired depth
456     M_BITMAPDATA->m_depth = 24;
457     M_BITMAPDATA->m_ok = true;
458     M_BITMAPDATA->m_numColors = 0;
459     M_BITMAPDATA->m_quality = 0;
460     M_BITMAPDATA->m_cocoaNSBitmapImageRep = bitmapImage;
461     M_BITMAPDATA->m_bitmapMask = new wxMask(*this,wxColour(image.GetMaskRed(),image.GetMaskGreen(),image.GetMaskBlue()));
462     return true;
463 }
464
465 void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp)
466 {
467     if(!Ok())
468         return NULL;
469
470     NSBitmapImageRep *bitmapRep = M_BITMAPDATA->m_cocoaNSBitmapImageRep;
471     if(!bitmapRep)
472         return NULL;
473
474     if([bitmapRep bitsPerPixel]!=bpp)
475     {
476         wxFAIL_MSG( _T("incorrect bitmap type in wxBitmap::GetRawData()") );
477         return NULL;
478     }
479     data.m_width = [bitmapRep pixelsWide];
480     data.m_height = [bitmapRep pixelsHigh];
481     data.m_stride = [bitmapRep bytesPerRow];
482     return [bitmapRep bitmapData];
483
484     // NOTE: It is up to the user to make sure they used the proper
485     // pixel format class that details what is actually inside the pixels
486     // We can only check to make sure that the total number of bits per
487     // pixel are being iterated over properly
488     // NSBitmapImageRep can contain grayscale or CMYK data and
489     // wxPixelDataBase doesn't really define the color format
490 }
491
492 void wxBitmap::UngetRawData(wxPixelDataBase& data)
493 {   // TODO
494 }
495
496 void wxBitmap::UseAlpha()
497 {   // TODO
498 }
499
500 // ========================================================================
501 // wxMask
502 // ========================================================================
503
504 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
505
506 wxMask::wxMask()
507 {
508     m_cocoaNSBitmapImageRep = nil;
509 }
510
511 // Construct a mask from a bitmap and a colour indicating
512 // the transparent area
513 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
514 {
515     m_cocoaNSBitmapImageRep = nil;
516     Create(bitmap, colour);
517 }
518
519 // Construct a mask from a bitmap and a palette index indicating
520 // the transparent area
521 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
522 {
523     m_cocoaNSBitmapImageRep = nil;
524
525     Create(bitmap, paletteIndex);
526 }
527
528 // Construct a mask from a mono bitmap (copies the bitmap).
529 wxMask::wxMask(const wxBitmap& bitmap)
530 {
531     m_cocoaNSBitmapImageRep = nil;
532
533     Create(bitmap);
534 }
535
536 wxMask::~wxMask()
537 {
538     [m_cocoaNSBitmapImageRep release];
539 }
540
541 // Create a mask from a mono bitmap (copies the bitmap).
542 bool wxMask::Create(const wxBitmap& bitmap)
543 {
544 // TODO
545     return FALSE;
546 }
547
548 // Create a mask from a bitmap and a palette index indicating
549 // the transparent area
550 bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
551 {
552 // TODO
553     return FALSE;
554 }
555
556 template <typename PixelData>
557 static bool wxMask_CreateFromBitmapData(PixelData srcData, const wxColour& colour, unsigned char *dstData)
558 {
559     wxCHECK_MSG(dstData,false,wxT("Couldn't access mask data"));
560     typename PixelData::Iterator p(srcData);
561     const int nRows = srcData.GetHeight();
562     const int nCols = srcData.GetWidth();
563     // Total number of bytes per destination column
564     const int dstRowLength = (nCols+7)/8;
565     // Number of source columns that fit into a byte in the destination
566     const int width_aligned = nCols/8*8;
567     for(int y=0; y<nRows; ++y)
568     {
569         typename PixelData::Iterator rowStart(p);
570         unsigned char *dstRow = dstData + y*dstRowLength;
571         for(int x=0; x<width_aligned; x+=8)
572         {
573             unsigned char *dstByte = dstRow + x/8;
574             *dstByte = 0;
575             // Take source RGB, compare it with the wxColour
576             for(int j=0; j<8; ++j, ++p)
577             {
578                 *dstByte +=
579                 (   p.Red()!=colour.Red()
580                 ||  p.Green()!=colour.Green()
581                 ||  p.Blue()!=colour.Blue()
582                 )   << (7-j);
583             }
584         }
585         // Handle the remaining 0-7 pixels in the row
586         unsigned char *dstByte = dstRow + width_aligned/8;
587         if(nCols%8>0)
588             *dstByte = 0;
589         for(int j=0; j<(nCols%8); ++j, ++p)
590         {
591             *dstByte +=
592             (   p.Red()!=colour.Red()
593             ||  p.Green()!=colour.Green()
594             ||  p.Blue()!=colour.Blue()
595             )   << (7-j);
596         }
597         p = rowStart;
598         p.OffsetY(srcData,1);
599     }
600     return true;
601 }
602
603 // Create a mask from a bitmap and a colour indicating
604 // the transparent area
605 bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
606 {
607     wxAutoNSAutoreleasePool pool;
608     if(!bitmap.Ok())
609         return false;
610     int bmpWidth = bitmap.GetWidth();
611     int bmpHeight = bitmap.GetHeight();
612     int dstRowLength = (bmpWidth+7)/8;
613
614     // Create a bitmap image rep with 1-bit per pixel data representing
615     // the alpha channel padded such that rows end on byte boundaries
616     // Since NSBitmapImageRep doesn't have any sort of NSNullColorSpace
617     // we must have at least one channel of non-alpha data.  In order to
618     // make our life easy, we use planar data which results in two
619     // separate arrays.  We don't need to touch the first because it
620     // should never be used.  The second is the 1-bit "alpha" data.
621     NSBitmapImageRep *maskRep = [[[NSBitmapImageRep alloc]
622         initWithBitmapDataPlanes:NULL pixelsWide:bmpWidth
623         pixelsHigh:bmpHeight bitsPerSample:1
624         samplesPerPixel:2 hasAlpha:YES isPlanar:YES
625         colorSpaceName:NSCalibratedWhiteColorSpace
626         bytesPerRow:dstRowLength bitsPerPixel:1] autorelease];
627     wxCHECK(maskRep,false);
628
629     // We need the source NSBitmapImageRep to detemine its pixel format
630     NSBitmapImageRep *srcBitmapRep = const_cast<wxBitmap&>(bitmap).GetNSBitmapImageRep();
631     wxCHECK_MSG(srcBitmapRep,false,wxT("Can't create mask for an uninitialized bitmap"));
632
633     // Get a pointer to the destination data
634     unsigned char *dstPlanes[5] = {NULL,NULL,NULL,NULL,NULL};
635     [maskRep getBitmapDataPlanes:dstPlanes];
636     unsigned char *dstData = dstPlanes[1];
637     // The wxImage format (which we use whenever we imported from wxImage)
638     if([srcBitmapRep bitsPerPixel]==24 && [srcBitmapRep bitsPerSample]==8 && [srcBitmapRep samplesPerPixel]==3 && [srcBitmapRep hasAlpha]==NO)
639     {
640         wxPixelData<wxBitmap,wxNativePixelFormat> pixelData(const_cast<wxBitmap&>(bitmap));
641         wxCHECK_MSG(wxMask_CreateFromBitmapData(pixelData, colour, dstData),
642             false, wxT("Unable to access raw data"));
643     }
644     // 32-bpp RGBx (x=throw away, no alpha)
645     else if([srcBitmapRep bitsPerPixel]==32 && [srcBitmapRep bitsPerSample]==8 && [srcBitmapRep samplesPerPixel]==3 && [srcBitmapRep hasAlpha]==NO)
646     {
647         typedef wxPixelFormat<unsigned char,32,0,1,2> PixelFormat;
648         wxPixelData<wxBitmap,PixelFormat> pixelData(const_cast<wxBitmap&>(bitmap));
649         wxCHECK_MSG(wxMask_CreateFromBitmapData(pixelData, colour, dstData),
650             false, wxT("Unable to access raw data"));
651     }
652     // 32-bpp RGBA
653     else if([srcBitmapRep bitsPerPixel]==32 && [srcBitmapRep bitsPerSample]==8 && [srcBitmapRep samplesPerPixel]==4 && [srcBitmapRep hasAlpha]==YES)
654     {
655         wxPixelData<wxBitmap,wxAlphaPixelFormat> pixelData(const_cast<wxBitmap&>(bitmap));
656         wxCHECK_MSG(wxMask_CreateFromBitmapData(pixelData, colour, dstData),
657             false, wxT("Unable to access raw data"));
658     }
659     else
660     {   wxCHECK_MSG(false,false,wxT("Unimplemented pixel format")); }
661
662     // maskRep was autoreleased in case we had to exit quickly
663     m_cocoaNSBitmapImageRep = [maskRep retain];
664     return true;
665 }
666