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