]> git.saurik.com Git - wxWidgets.git/blame_incremental - include/wx/rawbmp.h
Don't define __STRICT_ANSI__, we should build both with and without it.
[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// Copyright: (c) 2002 Vadim Zeitlin <vadim@wxwidgets.org>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11#ifndef _WX_RAWBMP_H_
12#define _WX_RAWBMP_H_
13
14#include "wx/defs.h"
15
16#ifdef wxHAS_RAW_BITMAP
17
18#include "wx/image.h"
19#include "wx/bitmap.h"
20
21// ----------------------------------------------------------------------------
22// Abstract Pixel API
23//
24// We need to access our raw bitmap data (1) portably and (2) efficiently.
25// We do this using a two-dimensional "iteration" interface. Performance
26// is extremely important here: these functions will be called hundreds
27// of thousands of times in a row, and even small inefficiencies will
28// make applications seem slow.
29//
30// We can't always rely on inline functions, because not all compilers actually
31// bother to inline them unless we crank the optimization levels way up.
32// Therefore, we also provide macros to wring maximum speed out of compiler
33// unconditionally (e.g. even in debug builds). Of course, if the performance
34// isn't absolutely crucial for you you shouldn't be using them but the inline
35// functions instead.
36// ----------------------------------------------------------------------------
37
38/*
39 Usage example:
40
41 typedef wxPixelData<wxBitmap, wxNativePixelFormat> PixelData;
42
43 wxBitmap bmp;
44 PixelData data(bmp);
45 if ( !data )
46 {
47 ... raw access to bitmap data unavailable, do something else ...
48 return;
49 }
50
51 if ( data.GetWidth() < 20 || data.GetHeight() < 20 )
52 {
53 ... complain: the bitmap it too small ...
54 return;
55 }
56
57 PixelData::Iterator p(data);
58
59 // we draw a (10, 10)-(20, 20) rect manually using the given r, g, b
60 p.Offset(data, 10, 10);
61
62 for ( int y = 0; y < 10; ++y )
63 {
64 PixelData::Iterator rowStart = p;
65
66 for ( int x = 0; x < 10; ++x, ++p )
67 {
68 p.Red() = r;
69 p.Green() = g;
70 p.Blue() = b;
71 }
72
73 p = rowStart;
74 p.OffsetY(data, 1);
75 }
76 */
77
78/*
79 Note: we do not use WXDLLIMPEXP_CORE with classes in this file because VC++ has
80 problems with exporting inner class defined inside a specialization of a
81 template class from a DLL. Besides, as all the methods are inline it's not
82 really necessary to put them in DLL at all.
83 */
84
85// ----------------------------------------------------------------------------
86// wxPixelFormat
87// ----------------------------------------------------------------------------
88
89/*
90 wxPixelFormat is a template class describing the bitmap data format. It
91 contains the constants describing the format of pixel data, but does not
92 describe how the entire bitmap is stored (i.e. top-to-bottom,
93 bottom-to-top, ...). It is also a "traits"-like class, i.e. it only
94 contains some constants and maybe static methods but nothing more, so it
95 can be safely used without incurring any overhead as all accesses to it are
96 done at compile-time.
97
98 Current limitations: we don't support RAGABA and ARAGAB formats supported
99 by Mac OS X. If there is sufficient interest, these classes could be
100 extended to deal with them. Neither do we support alpha channel having
101 different representation from the RGB ones (happens under QNX/Photon I
102 think), but again this could be achieved with some small extra effort.
103
104 Template parameters are:
105 - type of a single pixel component
106 - size of the single pixel in bits
107 - indices of red, green and blue pixel components inside the pixel
108 - index of the alpha component or -1 if none
109 - type which can contain the full pixel value (all channels)
110 */
111
112template <class Channel,
113 size_t Bpp, int R, int G, int B, int A = -1,
114 class Pixel = wxUint32>
115
116struct wxPixelFormat
117{
118 // iterator over pixels is usually of type "ChannelType *"
119 typedef Channel ChannelType;
120
121 // the type which may hold the entire pixel value
122 typedef Pixel PixelType;
123
124 // NB: using static ints initialized inside the class declaration is not
125 // portable as it doesn't work with VC++ 6, so we must use enums
126
127 // size of one pixel in bits
128 enum { BitsPerPixel = Bpp };
129
130 // size of one pixel in ChannelType units (usually bytes)
131 enum { SizePixel = Bpp / (8 * sizeof(Channel)) };
132
133 // the channels indices inside the pixel
134 enum
135 {
136 RED = R,
137 GREEN = G,
138 BLUE = B,
139 ALPHA = A
140 };
141
142 // true if we have an alpha channel (together with the other channels, this
143 // doesn't cover the case of wxImage which stores alpha separately)
144 enum { HasAlpha = A != -1 };
145};
146
147// some "predefined" pixel formats
148// -------------------------------
149
150// wxImage format is common to all platforms
151typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxImagePixelFormat;
152
153// the (most common) native bitmap format without alpha support
154#if defined(__WXMSW__)
155 // under MSW the RGB components are reversed, they're in BGR order
156 typedef wxPixelFormat<unsigned char, 24, 2, 1, 0> wxNativePixelFormat;
157
158 #define wxPIXEL_FORMAT_ALPHA 3
159#elif defined(__WXMAC__)
160 // under Mac, first component is unused but still present, hence we use
161 // 32bpp, not 24
162 typedef wxPixelFormat<unsigned char, 32, 1, 2, 3> wxNativePixelFormat;
163
164 #define wxPIXEL_FORMAT_ALPHA 0
165#elif defined(__WXCOCOA__)
166 // Cocoa is standard RGB or RGBA (normally it is RGBA)
167 typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxNativePixelFormat;
168
169 #define wxPIXEL_FORMAT_ALPHA 3
170#elif defined(__WXGTK__)
171 // Under GTK+ 2.X we use GdkPixbuf, which is standard RGB or RGBA
172 typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxNativePixelFormat;
173
174 #define wxPIXEL_FORMAT_ALPHA 3
175#elif defined(__WXPM__)
176 // Under PM, we can use standard RGB or RGBA
177 typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxNativePixelFormat;
178
179 #define wxPIXEL_FORMAT_ALPHA 3
180#elif defined(__WXDFB__)
181 // Under DirectFB, RGB components are reversed, they're in BGR order
182 typedef wxPixelFormat<unsigned char, 24, 2, 1, 0> wxNativePixelFormat;
183
184 #define wxPIXEL_FORMAT_ALPHA 3
185#endif
186
187// the (most common) native format for bitmaps with alpha channel
188#ifdef wxPIXEL_FORMAT_ALPHA
189 typedef wxPixelFormat<unsigned char, 32,
190 wxNativePixelFormat::RED,
191 wxNativePixelFormat::GREEN,
192 wxNativePixelFormat::BLUE,
193 wxPIXEL_FORMAT_ALPHA> wxAlphaPixelFormat;
194#endif // wxPIXEL_FORMAT_ALPHA
195
196// we also define the (default/best) pixel format for the given class: this is
197// used as default value for the pixel format in wxPixelIterator template
198template <class T> struct wxPixelFormatFor;
199
200#if wxUSE_IMAGE
201// wxPixelFormatFor is only defined for wxImage, attempt to use it with other
202// classes (wxBitmap...) will result in compile errors which is exactly what we
203// want
204template <>
205struct wxPixelFormatFor<wxImage>
206{
207 typedef wxImagePixelFormat Format;
208};
209#endif //wxUSE_IMAGE
210
211// ----------------------------------------------------------------------------
212// wxPixelData
213// ----------------------------------------------------------------------------
214
215/*
216 wxPixelDataBase is just a helper for wxPixelData: it contains things common
217 to both wxImage and wxBitmap specializations.
218 */
219class wxPixelDataBase
220{
221public:
222 // origin of the rectangular region we represent
223 wxPoint GetOrigin() const { return m_ptOrigin; }
224
225 // width and height of the region we represent
226 int GetWidth() const { return m_width; }
227 int GetHeight() const { return m_height; }
228
229 wxSize GetSize() const { return wxSize(m_width, m_height); }
230
231 // the distance between two rows
232 int GetRowStride() const { return m_stride; }
233
234// private: -- see comment in the beginning of the file
235
236 // the origin of this image inside the bigger bitmap (usually (0, 0))
237 wxPoint m_ptOrigin;
238
239 // the size of the image we address, in pixels
240 int m_width,
241 m_height;
242
243 // this parameter is the offset of the start of the (N+1)st row from the
244 // Nth one and can be different from m_bypp*width in some cases:
245 // a) the most usual one is to force 32/64 bit alignment of rows
246 // b) another one is for bottom-to-top images where it's negative
247 // c) finally, it could conceivably be 0 for the images with all
248 // lines being identical
249 int m_stride;
250
251protected:
252 // ctor is protected because this class is only meant to be used as the
253 // base class by wxPixelData
254 wxPixelDataBase()
255 {
256 m_width =
257 m_height =
258 m_stride = 0;
259 }
260};
261
262/*
263 wxPixelData represents the entire bitmap data, i.e. unlike
264 wxPixelFormat (which it uses) it also stores the global bitmap
265 characteristics such as its size, inter-row separation and so on.
266
267 Because of this it can be used to move the pixel iterators (which don't
268 have enough information about the bitmap themselves). This may seem a bit
269 unnatural but must be done in this way to keep the iterator objects as
270 small as possible for maximum efficiency as otherwise they wouldn't be put
271 into the CPU registers by the compiler any more.
272
273 Implementation note: we use the standard workaround for lack of partial
274 template specialization support in VC (both 6 and 7): instead of partly
275 specializing the class Foo<T, U> for some T we introduce FooOut<T> and
276 FooIn<U> nested in it, make Foo<T, U> equivalent to FooOut<T>::FooIn<U> and
277 fully specialize FooOut.
278
279 Also note that this class doesn't have any default definition because we
280 can't really do anything without knowing the exact image class. We do
281 provide wxPixelDataBase to make it simpler to write new wxPixelData
282 specializations.
283 */
284
285// we need to define this skeleton template to mollify VC++
286template <class Image>
287struct wxPixelDataOut
288{
289 template <class PixelFormat>
290 class wxPixelDataIn
291 {
292 public:
293 class Iterator { };
294 };
295};
296
297#if wxUSE_IMAGE
298// wxPixelData specialization for wxImage: this is the simplest case as we
299// don't have to care about different pixel formats here
300template <>
301struct wxPixelDataOut<wxImage>
302{
303 // NB: this is a template class even though it doesn't use its template
304 // parameter because otherwise wxPixelData couldn't compile
305 template <class dummyPixelFormat>
306 class wxPixelDataIn : public wxPixelDataBase
307 {
308 public:
309 // the type of the class we're working with
310 typedef wxImage ImageType;
311
312 // the iterator which should be used for working with data in this
313 // format
314 class Iterator
315 {
316 public:
317 // the pixel format we use
318 typedef wxImagePixelFormat PixelFormat;
319
320 // the pixel data we're working with
321 typedef
322 wxPixelDataOut<wxImage>::wxPixelDataIn<PixelFormat> PixelData;
323
324 // go back to (0, 0)
325 void Reset(const PixelData& data)
326 {
327 *this = data.GetPixels();
328 }
329
330 // creates the iterator pointing to the beginning of data
331 Iterator(PixelData& data)
332 {
333 Reset(data);
334 }
335
336 // creates the iterator initially pointing to the image origin
337 Iterator(const wxImage& image)
338 {
339 m_pRGB = image.GetData();
340
341 if ( image.HasAlpha() )
342 {
343 m_pAlpha = image.GetAlpha();
344 }
345 else // alpha is not used at all
346 {
347 m_pAlpha = NULL;
348 }
349 }
350
351 // true if the iterator is valid
352 bool IsOk() const { return m_pRGB != NULL; }
353
354
355 // navigation
356 // ----------
357
358 // advance the iterator to the next pixel, prefix version
359 Iterator& operator++()
360 {
361 m_pRGB += PixelFormat::SizePixel;
362 if ( m_pAlpha )
363 ++m_pAlpha;
364
365 return *this;
366 }
367
368 // postfix (hence less efficient -- don't use it unless you
369 // absolutely must) version
370 Iterator operator++(int)
371 {
372 Iterator p(*this);
373 ++*this;
374 return p;
375 }
376
377 // move x pixels to the right and y down
378 //
379 // note that the rows don't wrap!
380 void Offset(const PixelData& data, int x, int y)
381 {
382 m_pRGB += data.GetRowStride()*y + PixelFormat::SizePixel*x;
383 if ( m_pAlpha )
384 m_pAlpha += data.GetWidth() + x;
385 }
386
387 // move x pixels to the right (again, no row wrapping)
388 void OffsetX(const PixelData& WXUNUSED(data), int x)
389 {
390 m_pRGB += PixelFormat::SizePixel*x;
391 if ( m_pAlpha )
392 m_pAlpha += x;
393 }
394
395 // move y rows to the bottom
396 void OffsetY(const PixelData& data, int y)
397 {
398 m_pRGB += data.GetRowStride()*y;
399 if ( m_pAlpha )
400 m_pAlpha += data.GetWidth();
401 }
402
403 // go to the given position
404 void MoveTo(const PixelData& data, int x, int y)
405 {
406 Reset(data);
407 Offset(data, x, y);
408 }
409
410
411 // data access
412 // -----------
413
414 // access to individual colour components
415 PixelFormat::ChannelType& Red() { return m_pRGB[PixelFormat::RED]; }
416 PixelFormat::ChannelType& Green() { return m_pRGB[PixelFormat::GREEN]; }
417 PixelFormat::ChannelType& Blue() { return m_pRGB[PixelFormat::BLUE]; }
418 PixelFormat::ChannelType& Alpha() { return *m_pAlpha; }
419
420 // address the pixel contents directly (always RGB, without alpha)
421 //
422 // this can't be used to modify the image as assigning a 32bpp
423 // value to 24bpp pixel would overwrite an extra byte in the next
424 // pixel or beyond the end of image
425 const typename PixelFormat::PixelType& Data()
426 { return *(typename PixelFormat::PixelType *)m_pRGB; }
427
428 // private: -- see comment in the beginning of the file
429
430 // pointer into RGB buffer
431 unsigned char *m_pRGB;
432
433 // pointer into alpha buffer or NULL if alpha isn't used
434 unsigned char *m_pAlpha;
435 };
436
437 // initializes us with the data of the given image
438 wxPixelDataIn(ImageType& image) : m_image(image), m_pixels(image)
439 {
440 m_width = image.GetWidth();
441 m_height = image.GetHeight();
442 m_stride = Iterator::PixelFormat::SizePixel * m_width;
443 }
444
445 // initializes us with the given region of the specified image
446 wxPixelDataIn(ImageType& image,
447 const wxPoint& pt,
448 const wxSize& sz) : m_image(image), m_pixels(image)
449 {
450 m_stride = Iterator::PixelFormat::SizePixel * m_width;
451
452 InitRect(pt, sz);
453 }
454
455 // initializes us with the given region of the specified image
456 wxPixelDataIn(ImageType& image,
457 const wxRect& rect) : m_image(image), m_pixels(image)
458 {
459 m_stride = Iterator::PixelFormat::SizePixel * m_width;
460
461 InitRect(rect.GetPosition(), rect.GetSize());
462 }
463
464 // we evaluate to true only if we could get access to bitmap data
465 // successfully
466 operator bool() const { return m_pixels.IsOk(); }
467
468 // get the iterator pointing to the origin
469 Iterator GetPixels() const { return m_pixels; }
470
471 private:
472 void InitRect(const wxPoint& pt, const wxSize& sz)
473 {
474 m_width = sz.x;
475 m_height = sz.y;
476
477 m_ptOrigin = pt;
478 m_pixels.Offset(*this, pt.x, pt.y);
479 }
480
481 // the image we're working with
482 ImageType& m_image;
483
484 // the iterator pointing to the image origin
485 Iterator m_pixels;
486 };
487};
488#endif //wxUSE_IMAGE
489
490#if wxUSE_GUI
491// wxPixelData specialization for wxBitmap: here things are more interesting as
492// we also have to support different pixel formats
493template <>
494struct wxPixelDataOut<wxBitmap>
495{
496 template <class Format>
497 class wxPixelDataIn : public wxPixelDataBase
498 {
499 public:
500 // the type of the class we're working with
501 typedef wxBitmap ImageType;
502
503 class Iterator
504 {
505 public:
506 // the pixel format we use
507 typedef Format PixelFormat;
508
509 // the type of the pixel components
510 typedef typename PixelFormat::ChannelType ChannelType;
511
512 // the pixel data we're working with
513 typedef wxPixelDataOut<wxBitmap>::wxPixelDataIn<Format> PixelData;
514
515
516 // go back to (0, 0)
517 void Reset(const PixelData& data)
518 {
519 *this = data.GetPixels();
520 }
521
522 // initializes the iterator to point to the origin of the given
523 // pixel data
524 Iterator(PixelData& data)
525 {
526 Reset(data);
527 }
528
529 // initializes the iterator to point to the origin of the given
530 // bitmap
531 Iterator(wxBitmap& bmp, PixelData& data)
532 {
533 // using cast here is ugly but it should be safe as
534 // GetRawData() real return type should be consistent with
535 // BitsPerPixel (which is in turn defined by ChannelType) and
536 // this is the only thing we can do without making GetRawData()
537 // a template function which is undesirable
538 m_ptr = (ChannelType *)
539 bmp.GetRawData(data, PixelFormat::BitsPerPixel);
540 }
541
542 // default constructor
543 Iterator()
544 {
545 m_ptr = NULL;
546 }
547
548 // return true if this iterator is valid
549 bool IsOk() const { return m_ptr != NULL; }
550
551
552 // navigation
553 // ----------
554
555 // advance the iterator to the next pixel, prefix version
556 Iterator& operator++()
557 {
558 m_ptr += PixelFormat::SizePixel;
559
560 return *this;
561 }
562
563 // postfix (hence less efficient -- don't use it unless you
564 // absolutely must) version
565 Iterator operator++(int)
566 {
567 Iterator p(*this);
568 ++*this;
569 return p;
570 }
571
572 // move x pixels to the right and y down
573 //
574 // note that the rows don't wrap!
575 void Offset(const PixelData& data, int x, int y)
576 {
577 m_ptr += data.GetRowStride()*y + PixelFormat::SizePixel*x;
578 }
579
580 // move x pixels to the right (again, no row wrapping)
581 void OffsetX(const PixelData& WXUNUSED(data), int x)
582 {
583 m_ptr += PixelFormat::SizePixel*x;
584 }
585
586 // move y rows to the bottom
587 void OffsetY(const PixelData& data, int y)
588 {
589 m_ptr += data.GetRowStride()*y;
590 }
591
592 // go to the given position
593 void MoveTo(const PixelData& data, int x, int y)
594 {
595 Reset(data);
596 Offset(data, x, y);
597 }
598
599
600 // data access
601 // -----------
602
603 // access to individual colour components
604 ChannelType& Red() { return m_ptr[PixelFormat::RED]; }
605 ChannelType& Green() { return m_ptr[PixelFormat::GREEN]; }
606 ChannelType& Blue() { return m_ptr[PixelFormat::BLUE]; }
607 ChannelType& Alpha() { return m_ptr[PixelFormat::ALPHA]; }
608
609 // address the pixel contents directly
610 //
611 // warning: the format is platform dependent
612 //
613 // warning 2: assigning to Data() only works correctly for 16bpp or
614 // 32bpp formats but using it for 24bpp ones overwrites
615 // one extra byte and so can't be done
616 typename PixelFormat::PixelType& Data()
617 { return *(typename PixelFormat::PixelType *)m_ptr; }
618
619 // private: -- see comment in the beginning of the file
620
621 // for efficiency reasons this class should not have any other
622 // fields, otherwise it won't be put into a CPU register (as it
623 // should inside the inner loops) by some compilers, notably gcc
624 ChannelType *m_ptr;
625 };
626
627 // ctor associates this pointer with a bitmap and locks the bitmap for
628 // raw access, it will be unlocked only by our dtor and so these
629 // objects should normally be only created on the stack, i.e. have
630 // limited life-time
631 wxPixelDataIn(wxBitmap& bmp) : m_bmp(bmp), m_pixels(bmp, *this)
632 {
633 }
634
635 wxPixelDataIn(wxBitmap& bmp, const wxRect& rect)
636 : m_bmp(bmp), m_pixels(bmp, *this)
637 {
638 InitRect(rect.GetPosition(), rect.GetSize());
639 }
640
641 wxPixelDataIn(wxBitmap& bmp, const wxPoint& pt, const wxSize& sz)
642 : m_bmp(bmp), m_pixels(bmp, *this)
643 {
644 InitRect(pt, sz);
645 }
646
647 // we evaluate to true only if we could get access to bitmap data
648 // successfully
649 operator bool() const { return m_pixels.IsOk(); }
650
651 // get the iterator pointing to the origin
652 Iterator GetPixels() const { return m_pixels; }
653
654 // dtor unlocks the bitmap
655 ~wxPixelDataIn()
656 {
657 if ( m_pixels.IsOk() )
658 {
659#if defined(__WXMSW__) || defined(__WXMAC__)
660 // this is a hack to mark wxBitmap as using alpha channel
661 if ( Format::HasAlpha )
662 m_bmp.UseAlpha();
663#endif
664 m_bmp.UngetRawData(*this);
665 }
666 // else: don't call UngetRawData() if GetRawData() failed
667 }
668
669#if WXWIN_COMPATIBILITY_2_8
670 // not needed anymore, calls to it should be simply removed
671 wxDEPRECATED_INLINE( void UseAlpha(), wxEMPTY_PARAMETER_VALUE )
672#endif
673
674 // private: -- see comment in the beginning of the file
675
676 // the bitmap we're associated with
677 wxBitmap m_bmp;
678
679 // the iterator pointing to the image origin
680 Iterator m_pixels;
681
682 private:
683 void InitRect(const wxPoint& pt, const wxSize& sz)
684 {
685 m_pixels.Offset(*this, pt.x, pt.y);
686
687 m_ptOrigin = pt;
688 m_width = sz.x;
689 m_height = sz.y;
690 }
691 };
692};
693
694#endif //wxUSE_GUI
695
696// FIXME-VC6: VC6 doesn't like typename in default template parameters while
697// it is necessary with standard-conforming compilers, remove this
698// #define and just use typename when we drop VC6 support
699#if defined(__VISUALC__) && !wxCHECK_VISUALC_VERSION(7)
700 #define wxTYPENAME_IN_TEMPLATE_DEFAULT_PARAM
701#else
702 #define wxTYPENAME_IN_TEMPLATE_DEFAULT_PARAM typename
703#endif
704
705template <class Image,
706 class PixelFormat = wxTYPENAME_IN_TEMPLATE_DEFAULT_PARAM
707 wxPixelFormatFor<Image>::Format >
708class wxPixelData :
709 public wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>
710{
711public:
712 typedef
713 typename wxPixelDataOut<Image>::template wxPixelDataIn<PixelFormat>
714 Base;
715
716 wxPixelData(Image& image) : Base(image) { }
717
718 wxPixelData(Image& i, const wxRect& rect) : Base(i, rect) { }
719
720 wxPixelData(Image& i, const wxPoint& pt, const wxSize& sz)
721 : Base(i, pt, sz)
722 {
723 }
724};
725
726// some "predefined" pixel data classes
727#if wxUSE_IMAGE
728typedef wxPixelData<wxImage> wxImagePixelData;
729#endif //wxUSE_IMAGE
730#if wxUSE_GUI
731typedef wxPixelData<wxBitmap, wxNativePixelFormat> wxNativePixelData;
732typedef wxPixelData<wxBitmap, wxAlphaPixelFormat> wxAlphaPixelData;
733
734#endif //wxUSE_GUI
735
736// ----------------------------------------------------------------------------
737// wxPixelIterator
738// ----------------------------------------------------------------------------
739
740/*
741 wxPixel::Iterator represents something which points to the pixel data and
742 allows us to iterate over it. In the simplest case of wxBitmap it is,
743 indeed, just a pointer, but it can be something more complicated and,
744 moreover, you are free to specialize it for other image classes and bitmap
745 formats.
746
747 Note that although it would have been much more intuitive to have a real
748 class here instead of what we have now, this class would need two template
749 parameters, and this can't be done because we'd need compiler support for
750 partial template specialization then and neither VC6 nor VC7 provide it.
751 */
752template < class Image, class PixelFormat = wxPixelFormatFor<Image> >
753struct wxPixelIterator : public wxPixelData<Image, PixelFormat>::Iterator
754{
755};
756
757#endif // wxHAS_RAW_BITMAP
758#endif // _WX_RAWBMP_H_