1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
// image2d.hpp
// 2008 Michael Thomas Greer
// Released to the Public Domain
#ifndef IMAGE2D_HPP
#define IMAGE2D_HPP
#include <algorithm>
//----------------------------------------------------------------------------
struct RGB_t
{
unsigned char red, green, blue;
unsigned char& operator [] (const int& index)
{
switch (index)
{
case 0: return red;
case 1: return green;
case 2: return blue;
}
throw 0;
}
RGB_t():
red( 0 ), green( 0 ), blue( 0 )
{ }
RGB_t( unsigned char red, unsigned char green, unsigned char blue ):
red( red ), green( green ), blue( blue )
{ }
RGB_t( const unsigned char* rgb ):
red( rgb[ 0 ] ), green( rgb[ 1 ] ), blue( rgb[ 2 ] )
{ }
};
//----------------------------------------------------------------------------
class Image2D
{
private:
// The image data is shared among all instances of the image.
struct ImageData
{
unsigned width;
unsigned height;
RGB_t* data;
unsigned ref_count;
ImageData( unsigned width, unsigned height, RGB_t* data, unsigned ref_count ):
width( width ),
height( height ),
data( data ),
ref_count( ref_count )
{ }
};
ImageData* f_data;
void f_free()
{
if (f_data != NULL)
if (--(f_data->ref_count) == 0)
{
delete [] f_data->data;
delete f_data;
}
f_data = NULL;
}
ImageData* f_getdata()
{
if (f_data == NULL) throw 0;
return f_data;
}
public:
// Defaultly constructed images can only be assigned to
Image2D():
f_data( NULL )
{ }
// Create a new image of (width, height) colors
Image2D( unsigned width, unsigned height ):
f_data( new ImageData( width, height, new RGB_t[ width * height ], 1 ) )
{ }
// Destroy image data only if we are the last referent
~Image2D()
{
f_free();
}
// Copy constructors
Image2D( const Image2D& image2d )
{
*this = const_cast<Image2D&>( image2d );
}
Image2D( Image2D& image2d )
{
*this = image2d;
}
// Assignment operators
Image2D& operator = ( const Image2D& image2d )
{
return *this = const_cast<Image2D&>( image2d );
}
Image2D& operator = ( Image2D& image2d )
{
if (&image2d != this)
{
f_free();
f_data = image2d.f_data;
f_getdata()->ref_count++;
}
return *this;
}
// Make a deep copy
Image2D copy()
{
Image2D result( f_getdata()->width, f_getdata()->height );
result.f_data->width = f_data->width;
result.f_data->height = f_data->height;
result.f_data->ref_count = f_data->ref_count;
std::copy(
f_data->data,
f_data->data + (f_data->width * f_data->height),
result.f_data->data
);
return result;
}
// Access the data directly
// It is stored in row-major format (height rows of width colors).
RGB_t* data() { return f_getdata()->data; }
const RGB_t* data() const { return f_getdata()->data; }
// Index an individual color
RGB_t& index( unsigned x, unsigned y )
{
if ((x >= f_getdata()->width) or (y >= f_getdata()->height)) throw 0;
return f_data->data[ (y * f_data->height) + x ];
}
const RGB_t& index( unsigned x, unsigned y ) const
{
if ((x >= f_getdata()->width) or (y >= f_getdata()->height)) throw 0;
return f_data->data[ (y * f_data->height) + x ];
}
// Information about the image
unsigned width() const { return (f_data == NULL) ? 0 : f_data->width; }
unsigned height() const { return (f_data == NULL) ? 0 : f_data->height; }
unsigned size() const { return f_getdata()->width * f_getdata()->height; }
// Play with the [] operators
struct curry
{
Image2D* image2d;
unsigned x;
curry( Image2D* image2d, unsigned x ):
image2d(image2d),
x(x)
{ }
RGB_t& operator [] ( unsigned y )
{
return image2d->index( x, y );
}
const RGB_t& operator [] ( unsigned y ) const
{
return image2d->index( x, y );
}
};
curry operator [] ( unsigned x )
{
return curry( this, x );
}
const curry operator [] ( unsigned x ) const
{
return curry( const_cast<Image2D*>( this ), x );
}
};
#endif
// end image2d.hpp
|