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)
104 #ifdef __DIGITALMARS__
105 template <class Channel
,
106 size_t Bpp
, int R
, int G
, int B
, int A
= -1,
107 class Pixel
= wxUint32
>
109 template <typename Channel
,
110 size_t Bpp
, int R
, int G
, int B
, int A
= -1,
111 typename Pixel
= wxUint32
>
114 struct WXDLLEXPORT wxPixelFormat
116 // iterator over pixels is usually of type "ChannelType *"
117 typedef Channel ChannelType
;
119 // the type which may hold the entire pixel value
120 typedef Pixel PixelType
;
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
125 // size of one pixel in bits
126 enum { BitsPerPixel
= Bpp
};
128 // size of one pixel in ChannelType units (usually bytes)
129 enum { SizePixel
= BitsPerPixel
/ (8 * sizeof(ChannelType
)) };
131 // the channels indices inside the pixel
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 };
145 // some "predefined" pixel formats
146 // -------------------------------
148 // wxImage format is common to all platforms
149 typedef wxPixelFormat
<unsigned char, 24, 0, 1, 2> wxImagePixelFormat
;
151 // the (most common) native bitmap format without alpha support
152 typedef wxPixelFormat
<unsigned char, 24,
157 #endif // __WXMSW__/!__WXMSW__
158 > wxNativePixelFormat
;
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
;
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
;
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
175 struct WXDLLEXPORT wxPixelFormatFor
<wxImage
>
177 typedef wxImagePixelFormat Format
;
180 // ----------------------------------------------------------------------------
182 // ----------------------------------------------------------------------------
185 wxPixelDataBase is just a helper for wxPixelData: it contains things common
186 to both wxImage and wxBitmap specializations.
188 class WXDLLEXPORT wxPixelDataBase
191 // origin of the rectangular region we represent
192 wxPoint
GetOrigin() const { return m_ptOrigin
; }
194 // width and height of the region we represent
195 int GetWidth() const { return m_width
; }
196 int GetHeight() const { return m_height
; }
198 // the distance between two rows
199 int GetRowStride() const { return m_stride
; }
201 // private: -- see comment in the beginning of the file
203 // the origin of this image inside the bigger bitmap (usually (0, 0))
206 // the size of the image we address, in pixels
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
219 // ctor is protected because this class is only meant to be used as the
220 // base class by wxPixelData
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.
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.
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.
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
252 // we need to define this skeleton template to mollify VC++
253 template <class Image
>
254 struct WXDLLEXPORT wxPixelDataOut
256 template <class PixelFormat
>
257 class WXDLLEXPORT wxPixelDataIn
264 // wxPixelData specialization for wxImage: this is the simplest case as we
265 // don't have to care about different pixel formats here
267 struct WXDLLEXPORT wxPixelDataOut
<wxImage
>
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
274 // the type of the class we're working with
275 typedef wxImage ImageType
;
277 // the iterator which should be used for working with data in this
282 // the pixel format we use
283 typedef wxImagePixelFormat PixelFormat
;
285 // the type of the pixel components
286 typedef typename
dummyPixelFormat::ChannelType ChannelType
;
288 // the pixel data we're working with
290 wxPixelDataOut
<wxImage
>::wxPixelDataIn
<PixelFormat
> PixelData
;
293 void Reset(const PixelData
& data
)
295 *this = data
.GetPixels();
298 // creates the iterator pointing to the beginning of data
299 Iterator(PixelData
& data
)
304 // creates the iterator initially pointing to the image origin
305 Iterator(const wxImage
& image
)
307 m_pRGB
= image
.GetData();
309 if ( image
.HasAlpha() )
311 m_pAlpha
= image
.GetAlpha();
313 else // alpha is not used at all
319 // true if the iterator is valid
320 bool IsOk() const { return m_pRGB
!= NULL
; }
326 // advance the iterator to the next pixel, prefix version
327 Iterator
& operator++()
329 m_pRGB
+= PixelFormat::SizePixel
;
331 m_pAlpha
+= PixelFormat::SizePixel
;
336 // postfix (hence less efficient -- don't use it unless you
337 // absolutely must) version
338 Iterator
operator++(int)
345 // move x pixels to the right and y down
347 // note that the rows don't wrap!
348 void Offset(const PixelData
& data
, int x
, int y
)
350 m_pRGB
+= data
.GetRowStride()*y
+ PixelFormat::SizePixel
*x
;
352 m_pAlpha
+= data
.GetWidth() + x
;
355 // move x pixels to the right (again, no row wrapping)
356 void OffsetX(const PixelData
& WXUNUSED(data
), int x
)
358 m_pRGB
+= PixelFormat::SizePixel
*x
;
363 // move y rows to the bottom
364 void OffsetY(const PixelData
& data
, int y
)
366 m_pRGB
+= data
.GetRowStride()*y
;
368 m_pAlpha
+= data
.GetWidth();
371 // go to the given position
372 void MoveTo(const PixelData
& data
, int x
, int y
)
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
; }
388 // private: -- see comment in the beginning of the file
390 // pointer into RGB buffer
391 unsigned char *m_pRGB
;
393 // pointer into alpha buffer or NULL if alpha isn't used
394 unsigned char *m_pAlpha
;
397 // initializes us with the data of the given image
398 wxPixelDataIn(ImageType
& image
) : m_image(image
), m_pixels(image
)
400 m_width
= image
.GetWidth();
401 m_height
= image
.GetHeight();
402 m_stride
= Iterator::SizePixel
* m_width
;
405 // initializes us with the given region of the specified image
406 wxPixelDataIn(ImageType
& image
,
408 const wxSize
& sz
) : m_image(image
), m_pixels(image
)
410 m_stride
= Iterator::SizePixel
* m_width
;
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
)
419 m_stride
= Iterator::SizePixel
* m_width
;
421 InitRect(rect
.GetPositions(), rect
.GetSize());
424 // we evaluate to true only if we could get access to bitmap data
426 operator bool() const { return m_pixels
.IsOk(); }
428 // get the iterator pointing to the origin
429 Iterator
GetPixels() const { return m_pixels
; }
432 void InitRect(const wxPoint
& pt
, const wxSize
& sz
)
438 m_pixels
.Offset(*this, pt
.x
, pt
.y
);
441 // the image we're working with
444 // the iterator pointing to the image origin
449 // wxPixelData specialization for wxBitmap: here things are more interesting as
450 // we also have to support different pixel formats
452 struct WXDLLEXPORT wxPixelDataOut
<wxBitmap
>
454 template <class Format
>
455 class WXDLLEXPORT wxPixelDataIn
: public wxPixelDataBase
458 // the type of the class we're working with
459 typedef wxBitmap ImageType
;
464 // the pixel format we use
465 typedef Format PixelFormat
;
467 // the type of the pixel components
468 typedef typename
PixelFormat::ChannelType ChannelType
;
470 // the pixel data we're working with
471 typedef wxPixelDataOut
<wxBitmap
>::wxPixelDataIn
<Format
> PixelData
;
475 void Reset(const PixelData
& data
)
477 *this = data
.GetPixels();
480 // initializes the iterator to point to the origin of the given
482 Iterator(PixelData
& data
)
487 // initializes the iterator to point to the origin of the given
489 Iterator(wxBitmap
& bmp
, PixelData
& data
)
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
);
500 // return true if this iterator is valid
501 bool IsOk() const { return m_ptr
!= NULL
; }
507 // advance the iterator to the next pixel, prefix version
508 Iterator
& operator++()
510 m_ptr
+= PixelFormat::SizePixel
;
515 // postfix (hence less efficient -- don't use it unless you
516 // absolutely must) version
517 Iterator
operator++(int)
524 // move x pixels to the right and y down
526 // note that the rows don't wrap!
527 void Offset(const PixelData
& data
, int x
, int y
)
529 m_ptr
+= data
.GetRowStride()*y
+ PixelFormat::SizePixel
*x
;
532 // move x pixels to the right (again, no row wrapping)
533 void OffsetX(const PixelData
& WXUNUSED(data
), int x
)
535 m_ptr
+= PixelFormat::SizePixel
*x
;
538 // move y rows to the bottom
539 void OffsetY(const PixelData
& data
, int y
)
541 m_ptr
+= data
.GetRowStride()*y
;
544 // go to the given position
545 void MoveTo(const PixelData
& data
, int x
, int y
)
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
]; }
561 // address the pixel contents directly
563 // warning: the format is platform dependent
564 typename
PixelFormat::PixelType
& Data()
565 { return *(typename
PixelFormat::PixelType
*)m_ptr
; }
567 // private: -- see comment in the beginning of the file
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
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
580 wxPixelDataIn(wxBitmap
& bmp
) : m_bmp(bmp
), m_pixels(bmp
, *this)
584 wxPixelDataIn(wxBitmap
& bmp
, const wxRect
& rect
)
585 : m_bmp(bmp
), m_pixels(bmp
, *this)
587 InitRect(rect
.GetPositions(), rect
.GetSize());
590 wxPixelDataIn(wxBitmap
& bmp
, const wxPoint
& pt
, const wxSize
& sz
)
591 : m_bmp(bmp
), m_pixels(bmp
, *this)
596 // we evaluate to true only if we could get access to bitmap data
598 operator bool() const { return m_pixels
.IsOk(); }
600 // get the iterator pointing to the origin
601 Iterator
GetPixels() const { return m_pixels
; }
603 // dtor unlocks the bitmap
606 m_bmp
.UngetRawData(*this);
609 // call this to indicate that we should use the alpha channel
610 void UseAlpha() { m_bmp
.UseAlpha(); }
612 // private: -- see comment in the beginning of the file
614 // the bitmap we're associated with
617 // the iterator pointing to the image origin
621 void InitRect(const wxPoint
& pt
, const wxSize
& sz
)
623 m_pixels
.Offset(*this, pt
.x
, pt
.y
);
632 #ifdef __DIGITALMARS__
633 template <class Image
, class PixelFormat
= wxPixelFormatFor
<Image
> >
635 public wxPixelDataOut
<Image
>:: wxPixelDataIn
<PixelFormat
>
638 wxPixelData(Image
& image
)
639 : wxPixelDataOut
<Image
>:: wxPixelDataIn
<PixelFormat
>(image
)
643 wxPixelData(Image
& i
, const wxPoint
& pt
, const wxSize
& sz
)
644 : wxPixelDataOut
<Image
>:: wxPixelDataIn
<PixelFormat
>(i
, pt
, sz
)
648 wxPixelData(Image
& i
, const wxRect
& rect
)
649 : wxPixelDataOut
<Image
>:: wxPixelDataIn
<PixelFormat
>(i
, rect
)
653 #else // not __DIGITALMARS__
654 template <class Image
, class PixelFormat
= wxPixelFormatFor
<Image
> >
656 public wxPixelDataOut
<Image
>::template wxPixelDataIn
<PixelFormat
>
659 wxPixelData(Image
& image
)
660 : wxPixelDataOut
<Image
>::template wxPixelDataIn
<PixelFormat
>(image
)
664 wxPixelData(Image
& i
, const wxPoint
& pt
, const wxSize
& sz
)
665 : wxPixelDataOut
<Image
>::template wxPixelDataIn
<PixelFormat
>(i
, pt
, sz
)
669 wxPixelData(Image
& i
, const wxRect
& rect
)
670 : wxPixelDataOut
<Image
>::template wxPixelDataIn
<PixelFormat
>(i
, rect
)
674 #endif // __DIGITALMARS__
676 // some "predefined" pixel data classes
677 typedef wxPixelData
<wxImage
> wxImagePixelData
;
678 typedef wxPixelData
<wxBitmap
, wxNativePixelFormat
> wxNativePixelData
;
679 typedef wxPixelData
<wxBitmap
, wxAlphaPixelFormat
> wxAlphaPixelData
;
681 // ----------------------------------------------------------------------------
683 // ----------------------------------------------------------------------------
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
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.
697 template < class Image
, class PixelFormat
= wxPixelFormatFor
<Image
> >
698 struct WXDLLEXPORT wxPixelIterator
: wxPixelData
<Image
, PixelFormat
>::Iterator
703 #pragma warning(default: 4355)
706 #endif // _WX_RAWBMP_H_BASE_