+ public:
+ // the type of the class we're working with
+ typedef wxBitmap ImageType;
+
+ class Iterator
+ {
+ public:
+ // the pixel format we use
+ typedef Format PixelFormat;
+
+ // the type of the pixel components
+ typedef typename PixelFormat::ChannelType ChannelType;
+
+ // the pixel data we're working with
+ typedef wxPixelDataOut<wxBitmap>::wxPixelDataIn<Format> PixelData;
+
+
+ // go back to (0, 0)
+ void Reset(const PixelData& data)
+ {
+ *this = data.GetPixels();
+ }
+
+ // initializes the iterator to point to the origin of the given
+ // pixel data
+ Iterator(PixelData& data)
+ {
+ Reset(data);
+ }
+
+ // initializes the iterator to point to the origin of the given
+ // bitmap
+ Iterator(wxBitmap& bmp, PixelData& data)
+ {
+ // using cast here is ugly but it should be safe as
+ // GetRawData() real return type should be consistent with
+ // BitsPerPixel (which is in turn defined by ChannelType) and
+ // this is the only thing we can do without making GetRawData()
+ // a template function which is undesirable
+ m_ptr = (ChannelType *)
+ bmp.GetRawData(data, PixelFormat::BitsPerPixel);
+ }
+
+ // default constructor
+ Iterator()
+ {
+ m_ptr = NULL;
+ }
+
+ // return true if this iterator is valid
+ bool IsOk() const { return m_ptr != NULL; }
+
+
+ // navigation
+ // ----------
+
+ // advance the iterator to the next pixel, prefix version
+ Iterator& operator++()
+ {
+ m_ptr += PixelFormat::SizePixel;
+
+ 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_ptr += data.GetRowStride()*y + PixelFormat::SizePixel*x;
+ }
+
+ // move x pixels to the right (again, no row wrapping)
+ void OffsetX(const PixelData& WXUNUSED(data), int x)
+ {
+ m_ptr += PixelFormat::SizePixel*x;
+ }
+
+ // move y rows to the bottom
+ void OffsetY(const PixelData& data, int y)
+ {
+ m_ptr += data.GetRowStride()*y;
+ }
+
+ // 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_ptr[PixelFormat::RED]; }
+ ChannelType& Green() { return m_ptr[PixelFormat::GREEN]; }
+ ChannelType& Blue() { return m_ptr[PixelFormat::BLUE]; }
+ ChannelType& Alpha() { return m_ptr[PixelFormat::ALPHA]; }
+
+ // address the pixel contents directly
+ //
+ // warning: the format is platform dependent
+ //
+ // warning 2: assigning to Data() only works correctly for 16bpp or
+ // 32bpp formats but using it for 24bpp ones overwrites
+ // one extra byte and so can't be done
+ typename PixelFormat::PixelType& Data()
+ { return *(typename PixelFormat::PixelType *)m_ptr; }
+
+ // private: -- see comment in the beginning of the file
+
+ // for efficiency reasons this class should not have any other
+ // fields, otherwise it won't be put into a CPU register (as it
+ // should inside the inner loops) by some compilers, notably gcc
+ ChannelType *m_ptr;
+ };
+
+ // ctor associates this pointer with a bitmap and locks the bitmap for
+ // raw access, it will be unlocked only by our dtor and so these
+ // objects should normally be only created on the stack, i.e. have
+ // limited life-time
+ wxPixelDataIn(wxBitmap& bmp) : m_bmp(bmp), m_pixels(bmp, *this)
+ {
+ }