tpimage.h

Go to the documentation of this file.
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 /** @file tpimage.h
00013     Templated image class */
00014 
00015 /// Templated image class
00016 template<class T>
00017 class SImage {
00018   int width, height;
00019   T *image, *img;
00020   bool localalloc;
00021  public:
00022   /// Empty constructor
00023   SImage();
00024   /// Constructor
00025   /** @param w image width
00026       @param h image height
00027       @param ptr image data pointer (if NULL, allocated internally) */
00028   SImage(int w, int h, T *ptr=NULL);
00029   ~SImage() { if (localalloc) delete [] img; }
00030   /// Set new image size
00031   /** @param w image width
00032       @param h image height */
00033   void SetSize(int w, int h);
00034   /// Set image data position
00035   /** @param ptr image data pointer */
00036   void SetData(T *ptr) { image = ptr; }
00037   /// Load grey-level image from PGM file
00038   /** @param filename image file name */
00039   bool Load(const char *filename);
00040   /// Load RGB image (three values per pixel) from PPM file
00041   /** @param filename image file name */
00042   bool LoadRGB(const char *filename);
00043   /// Store grey-level image as PGM file
00044   /** @param filename image file name
00045       @param norm whether to normalize image before storage
00046       @param ascii whether to store in ASCII or binary format */
00047   void Store(const char *filename, bool norm = false, bool ascii =false) const;
00048   /// Store RGB image (three values per pixel) as PPM file
00049   /** @param filename image file name */
00050   void StoreRGB(const char *filename) const;
00051   /// Convert from UYVY (two values per pixel) to RGB and store as PPM file
00052   /** @param filename image file name */
00053   void StoreYUV(const char *filename) const;
00054   /// Get image data position
00055   T *GetData() const { return image; }
00056   /// Get image width
00057   int GetWidth() const { return width; }
00058   /// Get image height
00059   int GetHeight() const { return height; }
00060   /// Get pointer to pixel row \b i
00061   T *operator[](int i) { return &image[i*width]; }
00062   /// Copy image data
00063   void operator=(SImage<T> &src);
00064 };
00065 
00066 /// Templated circular buffer
00067 template<class T>
00068 class Buffer {
00069   int width, height;
00070   T *image, *img;
00071  public:
00072   /// Constructor
00073   /** @param w buffer width
00074       @param h buffer height */
00075   Buffer(int w, int h);
00076   ~Buffer() { delete [] img; }
00077   /// Get buffer data position
00078   T *GetData() const { return image; }
00079   /// Get buffer width
00080   int GetWidth() const { return width; }
00081   /// Get buffer height
00082   int GetHeight() const { return height; }
00083   /// Get pointer to pixel row \b i modulo \b height
00084   T *operator[](int i) {
00085     return &image[((i+height)%height)*width];
00086   }
00087   /// Clear buffer data
00088   /** @param val value to fill buffer with */
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     //image = (T *)((unsigned long)(img+extra-1) & (unsigned long)(~15));
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   //image  = (T *)((unsigned long)(img+extra-1) & (unsigned long)(~15));
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     //image  = (T *)((unsigned long)(img+extra) & (unsigned long)(~15));
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")) { // not ascii, thus raw
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 {                   // with ascii
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     //std::cout << comment << std::endl;
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     //image  = (T *)((unsigned long)(img+extra) & (unsigned long)(~15));
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")) { // not ascii, thus raw
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) {  // with rescale, with 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 {      // with rescale, no ascii
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) { // no rescale, with 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 {    // no rescale, no ascii
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     //std::cout << "Buffer: " << img << " " << &img[w*h+extra] << std::endl;
00400     //image  = (T *)((unsigned long)(img+extra) & (unsigned long)(~15));
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
Generated on Sun May 8 08:40:37 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3