3c5bd1886a
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@19726 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
260 lines
7.3 KiB
C++
260 lines
7.3 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// 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 <vadim@wxwindows.org>
|
|
// 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_
|
|
|