00001
00002
00003
00004 #ifndef IMAGE_H_HAS_BEEN_INCLUDED
00005 #define IMAGE_H_HAS_BEEN_INCLUDED
00006
00007 #include "std/fstream.H"
00008 #include <cmath>
00009 #include "std/support.H"
00010 #include "mlib/points.H"
00011 #include "mlib/point2i.H"
00012
00013
00014
00015
00016 inline unsigned int
00017 getPower2Size(int n)
00018 {
00019 return (1 << ((n>0) ? (int)ceil(log((double) n)/log(2.0)) : 0));
00020 }
00021
00022 typedef unsigned int uint;
00023 typedef unsigned char uchar;
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 class Image {
00034 protected:
00035 uint _width;
00036 uint _height;
00037 uint _bpp;
00038 uchar* _data;
00039 bool _no_delete;
00040
00041 enum { PNG_BYTES_TO_CHECK = 8 };
00042 FILE* open_png(char* file);
00043
00044 public:
00045 Image() : _width(0), _height(0), _bpp(0), _data(0), _no_delete(0) {}
00046 Image(Cstr_ptr& file) :
00047 _width(0),
00048 _height(0),
00049 _bpp(0),
00050 _data(0),
00051 _no_delete(false) {
00052 if (file)
00053 load_file(**file);
00054 }
00055 Image(uint w, uint h, uint bpp, uchar* data, bool nd=1) {
00056 set(w,h,bpp,data,nd);
00057 }
00058 Image(uint w, uint h, uint bpp) :
00059 _width(0), _height(0), _bpp(0), _data(0), _no_delete(false) {
00060 resize(w,h,bpp);
00061 }
00062 virtual ~Image() { clear(); }
00063
00064 void set(int w, int h, uint bpp, uchar* data, bool nd=1) {
00065 if (bpp < 1 || bpp > 4) {
00066 err_msg("Image::Image: %d bytes/pixel not supported", bpp);
00067 } else {
00068 clear();
00069 _width = w;
00070 _height = h;
00071 _bpp = bpp;
00072 _data = data;
00073 _no_delete = nd;
00074 }
00075 }
00076
00077 void freedata() {
00078 if (!_no_delete) {
00079 delete [] _data;
00080 }
00081 _data = 0;
00082 }
00083
00084 void clear() {
00085 freedata();
00086 _width = _height = _bpp = 0;
00087 _no_delete = 0;
00088 }
00089
00090 bool resize(uint w, uint h, uint b) {
00091
00092
00093
00094
00095
00096
00097 if (_width != w || _height != h || _bpp != b) {
00098 _width = w;
00099 _height = h;
00100 _bpp = b;
00101 if (!_no_delete)
00102 delete [] _data;
00103 _data = 0;
00104 _no_delete = 0;
00105 if ((_data = new uchar [ size() ]) == 0) {
00106 err_ret("Image::resize: can't allocate data");
00107 return 0;
00108 }
00109 }
00110 return 1;
00111 }
00112 bool resize(uint w, uint h) { return resize(w,h,_bpp); }
00113
00114 int copy_tile(const Image& tile, uint i, uint j);
00115
00116
00117 uint width() const { return _width; }
00118 uint height() const { return _height; }
00119 uint bpp() const { return _bpp; }
00120 uint size() const { return _width*_height*_bpp; }
00121 uint row_size() const { return _width*_bpp; }
00122 mlib::Point2i dims() const { return mlib::Point2i(_width,_height); }
00123 uchar* data() const { return _data; }
00124 uchar* row(int k) const { return _data + k*row_size(); }
00125 uchar* copy();
00126
00127 uchar pixel(uint x, uint y) const {
00128 if (x >= _width || y >= _height)
00129 return 0;
00130 return row(y)[x * _bpp];
00131 }
00132 uint pixel_rgba(uint x, uint y) const;
00133 uint pixel_r(uint x, uint y) const;
00134 uint pixel_g(uint x, uint y) const;
00135 uint pixel_b(uint x, uint y) const;
00136 uint pixel_a(uint x, uint y) const;
00137
00138 bool empty() const { return !(_width && _height && _bpp && _data); }
00139
00140
00141
00142 bool expand_power2();
00143
00144 int resize_rows_mult_4();
00145 int load_file(char* file);
00146 int read_png(char* file);
00147 int read_png(FILE* fp);
00148 int write_png(char* file) const;
00149
00150 int read_pnm(char* file);
00151 int read_pgm(istream& in, bool ascii);
00152 int read_ppm(istream& in, bool ascii);
00153 int write_pnm(char* file) const;
00154
00155 static int write_png(int w, int h, uint bpp, uchar* data, Cstr_ptr& file) {
00156 Image img(w,h,bpp,data,1);
00157 return img.write_png(**file);
00158 }
00159 };
00160
00161 #endif // IMAGE_H_HAS_BEEN_INCLUDED
00162
00163