/////////////////////////////////////////////////////////////////////////////// // Name: wx/rawbmp.h // Purpose: macros for fast, raw bitmap data access // Author: Eric Kidd, Vadim Zeitlin // Modified by: // Created: 10.03.03 // RCS-ID: $Id$ // Copyright: (c) 2002 Vadim Zeitlin // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// #ifndef _WX_RAWBMP_H_BASE_ #define _WX_RAWBMP_H_BASE_ // ---------------------------------------------------------------------------- // Abstract Pixel API // // We need to access our raw bitmap data (1) portably and (2) efficiently. // We do this using a two-dimensional "iteration" interface. Performance // is extremely important here: these functions will be called hundreds // of thousands of times in a row, and even small inefficiencies will // make applications seem slow. // // We can't always rely on inline functions, because not all compilers actually // bother to inline them unless we crank the optimization levels way up. // Therefore, we also provide macros to wring maximum speed out of compiler // unconditionally (e.g. even in debug builds). Of course, if the performance // isn't absolutely crucial for you you shouldn't be using them but the inline // functions instead. // ---------------------------------------------------------------------------- /* Usage example: wxBitmap bmp; wxRawBitmapData data(bitmap); if ( !data ) { ... raw access to bitmap data unavailable, do something else ... return; } if ( data.m_width < 20 || data.m_height < 20 ) { ... complain: the bitmap it too small ... return; } wxRawBitmapIterator p(data); // we draw a (10, 10)-(20, 20) rect manually using the given r, g, b p.Offset(10, 10); for ( int y = 0; y < 10; ++y ) { wxRawBitmapIterator rowStart = p; for ( int x = 0; x < 10; ++x, ++p ) { p.Red() = r; p.Green() = g; p.Blue() = b; } p = rowStart; p.OffsetY(1); } */ // this struct represents a pointer to raw bitmap data class wxRawBitmapData { public: // 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 wxRawBitmapData(wxBitmap bmp) : m_bmp(bmp) { if ( !bmp.GetRawData(this) ) m_pixels = NULL; } // we evaluate to true only if we could get access to bitmap data // successfully operator bool() const { return m_pixels != NULL; } // dtor unlocks the bitmap ~wxRawBitmapData() { m_bmp.UngetRawData(this); } // accessors unsigned char *GetPixels() const { return m_pixels; } int GetWidth() const { return m_width; } int GetHeight() const { return m_height; } int GetByPP() const { return m_bypp; } int GetBPP() const { return 8*GetByPP(); } int GetRowStride() const { return m_stride; } // private: -- public because accessed by the macros below but still mustn't be // used directly // the bitmap we're associated with wxBitmap m_bmp; // pointer to the start of the data unsigned char *m_pixels; // the size of the image we address, in pixels int m_width, m_height; // number of bytes (NOT bits) per pixel, including alpha channel if any int m_bypp; // this parameter is the offset of the start of the (N+1)st row from the // Nth one and can be different from m_bypp*width in some cases: // a) the most usual one is to force 32/64 bit alignment of rows // b) another one is for bottom-to-top images where it's negative // c) finally, it could conceivably be 0 for the images with all // lines being identical int m_stride; }; // this is the type for the iterator over raw bitmap data class wxRawBitmapIterator { public: // ctors and such // -------------- // we must be associated/initialized with some bitmap data object wxRawBitmapIterator(const wxRawBitmapData& data) : m_data(&data) { m_ptr = m_data->GetPixels(); } // default copy ctor, assignment operator and dtor are ok // navigation // ---------- // move x pixels to the right and y down // // note that the rows don't wrap! void Offset(int x, int y) { m_ptr += m_data->GetRowStride()*y + m_data->GetByPP()*x; } // move x pixels to the right (again, no row wrapping) void OffsetX(int x) { m_ptr += m_data->GetByPP()*x; } // move y rows to the bottom void OffsetY(int y) { m_ptr += m_data->GetRowStride()*y; } // go back to (0, 0) void Reset() { m_ptr = m_data->GetPixels(); } // go to the given position void MoveTo(int x, int y) { Reset(); Offset(x, y); } // same as OffsetX(1) for convenience wxRawBitmapIterator& operator++() { OffsetX(1); return *this; } // postfix (hence less efficient) version wxRawBitmapIterator operator++(int) { wxRawBitmapIterator p(*this); OffsetX(1); return p; } // data access // ----------- // DIBs store data in BGR format, i.e. "little endian" RGB enum { #ifdef __WXMSW__ BLUE, GREEN, RED, #else // !__WXMSW__ RED, GREEN, BLUE, #endif // __WXMSW__/!__WXMSW__ ALPHA }; // access to invidividual colour components unsigned char& Red() { return m_ptr[RED]; } unsigned char& Green() { return m_ptr[GREEN]; } unsigned char& Blue() { return m_ptr[BLUE]; } unsigned char& Alpha() { return m_ptr[ALPHA]; } // address the pixel contents directly // // warning: the format is platform dependent wxUint32& Data() { return *(wxUint32 *)m_ptr; } // private: -- don't access these fields directly, same as as above unsigned char *m_ptr; const wxRawBitmapData *m_data; }; // these macros are used to change the current location in the bitmap // ------------------------------------------------------------------ // move x pixels to the right and y down // // note that the rows don't wrap! #define wxBMP_OFFSET(p, x, y) \ p.m_ptr += p.m_data->m_stride * (y) + p.m_data->m_bypp * (x) // move x pixels to the right (again, no row wrapping) #define wxBMP_OFFSET_X(p, x) p.m_ptr += p.m_data->m_bypp * (x) // move y rows to the bottom #define wxBMP_OFFSET_Y(p, y) p.m_ptr += p.m_data->m_stride * (y) // these macros are used to work with the pixel values // // all of them can be used as either lvalues or rvalues. // ---------------------------------------------------- #define wxBMP_RED(p) (p.m_ptr[wxRawBitmapIterator::RED]) #define wxBMP_GREEN(p) (p.m_ptr[wxRawBitmapIterator::GREEN]) #define wxBMP_BLUE(p) (p.m_ptr[wxRawBitmapIterator::BLUE]) #define wxBMP_ALPHA(p) (p.m_ptr[wxRawBitmapIterator::ALPHA]) // these macros are most efficient but return the buffer contents in // platform-specific format, e.g. RGB on all sane platforms and BGR under Win32 #define wxBMP_RGB(p) *(wxUint32 *)(p.m_ptr) #define wxBMP_RGBA(p) *(wxUint32 *)(p.m_ptr) #endif // _WX_RAWBMP_H_BASE_