]> git.saurik.com Git - wxWidgets.git/blob - include/wx/rawbmp.h
MinGW compilation fix.
[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 int GetWidth() const { return m_width; }
184 int GetHeight() const { return m_height; }
185 int GetRowStride() const { return m_stride; }
186
187 // private: -- see comment in the beginning of the file
188
189 // the size of the image we address, in pixels
190 int m_width,
191 m_height;
192
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
199 int m_stride;
200
201 protected:
202 // ctor is protected because this class is only meant to be used as the
203 // base class by wxPixelData
204 wxPixelDataBase()
205 {
206 m_width =
207 m_height =
208 m_stride = 0;
209 }
210 };
211
212 /*
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.
216
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.
222
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.
228
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
232 specializations.
233 */
234
235 // we need to define this skeleton template to mollify VC++
236 template <class Image>
237 struct WXDLLEXPORT wxPixelDataOut
238 {
239 template <class PixelFormat>
240 class WXDLLEXPORT wxPixelDataIn
241 {
242 public:
243 class Iterator { };
244 };
245 };
246
247 // wxPixelData specialization for wxImage: this is the simplest case as we
248 // don't have to care about different pixel formats here
249 template <>
250 struct WXDLLEXPORT wxPixelDataOut<wxImage>
251 {
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
256 {
257 // the type of the class we're working with
258 typedef wxImage ImageType;
259
260 // the iterator which should be used for working with data in this
261 // format
262 class Iterator
263 {
264 public:
265 // the pixel format we use
266 typedef wxImagePixelFormat PixelFormat;
267
268 // the type of the pixel components
269 typedef typename PixelFormat::ChannelType ChannelType;
270
271 // the pixel data we're working with
272 typedef
273 wxPixelDataOut<wxImage>::wxPixelDataIn<PixelFormat> PixelData;
274
275 // go back to (0, 0)
276 void Reset(const PixelData& data)
277 {
278 *this = data.GetPixels();
279 }
280
281 // creates the iterator pointing to the beginning of data
282 Iterator(PixelData& data)
283 {
284 Reset(data);
285 }
286
287 // creates the iterator initially pointing to the image origin
288 Iterator(const wxImage& image)
289 {
290 m_pRGB = image.GetData();
291
292 if ( image.HasAlpha() )
293 {
294 m_pAlpha = image.GetAlpha();
295 }
296 else // alpha is not used at all
297 {
298 m_pAlpha = NULL;
299 }
300 }
301
302 // true if the iterator is valid
303 bool IsOk() const { return m_pRGB != NULL; }
304
305
306 // navigation
307 // ----------
308
309 // advance the iterator to the next pixel, prefix version
310 Iterator& operator++()
311 {
312 m_pRGB += PixelFormat::SizePixel;
313 if ( m_pAlpha )
314 m_pAlpha += PixelFormat::SizePixel;
315
316 return *this;
317 }
318
319 // postfix (hence less efficient -- don't use unless you must) version
320 Iterator operator++(int)
321 {
322 Iterator p(*this);
323 ++*this;
324 return p;
325 }
326
327 // move x pixels to the right and y down
328 //
329 // note that the rows don't wrap!
330 void Offset(const PixelData& data, int x, int y)
331 {
332 m_pRGB += data.GetRowStride()*y + PixelFormat::SizePixel*x;
333 if ( m_pAlpha )
334 m_pAlpha += data.GetWidth() + x;
335 }
336
337 // move x pixels to the right (again, no row wrapping)
338 void OffsetX(const PixelData& WXUNUSED(data), int x)
339 {
340 m_pRGB += PixelFormat::SizePixel*x;
341 if ( m_pAlpha )
342 m_pAlpha += x;
343 }
344
345 // move y rows to the bottom
346 void OffsetY(const PixelData& data, int y)
347 {
348 m_pRGB += data.GetRowStride()*y;
349 if ( m_pAlpha )
350 m_pAlpha += data.GetWidth();
351 }
352
353 // go to the given position
354 void MoveTo(const PixelData& data, int x, int y)
355 {
356 Reset(data);
357 Offset(data, x, y);
358 }
359
360
361 // data access
362 // -----------
363
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; }
369
370 // private: -- see comment in the beginning of the file
371
372 // pointer into RGB buffer
373 unsigned char *m_pRGB;
374
375 // pointer into alpha buffer or NULL if alpha isn't used
376 unsigned char *m_pAlpha;
377 };
378
379 // initializes us with the data of the given image
380 wxPixelDataIn(ImageType& image) : m_image(image), m_pixels(image)
381 {
382 m_width = image.GetWidth();
383 m_height = image.GetHeight();
384 m_stride = Iterator::SizePixel * m_width;
385 }
386
387 // we evaluate to true only if we could get access to bitmap data
388 // successfully
389 operator bool() const { return m_pixels.IsOk(); }
390
391 // get the iterator pointing to the origin
392 Iterator GetPixels() const { return m_pixels; }
393
394 private:
395 // the image we're working with
396 ImageType& m_image;
397
398 // the iterator pointing to the image origin
399 Iterator m_pixels;
400 };
401 };
402
403 // wxPixelData specialization for wxBitmap: here things are more interesting as
404 // we also have to support different pixel formats
405 template <>
406 struct WXDLLEXPORT wxPixelDataOut<wxBitmap>
407 {
408 template <class Format>
409 class WXDLLEXPORT wxPixelDataIn : public wxPixelDataBase
410 {
411 public:
412 // the type of the class we're working with
413 typedef wxBitmap ImageType;
414
415 class Iterator
416 {
417 public:
418 // the pixel format we use
419 typedef Format PixelFormat;
420
421 // the type of the pixel components
422 typedef typename PixelFormat::ChannelType ChannelType;
423
424 // the pixel data we're working with
425 typedef wxPixelDataOut<wxBitmap>::wxPixelDataIn<Format> PixelData;
426
427
428 // go back to (0, 0)
429 void Reset(const PixelData& data)
430 {
431 *this = data.GetPixels();
432 }
433
434 // initializes the iterator to point to the origin of the given pixel
435 // data
436 Iterator(PixelData& data)
437 {
438 Reset(data);
439 }
440
441 // initializes the iterator to point to the origin of the given bitmap
442 Iterator(wxBitmap& bmp, PixelData& data)
443 {
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
448 // undesirable
449 m_ptr = (ChannelType *)
450 bmp.GetRawData(data, PixelFormat::BitsPerPixel);
451 }
452
453 // return true if this iterator is valid
454 bool IsOk() const { return m_ptr != NULL; }
455
456
457 // navigation
458 // ----------
459
460 // advance the iterator to the next pixel, prefix version
461 Iterator& operator++()
462 {
463 m_ptr += PixelFormat::SizePixel;
464
465 return *this;
466 }
467
468 // postfix (hence less efficient -- don't use unless you must) version
469 Iterator operator++(int)
470 {
471 Iterator p(*this);
472 ++*this;
473 return p;
474 }
475
476 // move x pixels to the right and y down
477 //
478 // note that the rows don't wrap!
479 void Offset(const PixelData& data, int x, int y)
480 {
481 m_ptr += data.GetRowStride()*y + PixelFormat::SizePixel*x;
482 }
483
484 // move x pixels to the right (again, no row wrapping)
485 void OffsetX(const PixelData& WXUNUSED(data), int x)
486 {
487 m_ptr += PixelFormat::SizePixel*x;
488 }
489
490 // move y rows to the bottom
491 void OffsetY(const PixelData& data, int y)
492 {
493 m_ptr += data.GetRowStride()*y;
494 }
495
496 // go to the given position
497 void MoveTo(const PixelData& data, int x, int y)
498 {
499 Reset(data);
500 Offset(data, x, y);
501 }
502
503
504 // data access
505 // -----------
506
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]; }
512
513 // address the pixel contents directly
514 //
515 // warning: the format is platform dependent
516 typename PixelFormat::PixelType& Data()
517 { return *(typename PixelFormat::PixelType *)m_ptr; }
518
519 // private: -- see comment in the beginning of the file
520
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
524 ChannelType *m_ptr;
525 };
526
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)
531 {
532 }
533
534 // we evaluate to true only if we could get access to bitmap data
535 // successfully
536 operator bool() const { return m_pixels.IsOk(); }
537
538 // get the iterator pointing to the origin
539 Iterator GetPixels() const { return m_pixels; }
540
541 // dtor unlocks the bitmap
542 ~wxPixelDataIn()
543 {
544 m_bmp.UngetRawData(*this);
545 }
546
547 // call this to indicate that we should use the alpha channel
548 void UseAlpha() { m_bmp.UseAlpha(); }
549
550 // private: -- see comment in the beginning of the file
551
552 // the bitmap we're associated with
553 wxBitmap m_bmp;
554
555 // the iterator pointing to the image origin
556 Iterator m_pixels;
557 };
558 };
559
560 template <class Image, class PixelFormat = wxPixelFormatFor<Image> >
561 class wxPixelData :
562 public wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>
563 {
564 public:
565 wxPixelData(const Image& image)
566 : wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>(image)
567 {
568 }
569 };
570
571 // some "predefined" pixel data classes
572 typedef wxPixelData<wxImage> wxImagePixelData;
573 typedef wxPixelData<wxBitmap, wxNativePixelFormat> wxNativePixelData;
574 typedef wxPixelData<wxBitmap, wxAlphaPixelFormat> wxAlphaPixelData;
575
576 // ----------------------------------------------------------------------------
577 // wxPixelIterator
578 // ----------------------------------------------------------------------------
579
580 /*
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
585 formats.
586
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.
591 */
592 template < class Image, class PixelFormat = wxPixelFormatFor<Image> >
593 struct WXDLLEXPORT wxPixelIterator : wxPixelData<Image, PixelFormat>::Iterator
594 {
595 };
596
597 #ifdef __VISUALC__
598 #pragma warning(default: 4355)
599 #endif
600
601 #endif // _WX_RAWBMP_H_BASE_
602