]> git.saurik.com Git - wxWidgets.git/blob - include/wx/rawbmp.h
possible fix for templates with digitalmars
[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
104 #ifdef __DIGITALMARS__
105 template <class Channel,
106 size_t Bpp, int R, int G, int B, int A = -1,
107 class Pixel = wxUint32>
108 #else
109 template <typename Channel,
110 size_t Bpp, int R, int G, int B, int A = -1,
111 typename Pixel = wxUint32>
112 #endif
113
114 struct WXDLLEXPORT wxPixelFormat
115 {
116 // iterator over pixels is usually of type "ChannelType *"
117 typedef Channel ChannelType;
118
119 // the type which may hold the entire pixel value
120 typedef Pixel PixelType;
121
122 // NB: using static ints initialized inside the class declaration is not
123 // portable as it doesn't work with VC++ 6, so we must use enums
124
125 // size of one pixel in bits
126 enum { BitsPerPixel = Bpp };
127
128 // size of one pixel in ChannelType units (usually bytes)
129 enum { SizePixel = BitsPerPixel / (8 * sizeof(ChannelType)) };
130
131 // the channels indices inside the pixel
132 enum
133 {
134 RED = R,
135 GREEN = G,
136 BLUE = B,
137 ALPHA = A
138 };
139
140 // true if we have an alpha channel (together with the other channels, this
141 // doesn't cover the case of wxImage which stores alpha separately)
142 enum { HasAlpha = A != -1 };
143 };
144
145 // some "predefined" pixel formats
146 // -------------------------------
147
148 // wxImage format is common to all platforms
149 typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxImagePixelFormat;
150
151 // the (most common) native bitmap format without alpha support
152 typedef wxPixelFormat<unsigned char, 24,
153 #ifdef __WXMSW__
154 2, 1, 0
155 #else // !__WXMSW__
156 0, 1, 2
157 #endif // __WXMSW__/!__WXMSW__
158 > wxNativePixelFormat;
159
160 // the (most common) native format for bitmaps with alpha channel
161 typedef wxPixelFormat<unsigned char, 32,
162 wxNativePixelFormat::RED,
163 wxNativePixelFormat::GREEN,
164 wxNativePixelFormat::BLUE,
165 3> wxAlphaPixelFormat;
166
167 // we also define the (default/best) pixel format for the given class: this is
168 // used as default value for the pixel format in wxPixelIterator template
169 template <class T> struct wxPixelFormatFor;
170
171 // wxPixelFormatFor is only defined for wxImage, attempt to use it with other
172 // classes (wxBitmap...) will result in compile errors which is exactly what we
173 // want
174 template <>
175 struct WXDLLEXPORT wxPixelFormatFor<wxImage>
176 {
177 typedef wxImagePixelFormat Format;
178 };
179
180 // ----------------------------------------------------------------------------
181 // wxPixelData
182 // ----------------------------------------------------------------------------
183
184 /*
185 wxPixelDataBase is just a helper for wxPixelData: it contains things common
186 to both wxImage and wxBitmap specializations.
187 */
188 class WXDLLEXPORT wxPixelDataBase
189 {
190 public:
191 // origin of the rectangular region we represent
192 wxPoint GetOrigin() const { return m_ptOrigin; }
193
194 // width and height of the region we represent
195 int GetWidth() const { return m_width; }
196 int GetHeight() const { return m_height; }
197
198 // the distance between two rows
199 int GetRowStride() const { return m_stride; }
200
201 // private: -- see comment in the beginning of the file
202
203 // the origin of this image inside the bigger bitmap (usually (0, 0))
204 wxPoint m_ptOrigin;
205
206 // the size of the image we address, in pixels
207 int m_width,
208 m_height;
209
210 // this parameter is the offset of the start of the (N+1)st row from the
211 // Nth one and can be different from m_bypp*width in some cases:
212 // a) the most usual one is to force 32/64 bit alignment of rows
213 // b) another one is for bottom-to-top images where it's negative
214 // c) finally, it could conceivably be 0 for the images with all
215 // lines being identical
216 int m_stride;
217
218 protected:
219 // ctor is protected because this class is only meant to be used as the
220 // base class by wxPixelData
221 wxPixelDataBase()
222 {
223 m_width =
224 m_height =
225 m_stride = 0;
226 }
227 };
228
229 /*
230 wxPixelData represents the entire bitmap data, i.e. unlike
231 wxPixelFormat (which it uses) it also stores the global bitmap
232 characteristics such as its size, inter-row separation and so on.
233
234 Because of this it can be used to move the pixel iterators (which don't
235 have enough information about the bitmap themselves). This may seem a bit
236 unnatural but must be done in this way to keep the iterator objects as
237 small as possible for maximum efficiency as otherwise they wouldn't be put
238 into the CPU registers by the compiler any more.
239
240 Implementation note: we use the standard workaround for lack of partial
241 template specialization support in VC (both 6 and 7): instead of partly
242 specializing the class Foo<T, U> for some T we introduce FooOut<T> and
243 FooIn<U> nested in it, make Foo<T, U> equivalent to FooOut<T>::FooIn<U> and
244 fully specialize FooOut.
245
246 Also note that this class doesn't have any default definition because we
247 can't really do anything without knowing the exact image class. We do
248 provide wxPixelDataBase to make it simpler to write new wxPixelData
249 specializations.
250 */
251
252 // we need to define this skeleton template to mollify VC++
253 template <class Image>
254 struct WXDLLEXPORT wxPixelDataOut
255 {
256 template <class PixelFormat>
257 class WXDLLEXPORT wxPixelDataIn
258 {
259 public:
260 class Iterator { };
261 };
262 };
263
264 // wxPixelData specialization for wxImage: this is the simplest case as we
265 // don't have to care about different pixel formats here
266 template <>
267 struct WXDLLEXPORT wxPixelDataOut<wxImage>
268 {
269 // NB: this is a template class even though it doesn't use its template
270 // parameter because otherwise wxPixelData couldn't compile
271 template <class dummyPixelFormat>
272 class WXDLLEXPORT wxPixelDataIn : public wxPixelDataBase
273 {
274 // the type of the class we're working with
275 typedef wxImage ImageType;
276
277 // the iterator which should be used for working with data in this
278 // format
279 class Iterator
280 {
281 public:
282 // the pixel format we use
283 typedef wxImagePixelFormat PixelFormat;
284
285 // the type of the pixel components
286 typedef typename dummyPixelFormat::ChannelType ChannelType;
287
288 // the pixel data we're working with
289 typedef
290 wxPixelDataOut<wxImage>::wxPixelDataIn<PixelFormat> PixelData;
291
292 // go back to (0, 0)
293 void Reset(const PixelData& data)
294 {
295 *this = data.GetPixels();
296 }
297
298 // creates the iterator pointing to the beginning of data
299 Iterator(PixelData& data)
300 {
301 Reset(data);
302 }
303
304 // creates the iterator initially pointing to the image origin
305 Iterator(const wxImage& image)
306 {
307 m_pRGB = image.GetData();
308
309 if ( image.HasAlpha() )
310 {
311 m_pAlpha = image.GetAlpha();
312 }
313 else // alpha is not used at all
314 {
315 m_pAlpha = NULL;
316 }
317 }
318
319 // true if the iterator is valid
320 bool IsOk() const { return m_pRGB != NULL; }
321
322
323 // navigation
324 // ----------
325
326 // advance the iterator to the next pixel, prefix version
327 Iterator& operator++()
328 {
329 m_pRGB += PixelFormat::SizePixel;
330 if ( m_pAlpha )
331 m_pAlpha += PixelFormat::SizePixel;
332
333 return *this;
334 }
335
336 // postfix (hence less efficient -- don't use it unless you
337 // absolutely must) version
338 Iterator operator++(int)
339 {
340 Iterator p(*this);
341 ++*this;
342 return p;
343 }
344
345 // move x pixels to the right and y down
346 //
347 // note that the rows don't wrap!
348 void Offset(const PixelData& data, int x, int y)
349 {
350 m_pRGB += data.GetRowStride()*y + PixelFormat::SizePixel*x;
351 if ( m_pAlpha )
352 m_pAlpha += data.GetWidth() + x;
353 }
354
355 // move x pixels to the right (again, no row wrapping)
356 void OffsetX(const PixelData& WXUNUSED(data), int x)
357 {
358 m_pRGB += PixelFormat::SizePixel*x;
359 if ( m_pAlpha )
360 m_pAlpha += x;
361 }
362
363 // move y rows to the bottom
364 void OffsetY(const PixelData& data, int y)
365 {
366 m_pRGB += data.GetRowStride()*y;
367 if ( m_pAlpha )
368 m_pAlpha += data.GetWidth();
369 }
370
371 // go to the given position
372 void MoveTo(const PixelData& data, int x, int y)
373 {
374 Reset(data);
375 Offset(data, x, y);
376 }
377
378
379 // data access
380 // -----------
381
382 // access to invidividual colour components
383 ChannelType& Red() { return m_ptr[PixelFormat::RED]; }
384 ChannelType& Green() { return m_ptr[PixelFormat::GREEN]; }
385 ChannelType& Blue() { return m_ptr[PixelFormat::BLUE]; }
386 ChannelType& Alpha() { return *m_pAlpha; }
387
388 // private: -- see comment in the beginning of the file
389
390 // pointer into RGB buffer
391 unsigned char *m_pRGB;
392
393 // pointer into alpha buffer or NULL if alpha isn't used
394 unsigned char *m_pAlpha;
395 };
396
397 // initializes us with the data of the given image
398 wxPixelDataIn(ImageType& image) : m_image(image), m_pixels(image)
399 {
400 m_width = image.GetWidth();
401 m_height = image.GetHeight();
402 m_stride = Iterator::SizePixel * m_width;
403 }
404
405 // initializes us with the given region of the specified image
406 wxPixelDataIn(ImageType& image,
407 const wxPoint& pt,
408 const wxSize& sz) : m_image(image), m_pixels(image)
409 {
410 m_stride = Iterator::SizePixel * m_width;
411
412 InitRect(pt, sz);
413 }
414
415 // initializes us with the given region of the specified image
416 wxPixelDataIn(ImageType& image,
417 const wxRect& rect) : m_image(image), m_pixels(image)
418 {
419 m_stride = Iterator::SizePixel * m_width;
420
421 InitRect(rect.GetPositions(), rect.GetSize());
422 }
423
424 // we evaluate to true only if we could get access to bitmap data
425 // successfully
426 operator bool() const { return m_pixels.IsOk(); }
427
428 // get the iterator pointing to the origin
429 Iterator GetPixels() const { return m_pixels; }
430
431 private:
432 void InitRect(const wxPoint& pt, const wxSize& sz)
433 {
434 m_width = sz.x;
435 m_height = sz.y;
436
437 m_ptOrigin = pt;
438 m_pixels.Offset(*this, pt.x, pt.y);
439 }
440
441 // the image we're working with
442 ImageType& m_image;
443
444 // the iterator pointing to the image origin
445 Iterator m_pixels;
446 };
447 };
448
449 // wxPixelData specialization for wxBitmap: here things are more interesting as
450 // we also have to support different pixel formats
451 template <>
452 struct WXDLLEXPORT wxPixelDataOut<wxBitmap>
453 {
454 template <class Format>
455 class WXDLLEXPORT wxPixelDataIn : public wxPixelDataBase
456 {
457 public:
458 // the type of the class we're working with
459 typedef wxBitmap ImageType;
460
461 class Iterator
462 {
463 public:
464 // the pixel format we use
465 typedef Format PixelFormat;
466
467 // the type of the pixel components
468 typedef typename PixelFormat::ChannelType ChannelType;
469
470 // the pixel data we're working with
471 typedef wxPixelDataOut<wxBitmap>::wxPixelDataIn<Format> PixelData;
472
473
474 // go back to (0, 0)
475 void Reset(const PixelData& data)
476 {
477 *this = data.GetPixels();
478 }
479
480 // initializes the iterator to point to the origin of the given
481 // pixel data
482 Iterator(PixelData& data)
483 {
484 Reset(data);
485 }
486
487 // initializes the iterator to point to the origin of the given
488 // bitmap
489 Iterator(wxBitmap& bmp, PixelData& data)
490 {
491 // using cast here is ugly but it should be safe as
492 // GetRawData() real return type should be consistent with
493 // BitsPerPixel (which is in turn defined by ChannelType) and
494 // this is the only thing we can do without making GetRawData()
495 // a template function which is undesirable
496 m_ptr = (ChannelType *)
497 bmp.GetRawData(data, PixelFormat::BitsPerPixel);
498 }
499
500 // return true if this iterator is valid
501 bool IsOk() const { return m_ptr != NULL; }
502
503
504 // navigation
505 // ----------
506
507 // advance the iterator to the next pixel, prefix version
508 Iterator& operator++()
509 {
510 m_ptr += PixelFormat::SizePixel;
511
512 return *this;
513 }
514
515 // postfix (hence less efficient -- don't use it unless you
516 // absolutely must) version
517 Iterator operator++(int)
518 {
519 Iterator p(*this);
520 ++*this;
521 return p;
522 }
523
524 // move x pixels to the right and y down
525 //
526 // note that the rows don't wrap!
527 void Offset(const PixelData& data, int x, int y)
528 {
529 m_ptr += data.GetRowStride()*y + PixelFormat::SizePixel*x;
530 }
531
532 // move x pixels to the right (again, no row wrapping)
533 void OffsetX(const PixelData& WXUNUSED(data), int x)
534 {
535 m_ptr += PixelFormat::SizePixel*x;
536 }
537
538 // move y rows to the bottom
539 void OffsetY(const PixelData& data, int y)
540 {
541 m_ptr += data.GetRowStride()*y;
542 }
543
544 // go to the given position
545 void MoveTo(const PixelData& data, int x, int y)
546 {
547 Reset(data);
548 Offset(data, x, y);
549 }
550
551
552 // data access
553 // -----------
554
555 // access to invidividual colour components
556 ChannelType& Red() { return m_ptr[PixelFormat::RED]; }
557 ChannelType& Green() { return m_ptr[PixelFormat::GREEN]; }
558 ChannelType& Blue() { return m_ptr[PixelFormat::BLUE]; }
559 ChannelType& Alpha() { return m_ptr[PixelFormat::ALPHA]; }
560
561 // address the pixel contents directly
562 //
563 // warning: the format is platform dependent
564 typename PixelFormat::PixelType& Data()
565 { return *(typename PixelFormat::PixelType *)m_ptr; }
566
567 // private: -- see comment in the beginning of the file
568
569 // NB: for efficiency reasons this class must *not* have any other
570 // fields, otherwise it won't be put into a CPU register (as it
571 // should inside the inner loops) by some compilers, notably
572 // gcc
573 ChannelType *m_ptr;
574 };
575
576 // ctor associates this pointer with a bitmap and locks the bitmap for
577 // raw access, it will be unlocked only by our dtor and so these
578 // objects should normally be only created on the stack, i.e. have
579 // limited life-time
580 wxPixelDataIn(wxBitmap& bmp) : m_bmp(bmp), m_pixels(bmp, *this)
581 {
582 }
583
584 wxPixelDataIn(wxBitmap& bmp, const wxRect& rect)
585 : m_bmp(bmp), m_pixels(bmp, *this)
586 {
587 InitRect(rect.GetPositions(), rect.GetSize());
588 }
589
590 wxPixelDataIn(wxBitmap& bmp, const wxPoint& pt, const wxSize& sz)
591 : m_bmp(bmp), m_pixels(bmp, *this)
592 {
593 InitRect(pt, sz);
594 }
595
596 // we evaluate to true only if we could get access to bitmap data
597 // successfully
598 operator bool() const { return m_pixels.IsOk(); }
599
600 // get the iterator pointing to the origin
601 Iterator GetPixels() const { return m_pixels; }
602
603 // dtor unlocks the bitmap
604 ~wxPixelDataIn()
605 {
606 m_bmp.UngetRawData(*this);
607 }
608
609 // call this to indicate that we should use the alpha channel
610 void UseAlpha() { m_bmp.UseAlpha(); }
611
612 // private: -- see comment in the beginning of the file
613
614 // the bitmap we're associated with
615 wxBitmap m_bmp;
616
617 // the iterator pointing to the image origin
618 Iterator m_pixels;
619
620 private:
621 void InitRect(const wxPoint& pt, const wxSize& sz)
622 {
623 m_pixels.Offset(*this, pt.x, pt.y);
624
625 m_ptOrigin = pt;
626 m_width = sz.x;
627 m_height = sz.y;
628 }
629 };
630 };
631
632 #ifdef __DIGITALMARS__
633 template <class Image, class PixelFormat = wxPixelFormatFor<Image> >
634 class wxPixelData :
635 public wxPixelDataOut<Image>:: wxPixelDataIn<PixelFormat>
636 {
637 public:
638 wxPixelData(Image& image)
639 : wxPixelDataOut<Image>:: wxPixelDataIn<PixelFormat>(image)
640 {
641 }
642
643 wxPixelData(Image& i, const wxPoint& pt, const wxSize& sz)
644 : wxPixelDataOut<Image>:: wxPixelDataIn<PixelFormat>(i, pt, sz)
645 {
646 }
647
648 wxPixelData(Image& i, const wxRect& rect)
649 : wxPixelDataOut<Image>:: wxPixelDataIn<PixelFormat>(i, rect)
650 {
651 }
652 };
653 #else // not __DIGITALMARS__
654 template <class Image, class PixelFormat = wxPixelFormatFor<Image> >
655 class wxPixelData :
656 public wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>
657 {
658 public:
659 wxPixelData(Image& image)
660 : wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>(image)
661 {
662 }
663
664 wxPixelData(Image& i, const wxPoint& pt, const wxSize& sz)
665 : wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>(i, pt, sz)
666 {
667 }
668
669 wxPixelData(Image& i, const wxRect& rect)
670 : wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>(i, rect)
671 {
672 }
673 };
674 #endif // __DIGITALMARS__
675
676 // some "predefined" pixel data classes
677 typedef wxPixelData<wxImage> wxImagePixelData;
678 typedef wxPixelData<wxBitmap, wxNativePixelFormat> wxNativePixelData;
679 typedef wxPixelData<wxBitmap, wxAlphaPixelFormat> wxAlphaPixelData;
680
681 // ----------------------------------------------------------------------------
682 // wxPixelIterator
683 // ----------------------------------------------------------------------------
684
685 /*
686 wxPixel::Iterator represents something which points to the pixel data and
687 allows us to iterate over it. In the simplest case of wxBitmap it is,
688 indeed, just a pointer, but it can be something more complicated and,
689 moreover, you are free to specialize it for other image classes and bitmap
690 formats.
691
692 Note that although it would have been much more intuitive to have a real
693 class here instead of what we have now, this class would need two template
694 parameters, and this can't be done because we'd need compiler support for
695 partial template specialization then and neither VC6 nor VC7 provide it.
696 */
697 template < class Image, class PixelFormat = wxPixelFormatFor<Image> >
698 struct WXDLLEXPORT wxPixelIterator : wxPixelData<Image, PixelFormat>::Iterator
699 {
700 };
701
702 #ifdef __VISUALC__
703 #pragma warning(default: 4355)
704 #endif
705
706 #endif // _WX_RAWBMP_H_BASE_
707