]> git.saurik.com Git - wxWidgets.git/blob - include/wx/rawbmp.h
allow raw access to a part of the image only (faster when using alpha)
[wxWidgets.git] / include / wx / rawbmp.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/rawbmp.h
3 // Purpose: macros for fast, raw bitmap data access
4 // Author: Eric Kidd, Vadim Zeitlin
5 // Modified by:
6 // Created: 10.03.03
7 // RCS-ID: $Id$
8 // Copyright: (c) 2002 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_RAWBMP_H_BASE_
13 #define _WX_RAWBMP_H_BASE_
14
15 // ----------------------------------------------------------------------------
16 // Abstract Pixel API
17 //
18 // We need to access our raw bitmap data (1) portably and (2) efficiently.
19 // We do this using a two-dimensional "iteration" interface. Performance
20 // is extremely important here: these functions will be called hundreds
21 // of thousands of times in a row, and even small inefficiencies will
22 // make applications seem slow.
23 //
24 // We can't always rely on inline functions, because not all compilers actually
25 // bother to inline them unless we crank the optimization levels way up.
26 // Therefore, we also provide macros to wring maximum speed out of compiler
27 // unconditionally (e.g. even in debug builds). Of course, if the performance
28 // isn't absolutely crucial for you you shouldn't be using them but the inline
29 // functions instead.
30 // ----------------------------------------------------------------------------
31
32 /*
33 Usage example:
34
35 typedef wxPixelData<wxBitmap, wxNativePixelFormat> PixelData;
36
37 wxBitmap bmp;
38 PixelData data(bmp);
39 if ( !data )
40 {
41 ... raw access to bitmap data unavailable, do something else ...
42 return;
43 }
44
45 if ( data.GetWidth() < 20 || data.GetHeight() < 20 )
46 {
47 ... complain: the bitmap it too small ...
48 return;
49 }
50
51 PixelData::Iterator p(data);
52
53 // we draw a (10, 10)-(20, 20) rect manually using the given r, g, b
54 p.Offset(data, 10, 10);
55
56 for ( int y = 0; y < 10; ++y )
57 {
58 PixelData::Iterator rowStart = p;
59
60 for ( int x = 0; x < 10; ++x, ++p )
61 {
62 p.Red() = r;
63 p.Green() = g;
64 p.Blue() = b;
65 }
66
67 p = rowStart;
68 p.OffsetY(data, 1);
69 }
70 */
71
72 #ifdef __VISUALC__
73 // VC++ gives an absolutely harmless warning for wxPixelData<wxBitmap> ctor
74 #pragma warning(disable: 4355) // 'this' used in initializer list
75 #endif
76
77 // ----------------------------------------------------------------------------
78 // wxPixelFormat
79 // ----------------------------------------------------------------------------
80
81 /*
82 wxPixelFormat is a template class describing the bitmap data format. It
83 contains the constants describing the format of pixel data, but does not
84 describe how the entire bitmap is stored (i.e. top-to-bottom,
85 bottom-to-top, ...). It is also a "traits"-like class, i.e. it only
86 contains some constants and maybe static methods but nothing more, so it
87 can be safely used without incurring any overhead as all accesses to it are
88 done at compile-time.
89
90 Current limitations: we don't support RAGABA and ARAGAB formats supported
91 by Mac OS X. If there is sufficient interest, these classes could be
92 extended to deal with them. Neither do we support alpha channel having
93 different representation from the RGB ones (happens under QNX/Photon I
94 think), but again this could be achieved with some small extra effort.
95
96 Template parameters are:
97 - type of a single pixel component
98 - size of the single pixel in bits
99 - indices of red, green and blue pixel components inside the pixel
100 - index of the alpha component or -1 if none
101 - type which can contain the full pixel value (all channels)
102 */
103 template <typename Channel,
104 size_t Bpp, int R, int G, int B, int A = -1,
105 typename Pixel = wxUint32>
106 struct WXDLLEXPORT wxPixelFormat
107 {
108 // iterator over pixels is usually of type "ChannelType *"
109 typedef Channel ChannelType;
110
111 // the type which may hold the entire pixel value
112 typedef Pixel PixelType;
113
114 // NB: using static ints initialized inside the class declaration is not
115 // portable as it doesn't work with VC++ 6, so we must use enums
116
117 // size of one pixel in bits
118 enum { BitsPerPixel = Bpp };
119
120 // size of one pixel in ChannelType units (usually bytes)
121 enum { SizePixel = BitsPerPixel / (8 * sizeof(ChannelType)) };
122
123 // the channels indices inside the pixel
124 enum
125 {
126 RED = R,
127 GREEN = G,
128 BLUE = B,
129 ALPHA = A
130 };
131
132 // true if we have an alpha channel (together with the other channels, this
133 // doesn't cover the case of wxImage which stores alpha separately)
134 enum { HasAlpha = A != -1 };
135 };
136
137 // some "predefined" pixel formats
138 // -------------------------------
139
140 // wxImage format is common to all platforms
141 typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxImagePixelFormat;
142
143 // the (most common) native bitmap format without alpha support
144 typedef wxPixelFormat<unsigned char, 24,
145 #ifdef __WXMSW__
146 2, 1, 0
147 #else // !__WXMSW__
148 0, 1, 2
149 #endif // __WXMSW__/!__WXMSW__
150 > wxNativePixelFormat;
151
152 // the (most common) native format for bitmaps with alpha channel
153 typedef wxPixelFormat<unsigned char, 32,
154 wxNativePixelFormat::RED,
155 wxNativePixelFormat::GREEN,
156 wxNativePixelFormat::BLUE,
157 3> wxAlphaPixelFormat;
158
159 // we also define the (default/best) pixel format for the given class: this is
160 // used as default value for the pixel format in wxPixelIterator template
161 template <class T> struct wxPixelFormatFor;
162
163 // wxPixelFormatFor is only defined for wxImage, attempt to use it with other
164 // classes (wxBitmap...) will result in compile errors which is exactly what we
165 // want
166 template <>
167 struct WXDLLEXPORT wxPixelFormatFor<wxImage>
168 {
169 typedef wxImagePixelFormat Format;
170 };
171
172 // ----------------------------------------------------------------------------
173 // wxPixelData
174 // ----------------------------------------------------------------------------
175
176 /*
177 wxPixelDataBase is just a helper for wxPixelData: it contains things common
178 to both wxImage and wxBitmap specializations.
179 */
180 class WXDLLEXPORT wxPixelDataBase
181 {
182 public:
183 // origin of the rectangular region we represent
184 wxPoint GetOrigin() const { return m_ptOrigin; }
185
186 // width and height of the region we represent
187 int GetWidth() const { return m_width; }
188 int GetHeight() const { return m_height; }
189
190 // the distance between two rows
191 int GetRowStride() const { return m_stride; }
192
193 // private: -- see comment in the beginning of the file
194
195 // the origin of this image inside the bigger bitmap (usually (0, 0))
196 wxPoint m_ptOrigin;
197
198 // the size of the image we address, in pixels
199 int m_width,
200 m_height;
201
202 // this parameter is the offset of the start of the (N+1)st row from the
203 // Nth one and can be different from m_bypp*width in some cases:
204 // a) the most usual one is to force 32/64 bit alignment of rows
205 // b) another one is for bottom-to-top images where it's negative
206 // c) finally, it could conceivably be 0 for the images with all
207 // lines being identical
208 int m_stride;
209
210 protected:
211 // ctor is protected because this class is only meant to be used as the
212 // base class by wxPixelData
213 wxPixelDataBase()
214 {
215 m_width =
216 m_height =
217 m_stride = 0;
218 }
219 };
220
221 /*
222 wxPixelData represents the entire bitmap data, i.e. unlike
223 wxPixelFormat (which it uses) it also stores the global bitmap
224 characteristics such as its size, inter-row separation and so on.
225
226 Because of this it can be used to move the pixel iterators (which don't
227 have enough information about the bitmap themselves). This may seem a bit
228 unnatural but must be done in this way to keep the iterator objects as
229 small as possible for maximum efficiency as otherwise they wouldn't be put
230 into the CPU registers by the compiler any more.
231
232 Implementation note: we use the standard workaround for lack of partial
233 template specialization support in VC (both 6 and 7): instead of partly
234 specializing the class Foo<T, U> for some T we introduce FooOut<T> and
235 FooIn<U> nested in it, make Foo<T, U> equivalent to FooOut<T>::FooIn<U> and
236 fully specialize FooOut.
237
238 Also note that this class doesn't have any default definition because we
239 can't really do anything without knowing the exact image class. We do
240 provide wxPixelDataBase to make it simpler to write new wxPixelData
241 specializations.
242 */
243
244 // we need to define this skeleton template to mollify VC++
245 template <class Image>
246 struct WXDLLEXPORT wxPixelDataOut
247 {
248 template <class PixelFormat>
249 class WXDLLEXPORT wxPixelDataIn
250 {
251 public:
252 class Iterator { };
253 };
254 };
255
256 // wxPixelData specialization for wxImage: this is the simplest case as we
257 // don't have to care about different pixel formats here
258 template <>
259 struct WXDLLEXPORT wxPixelDataOut<wxImage>
260 {
261 // NB: this is a template class even though it doesn't use its template
262 // parameter because otherwise wxPixelData couldn't compile
263 template <class dummyPixelFormat>
264 class WXDLLEXPORT wxPixelDataIn : public wxPixelDataBase
265 {
266 // the type of the class we're working with
267 typedef wxImage ImageType;
268
269 // the iterator which should be used for working with data in this
270 // format
271 class Iterator
272 {
273 public:
274 // the pixel format we use
275 typedef wxImagePixelFormat PixelFormat;
276
277 // the type of the pixel components
278 typedef typename PixelFormat::ChannelType ChannelType;
279
280 // the pixel data we're working with
281 typedef
282 wxPixelDataOut<wxImage>::wxPixelDataIn<PixelFormat> PixelData;
283
284 // go back to (0, 0)
285 void Reset(const PixelData& data)
286 {
287 *this = data.GetPixels();
288 }
289
290 // creates the iterator pointing to the beginning of data
291 Iterator(PixelData& data)
292 {
293 Reset(data);
294 }
295
296 // creates the iterator initially pointing to the image origin
297 Iterator(const wxImage& image)
298 {
299 m_pRGB = image.GetData();
300
301 if ( image.HasAlpha() )
302 {
303 m_pAlpha = image.GetAlpha();
304 }
305 else // alpha is not used at all
306 {
307 m_pAlpha = NULL;
308 }
309 }
310
311 // true if the iterator is valid
312 bool IsOk() const { return m_pRGB != NULL; }
313
314
315 // navigation
316 // ----------
317
318 // advance the iterator to the next pixel, prefix version
319 Iterator& operator++()
320 {
321 m_pRGB += PixelFormat::SizePixel;
322 if ( m_pAlpha )
323 m_pAlpha += PixelFormat::SizePixel;
324
325 return *this;
326 }
327
328 // postfix (hence less efficient -- don't use it unless you
329 // absolutely must) version
330 Iterator operator++(int)
331 {
332 Iterator p(*this);
333 ++*this;
334 return p;
335 }
336
337 // move x pixels to the right and y down
338 //
339 // note that the rows don't wrap!
340 void Offset(const PixelData& data, int x, int y)
341 {
342 m_pRGB += data.GetRowStride()*y + PixelFormat::SizePixel*x;
343 if ( m_pAlpha )
344 m_pAlpha += data.GetWidth() + x;
345 }
346
347 // move x pixels to the right (again, no row wrapping)
348 void OffsetX(const PixelData& WXUNUSED(data), int x)
349 {
350 m_pRGB += PixelFormat::SizePixel*x;
351 if ( m_pAlpha )
352 m_pAlpha += x;
353 }
354
355 // move y rows to the bottom
356 void OffsetY(const PixelData& data, int y)
357 {
358 m_pRGB += data.GetRowStride()*y;
359 if ( m_pAlpha )
360 m_pAlpha += data.GetWidth();
361 }
362
363 // go to the given position
364 void MoveTo(const PixelData& data, int x, int y)
365 {
366 Reset(data);
367 Offset(data, x, y);
368 }
369
370
371 // data access
372 // -----------
373
374 // access to invidividual colour components
375 ChannelType& Red() { return m_ptr[PixelFormat::RED]; }
376 ChannelType& Green() { return m_ptr[PixelFormat::GREEN]; }
377 ChannelType& Blue() { return m_ptr[PixelFormat::BLUE]; }
378 ChannelType& Alpha() { return *m_pAlpha; }
379
380 // private: -- see comment in the beginning of the file
381
382 // pointer into RGB buffer
383 unsigned char *m_pRGB;
384
385 // pointer into alpha buffer or NULL if alpha isn't used
386 unsigned char *m_pAlpha;
387 };
388
389 // initializes us with the data of the given image
390 wxPixelDataIn(ImageType& image) : m_image(image), m_pixels(image)
391 {
392 m_width = image.GetWidth();
393 m_height = image.GetHeight();
394 m_stride = Iterator::SizePixel * m_width;
395 }
396
397 // initializes us with the given region of the specified image
398 wxPixelDataIn(ImageType& image,
399 const wxPoint& pt,
400 const wxSize& sz) : m_image(image), m_pixels(image)
401 {
402 m_stride = Iterator::SizePixel * m_width;
403
404 InitRect(pt, sz);
405 }
406
407 // initializes us with the given region of the specified image
408 wxPixelDataIn(ImageType& image,
409 const wxRect& rect) : m_image(image), m_pixels(image)
410 {
411 m_stride = Iterator::SizePixel * m_width;
412
413 InitRect(rect.GetPositions(), rect.GetSize());
414 }
415
416 // we evaluate to true only if we could get access to bitmap data
417 // successfully
418 operator bool() const { return m_pixels.IsOk(); }
419
420 // get the iterator pointing to the origin
421 Iterator GetPixels() const { return m_pixels; }
422
423 private:
424 void InitRect(const wxPoint& pt, const wxSize& sz)
425 {
426 m_width = sz.x;
427 m_height = sz.y;
428
429 m_ptOrigin = pt;
430 m_pixels.Offset(*this, pt.x, pt.y);
431 }
432
433 // the image we're working with
434 ImageType& m_image;
435
436 // the iterator pointing to the image origin
437 Iterator m_pixels;
438 };
439 };
440
441 // wxPixelData specialization for wxBitmap: here things are more interesting as
442 // we also have to support different pixel formats
443 template <>
444 struct WXDLLEXPORT wxPixelDataOut<wxBitmap>
445 {
446 template <class Format>
447 class WXDLLEXPORT wxPixelDataIn : public wxPixelDataBase
448 {
449 public:
450 // the type of the class we're working with
451 typedef wxBitmap ImageType;
452
453 class Iterator
454 {
455 public:
456 // the pixel format we use
457 typedef Format PixelFormat;
458
459 // the type of the pixel components
460 typedef typename PixelFormat::ChannelType ChannelType;
461
462 // the pixel data we're working with
463 typedef wxPixelDataOut<wxBitmap>::wxPixelDataIn<Format> PixelData;
464
465
466 // go back to (0, 0)
467 void Reset(const PixelData& data)
468 {
469 *this = data.GetPixels();
470 }
471
472 // initializes the iterator to point to the origin of the given
473 // pixel data
474 Iterator(PixelData& data)
475 {
476 Reset(data);
477 }
478
479 // initializes the iterator to point to the origin of the given
480 // bitmap
481 Iterator(wxBitmap& bmp, PixelData& data)
482 {
483 // using cast here is ugly but it should be safe as
484 // GetRawData() real return type should be consistent with
485 // BitsPerPixel (which is in turn defined by ChannelType) and
486 // this is the only thing we can do without making GetRawData()
487 // a template function which is undesirable
488 m_ptr = (ChannelType *)
489 bmp.GetRawData(data, PixelFormat::BitsPerPixel);
490 }
491
492 // return true if this iterator is valid
493 bool IsOk() const { return m_ptr != NULL; }
494
495
496 // navigation
497 // ----------
498
499 // advance the iterator to the next pixel, prefix version
500 Iterator& operator++()
501 {
502 m_ptr += PixelFormat::SizePixel;
503
504 return *this;
505 }
506
507 // postfix (hence less efficient -- don't use it unless you
508 // absolutely must) version
509 Iterator operator++(int)
510 {
511 Iterator p(*this);
512 ++*this;
513 return p;
514 }
515
516 // move x pixels to the right and y down
517 //
518 // note that the rows don't wrap!
519 void Offset(const PixelData& data, int x, int y)
520 {
521 m_ptr += data.GetRowStride()*y + PixelFormat::SizePixel*x;
522 }
523
524 // move x pixels to the right (again, no row wrapping)
525 void OffsetX(const PixelData& WXUNUSED(data), int x)
526 {
527 m_ptr += PixelFormat::SizePixel*x;
528 }
529
530 // move y rows to the bottom
531 void OffsetY(const PixelData& data, int y)
532 {
533 m_ptr += data.GetRowStride()*y;
534 }
535
536 // go to the given position
537 void MoveTo(const PixelData& data, int x, int y)
538 {
539 Reset(data);
540 Offset(data, x, y);
541 }
542
543
544 // data access
545 // -----------
546
547 // access to invidividual colour components
548 ChannelType& Red() { return m_ptr[PixelFormat::RED]; }
549 ChannelType& Green() { return m_ptr[PixelFormat::GREEN]; }
550 ChannelType& Blue() { return m_ptr[PixelFormat::BLUE]; }
551 ChannelType& Alpha() { return m_ptr[PixelFormat::ALPHA]; }
552
553 // address the pixel contents directly
554 //
555 // warning: the format is platform dependent
556 typename PixelFormat::PixelType& Data()
557 { return *(typename PixelFormat::PixelType *)m_ptr; }
558
559 // private: -- see comment in the beginning of the file
560
561 // NB: for efficiency reasons this class must *not* have any other
562 // fields, otherwise it won't be put into a CPU register (as it
563 // should inside the inner loops) by some compilers, notably
564 // gcc
565 ChannelType *m_ptr;
566 };
567
568 // ctor associates this pointer with a bitmap and locks the bitmap for
569 // raw access, it will be unlocked only by our dtor and so these
570 // objects should normally be only created on the stack, i.e. have
571 // limited life-time
572 wxPixelDataIn(wxBitmap& bmp) : m_bmp(bmp), m_pixels(bmp, *this)
573 {
574 }
575
576 wxPixelDataIn(wxBitmap& bmp, const wxRect& rect)
577 : m_bmp(bmp), m_pixels(bmp, *this)
578 {
579 InitRect(rect.GetPositions(), rect.GetSize());
580 }
581
582 wxPixelDataIn(wxBitmap& bmp, const wxPoint& pt, const wxSize& sz)
583 : m_bmp(bmp), m_pixels(bmp, *this)
584 {
585 InitRect(pt, sz);
586 }
587
588 // we evaluate to true only if we could get access to bitmap data
589 // successfully
590 operator bool() const { return m_pixels.IsOk(); }
591
592 // get the iterator pointing to the origin
593 Iterator GetPixels() const { return m_pixels; }
594
595 // dtor unlocks the bitmap
596 ~wxPixelDataIn()
597 {
598 m_bmp.UngetRawData(*this);
599 }
600
601 // call this to indicate that we should use the alpha channel
602 void UseAlpha() { m_bmp.UseAlpha(); }
603
604 // private: -- see comment in the beginning of the file
605
606 // the bitmap we're associated with
607 wxBitmap m_bmp;
608
609 // the iterator pointing to the image origin
610 Iterator m_pixels;
611
612 private:
613 void InitRect(const wxPoint& pt, const wxSize& sz)
614 {
615 m_pixels.Offset(*this, pt.x, pt.y);
616
617 m_ptOrigin = pt;
618 m_width = sz.x;
619 m_height = sz.y;
620 }
621 };
622 };
623
624 template <class Image, class PixelFormat = wxPixelFormatFor<Image> >
625 class wxPixelData :
626 public wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>
627 {
628 public:
629 wxPixelData(Image& image)
630 : wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>(image)
631 {
632 }
633
634 wxPixelData(Image& i, const wxPoint& pt, const wxSize& sz)
635 : wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>(i, pt, sz)
636 {
637 }
638
639 wxPixelData(Image& i, const wxRect& rect)
640 : wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>(i, rect)
641 {
642 }
643 };
644
645 // some "predefined" pixel data classes
646 typedef wxPixelData<wxImage> wxImagePixelData;
647 typedef wxPixelData<wxBitmap, wxNativePixelFormat> wxNativePixelData;
648 typedef wxPixelData<wxBitmap, wxAlphaPixelFormat> wxAlphaPixelData;
649
650 // ----------------------------------------------------------------------------
651 // wxPixelIterator
652 // ----------------------------------------------------------------------------
653
654 /*
655 wxPixel::Iterator represents something which points to the pixel data and
656 allows us to iterate over it. In the simplest case of wxBitmap it is,
657 indeed, just a pointer, but it can be something more complicated and,
658 moreover, you are free to specialize it for other image classes and bitmap
659 formats.
660
661 Note that although it would have been much more intuitive to have a real
662 class here instead of what we have now, this class would need two template
663 parameters, and this can't be done because we'd need compiler support for
664 partial template specialization then and neither VC6 nor VC7 provide it.
665 */
666 template < class Image, class PixelFormat = wxPixelFormatFor<Image> >
667 struct WXDLLEXPORT wxPixelIterator : wxPixelData<Image, PixelFormat>::Iterator
668 {
669 };
670
671 #ifdef __VISUALC__
672 #pragma warning(default: 4355)
673 #endif
674
675 #endif // _WX_RAWBMP_H_BASE_
676