inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/image
Go to the documentation of this file.
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
00002 // See the file inlib.license for terms.
00003 
00004 #ifndef inlib_image
00005 #define inlib_image
00006 
00007 #include <vector>
00008 #include <cstring> //memcpy
00009 
00010 #include "mnmx"
00011 
00012 namespace inlib {
00013 namespace image {
00014 
00015 // give a set of cols*rows same size rgb-image and build 
00016 // a big image :
00017 inline unsigned char* concatenate(unsigned char** a_buffers,
00018                                   unsigned int a_w,unsigned int a_h,
00019                                   unsigned int a_bpp,
00020                                   unsigned int a_cols,unsigned int a_rows,
00021                                   unsigned int a_bw,unsigned int a_bh,
00022                                   unsigned char a_bc,
00023                                   unsigned int& a_rw,unsigned int& a_rh){
00024 
00025   // assume a_buffers has a_cols*a_rows entries.
00026   // a_buffers[0] is bottom-left
00027   // a_row=0 is bottom.
00028 
00029   unsigned wbw = a_w + 2*a_bw;
00030   unsigned hbh = a_h + 2*a_bh;
00031 
00032   a_rw = wbw * a_cols;
00033   a_rh = hbh * a_rows;
00034 
00035   //printf("debug : %d %d\n",a_rw,a_rh);
00036 
00037   // on big concatenated image the below may fail :
00038   unsigned char* rb = new unsigned char[a_rh*a_rw*a_bpp];
00039   if(!rb) {a_rw = 0;a_rh = 0;return 0;}
00040 
00041   unsigned int wbw3 = wbw*a_bpp;
00042   unsigned int aw3 = a_w*a_bpp;
00043   
00044   //copy tiles :  
00045   unsigned int index = 0;
00046   for(unsigned int j=0;j<a_rows;j++) {
00047     for(unsigned int i=0;i<a_cols;i++) {
00048       unsigned char* tile = a_buffers[index];
00049 
00050       for(unsigned int r=0;r<hbh;r++) {
00051         unsigned char* pos = rb + (j*hbh+r)*a_rw*a_bpp + i*wbw*a_bpp;
00052         ::memset(pos,a_bc,wbw3);
00053       }
00054 
00055       for(unsigned int r=0;r<a_h;r++) {
00056         unsigned char* pos = rb + (j*hbh+r+a_bh)*a_rw*a_bpp + 
00057           (i*wbw+a_bw)*a_bpp;
00058         unsigned char* ptile = tile+r*aw3;        
00059         for(unsigned int c=0;c<aw3;c++) *pos++ = *ptile++;
00060       }
00061 
00062       index++;
00063     }
00064   }
00065 
00066   return rb;
00067 }
00068 
00069 /*
00070 inline unsigned char* expand(unsigned char* a_buffer,
00071                              unsigned int a_w,unsigned int a_h,
00072                              unsigned int a_factor) {
00073   if(!a_factor) return 0;
00074   if(a_factor==1) return a_buffer; //WARNING : same buffer.
00075 
00076   unsigned int nw = a_w*a_factor;
00077   unsigned int nh = a_h*a_factor;
00078 
00079   //std::cout << "debug :"
00080   //          << " " << a_w << " " << a_h
00081   //          << " " << a_rw << " " << a_rh
00082   //          << std::endl;
00083 
00084   unsigned char* nb = new unsigned char[nh*(nw*3)];
00085   if(!nb) return 0;
00086 
00087   for(unsigned int j=0;j<a_h;j++) {
00088     for(unsigned int i=0;i<a_w;i++) {
00089       //position in the original image.
00090       unsigned char* pos = a_buffer + j * (a_w * 3) + i*3;
00091 
00092       for(unsigned int fr=0;fr<a_factor;fr++) {
00093         for(unsigned int fc=0;fc<a_factor;fc++) {
00094           //position in the new image.
00095           unsigned char* npos = 
00096             nb + (j*a_factor+fr) * (nw * 3) + (i*a_factor+fc)*3;
00097           *npos = *pos;
00098           *(npos+1) = *(pos+1);
00099           *(npos+2) = *(pos+2);
00100         }
00101       }
00102 
00103     }
00104   }
00105 
00106   return nb;
00107 }
00108 
00109 inline unsigned char* to_texture(unsigned char* a_buffer,
00110                                  unsigned int a_w,unsigned int a_h,
00111                                  bool a_expand,
00112                                  unsigned char a_r,
00113                                  unsigned char a_g,
00114                                  unsigned char a_b,
00115                                  unsigned int& a_rw,unsigned int& a_rh) {
00116 
00117   if(a_expand) {
00118     // if a_w, a_h are not power of two, we expand
00119     // the image and fill new spaces with rgb.
00120 
00121     // are a_w, a_h power of two ?
00122     a_rw = 2;
00123     while(true) {if(a_rw>=a_w) break;a_rw *=2;}
00124     a_rh = 2;
00125     while(true) {if(a_rh>=a_h) break;a_rh *=2;}
00126   
00127     if((a_rw==a_w)&&(a_rh==a_h)) return a_buffer; //WARNING : same buffer.
00128   
00129     //std::cout << "debug :"
00130     //          << " " << a_w << " " << a_h
00131     //          << " " << a_rw << " " << a_rh
00132     //          << std::endl;
00133   
00134     unsigned char* rb = new unsigned char[a_rh*(a_rw*3)];
00135     if(!rb) {a_rw = 0;a_rh = 0;return 0;}
00136   
00137     // initialize with given color :
00138     for(unsigned int j=0;j<a_rh;j++) {  //j=0 -> bottom.
00139       unsigned char* pos = rb + j * (a_rw * 3);
00140       for(unsigned int i=0;i<a_rw;i++) {
00141         *pos = a_r;pos++;
00142         *pos = a_g;pos++;
00143         *pos = a_b;pos++;
00144       }
00145     }
00146   
00147     // center :
00148     unsigned int col = (a_rw-a_w)/2;  
00149     unsigned int row = (a_rh-a_h)/2;  
00150   
00151     // copy original image in a centered part of the new one :
00152     for(unsigned int j=0;j<a_h;j++) {
00153       unsigned char* pos = a_buffer + j * (a_w * 3);
00154       unsigned char* rpos = rb + (j+row) * (a_rw * 3) + col*3;
00155       ::memcpy(rpos,pos,a_w*3);
00156     }
00157   
00158     return rb;
00159   } else {
00160 
00161     // closest w,h power of two :
00162     unsigned int sw = 2;
00163     while(true) {if((sw*2)>a_w) break;sw *=2;}
00164     unsigned int sh = 2;
00165     while(true) {if((sh*2)>a_h) break;sh *=2;}
00166 
00167     if((sw==a_w)&&(sh==a_h)) {
00168       a_rw = sw;
00169       a_rh = sh;
00170       return a_buffer; //WARNING : same buffer.
00171     }
00172 
00173     unsigned int sx = (a_w-sw)/2;
00174     unsigned int sy = (a_h-sh)/2;
00175 
00176     return inlib::image::get_part(a_buffer,a_w,a_h,sx,sy,sw,sh,a_rw,a_rh);
00177 
00178   }
00179 
00180 }
00181 */
00182 
00183 }}
00184 
00185 #include <ostream>
00186 #include <string>
00187 
00188 namespace inlib {
00189 namespace image {
00190 
00191 typedef unsigned char* (*file_reader)(std::ostream&,const std::string&,unsigned int&,unsigned int&,unsigned int&);
00192 
00193 inline unsigned char* concatenate(std::ostream& a_out,
00194                                   const std::vector<std::string>& a_files,
00195                                   unsigned int a_cols,unsigned int a_rows,
00196                                   unsigned int a_bw,unsigned int a_bh,
00197                                   unsigned char a_bc,
00198                                   file_reader a_file_reader,
00199                                   unsigned int& a_w,unsigned int& a_h,
00200                                   unsigned int& a_bpp) {
00201   // a_files[0] is cols=0, rows=0
00202   // a_files[1] is cols=1, rows=0
00203   // a_files[2] is cols=2, rows=0
00204   // ...
00205   // and row=0 is bottom of big image.
00206 
00207   unsigned int number = a_cols*a_rows;
00208   if(number!=a_files.size()) {
00209     a_out << "inlib::image::concatenate :"
00210               << " bad number of files. " << number << " expected."
00211               << std::endl;
00212     a_bpp = a_w = a_h = 0;
00213     return 0;
00214   }
00215   if(a_files.empty()) {
00216     a_out << "inlib::image::concatenate :"
00217           << " list of files is empty."
00218           << std::endl;
00219     a_bpp = a_w = a_h = 0;
00220     return 0;
00221   }
00222 
00223   unsigned int w1 = 0;
00224   unsigned int h1 = 0;
00225   unsigned int bpp1 = 0;
00226    
00227   typedef unsigned char* buffer_t;
00228   buffer_t* bs = new buffer_t[number];
00229  {for(unsigned int i=0;i<number;i++) {bs[i] = 0;}}
00230 
00231   bool read_failed = false;
00232   unsigned int index = 0;
00233   for(unsigned int j=0;j<a_rows;j++) {
00234     for(unsigned int i=0;i<a_cols;i++) {
00235       const std::string& file = a_files[index];
00236       unsigned int w,h,bpp;
00237       unsigned char* b = a_file_reader(a_out,file,w,h,bpp);
00238       if(!b) {
00239         a_out << "inlib::image::concatenate :"
00240               << " can't read " << file << " expected."
00241               << std::endl;
00242         read_failed = true;
00243         break;
00244       }
00245       if(!index) {
00246         w1 = w;
00247         h1 = h;
00248         bpp1 = bpp;
00249       } else {
00250         if(w!=w1) {
00251           a_out << "inlib::image::concatenate :"
00252                 << " file " << file
00253                 << " does not have same width image as the first file one."
00254                 << " (" << w << "," << w1 << ")."
00255                 << std::endl;
00256           delete [] b;
00257           read_failed = true;
00258           break;
00259         }
00260         if(h!=h1) {
00261           a_out << "inlib::image::concatenate :"
00262                 << " file " << file
00263                 << " does not have same height image as the first file one."
00264                 << " (" << h << "," << h1 << ")."
00265                 << std::endl;
00266           delete [] b;
00267           read_failed = true;
00268           break;
00269         }
00270         if(bpp!=bpp1) {
00271           a_out << "inlib::image::concatenate :"
00272                 << " file " << file
00273                 << " does not have same bytes per pixel as the first file one."
00274                 << " (" << h << "," << h1 << ")."
00275                 << std::endl;
00276           delete [] b;
00277           read_failed = true;
00278           break;
00279         }
00280       }
00281 
00282       bs[index] = b;
00283 
00284       index++;
00285     }
00286     if(read_failed) break;
00287   }
00288 
00289   if(read_failed) {
00290     {for(unsigned int i=0;i<number;i++) {delete [] bs[i];}}
00291     a_bpp = a_w = a_h = 0;
00292     return 0;
00293   }
00294 
00295   unsigned int wa,ha;
00296   unsigned char* ba = 
00297     inlib::image::concatenate(bs,w1,h1,bpp1,
00298                               a_cols,a_rows,a_bw,a_bh,a_bc,wa,ha);
00299   if(!ba) {
00300     a_out << "inlib::image::concatenate :"
00301           << " failed to concatenate all buffers."
00302           << std::endl;
00303     {for(unsigned int i=0;i<number;i++) {delete [] bs[i];}}
00304     a_bpp = a_w = a_h = 0;
00305     return 0;
00306   } 
00307 
00308   {for(unsigned int i=0;i<number;i++) {delete [] bs[i];}}
00309 
00310   a_w = wa;
00311   a_h = ha;
00312   a_bpp = bpp1;
00313   return ba;
00314 }
00315 
00316 #if defined(__CINT__)
00317 // something does not pass with the below.
00318 #else
00319 typedef unsigned char* (*reader)(FILE*,unsigned int&,unsigned int&);
00320 typedef bool(*writer)(FILE*,unsigned char*,unsigned int,unsigned int);
00321 
00322 inline bool convert(std::ostream& a_out,
00323                     const std::string& a_sin,
00324                     reader a_reader,
00325                     const std::string& a_sout,
00326                     writer a_writer){
00327   
00328   FILE* fin = ::fopen(a_sin.c_str(),"rb");
00329   if(!fin) {
00330     a_out << "inlib::image::convert :"
00331           << " can't open " << a_sin
00332           << std::endl;
00333     return false;
00334   }
00335 
00336   unsigned int w,h;
00337   unsigned char* b = a_reader(fin,w,h);
00338   if(!b) {
00339     a_out << "inlib::image::convert :"
00340           << " can't read " << a_sin
00341           << std::endl;
00342     ::fclose(fin);
00343     return false;
00344   }
00345   ::fclose(fin);
00346 
00347   FILE* fout = ::fopen(a_sout.c_str(),"wb");
00348   if(!fout) {
00349     a_out << "inlib::image::convert :"
00350           << " can't open " << a_sout
00351           << std::endl;
00352     delete [] b;
00353     return false;
00354   }
00355 
00356   if(!a_writer(fout,b,w,h)) {
00357     a_out << "inlib::image::convert :"
00358           << " can't write " << a_sout
00359           << std::endl;
00360     ::fclose(fout);
00361     delete [] b;
00362     return false;
00363   }
00364   ::fclose(fout);
00365   delete [] b;
00366   return true;
00367 }
00368 #endif
00369 
00370 }}
00371 
00372 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines