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 // origin of the rectangular region we represent
184 wxPoint
GetOrigin() const { return m_ptOrigin
; }
186 // width and height of the region we represent
187 int GetWidth() const { return m_width
; }
188 int GetHeight() const { return m_height
; }
190 // the distance between two rows
191 int GetRowStride() const { return m_stride
; }
193 // private: -- see comment in the beginning of the file
195 // the origin of this image inside the bigger bitmap (usually (0, 0))
198 // the size of the image we address, in pixels
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
211 // ctor is protected because this class is only meant to be used as the
212 // base class by wxPixelData
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.
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.
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.
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
244 // we need to define this skeleton template to mollify VC++
245 template <class Image
>
246 struct WXDLLEXPORT wxPixelDataOut
248 template <class PixelFormat
>
249 class WXDLLEXPORT wxPixelDataIn
256 // wxPixelData specialization for wxImage: this is the simplest case as we
257 // don't have to care about different pixel formats here
259 struct WXDLLEXPORT wxPixelDataOut
<wxImage
>
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
266 // the type of the class we're working with
267 typedef wxImage ImageType
;
269 // the iterator which should be used for working with data in this
274 // the pixel format we use
275 typedef wxImagePixelFormat PixelFormat
;
277 // the type of the pixel components
278 typedef typename
dummyPixelFormat::ChannelType ChannelType
;
280 // the pixel data we're working with
282 wxPixelDataOut
<wxImage
>::wxPixelDataIn
<PixelFormat
> PixelData
;
285 void Reset(const PixelData
& data
)
287 *this = data
.GetPixels();
290 // creates the iterator pointing to the beginning of data
291 Iterator(PixelData
& data
)
296 // creates the iterator initially pointing to the image origin
297 Iterator(const wxImage
& image
)
299 m_pRGB
= image
.GetData();
301 if ( image
.HasAlpha() )
303 m_pAlpha
= image
.GetAlpha();
305 else // alpha is not used at all
311 // true if the iterator is valid
312 bool IsOk() const { return m_pRGB
!= NULL
; }
318 // advance the iterator to the next pixel, prefix version
319 Iterator
& operator++()
321 m_pRGB
+= PixelFormat::SizePixel
;
323 m_pAlpha
+= PixelFormat::SizePixel
;
328 // postfix (hence less efficient -- don't use it unless you
329 // absolutely must) version
330 Iterator
operator++(int)
337 // move x pixels to the right and y down
339 // note that the rows don't wrap!
340 void Offset(const PixelData
& data
, int x
, int y
)
342 m_pRGB
+= data
.GetRowStride()*y
+ PixelFormat::SizePixel
*x
;
344 m_pAlpha
+= data
.GetWidth() + x
;
347 // move x pixels to the right (again, no row wrapping)
348 void OffsetX(const PixelData
& WXUNUSED(data
), int x
)
350 m_pRGB
+= PixelFormat::SizePixel
*x
;
355 // move y rows to the bottom
356 void OffsetY(const PixelData
& data
, int y
)
358 m_pRGB
+= data
.GetRowStride()*y
;
360 m_pAlpha
+= data
.GetWidth();
363 // go to the given position
364 void MoveTo(const PixelData
& data
, int x
, int y
)
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
; }
380 // private: -- see comment in the beginning of the file
382 // pointer into RGB buffer
383 unsigned char *m_pRGB
;
385 // pointer into alpha buffer or NULL if alpha isn't used
386 unsigned char *m_pAlpha
;
389 // initializes us with the data of the given image
390 wxPixelDataIn(ImageType
& image
) : m_image(image
), m_pixels(image
)
392 m_width
= image
.GetWidth();
393 m_height
= image
.GetHeight();
394 m_stride
= Iterator::SizePixel
* m_width
;
397 // initializes us with the given region of the specified image
398 wxPixelDataIn(ImageType
& image
,
400 const wxSize
& sz
) : m_image(image
), m_pixels(image
)
402 m_stride
= Iterator::SizePixel
* m_width
;
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
)
411 m_stride
= Iterator::SizePixel
* m_width
;
413 InitRect(rect
.GetPositions(), rect
.GetSize());
416 // we evaluate to true only if we could get access to bitmap data
418 operator bool() const { return m_pixels
.IsOk(); }
420 // get the iterator pointing to the origin
421 Iterator
GetPixels() const { return m_pixels
; }
424 void InitRect(const wxPoint
& pt
, const wxSize
& sz
)
430 m_pixels
.Offset(*this, pt
.x
, pt
.y
);
433 // the image we're working with
436 // the iterator pointing to the image origin
441 // wxPixelData specialization for wxBitmap: here things are more interesting as
442 // we also have to support different pixel formats
444 struct WXDLLEXPORT wxPixelDataOut
<wxBitmap
>
446 template <class Format
>
447 class WXDLLEXPORT wxPixelDataIn
: public wxPixelDataBase
450 // the type of the class we're working with
451 typedef wxBitmap ImageType
;
456 // the pixel format we use
457 typedef Format PixelFormat
;
459 // the type of the pixel components
460 typedef typename
PixelFormat::ChannelType ChannelType
;
462 // the pixel data we're working with
463 typedef wxPixelDataOut
<wxBitmap
>::wxPixelDataIn
<Format
> PixelData
;
467 void Reset(const PixelData
& data
)
469 *this = data
.GetPixels();
472 // initializes the iterator to point to the origin of the given
474 Iterator(PixelData
& data
)
479 // initializes the iterator to point to the origin of the given
481 Iterator(wxBitmap
& bmp
, PixelData
& data
)
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
);
492 // return true if this iterator is valid
493 bool IsOk() const { return m_ptr
!= NULL
; }
499 // advance the iterator to the next pixel, prefix version
500 Iterator
& operator++()
502 m_ptr
+= PixelFormat::SizePixel
;
507 // postfix (hence less efficient -- don't use it unless you
508 // absolutely must) version
509 Iterator
operator++(int)
516 // move x pixels to the right and y down
518 // note that the rows don't wrap!
519 void Offset(const PixelData
& data
, int x
, int y
)
521 m_ptr
+= data
.GetRowStride()*y
+ PixelFormat::SizePixel
*x
;
524 // move x pixels to the right (again, no row wrapping)
525 void OffsetX(const PixelData
& WXUNUSED(data
), int x
)
527 m_ptr
+= PixelFormat::SizePixel
*x
;
530 // move y rows to the bottom
531 void OffsetY(const PixelData
& data
, int y
)
533 m_ptr
+= data
.GetRowStride()*y
;
536 // go to the given position
537 void MoveTo(const PixelData
& data
, int x
, int y
)
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
]; }
553 // address the pixel contents directly
555 // warning: the format is platform dependent
556 typename
PixelFormat::PixelType
& Data()
557 { return *(typename
PixelFormat::PixelType
*)m_ptr
; }
559 // private: -- see comment in the beginning of the file
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
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
572 wxPixelDataIn(wxBitmap
& bmp
) : m_bmp(bmp
), m_pixels(bmp
, *this)
576 wxPixelDataIn(wxBitmap
& bmp
, const wxRect
& rect
)
577 : m_bmp(bmp
), m_pixels(bmp
, *this)
579 InitRect(rect
.GetPositions(), rect
.GetSize());
582 wxPixelDataIn(wxBitmap
& bmp
, const wxPoint
& pt
, const wxSize
& sz
)
583 : m_bmp(bmp
), m_pixels(bmp
, *this)
588 // we evaluate to true only if we could get access to bitmap data
590 operator bool() const { return m_pixels
.IsOk(); }
592 // get the iterator pointing to the origin
593 Iterator
GetPixels() const { return m_pixels
; }
595 // dtor unlocks the bitmap
598 m_bmp
.UngetRawData(*this);
601 // call this to indicate that we should use the alpha channel
602 void UseAlpha() { m_bmp
.UseAlpha(); }
604 // private: -- see comment in the beginning of the file
606 // the bitmap we're associated with
609 // the iterator pointing to the image origin
613 void InitRect(const wxPoint
& pt
, const wxSize
& sz
)
615 m_pixels
.Offset(*this, pt
.x
, pt
.y
);
624 template <class Image
, class PixelFormat
= wxPixelFormatFor
<Image
> >
626 public wxPixelDataOut
<Image
>::template wxPixelDataIn
<PixelFormat
>
629 wxPixelData(Image
& image
)
630 : wxPixelDataOut
<Image
>::template wxPixelDataIn
<PixelFormat
>(image
)
634 wxPixelData(Image
& i
, const wxPoint
& pt
, const wxSize
& sz
)
635 : wxPixelDataOut
<Image
>::template wxPixelDataIn
<PixelFormat
>(i
, pt
, sz
)
639 wxPixelData(Image
& i
, const wxRect
& rect
)
640 : wxPixelDataOut
<Image
>::template wxPixelDataIn
<PixelFormat
>(i
, rect
)
645 // some "predefined" pixel data classes
646 typedef wxPixelData
<wxImage
> wxImagePixelData
;
647 typedef wxPixelData
<wxBitmap
, wxNativePixelFormat
> wxNativePixelData
;
648 typedef wxPixelData
<wxBitmap
, wxAlphaPixelFormat
> wxAlphaPixelData
;
650 // ----------------------------------------------------------------------------
652 // ----------------------------------------------------------------------------
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
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.
666 template < class Image
, class PixelFormat
= wxPixelFormatFor
<Image
> >
667 struct WXDLLEXPORT wxPixelIterator
: wxPixelData
<Image
, PixelFormat
>::Iterator
672 #pragma warning(default: 4355)
675 #endif // _WX_RAWBMP_H_BASE_