1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: macros for fast, raw bitmap data access
4 // Author: Eric Kidd, Vadim Zeitlin
8 // Copyright: (c) 2002 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 #ifndef _WX_RAWBMP_H_BASE_
13 #define _WX_RAWBMP_H_BASE_
15 // ----------------------------------------------------------------------------
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.
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
30 // ----------------------------------------------------------------------------
35 typedef wxPixelData<wxBitmap, wxNativePixelFormat> PixelData;
41 ... raw access to bitmap data unavailable, do something else ...
45 if ( data.GetWidth() < 20 || data.GetHeight() < 20 )
47 ... complain: the bitmap it too small ...
51 PixelData::Iterator p(data);
53 // we draw a (10, 10)-(20, 20) rect manually using the given r, g, b
54 p.Offset(data, 10, 10);
56 for ( int y = 0; y < 10; ++y )
58 PixelData::Iterator rowStart = p;
60 for ( int x = 0; x < 10; ++x, ++p )
73 // VC++ gives an absolutely harmless warning for wxPixelData<wxBitmap> ctor
74 #pragma warning(disable: 4355) // 'this' used in initializer list
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
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
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.
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)
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
108 // iterator over pixels is usually of type "ChannelType *"
109 typedef Channel ChannelType
;
111 // the type which may hold the entire pixel value
112 typedef Pixel PixelType
;
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
117 // size of one pixel in bits
118 enum { BitsPerPixel
= Bpp
};
120 // size of one pixel in ChannelType units (usually bytes)
121 enum { SizePixel
= BitsPerPixel
/ (8 * sizeof(ChannelType
)) };
123 // the channels indices inside the pixel
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 };
137 // some "predefined" pixel formats
138 // -------------------------------
140 // wxImage format is common to all platforms
141 typedef wxPixelFormat
<unsigned char, 24, 0, 1, 2> wxImagePixelFormat
;
143 // the (most common) native bitmap format without alpha support
144 typedef wxPixelFormat
<unsigned char, 24,
149 #endif // __WXMSW__/!__WXMSW__
150 > wxNativePixelFormat
;
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
;
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
;
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
167 struct WXDLLEXPORT wxPixelFormatFor
<wxImage
>
169 typedef wxImagePixelFormat Format
;
172 // ----------------------------------------------------------------------------
174 // ----------------------------------------------------------------------------
177 wxPixelDataBase is just a helper for wxPixelData: it contains things common
178 to both wxImage and wxBitmap specializations.
180 class WXDLLEXPORT wxPixelDataBase
183 int GetWidth() const { return m_width
; }
184 int GetHeight() const { return m_height
; }
185 int GetRowStride() const { return m_stride
; }
187 // private: -- see comment in the beginning of the file
189 // the size of the image we address, in pixels
193 // this parameter is the offset of the start of the (N+1)st row from the
194 // Nth one and can be different from m_bypp*width in some cases:
195 // a) the most usual one is to force 32/64 bit alignment of rows
196 // b) another one is for bottom-to-top images where it's negative
197 // c) finally, it could conceivably be 0 for the images with all
198 // lines being identical
202 // ctor is protected because this class is only meant to be used as the
203 // base class by wxPixelData
213 wxPixelData represents the entire bitmap data, i.e. unlike
214 wxPixelFormat (which it uses) it also stores the global bitmap
215 characteristics such as its size, inter-row separation and so on.
217 Because of this it can be used to move the pixel iterators (which don't
218 have enough information about the bitmap themselves). This may seem a bit
219 unnatural but must be done in this way to keep the iterator objects as
220 small as possible for maximum efficiency as otherwise they wouldn't be put
221 into the CPU registers by the compiler any more.
223 Implementation note: we use the standard workaround for lack of partial
224 template specialization support in VC (both 6 and 7): instead of partly
225 specializing the class Foo<T, U> for some T we introduce FooOut<T> and
226 FooIn<U> nested in it, make Foo<T, U> equivalent to FooOut<T>::FooIn<U> and
227 fully specialize FooOut.
229 Also note that this class doesn't have any default definition because we
230 can't really do anything without knowing the exact image class. We do
231 provide wxPixelDataBase to make it simpler to write new wxPixelData
235 // we need to define this skeleton template to mollify VC++
236 template <class Image
>
237 struct WXDLLEXPORT wxPixelDataOut
239 template <class PixelFormat
>
240 class WXDLLEXPORT wxPixelDataIn
247 // wxPixelData specialization for wxImage: this is the simplest case as we
248 // don't have to care about different pixel formats here
250 struct WXDLLEXPORT wxPixelDataOut
<wxImage
>
252 // NB: this is a template class even though it doesn't use its template
253 // parameter because otherwise wxPixelData couldn't compile
254 template <class dummyPixelFormat
>
255 class WXDLLEXPORT wxPixelDataIn
: public wxPixelDataBase
257 // the type of the class we're working with
258 typedef wxImage ImageType
;
260 // the iterator which should be used for working with data in this
265 // the pixel format we use
266 typedef wxImagePixelFormat PixelFormat
;
268 // the type of the pixel components
269 typedef typename
PixelFormat::ChannelType ChannelType
;
271 // the pixel data we're working with
273 wxPixelDataOut
<wxImage
>::wxPixelDataIn
<PixelFormat
> PixelData
;
276 void Reset(const PixelData
& data
)
278 *this = data
.GetPixels();
281 // creates the iterator pointing to the beginning of data
282 Iterator(PixelData
& data
)
287 // creates the iterator initially pointing to the image origin
288 Iterator(const wxImage
& image
)
290 m_pRGB
= image
.GetData();
292 if ( image
.HasAlpha() )
294 m_pAlpha
= image
.GetAlpha();
296 else // alpha is not used at all
302 // true if the iterator is valid
303 bool IsOk() const { return m_pRGB
!= NULL
; }
309 // advance the iterator to the next pixel, prefix version
310 Iterator
& operator++()
312 m_pRGB
+= PixelFormat::SizePixel
;
314 m_pAlpha
+= PixelFormat::SizePixel
;
319 // postfix (hence less efficient -- don't use unless you must) version
320 Iterator
operator++(int)
327 // move x pixels to the right and y down
329 // note that the rows don't wrap!
330 void Offset(const PixelData
& data
, int x
, int y
)
332 m_pRGB
+= data
.GetRowStride()*y
+ PixelFormat::SizePixel
*x
;
334 m_pAlpha
+= data
.GetWidth() + x
;
337 // move x pixels to the right (again, no row wrapping)
338 void OffsetX(const PixelData
& WXUNUSED(data
), int x
)
340 m_pRGB
+= PixelFormat::SizePixel
*x
;
345 // move y rows to the bottom
346 void OffsetY(const PixelData
& data
, int y
)
348 m_pRGB
+= data
.GetRowStride()*y
;
350 m_pAlpha
+= data
.GetWidth();
353 // go to the given position
354 void MoveTo(const PixelData
& data
, int x
, int y
)
364 // access to invidividual colour components
365 ChannelType
& Red() { return m_ptr
[PixelFormat::RED
]; }
366 ChannelType
& Green() { return m_ptr
[PixelFormat::GREEN
]; }
367 ChannelType
& Blue() { return m_ptr
[PixelFormat::BLUE
]; }
368 ChannelType
& Alpha() { return *m_pAlpha
; }
370 // private: -- see comment in the beginning of the file
372 // pointer into RGB buffer
373 unsigned char *m_pRGB
;
375 // pointer into alpha buffer or NULL if alpha isn't used
376 unsigned char *m_pAlpha
;
379 // initializes us with the data of the given image
380 wxPixelDataIn(ImageType
& image
) : m_image(image
), m_pixels(image
)
382 m_width
= image
.GetWidth();
383 m_height
= image
.GetHeight();
384 m_stride
= Iterator::SizePixel
* m_width
;
387 // we evaluate to true only if we could get access to bitmap data
389 operator bool() const { return m_pixels
.IsOk(); }
391 // get the iterator pointing to the origin
392 Iterator
GetPixels() const { return m_pixels
; }
395 // the image we're working with
398 // the iterator pointing to the image origin
403 // wxPixelData specialization for wxBitmap: here things are more interesting as
404 // we also have to support different pixel formats
406 struct WXDLLEXPORT wxPixelDataOut
<wxBitmap
>
408 template <class Format
>
409 class WXDLLEXPORT wxPixelDataIn
: public wxPixelDataBase
412 // the type of the class we're working with
413 typedef wxBitmap ImageType
;
418 // the pixel format we use
419 typedef Format PixelFormat
;
421 // the type of the pixel components
422 typedef typename
PixelFormat::ChannelType ChannelType
;
424 // the pixel data we're working with
425 typedef wxPixelDataOut
<wxBitmap
>::wxPixelDataIn
<Format
> PixelData
;
429 void Reset(const PixelData
& data
)
431 *this = data
.GetPixels();
434 // initializes the iterator to point to the origin of the given pixel
436 Iterator(PixelData
& data
)
441 // initializes the iterator to point to the origin of the given bitmap
442 Iterator(wxBitmap
& bmp
, PixelData
& data
)
444 // using cast here is ugly but it should be safe as GetRawData()
445 // real return type should be consistent with BitsPerPixel (which
446 // is in turn defined by ChannelType) and this is the only thing we
447 // can do without making GetRawData() a template function which is
449 m_ptr
= (ChannelType
*)
450 bmp
.GetRawData(data
, PixelFormat::BitsPerPixel
);
453 // return true if this iterator is valid
454 bool IsOk() const { return m_ptr
!= NULL
; }
460 // advance the iterator to the next pixel, prefix version
461 Iterator
& operator++()
463 m_ptr
+= PixelFormat::SizePixel
;
468 // postfix (hence less efficient -- don't use unless you must) version
469 Iterator
operator++(int)
476 // move x pixels to the right and y down
478 // note that the rows don't wrap!
479 void Offset(const PixelData
& data
, int x
, int y
)
481 m_ptr
+= data
.GetRowStride()*y
+ PixelFormat::SizePixel
*x
;
484 // move x pixels to the right (again, no row wrapping)
485 void OffsetX(const PixelData
& WXUNUSED(data
), int x
)
487 m_ptr
+= PixelFormat::SizePixel
*x
;
490 // move y rows to the bottom
491 void OffsetY(const PixelData
& data
, int y
)
493 m_ptr
+= data
.GetRowStride()*y
;
496 // go to the given position
497 void MoveTo(const PixelData
& data
, int x
, int y
)
507 // access to invidividual colour components
508 ChannelType
& Red() { return m_ptr
[PixelFormat::RED
]; }
509 ChannelType
& Green() { return m_ptr
[PixelFormat::GREEN
]; }
510 ChannelType
& Blue() { return m_ptr
[PixelFormat::BLUE
]; }
511 ChannelType
& Alpha() { return m_ptr
[PixelFormat::ALPHA
]; }
513 // address the pixel contents directly
515 // warning: the format is platform dependent
516 typename
PixelFormat::PixelType
& Data()
517 { return *(typename
PixelFormat::PixelType
*)m_ptr
; }
519 // private: -- see comment in the beginning of the file
521 // NB: for efficiency reasons this class must *not* have any other
522 // fields, otherwise it won't be put into a CPU register (as it
523 // should inside the inner loops) by some compilers, notably gcc
527 // ctor associates this pointer with a bitmap and locks the bitmap for raw
528 // access, it will be unlocked only by our dtor and so these objects should
529 // normally be only created on the stack, i.e. have limited life-time
530 wxPixelDataIn(wxBitmap bmp
) : m_bmp(bmp
), m_pixels(bmp
, *this)
534 // we evaluate to true only if we could get access to bitmap data
536 operator bool() const { return m_pixels
.IsOk(); }
538 // get the iterator pointing to the origin
539 Iterator
GetPixels() const { return m_pixels
; }
541 // dtor unlocks the bitmap
544 m_bmp
.UngetRawData(*this);
547 // call this to indicate that we should use the alpha channel
548 void UseAlpha() { m_bmp
.UseAlpha(); }
550 // private: -- see comment in the beginning of the file
552 // the bitmap we're associated with
555 // the iterator pointing to the image origin
560 template <class Image
, class PixelFormat
= wxPixelFormatFor
<Image
> >
562 public wxPixelDataOut
<Image
>::template wxPixelDataIn
<PixelFormat
>
565 wxPixelData(const Image
& image
)
566 : wxPixelDataOut
<Image
>::template wxPixelDataIn
<PixelFormat
>(image
)
571 // some "predefined" pixel data classes
572 typedef wxPixelData
<wxImage
> wxImagePixelData
;
573 typedef wxPixelData
<wxBitmap
, wxNativePixelFormat
> wxNativePixelData
;
574 typedef wxPixelData
<wxBitmap
, wxAlphaPixelFormat
> wxAlphaPixelData
;
576 // ----------------------------------------------------------------------------
578 // ----------------------------------------------------------------------------
581 wxPixel::Iterator represents something which points to the pixel data and
582 allows us to iterate over it. In the simplest case of wxBitmap it is,
583 indeed, just a pointer, but it can be something more complicated and,
584 moreover, you are free to specialize it for other image classes and bitmap
587 Note that although it would have been much more intuitive to have a real
588 class here instead of what we have now, this class would need two template
589 parameters, and this can't be done because we'd need compiler support for
590 partial template specialization then and neither VC6 nor VC7 provide it.
592 template < class Image
, class PixelFormat
= wxPixelFormatFor
<Image
> >
593 struct WXDLLEXPORT wxPixelIterator
: wxPixelData
<Image
, PixelFormat
>::Iterator
598 #pragma warning(default: 4355)
601 #endif // _WX_RAWBMP_H_BASE_