00001 #ifndef TPIMAGE_H
00002 #define TPIMAGE_H
00003
00004 #include <fstream>
00005 #include <iostream>
00006 #include <cstring>
00007 #include <string>
00008 #include <cassert>
00009 #include <typeinfo>
00010 #include <stdint.h>
00011
00012
00013
00014
00015
00016 template<class T>
00017 class SImage {
00018 int width, height;
00019 T *image, *img;
00020 bool localalloc;
00021 public:
00022
00023 SImage();
00024
00025
00026
00027
00028 SImage(int w, int h, T *ptr=NULL);
00029 ~SImage() { if (localalloc) delete [] img; }
00030
00031
00032
00033 void SetSize(int w, int h);
00034
00035
00036 void SetData(T *ptr) { image = ptr; }
00037
00038
00039 bool Load(const char *filename);
00040
00041
00042 bool LoadRGB(const char *filename);
00043
00044
00045
00046
00047 void Store(const char *filename, bool norm = false, bool ascii =false) const;
00048
00049
00050 void StoreRGB(const char *filename) const;
00051
00052
00053 void StoreYUV(const char *filename) const;
00054
00055 T *GetData() const { return image; }
00056
00057 int GetWidth() const { return width; }
00058
00059 int GetHeight() const { return height; }
00060
00061 T *operator[](int i) { return &image[i*width]; }
00062
00063 void operator=(SImage<T> &src);
00064 };
00065
00066
00067 template<class T>
00068 class Buffer {
00069 int width, height;
00070 T *image, *img;
00071 public:
00072
00073
00074
00075 Buffer(int w, int h);
00076 ~Buffer() { delete [] img; }
00077
00078 T *GetData() const { return image; }
00079
00080 int GetWidth() const { return width; }
00081
00082 int GetHeight() const { return height; }
00083
00084 T *operator[](int i) {
00085 return &image[((i+height)%height)*width];
00086 }
00087
00088
00089 void Clear(T val = (T) 0);
00090 };
00091
00092 template<class T>
00093 SImage<T>::SImage() : SImage(32, 32, NULL)
00094 {
00095
00096 }
00097
00098 template<class T>
00099 SImage<T>::SImage(int w, int h, T *ptr) : width(w), height(h)
00100 {
00101 int extra = 16 / sizeof(T);
00102 if (ptr==NULL) {
00103 img = new T[w*h+extra];
00104 localalloc = true;
00105
00106 #if __WORDSIZE == 64
00107 image = (T *)((uint64_t)(img+extra-1) & (uint64_t)(~15));
00108 #else
00109 image = (T *)((uint32_t)(img+extra-1) & (uint32_t)(~15));
00110 #endif
00111 } else {
00112 img = ptr;
00113 localalloc = false;
00114 image = img;
00115 }
00116 }
00117
00118 template<class T>
00119 void SImage<T>::SetSize(int w, int h)
00120 {
00121 if (w==width && h==height)
00122 return;
00123 if (localalloc)
00124 delete [] img;
00125 width = w;
00126 height = h;
00127 int extra = 16 / sizeof(T);
00128 img = new T[w*h+extra];
00129 localalloc = true;
00130
00131 #if __WORDSIZE == 64
00132 image = (T *)((uint64_t)(img+extra-1) & (uint64_t)(~15));
00133 #else
00134 image = (T *)((uint32_t)(img+extra-1) & (uint32_t)(~15));
00135 #endif
00136 }
00137
00138 template<class T>
00139 bool SImage<T>::Load(const char *filename)
00140 {
00141 std::ifstream imagefile;
00142 imagefile.open(filename, std::ios::binary);
00143 if (!imagefile) {
00144 std::cerr << "Error: couldn't find PPM file " << filename << std::endl;
00145 return false;
00146 }
00147 char string[80];
00148 imagefile >> string;
00149 if (strcmp(string,"P2") && strcmp(string,"P5")) {
00150 std::cerr << "Error: " << filename << " is not an PGM file" << std::endl;
00151 return false;
00152 }
00153 char comment[120];
00154 imagefile >> comment[0];
00155 while (comment[0]=='#') {
00156 imagefile.getline(comment, 119, '\n');
00157 imagefile >> comment[0];
00158 }
00159 imagefile.putback(comment[0]);
00160 int w, h, d;
00161 imagefile >> w;
00162 imagefile >> h;
00163 imagefile >> d;
00164 int size = w * h;
00165 if (w!=width || h!=height) {
00166 delete [] img;
00167 width = w;
00168 height = h;
00169 int extra = 16 / sizeof(T);
00170 img = new T[size+extra];
00171
00172 #if __WORDSIZE == 64
00173 image = (T *)((uint64_t)(img+extra) & (uint64_t)(~15));
00174 #else
00175 image = (T *)((uint32_t)(img+extra) & (uint32_t)(~15));
00176 #endif
00177 std::cout << "WARNING: The size of the loaded image was changed" << std::endl;
00178 }
00179 int value;
00180 if (strcmp(string,"P2")) {
00181 unsigned char *tmp = new unsigned char[size];
00182 imagefile.ignore(1, '\n');
00183 imagefile.read((char*)tmp, size);
00184 for(int cnt=0;cnt<size;cnt++)
00185 image[cnt] = (T)tmp[cnt];
00186 delete [] tmp;
00187 } else {
00188 for(int cnt=0;cnt<size;cnt++) {
00189 imagefile >> value;
00190 image[cnt] = (T)value;
00191 }
00192 }
00193 imagefile.close();
00194 return true;
00195 }
00196
00197 template<class T>
00198 bool SImage<T>::LoadRGB(const char *filename)
00199 {
00200 std::ifstream imagefile;
00201 imagefile.open(filename);
00202 if (!imagefile) {
00203 std::cerr << "Error: couldn't find PPM file " << filename << std::endl;
00204 return false;
00205 }
00206 char string[80];
00207 imagefile >> string;
00208 if (strcmp(string,"P3") && strcmp(string,"P6")) {
00209 std::cerr << "Error: " << filename << " is not an PPM file" << std::endl;
00210 return false;
00211 }
00212 char comment[120];
00213 imagefile >> comment[0];
00214 while (comment[0]=='#') {
00215 imagefile.getline(comment, 119, '\n');
00216
00217 imagefile >> comment[0];
00218 }
00219 imagefile.putback(comment[0]);
00220 int w, h, d;
00221 imagefile >> w;
00222 imagefile >> h;
00223 imagefile >> d;
00224 w *= 3;
00225 int size = w * h;
00226 if (w!=width || h!=height) {
00227 delete [] img;
00228 width = w;
00229 height = h;
00230 int extra = 16 / sizeof(T);
00231 img = new T[size+extra];
00232
00233 #if __WORDSIZE == 64
00234 image = (T *)((uint64_t)(img+extra) & (uint64_t)(~15));
00235 #else
00236 image = (T *)((uint32_t)(img+extra) & (uint32_t)(~15));
00237 #endif
00238 std::cout << "WARNING: The size of the loaded image was changed" << std::endl;
00239 }
00240 if (strcmp(string,"P3")) {
00241 unsigned char *tmp = new unsigned char[size];
00242 imagefile.ignore(1, '\n');
00243 imagefile.read((char*)tmp, size);
00244 for (int cnt=0;cnt<size;cnt+=3) {
00245 image[cnt+0] = (T)tmp[cnt+0];
00246 image[cnt+1] = (T)tmp[cnt+1];
00247 image[cnt+2] = (T)tmp[cnt+2];
00248 }
00249 delete [] tmp;
00250 } else {
00251 int value;
00252 for (int cnt=0;cnt<size;cnt+=3) {
00253 imagefile >> value;
00254 image[cnt+0] = (T)value;
00255 imagefile >> value;
00256 image[cnt+1] = (T)value;
00257 imagefile >> value;
00258 image[cnt+2] = (T)value;
00259 }
00260 }
00261 imagefile.close();
00262 return true;
00263 }
00264
00265 template<class T>
00266 void SImage<T>::Store(const char *filename, bool type, bool ascii) const
00267 {
00268 std::ofstream imagefile;
00269 imagefile.open(filename, std::ios::binary);
00270 if (ascii)
00271 imagefile << "P2\n";
00272 else
00273 imagefile << "P5\n";
00274 imagefile << width << " " << height << "\n";
00275 imagefile << "255\n";
00276 int size = width * height;
00277 float small, delta, large;
00278 if (type) {
00279 small = large = image[0];
00280 for (int cnt=0;cnt<size;cnt++) {
00281 if (small>image[cnt]) small = (float)image[cnt];
00282 if (large<image[cnt]) large = (float)image[cnt];
00283 }
00284 delta = (float)255.0 / (large-small);
00285 if (ascii) {
00286 for (int cnt=0;cnt<size;cnt++) {
00287 int value = (int)(delta * ((float)image[cnt]-small));
00288 if (value<0) value = 0;
00289 else if (value>255) value = 255;
00290 imagefile << value;
00291 if ((cnt&15)==15) imagefile << "\n";
00292 else imagefile << " ";
00293 }
00294 } else {
00295 unsigned char *tmp = new unsigned char[size];
00296 for (int cnt=0;cnt<size;cnt++) {
00297 int value = (int)(delta * ((float)image[cnt]-small));
00298 if (value<0) tmp[cnt] = 0;
00299 else if (value>255) tmp[cnt] = 255;
00300 tmp[cnt] = (unsigned char)value;
00301 }
00302 imagefile.write((char*)tmp, size);
00303 delete [] tmp;
00304 }
00305 } else {
00306 if (ascii) {
00307 for(int cnt=0;cnt<size;cnt++) {
00308 int value = (int)image[cnt];
00309 imagefile << value;
00310 if ((cnt&15)==15) imagefile << "\n";
00311 else imagefile << " ";
00312 }
00313 } else {
00314 if (typeid(T)==typeid(unsigned char) || typeid(T)==typeid(char))
00315 imagefile.write((char*)image, size);
00316 else {
00317 unsigned char *tmp = new unsigned char[size];
00318 for (int cnt=0;cnt<size;cnt++)
00319 tmp[cnt] = (unsigned char)image[cnt];
00320 imagefile.write((char*)tmp, size);
00321 delete [] tmp;
00322 }
00323 }
00324 }
00325 imagefile.close();
00326 std::cout << "File " << filename << " saved. ";
00327 if (type) std::cout << "[" << small << "," << large << "]";
00328 std::cout << std::endl;
00329 }
00330
00331 template<class T>
00332 void SImage<T>::StoreRGB(const char *filename) const
00333 {
00334 assert(!(width%3));
00335 std::ofstream imagefile;
00336 imagefile.open(filename);
00337 imagefile << "P3\n";
00338 imagefile << width/3 << " " << height << "\n";
00339 imagefile << "255\n";
00340 int size = width * height;
00341 for(int cnt=0;cnt<size;cnt+=3) {
00342 imagefile << (int)image[cnt+0] << " ";
00343 imagefile << (int)image[cnt+1] << " ";
00344 imagefile << (int)image[cnt+2];
00345 if ((cnt%15)==12) imagefile << "\n";
00346 else imagefile << " ";
00347 }
00348 imagefile.close();
00349 std::cout << "File " << filename << " saved. " << std::endl;
00350 }
00351
00352 template<class T>
00353 void SImage<T>::StoreYUV(const char *filename) const
00354 {
00355 assert(!(width%2));
00356 std::ofstream imagefile;
00357 imagefile.open(filename);
00358 imagefile << "P3\n";
00359 imagefile << width/2 << " " << height << "\n";
00360 imagefile << "255\n";
00361 int size = width * height;
00362 for(int cnt=0;cnt<size;cnt+=4) {
00363 int y1 = (int)image[cnt+3];
00364 int v = (int)image[cnt+2]-128;
00365 int y0 = (int)image[cnt+1];
00366 int u = (int)image[cnt]-128;
00367 int r = (int)(1.0000*y0 - 0.0009*u + 1.1359*v);
00368 int g = (int)(1.0000*y0 - 0.3959*u - 0.5783*v);
00369 int b = (int)(1.0000*y0 + 2.0411*u - 0.0016*v);
00370 r = (r<0 ? 0 : (r>255 ? 255 : r));
00371 g = (g<0 ? 0 : (g>255 ? 255 : g));
00372 b = (b<0 ? 0 : (b>255 ? 255 : b));
00373 imagefile << r << " " << g << " " << b << " ";
00374 r = (int)(1.0000*y1 - 0.0009*u + 1.1359*v);
00375 g = (int)(1.0000*y1 - 0.3959*u - 0.5783*v);
00376 b = (int)(1.0000*y1 + 2.0411*u - 0.0016*v);
00377 r = (r<0 ? 0 : (r>255 ? 255 : r));
00378 g = (g<0 ? 0 : (g>255 ? 255 : g));
00379 b = (b<0 ? 0 : (b>255 ? 255 : b));
00380 imagefile << r << " " << g << " " << b << " ";
00381 if ((cnt%15)==12) imagefile << "\n";
00382 else imagefile << " ";
00383 }
00384 imagefile.close();
00385 std::cout << "File " << filename << " saved. " << std::endl;
00386 }
00387
00388 template <class T>
00389 void SImage<T>::operator=(SImage<T> &src)
00390 {
00391 memcpy(image, src.GetData(), sizeof(T) * width * height);
00392 }
00393
00394 template<class T>
00395 Buffer<T>::Buffer(int w, int h) : width(w), height(h)
00396 {
00397 int extra = 16 / sizeof(T);
00398 img = new T[w*h+extra];
00399
00400
00401 #if __WORDSIZE == 64
00402 image = (T *)((uint64_t)(img+extra) & (uint64_t)(~15));
00403 #else
00404 image = (T *)((uint32_t)(img+extra) & (uint32_t)(~15));
00405 #endif
00406 }
00407
00408 template<class T>
00409 void Buffer<T>::Clear(T val)
00410 {
00411 for (int i=0;i<(width*height);i++)
00412 image[i] = (T) val;
00413 }
00414
00415 #endif // TPIMAGE_H