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