+ public:
+ // the type of the class we're working with
+ typedef wxImage ImageType;
+
+ // the iterator which should be used for working with data in this
+ // format
+ class Iterator
+ {
+ public:
+ // the pixel format we use
+ typedef wxImagePixelFormat PixelFormat;
+
+ // the type of the pixel components
+ typedef typename PixelFormat::ChannelType ChannelType;
+
+ // the pixel data we're working with
+ typedef
+ wxPixelDataOut<wxImage>::wxPixelDataIn<PixelFormat> PixelData;
+
+ // go back to (0, 0)
+ void Reset(const PixelData& data)
+ {
+ *this = data.GetPixels();
+ }
+
+ // creates the iterator pointing to the beginning of data
+ Iterator(PixelData& data)
+ {
+ Reset(data);
+ }
+
+ // creates the iterator initially pointing to the image origin
+ Iterator(const wxImage& image)
+ {
+ m_pRGB = image.GetData();
+
+ if ( image.HasAlpha() )
+ {
+ m_pAlpha = image.GetAlpha();
+ }
+ else // alpha is not used at all
+ {
+ m_pAlpha = NULL;
+ }
+ }
+
+ // true if the iterator is valid
+ bool IsOk() const { return m_pRGB != NULL; }
+
+
+ // navigation
+ // ----------
+
+ // advance the iterator to the next pixel, prefix version
+ Iterator& operator++()
+ {
+ m_pRGB += PixelFormat::SizePixel;
+ if ( m_pAlpha )
+ ++m_pAlpha;
+
+ return *this;
+ }
+
+ // postfix (hence less efficient -- don't use it unless you
+ // absolutely must) version
+ Iterator operator++(int)
+ {
+ Iterator p(*this);
+ ++*this;
+ return p;
+ }
+
+ // move x pixels to the right and y down
+ //
+ // note that the rows don't wrap!
+ void Offset(const PixelData& data, int x, int y)
+ {
+ m_pRGB += data.GetRowStride()*y + PixelFormat::SizePixel*x;
+ if ( m_pAlpha )
+ m_pAlpha += data.GetWidth() + x;
+ }
+
+ // move x pixels to the right (again, no row wrapping)
+ void OffsetX(const PixelData& WXUNUSED(data), int x)
+ {
+ m_pRGB += PixelFormat::SizePixel*x;
+ if ( m_pAlpha )
+ m_pAlpha += x;
+ }
+
+ // move y rows to the bottom
+ void OffsetY(const PixelData& data, int y)
+ {
+ m_pRGB += data.GetRowStride()*y;
+ if ( m_pAlpha )
+ m_pAlpha += data.GetWidth();
+ }
+
+ // go to the given position
+ void MoveTo(const PixelData& data, int x, int y)
+ {
+ Reset(data);
+ Offset(data, x, y);
+ }
+
+
+ // data access
+ // -----------
+
+ // access to individual colour components
+ ChannelType& Red() { return m_pRGB[PixelFormat::RED]; }
+ ChannelType& Green() { return m_pRGB[PixelFormat::GREEN]; }
+ ChannelType& Blue() { return m_pRGB[PixelFormat::BLUE]; }
+ ChannelType& Alpha() { return *m_pAlpha; }
+
+ // address the pixel contents directly (always RGB, without alpha)
+ //
+ // this can't be used to modify the image as assigning a 32bpp
+ // value to 24bpp pixel would overwrite an extra byte in the next
+ // pixel or beyond the end of image
+ const typename PixelFormat::PixelType& Data()
+ { return *(typename PixelFormat::PixelType *)m_pRGB; }
+
+ // private: -- see comment in the beginning of the file
+
+ // pointer into RGB buffer
+ unsigned char *m_pRGB;
+
+ // pointer into alpha buffer or NULL if alpha isn't used
+ unsigned char *m_pAlpha;
+ };
+
+ // initializes us with the data of the given image
+ wxPixelDataIn(ImageType& image) : m_image(image), m_pixels(image)
+ {
+ m_width = image.GetWidth();
+ m_height = image.GetHeight();
+ m_stride = Iterator::PixelFormat::SizePixel * m_width;
+ }
+
+ // initializes us with the given region of the specified image
+ wxPixelDataIn(ImageType& image,
+ const wxPoint& pt,
+ const wxSize& sz) : m_image(image), m_pixels(image)
+ {
+ m_stride = Iterator::PixelFormat::SizePixel * m_width;