inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/img_old
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_img
00005 #define inlib_img
00006 
00007 #ifdef INLIB_MEM
00008 #include "mem"
00009 #endif
00010 
00011 #include <string> //memcpy
00012 #include <cstring> //memcpy
00013 #include "mnmx"
00014 
00015 #include <vector> //concatenate
00016 
00017 namespace inlib {
00018 
00019 template <class T>
00020 class img {
00021   static const std::string& s_class() {
00022     static const std::string s_v("inlib::img");
00023     return s_v;
00024   }
00025 public:
00026   img(unsigned int a_n)
00027   :m_w(0),m_h(0),m_n(a_n)
00028   ,m_buffer(0)
00029   ,m_owner(false)
00030   {
00031 #ifdef INLIB_MEM
00032     mem::increment(s_class().c_str());
00033 #endif
00034   }
00035   img(unsigned int a_w,unsigned int a_h,unsigned int a_n,
00036              T* a_buffer,bool a_owner)
00037   :m_w(a_w),m_h(a_h),m_n(a_n)
00038   ,m_buffer(a_buffer)
00039   ,m_owner(a_owner)
00040   {
00041 #ifdef INLIB_MEM
00042     mem::increment(s_class().c_str());
00043 #endif
00044   }
00045   virtual ~img() {
00046     if(m_owner) delete [] m_buffer;
00047 #ifdef INLIB_MEM
00048     mem::decrement(s_class().c_str());
00049 #endif
00050   }
00051 public:
00052   img(const img& a_from)
00053   :m_w(a_from.m_w),m_h(a_from.m_h),m_n(a_from.m_n)
00054   ,m_buffer(0)
00055   ,m_owner(a_from.m_owner)
00056   {
00057 #ifdef INLIB_MEM
00058     mem::increment(s_class().c_str());
00059 #endif
00060     if(m_owner) {
00061       unsigned int sz = m_w*m_h*m_n;
00062       if(!sz) return;
00063       m_buffer = new T[sz];
00064       if(!m_buffer) {
00065         m_w = 0;m_h = 0;m_owner = false;
00066         return; //throw
00067       }
00068       ::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
00069     } else {
00070       m_buffer = a_from.m_buffer;
00071     }
00072   }
00073   img& operator=(const img& a_from){
00074     if(m_owner) delete [] m_buffer;
00075     m_buffer = 0;
00076     m_w = a_from.m_w;
00077     m_h = a_from.m_h;
00078     m_n = a_from.m_n;
00079     m_owner = a_from.m_owner;
00080     if(m_owner) {
00081       unsigned int sz = m_w*m_h*m_n;
00082       if(!sz) return *this;
00083       m_buffer = new T[sz];
00084       if(!m_buffer) {
00085         m_w = 0;m_h = 0;m_owner = false;
00086         return *this;  //throw
00087       }
00088       ::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
00089     } else {
00090       m_buffer = a_from.m_buffer;
00091     }
00092     return *this;
00093   }
00094 public:
00095   bool operator==(const img& a_from) const {return equal(a_from);}
00096   bool operator!=(const img& a_from) const {return !operator==(a_from);}
00097 public:
00098   void transfer(img& a_from) {
00099     if(m_owner) delete [] m_buffer;
00100     m_w = a_from.m_w;
00101     m_h = a_from.m_h;
00102     //don't touch m_n
00103     m_buffer = a_from.m_buffer;
00104     m_owner = a_from.m_owner;
00105     // empty a_from :
00106     a_from.m_w = 0;
00107     a_from.m_h = 0;
00108     a_from.m_buffer = 0;
00109     a_from.m_owner = false;
00110   }
00111 
00112   void clear() {
00113     if(m_owner) delete [] m_buffer;
00114     m_w = 0;
00115     m_h = 0;
00116     m_buffer = 0;
00117     m_owner = false;
00118   }
00119   void set(unsigned int a_w,unsigned int a_h,
00120                   T* a_buffer,bool a_owner) {
00121     if(m_owner) delete [] m_buffer;
00122     m_w = a_w;
00123     m_h = a_h;
00124     //don't touch m_n
00125     m_buffer = a_buffer;
00126     m_owner = a_owner;
00127   }
00128   bool copy(const img& a_from){
00129     if(m_owner) delete [] m_buffer;
00130     m_buffer = 0;
00131     m_w = a_from.m_w;
00132     m_h = a_from.m_h;
00133     m_n = a_from.m_n;
00134     unsigned int sz = m_w*m_h*m_n;
00135     if(!sz) {
00136       m_w = 0;m_h = 0;m_owner = false;
00137       return false;
00138     }
00139     m_buffer = new T[sz];
00140     if(!m_buffer) {
00141       m_w = 0;m_h = 0;m_owner = false;
00142       return false;
00143     }
00144     ::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
00145     m_owner = true;
00146     return true;
00147   }
00148   bool allocate(unsigned int a_w,unsigned int a_h){
00149     if(m_owner) delete [] m_buffer;
00150     m_buffer = 0;
00151     unsigned int sz = a_w*a_h*m_n;
00152     if(!sz) {
00153       m_w = 0;m_h = 0;m_owner = false;
00154       return false;
00155     }
00156     m_w = a_w;
00157     m_h = a_h;
00158     m_buffer = new T[sz];
00159     if(!m_buffer) {
00160       m_w = 0;m_h = 0;m_owner = false;
00161       return false;
00162     }
00163     m_owner = true;
00164     return true;
00165   }
00166   void make_empty() {
00167     if(m_owner) delete [] m_buffer;
00168     m_w = 0;
00169     m_h = 0;
00170     //don't touch m_n
00171     m_buffer = 0;
00172     m_owner = false;
00173   }
00174   bool equal(const img& a_from) const {
00175     if(m_w!=a_from.m_w) return false;
00176     if(m_h!=a_from.m_h) return false;
00177     if(m_n!=a_from.m_n) return false;
00178     //don't test ownership.
00179     unsigned int sz = m_w*m_h*m_n;
00180     T* pos = m_buffer;
00181     T* fpos = a_from.m_buffer;
00182     for(unsigned int index=0;index<sz;index++,pos++,fpos++) {
00183       if((*pos)!=(*fpos)) return false;
00184     }
00185     return true;
00186   }
00187   unsigned int width() const {return m_w;}
00188   unsigned int height() const {return m_h;}
00189   unsigned int bytes_per_pixel() const {return m_n;}
00190   unsigned int bpp() const {return m_n;}
00191   T* buffer() const {return m_buffer;}
00192   bool owner() const {return m_owner;}
00193   unsigned int size() const {return m_w*m_h*m_n*sizeof(T);} //bytes.
00194 public:
00195   bool expand(unsigned int a_factor,img<T>& a_res) const {
00196     if(a_res.m_n!=m_n) {
00197       a_res.make_empty();
00198       return false;
00199     }
00200     if(!a_factor) {
00201       a_res.make_empty();
00202       return false;
00203     }
00204     if(a_factor==1) {
00205       a_res.set(m_w,m_h,m_buffer,false);
00206       return true;
00207     }
00208   
00209     unsigned int nw = m_w*a_factor;
00210     unsigned int nh = m_h*a_factor;
00211   
00212     T* nb = new T[nh*nw*m_n];
00213     if(!nb) {
00214       a_res.make_empty();
00215       return false;
00216     }
00217   
00218     for(unsigned int j=0;j<m_h;j++) {
00219       for(unsigned int i=0;i<m_w;i++) {
00220         //position in the original image.
00221         T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
00222   
00223         for(unsigned int fr=0;fr<a_factor;fr++) {
00224           for(unsigned int fc=0;fc<a_factor;fc++) {
00225             //position in the new image.
00226             T* npos = nb + (j*a_factor+fr) * (nw * m_n) + (i*a_factor+fc)*m_n;
00227             for(unsigned int ipix=0;ipix<m_n;ipix++) {
00228               *(npos+ipix) = *(pos+ipix);
00229             }
00230           }
00231         }
00232   
00233       }
00234     }
00235   
00236     a_res.set(nw,nh,nb,true);
00237     return true;
00238   }
00239 
00240   bool contract(unsigned int a_factor,img<T>& a_res) const {
00241     // a_factor pixels are contracted in one.
00242     if(a_res.m_n!=m_n) {
00243       a_res.make_empty();
00244       return false;
00245     }
00246     if(!a_factor) {
00247       a_res.make_empty();
00248       return false;
00249     }
00250     if(a_factor==1) {
00251       a_res.set(m_w,m_h,m_buffer,false);
00252       return true;
00253     }
00254   
00255     unsigned int nw = m_w/a_factor;
00256     unsigned int nh = m_h/a_factor;
00257     unsigned int sz = nh*nw*m_n;
00258     if(!sz) {
00259       a_res.make_empty();
00260       return false;
00261     }
00262   
00263     T* nb = new T[sz];
00264     if(!nb) {
00265       a_res.make_empty();
00266       return false;
00267     }
00268 
00269     //T* npos = nb;
00270     //for(unsigned int ipix=0;ipix<sz;ipix++) {*npos = 125;npos++;}
00271 
00272     double* pixels = new double[m_n]; //for mean value.
00273     if(!pixels) {
00274       delete [] nb;
00275       a_res.make_empty();
00276       return false;
00277     }
00278     unsigned int nfac = a_factor*a_factor;
00279 
00280     for(unsigned int j=0;j<nh;j++) {
00281       for(unsigned int i=0;i<nw;i++) {
00282 
00283         // take mean value of a_factor*a_factor pixels :  
00284         for(unsigned int ipix=0;ipix<m_n;ipix++) pixels[ipix] = 0;
00285             
00286         for(unsigned int fr=0;fr<a_factor;fr++) {
00287           for(unsigned int fc=0;fc<a_factor;fc++) {
00288             T* pos = m_buffer + (j*a_factor+fr)*(m_w*m_n) +(i*a_factor+fc)*m_n;
00289             for(unsigned int ipix=0;ipix<m_n;ipix++) {
00290               pixels[ipix] += double(*pos);pos++;
00291             }
00292           }
00293         }
00294         for(unsigned int ipix=0;ipix<m_n;ipix++) {
00295           pixels[ipix] /= double(nfac);
00296         }
00297 
00298         //position in the result image.
00299         T* npos = nb + j * (nw * m_n) + i*m_n;
00300         for(unsigned int ipix=0;ipix<m_n;ipix++) {
00301           *npos = T(pixels[ipix]);npos++;
00302         }
00303       }
00304     }
00305 
00306     delete [] pixels;
00307 
00308     a_res.set(nw,nh,nb,true);
00309     return true;
00310   }
00311 
00312   bool get_part(unsigned int a_sx,unsigned int a_sy,
00313                        unsigned int a_sw,unsigned int a_sh,
00314                        img<T>& a_res) const {
00315 
00316     if(a_res.m_n!=m_n) {
00317       a_res.make_empty();
00318       return false;
00319     }
00320 
00321     if((a_sx>=m_w)||(a_sy>=m_h)){
00322       a_res.make_empty();
00323       return false;
00324     }
00325   
00326     // 012345
00327     unsigned int rw = inlib::mn<unsigned int>(m_w-a_sx,a_sw); 
00328     unsigned int rh = inlib::mn<unsigned int>(m_h-a_sy,a_sh); 
00329     if((!rw)||(!rh)) {
00330       a_res.make_empty();
00331       return false;
00332     }
00333   
00334     //printf("debug : %d %d\n",a_rw,a_rh);
00335   
00336     T* rb = new T[rh*rw*m_n];
00337     if(!rb) {
00338       a_res.make_empty();
00339       return false;
00340     }
00341   
00342     unsigned int rstride = rw * m_n;
00343     T* rpos = rb;
00344 
00345     unsigned int stride = m_w * m_n;
00346     T* pos = m_buffer+a_sy*stride+a_sx*m_n;
00347 
00348     for(unsigned int j=0;j<rh;j++,rpos+=rstride,pos+=stride) {//j=0 -> bottom.
00349       ::memcpy(rpos,pos,rstride*sizeof(T));
00350     }
00351 
00352     a_res.set(rw,rh,rb,true);  
00353     return true;
00354   }
00355 
00356   bool to_texture(bool a_expand,
00357                          T a_pixel[], //size shoulde be a_img.m_n.
00358                          img<T>& a_res) const {
00359     if(a_res.m_n!=m_n) {
00360       a_res.make_empty();
00361       return false;
00362     }
00363 
00364     if(a_expand) {
00365       // if a_w, a_h are not power of two, we expand
00366       // the image and fill new spaces with rgb.
00367   
00368       // are a_w, a_h power of two ?
00369       unsigned int rw = 2;
00370       while(true) {if(rw>=m_w) break;rw *=2;}
00371       unsigned int rh = 2;
00372       while(true) {if(rh>=m_h) break;rh *=2;}
00373     
00374       if((rw==m_w)&&(rh==m_h)) {
00375         a_res.set(m_w,m_h,m_buffer,false); //WARNING owner=false.
00376         return true;
00377       }
00378     
00379       T* rb = new T[rh*rw*m_n];
00380       if(!rb) {
00381         a_res.make_empty();
00382         return false;
00383       }
00384     
00385       // initialize with given color :
00386       for(unsigned int j=0;j<rh;j++) {  //j=0 -> bottom.
00387         T* pos = rb + j * (rw * m_n);
00388         for(unsigned int i=0;i<rw;i++) {
00389           for(unsigned int n=0;n<m_n;n++) {
00390             *pos = a_pixel[n];pos++; //memcpy ?
00391           }
00392         }
00393       }
00394     
00395       // center :
00396       unsigned int col = (rw-m_w)/2;  
00397       unsigned int row = (rh-m_h)/2;  
00398     
00399       // copy original image in a centered part of the new one :
00400       for(unsigned int j=0;j<m_h;j++) {
00401         T* pos = m_buffer + j * (m_w * m_n);
00402         T* rpos = rb + (j+row) * (rw * m_n) + col*m_n;
00403         ::memcpy(rpos,pos,m_w*m_n*sizeof(T));
00404       }
00405 
00406       a_res.set(rw,rh,rb,true);
00407     
00408       return true;
00409     } else {
00410   
00411       // closest w,h power of two :
00412       unsigned int sw = 2;
00413       while(true) {if((sw*2)>m_w) break;sw *=2;}
00414       unsigned int sh = 2;
00415       while(true) {if((sh*2)>m_h) break;sh *=2;}
00416   
00417       if((sw==m_w)&&(sh==m_h)) {
00418         a_res.set(m_w,m_h,m_buffer,false); //WARNING owner=false.
00419         return true;
00420       }
00421   
00422       unsigned int sx = (m_w-sw)/2;
00423       unsigned int sy = (m_h-sh)/2;
00424   
00425       return get_part(sx,sy,sw,sh,a_res);
00426     }
00427   
00428   }
00429 
00430 public:
00431   static bool concatenate(const std::vector< img<T> >& a_imgs,
00432                                  unsigned int a_cols,unsigned int a_rows,
00433                                  unsigned int a_bw,unsigned int a_bh,
00434                                  T a_bc, //border grey level.
00435                                  img<T>& a_res){
00436     //not tested yet.
00437   
00438     // We assume that size of a_imgs is a_cols*a_rows
00439 
00440     // We should check that all a_imgs are consistents.
00441     
00442     unsigned int num = a_cols*a_rows;
00443     if(!num) {a_res.make_empty();return false;}
00444 
00445     unsigned int a_w = a_imgs[0].m_w;
00446     unsigned int a_h = a_imgs[0].m_h;
00447     unsigned int a_n = a_imgs[0].m_n;
00448 
00449     if(a_res.m_n!=a_n) {
00450       a_res.make_empty();
00451       return false;
00452     }
00453  
00454     for(unsigned int index=1;index<num;index++) {
00455       if(a_imgs[index].m_n!=a_n) {
00456         a_res.make_empty();
00457         return false;
00458       }
00459       if(a_imgs[index].m_w!=a_w) {
00460         a_res.make_empty();
00461         return false;
00462       }
00463       if(a_imgs[index].m_h!=a_h) {
00464         a_res.make_empty();
00465         return false;
00466       }
00467     }
00468   
00469     unsigned wbw = a_w + 2*a_bw;
00470     unsigned hbh = a_h + 2*a_bh;
00471   
00472     unsigned int rw = wbw * a_cols;
00473     unsigned int rh = hbh * a_rows;
00474   
00475     //printf("debug : %d %d\n",rw,rh);
00476   
00477     // on big concatenated image the below may fail :
00478     T* rb = new T[rh*rw*a_n];
00479     if(!rb) {
00480       a_res.make_empty();
00481       return false;
00482     }
00483   
00484     unsigned int wbwn = wbw*a_n;
00485     unsigned int awn = a_w*a_n;
00486     
00487     //copy tiles :  
00488     unsigned int index = 0;
00489     for(unsigned int j=0;j<a_rows;j++) {
00490       for(unsigned int i=0;i<a_cols;i++) {
00491         T* tile = a_imgs[index].buffer();
00492   
00493         for(unsigned int r=0;r<hbh;r++) {
00494           T* pos = rb + (j*hbh+r)*rw*a_n + i*wbw*a_n;
00495           ::memset(pos,a_bc,wbwn*sizeof(T));
00496         }
00497   
00498         for(unsigned int r=0;r<a_h;r++) {
00499           T* pos = rb + (j*hbh+r+a_bh)*rw*a_n + (i*wbw+a_bw)*a_n;
00500           T* ptile = tile+r*awn;        
00501           for(unsigned int c=0;c<awn;c++) *pos++ = *ptile++;
00502         }
00503   
00504         index++;
00505       }
00506     }
00507   
00508     a_res.set(rw,rh,rb,true);
00509     return true;
00510   }
00511 
00512 protected:
00513   unsigned int m_w;
00514   unsigned int m_h;
00515   unsigned int m_n;
00516   T* m_buffer;
00517   bool m_owner;
00518 private:
00519   static void check_instantiation() {
00520     img<float> dummy(3);
00521     //dummy.width();
00522   }
00523 };
00524 
00525 
00526 typedef img<unsigned char> img_byte;
00527 
00528 // NOTE : img_byte is ready for OpenGL glTexImage2D UNSIGNED_BYTE RGB.
00529 //        For glTexImage2D, first row in m_buffer is bottom of image.
00530 
00531 }
00532 
00533 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines