inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/img
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 #include "math" //for power<T>
00015 
00016 #include <vector> //concatenate
00017 
00018 namespace inlib {
00019 
00020 template <class T>
00021 class img {
00022   static const std::string& s_class() {
00023     static const std::string s_v("inlib::img");
00024     return s_v;
00025   }
00026 public:
00027   img(unsigned int a_n)
00028   :m_w(0),m_h(0),m_n(a_n)
00029   ,m_buffer(0)
00030   ,m_owner(false)
00031   {
00032 #ifdef INLIB_MEM
00033     mem::increment(s_class().c_str());
00034 #endif
00035   }
00036   img(unsigned int a_w,unsigned int a_h,unsigned int a_n,
00037              T* a_buffer,bool a_owner)
00038   :m_w(a_w),m_h(a_h),m_n(a_n)
00039   ,m_buffer(a_buffer)
00040   ,m_owner(a_owner)
00041   {
00042 #ifdef INLIB_MEM
00043     mem::increment(s_class().c_str());
00044 #endif
00045   }
00046   virtual ~img() {
00047     if(m_owner) delete [] m_buffer;
00048 #ifdef INLIB_MEM
00049     mem::decrement(s_class().c_str());
00050 #endif
00051   }
00052 public:
00053   img(const img& a_from)
00054   :m_w(a_from.m_w),m_h(a_from.m_h),m_n(a_from.m_n)
00055   ,m_buffer(0)
00056   ,m_owner(a_from.m_owner)
00057   {
00058 #ifdef INLIB_MEM
00059     mem::increment(s_class().c_str());
00060 #endif
00061     if(m_owner) {
00062       unsigned int sz = m_w*m_h*m_n;
00063       if(!sz) return;
00064       m_buffer = new T[sz];
00065       if(!m_buffer) {
00066         m_w = 0;m_h = 0;m_owner = false;
00067         return; //throw
00068       }
00069       ::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
00070     } else {
00071       m_buffer = a_from.m_buffer;
00072     }
00073   }
00074   img& operator=(const img& a_from){
00075     if(m_owner) delete [] m_buffer;
00076     m_buffer = 0;
00077     m_w = a_from.m_w;
00078     m_h = a_from.m_h;
00079     m_n = a_from.m_n;
00080     m_owner = a_from.m_owner;
00081     if(m_owner) {
00082       unsigned int sz = m_w*m_h*m_n;
00083       if(!sz) return *this;
00084       m_buffer = new T[sz];
00085       if(!m_buffer) {
00086         m_w = 0;m_h = 0;m_owner = false;
00087         return *this;  //throw
00088       }
00089       ::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
00090     } else {
00091       m_buffer = a_from.m_buffer;
00092     }
00093     return *this;
00094   }
00095 public:
00096   bool operator==(const img& a_from) const {return equal(a_from);}
00097   bool operator!=(const img& a_from) const {return !operator==(a_from);}
00098 public:
00099   void transfer(img& a_from) {
00100     if(m_owner) delete [] m_buffer;
00101     m_w = a_from.m_w;
00102     m_h = a_from.m_h;
00103     //don't touch m_n
00104     m_buffer = a_from.m_buffer;
00105     m_owner = a_from.m_owner;
00106     // empty a_from :
00107     a_from.m_w = 0;
00108     a_from.m_h = 0;
00109     a_from.m_buffer = 0;
00110     a_from.m_owner = false;
00111   }
00112 
00113   void clear() {
00114     if(m_owner) delete [] m_buffer;
00115     m_w = 0;
00116     m_h = 0;
00117     m_buffer = 0;
00118     m_owner = false;
00119   }
00120   void set(unsigned int a_w,unsigned int a_h,
00121                   T* a_buffer,bool a_owner) {
00122     if(m_owner) delete [] m_buffer;
00123     m_w = a_w;
00124     m_h = a_h;
00125     //don't touch m_n
00126     m_buffer = a_buffer;
00127     m_owner = a_owner;
00128   }
00129   bool copy(const img& a_from){
00130     if(m_owner) delete [] m_buffer;
00131     m_buffer = 0;
00132     m_w = a_from.m_w;
00133     m_h = a_from.m_h;
00134     m_n = a_from.m_n;
00135     unsigned int sz = m_w*m_h*m_n;
00136     if(!sz) {
00137       m_w = 0;m_h = 0;m_owner = false;
00138       return false;
00139     }
00140     m_buffer = new T[sz];
00141     if(!m_buffer) {
00142       m_w = 0;m_h = 0;m_owner = false;
00143       return false;
00144     }
00145     ::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
00146     m_owner = true;
00147     return true;
00148   }
00149   bool allocate(unsigned int a_w,unsigned int a_h){
00150     if(m_owner) delete [] m_buffer;
00151     m_buffer = 0;
00152     unsigned int sz = a_w*a_h*m_n;
00153     if(!sz) {
00154       m_w = 0;m_h = 0;m_owner = false;
00155       return false;
00156     }
00157     m_w = a_w;
00158     m_h = a_h;
00159     m_buffer = new T[sz];
00160     if(!m_buffer) {
00161       m_w = 0;m_h = 0;m_owner = false;
00162       return false;
00163     }
00164     m_owner = true;
00165     return true;
00166   }
00167   void make_empty() {
00168     if(m_owner) delete [] m_buffer;
00169     m_w = 0;
00170     m_h = 0;
00171     //don't touch m_n
00172     m_buffer = 0;
00173     m_owner = false;
00174   }
00175   bool equal(const img& a_from) const {
00176     if(m_w!=a_from.m_w) return false;
00177     if(m_h!=a_from.m_h) return false;
00178     if(m_n!=a_from.m_n) return false;
00179     //don't test ownership.
00180     unsigned int sz = m_w*m_h*m_n;
00181     T* pos = m_buffer;
00182     T* fpos = a_from.m_buffer;
00183     for(unsigned int index=0;index<sz;index++,pos++,fpos++) {
00184       if((*pos)!=(*fpos)) return false;
00185     }
00186     return true;
00187   }
00188   unsigned int width() const {return m_w;}
00189   unsigned int height() const {return m_h;}
00190   unsigned int bytes_per_pixel() const {return m_n;}
00191   unsigned int bpp() const {return m_n;}
00192   T* buffer() const {return m_buffer;}
00193   bool owner() const {return m_owner;}
00194   unsigned int size() const {return m_w*m_h*m_n*sizeof(T);} //bytes.
00195 public:
00196   bool expand(unsigned int a_factor,img<T>& a_res) const {
00197     if(a_res.m_n!=m_n) {
00198       a_res.make_empty();
00199       return false;
00200     }
00201     if(a_factor==1) {
00202       a_res.set(m_w,m_h,m_buffer,false);
00203       return true;
00204     }
00205   
00206     unsigned int nw = m_w*a_factor;
00207     unsigned int nh = m_h*a_factor;
00208     unsigned int sz = nh*nw*m_n;
00209     if(!sz) {
00210       a_res.make_empty();
00211       return false;
00212     }
00213   
00214     T* nb = new T[sz];
00215     if(!nb) {
00216       a_res.make_empty();
00217       return false;
00218     }
00219   
00220     for(unsigned int j=0;j<m_h;j++) {
00221       for(unsigned int i=0;i<m_w;i++) {
00222         //position in the original image.
00223         T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
00224   
00225         for(unsigned int fr=0;fr<a_factor;fr++) {
00226           for(unsigned int fc=0;fc<a_factor;fc++) {
00227             //position in the new image.
00228             T* npos = nb + (j*a_factor+fr) * (nw * m_n) + (i*a_factor+fc)*m_n;
00229             for(unsigned int ipix=0;ipix<m_n;ipix++) {
00230               *(npos+ipix) = *(pos+ipix);
00231             }
00232           }
00233         }
00234   
00235       }
00236     }
00237   
00238     a_res.set(nw,nh,nb,true);
00239     return true;
00240   }
00241 
00242   bool contract(unsigned int a_factor,img<T>& a_res) const {
00243     // a_factor pixels are contracted in one.
00244     if(a_res.m_n!=m_n) {
00245       a_res.make_empty();
00246       return false;
00247     }
00248     if(a_factor==1) {
00249       a_res.set(m_w,m_h,m_buffer,false);
00250       return true;
00251     }
00252     if(!a_factor) {
00253       a_res.make_empty();
00254       return false;
00255     }
00256   
00257     unsigned int nw = m_w/a_factor;
00258     unsigned int nh = m_h/a_factor;
00259     unsigned int sz = nh*nw*m_n;
00260     if(!sz) {
00261       a_res.make_empty();
00262       return false;
00263     }
00264   
00265     T* nb = new T[sz];
00266     if(!nb) {
00267       a_res.make_empty();
00268       return false;
00269     }
00270 
00271     //T* npos = nb;
00272     //for(unsigned int ipix=0;ipix<sz;ipix++) {*npos = 125;npos++;}
00273 
00274     double* pixels = new double[m_n]; //for mean value.
00275     if(!pixels) {
00276       delete [] nb;
00277       a_res.make_empty();
00278       return false;
00279     }
00280     unsigned int nfac = a_factor*a_factor;
00281 
00282     for(unsigned int j=0;j<nh;j++) {
00283       for(unsigned int i=0;i<nw;i++) {
00284 
00285         // take mean value of a_factor*a_factor pixels :  
00286         for(unsigned int ipix=0;ipix<m_n;ipix++) pixels[ipix] = 0;
00287             
00288         for(unsigned int fr=0;fr<a_factor;fr++) {
00289           for(unsigned int fc=0;fc<a_factor;fc++) {
00290             T* pos = m_buffer + (j*a_factor+fr)*(m_w*m_n) +(i*a_factor+fc)*m_n;
00291             for(unsigned int ipix=0;ipix<m_n;ipix++) {
00292               pixels[ipix] += double(*pos);pos++;
00293             }
00294           }
00295         }
00296         for(unsigned int ipix=0;ipix<m_n;ipix++) {
00297           pixels[ipix] /= double(nfac);
00298         }
00299 
00300         //position in the result image.
00301         T* npos = nb + j * (nw * m_n) + i*m_n;
00302         for(unsigned int ipix=0;ipix<m_n;ipix++) {
00303           *npos = T(pixels[ipix]);npos++;
00304         }
00305       }
00306     }
00307 
00308     delete [] pixels;
00309 
00310     a_res.set(nw,nh,nb,true);
00311     return true;
00312   }
00313 
00314   bool get_part(unsigned int a_sx,unsigned int a_sy,
00315                        unsigned int a_sw,unsigned int a_sh,
00316                        img<T>& a_res) const {
00317 
00318     if(a_res.m_n!=m_n) {
00319       a_res.make_empty();
00320       return false;
00321     }
00322 
00323     if((a_sx>=m_w)||(a_sy>=m_h)){
00324       a_res.make_empty();
00325       return false;
00326     }
00327   
00328     // 012345
00329     unsigned int rw = inlib::mn<unsigned int>(m_w-a_sx,a_sw); 
00330     unsigned int rh = inlib::mn<unsigned int>(m_h-a_sy,a_sh); 
00331     unsigned int sz = rh*rw*m_n;
00332     if(!sz) {
00333       a_res.make_empty();
00334       return false;
00335     }
00336   
00337     //printf("debug : %d %d\n",a_rw,a_rh);
00338   
00339     T* rb = new T[sz];
00340     if(!rb) {
00341       a_res.make_empty();
00342       return false;
00343     }
00344   
00345     unsigned int rstride = rw * m_n;
00346     T* rpos = rb;
00347 
00348     unsigned int stride = m_w * m_n;
00349     T* pos = m_buffer+a_sy*stride+a_sx*m_n;
00350 
00351     for(unsigned int j=0;j<rh;j++,rpos+=rstride,pos+=stride) {//j=0 -> bottom.
00352       ::memcpy(rpos,pos,rstride*sizeof(T));
00353     }
00354 
00355     a_res.set(rw,rh,rb,true);  
00356     return true;
00357   }
00358 
00359   bool to_texture(bool a_expand,
00360                          T a_pixel[], //size shoulde be a_img.m_n.
00361                          img<T>& a_res) const {
00362 
00363     //NOTE : pixels of the original image are not expanded or shrinked.
00364 
00365     if(a_res.m_n!=m_n) {
00366       a_res.make_empty();
00367       return false;
00368     }
00369     if((!m_w)||(!m_h)) {
00370       a_res.make_empty();
00371       return false;
00372     }
00373 
00374     // in case (m_w==1)||(m_h==1), expand the pixel
00375     // up to the closest power of 2 ?
00376 
00377     if((m_w==1)||(m_h==1)||a_expand) {
00378       // find closest power of two upper than m_w, m_h :
00379       unsigned int rw = 2;
00380       while(true) {if(rw>=m_w) break;rw *=2;}
00381       unsigned int rh = 2;
00382       while(true) {if(rh>=m_h) break;rh *=2;}
00383     
00384       if((rw==m_w)&&(rh==m_h)) { //exact match.
00385         a_res.set(m_w,m_h,m_buffer,false); //WARNING owner=false.
00386         return true;
00387       }
00388     
00389       // we expand the image and fill new spaces with rgb.
00390   
00391       T* rb = new T[rh*rw*m_n];
00392       if(!rb) {
00393         a_res.make_empty();
00394         return false;
00395       }
00396     
00397       // initialize with given color :
00398       for(unsigned int j=0;j<rh;j++) {  //j=0 -> bottom.
00399         T* pos = rb + j * (rw * m_n);
00400         for(unsigned int i=0;i<rw;i++) {
00401           for(unsigned int n=0;n<m_n;n++) {
00402             *pos = a_pixel[n];pos++; //memcpy ?
00403           }
00404         }
00405       }
00406     
00407       // center :
00408       unsigned int col = (rw-m_w)/2;  
00409       unsigned int row = (rh-m_h)/2;  
00410     
00411       // copy original image in a centered part of the new one :
00412       for(unsigned int j=0;j<m_h;j++) {
00413         T* pos = m_buffer + j * (m_w * m_n);
00414         T* rpos = rb + (j+row) * (rw * m_n) + col*m_n;
00415         ::memcpy(rpos,pos,m_w*m_n*sizeof(T));
00416       }
00417 
00418       a_res.set(rw,rh,rb,true);
00419     
00420       return true;
00421     } else {
00422       // then m_w>=2 and m_h>=2
00423   
00424       // find closest power of two lower than m_w, m_h :
00425       unsigned int sw = 2;
00426       while(true) {if((sw*2)>m_w) break;sw *=2;}
00427       unsigned int sh = 2;
00428       while(true) {if((sh*2)>m_h) break;sh *=2;}
00429   
00430       if((sw==m_w)&&(sh==m_h)) { //exact match.
00431         a_res.set(m_w,m_h,m_buffer,false); //WARNING owner=false.
00432         return true;
00433       }
00434   
00435       unsigned int sx = (m_w-sw)/2;
00436       unsigned int sy = (m_h-sh)/2;
00437   
00438       return get_part(sx,sy,sw,sh,a_res);
00439     }
00440   
00441   }
00442 
00443 /*
00444   bool tex_match() const {
00445     if((!m_w)||(!m_h)) return false;
00446 
00447     ::printf("debug : tex_match : begin %d %d\n",m_w,m_h);
00448 
00449     // pixel expansion :
00450 
00451     // find closest power of two upper than m_w, m_h :
00452    {unsigned int rw = 2;
00453     unsigned int pw = 1;
00454     while(rw<m_w) {rw *=2;pw++;}
00455 
00456     for(unsigned int ipw=pw;ipw<30;ipw++) {
00457       unsigned int factor = 1;
00458       while(true) {
00459         unsigned int rw = power<unsigned int>(2,ipw);
00460         unsigned int n = rw/(m_w*factor);     
00461         unsigned int n1 = rw/(m_w*(factor+1));     
00462         if(n&&!n1) break;
00463         factor++;
00464       }
00465       unsigned int lost = (m_w*(factor+1)-rw)/(factor+1);      
00466       ::printf("debug : %d : %d lost %d w %d\n",
00467          ipw,factor+1,lost,m_w*(factor+1));
00468     }
00469     ::printf("debug : tex_match : exp end %d %d\n",
00470         pw,power<unsigned int>(2,pw));
00471     }
00472 
00473     // pixel contraction :
00474     if((m_w==1)||(m_h==1)) return false;
00475 
00476    {// closest w,h power of two below m_w,m_h :
00477     unsigned int sw = 2;
00478     unsigned int pw = 1;
00479     while((sw*2)<=m_w) {sw *=2;pw++;}
00480 
00481     for(unsigned int ipw=1;ipw<=pw;ipw++) {
00482       bool found = false;
00483       unsigned int factor = 1; //contraction factor.    
00484       while(true) {
00485         unsigned int sw = power<unsigned int>(2,ipw);
00486         unsigned int cw = m_w/factor; //width after contraction by factor.
00487         //unsigned int w = cw*factor;
00488         unsigned int cw1 = m_w/(factor+1);
00489         //unsigned int w1 = cw1*(factor+1);
00490         if((cw>=sw)&&(cw1<sw)) {found = true;break;}
00491         factor++;
00492       }
00493       if(!found) {
00494         ::printf("debug : ctrct : %d : not found\n",ipw);
00495       } else {
00496         unsigned int sw = power<unsigned int>(2,ipw);
00497         unsigned int cw = m_w/factor; //width after contraction by factor.
00498         unsigned int lost = cw-sw;
00499         ::printf("debug : ctrct : %d : %d lost %d w %d\n",
00500             ipw,factor,lost,(unsigned int)(m_w/factor));
00501       }
00502     }
00503     ::printf("debug : tex_match : contract end %d %d\n",
00504         pw,power<unsigned int>(2,pw));
00505 
00506     }
00507 
00508     return false;
00509   }
00510 
00511   enum to_tex_method { 
00512     to_tex_in_up_power_two,
00513     to_tex_expand_pixels_and_get_part,
00514     to_tex_get_part,
00515     to_tex_contract_pixels_and_get_part
00516   };
00517   
00518   bool guess_to_tex_method(to_tex_method& a_method) const {
00519     if((!m_w)||(!m_h)) {
00520       //any method is ok since to_texture() will do nothing.
00521       a_method = to_tex_in_up_power_two;
00522       return false;
00523     }
00524 
00525    {unsigned int rw = 2;
00526     while(true) {if(rw>=m_w) break;rw *=2;}
00527     unsigned int rh = 2;
00528     while(true) {if(rh>=m_h) break;rh *=2;}
00529     if((rw==m_w)&&(rh==m_h)) { //exact match.
00530       //any method is ok since to_texture() will do nothing.
00531       a_method = to_tex_in_up_power_two;
00532       return true;
00533     }}
00534 
00535     if((m_w==1)||(m_h==1)) {
00536       a_method = to_tex_in_up_power_two;
00537       return true;
00538     }
00539 
00540     // no exact match. Evaluate the best strategy
00541     // to minimize the number of pixels in the original image that
00542     // we can loose.
00543 
00544     // method = to_tex_in_up_power_two : no loose but new background pixel.
00545 
00546     unsigned int lost_expand_pixels_and_get_part_w = 0;
00547     unsigned int lost_expand_pixels_and_get_part_h = 0; 
00548     unsigned int lost_get_part_w = 0;
00549     unsigned int lost_get_part_h = 0; 
00550     unsigned int lost_contract_pixels_and_get_part_w = 0;
00551     unsigned int lost_contract_pixels_and_get_part_h = 0; 
00552 
00553    {//  method = expand_pixels_and_get_part;
00554     // closest power of two upper than m_w, mh :
00555     unsigned int rw = 2;
00556     while(true) {if(rw>=m_w) break;rw *=2;}
00557     unsigned int rh = 2;
00558     while(true) {if(rh>=m_h) break;rh *=2;}
00559 
00560     unsigned int fw = rw/m_w;
00561     if((fw*m_w)!=rw) fw++;    //to cover rw.
00562     unsigned int fh = rh/m_h;
00563     if((fh*m_h)!=rh) fh++;    //to cover rh.
00564     unsigned int factor = mx<unsigned int>(fw,fh); //pixel expansion factor.
00565     lost_expand_pixels_and_get_part_w = (factor*m_w-rw)/factor;
00566     lost_expand_pixels_and_get_part_h = (factor*m_h-rh)/factor;}
00567 
00568    {// closest w,h power of two below m_w,m_h :
00569     unsigned int sw = 2;
00570     while(true) {if((sw*2)>m_w) break;sw *=2;}
00571     unsigned int sh = 2;
00572     while(true) {if((sh*2)>m_h) break;sh *=2;}
00573     // method = get_part;
00574     lost_get_part_w = m_w-sw; 
00575     lost_get_part_h = m_h-sh; 
00576     // method = contract_and_get_part;
00577     unsigned int factor = 2; //=1 always pass the below with factor=1 !
00578     // exa m_[w,h] = 7. s[w,h] = 4.
00579     // 7/2=3<4 => 7/3=2<4 => 7/[4,5,6,7]=1<4 => 7/8=0.
00580 
00581     //  2**n <= w < 2**(n+1)
00582     //  2**n <= w/f
00583     //    f  <= w
00584     // f=1 ok.
00585     // for f not 1, if :
00586     //  w=p*f+q
00587     //  0<=q<f
00588     // same as :
00589     //  2**n <= p*f+q < (2**n)*2
00590     //  2**n <= p
00591     //  q < f
00592     // induces :
00593     //  (2**n)*f <= p*f <= p*f+q < (2**n)*2
00594     // induces :
00595     //  f < 2
00596     // not possible.
00597 
00598     while(true) {
00599       unsigned int nw = m_w/factor;
00600       unsigned int nh = m_h/factor;
00601       if((!nw)||(!nh)) {
00602         //enforce  method = expand_pix_and_get_part;
00603         return false;
00604       }
00605       if((nw>=sw)&&(nh>=sh)) break;          
00606       factor++;
00607     }
00608     unsigned int nw = m_w/factor;
00609     unsigned int nh = m_h/factor;
00610     // not in contracted image
00611     //  m_w-nw*factor 
00612     //  m_h-nh*factor 
00613     // not from contracted image :
00614     //  nw-sw
00615     //  nh-sh
00616     lost_contract_pixels_and_get_part_w = (nw-sw)+(m_w-nw*factor); 
00617     lost_contract_pixels_and_get_part_h = (nh-sh)+(m_h-nh*factor);}
00618 
00619     if(lost_get_part_h <=
00620                 mn<unsigned int>(lost_expand_pixels_and_get_part_h,
00621                                  lost_contract_pixels_and_get_part_h)) {
00622       a_method = to_tex_get_part;
00623 
00624     } else if(lost_expand_pixels_and_get_part_h <=
00625          mn<unsigned int>(lost_get_part_h,
00626                           lost_contract_pixels_and_get_part_h)){
00627       a_method = to_tex_expand_pixels_and_get_part;
00628 
00629     } else if(lost_contract_pixels_and_get_part_h <=
00630          mn<unsigned int>(lost_expand_pixels_and_get_part_h,
00631                           lost_get_part_h)) {
00632       a_method = to_tex_contract_pixels_and_get_part;
00633     }
00634 
00635     return true;
00636   }
00637 
00638   bool to_texture2(to_tex_method a_method,
00639                          T a_pixel[], //size shoulde be m_n.
00640                          img<T>& a_res) const {
00641     if(a_res.m_n!=m_n) {
00642       a_res.make_empty();
00643       return false;
00644     }
00645     if((!m_n)||(!m_w)||(!m_h)) {
00646       a_res.make_empty();
00647       return false;
00648     }
00649     // we have a valid image to work with.
00650 
00651     // exact match ?
00652    {// closest power of two upper than m_w, mh :
00653     unsigned int rw = 2;
00654     while(true) {if(rw>=m_w) break;rw *=2;}
00655     unsigned int rh = 2;
00656     while(true) {if(rh>=m_h) break;rh *=2;}
00657     if((rw==m_w)&&(rh==m_h)) {
00658       a_res.set(m_w,m_h,m_buffer,false); //WARNING owner=false.
00659       return true;
00660     }}
00661 
00662     if((m_w==1)||(m_h==1)||(a_method==to_tex_in_up_power_two)) {
00663       // closest power of two upper than m_w, mh :
00664       unsigned int rw = 2;
00665       while(true) {if(rw>=m_w) break;rw *=2;}
00666       unsigned int rh = 2;
00667       while(true) {if(rh>=m_h) break;rh *=2;}
00668     
00669       // we create a rw*rh image, init with given rgb
00670       // and copy original image at center of it.
00671   
00672       T* rb = new T[rh*rw*m_n];
00673       if(!rb) {
00674         a_res.make_empty();
00675         return false;
00676       }
00677     
00678       // initialize with given color :
00679       for(unsigned int j=0;j<rh;j++) {  //j=0 -> bottom.
00680         T* pos = rb + j * (rw * m_n);
00681         for(unsigned int i=0;i<rw;i++) {
00682           for(unsigned int n=0;n<m_n;n++) {
00683             *pos = a_pixel[n];pos++; //memcpy ?
00684           }
00685         }
00686       }
00687     
00688       // center :
00689       unsigned int col = (rw-m_w)/2;  
00690       unsigned int row = (rh-m_h)/2;  
00691     
00692       // copy original image in a centered part of the new one :
00693       for(unsigned int j=0;j<m_h;j++) {
00694         T* pos = m_buffer + j * (m_w * m_n);
00695         T* rpos = rb + (j+row) * (rw * m_n) + col*m_n;
00696         ::memcpy(rpos,pos,m_w*m_n*sizeof(T));
00697       }
00698 
00699       a_res.set(rw,rh,rb,true);
00700       return true;
00701 
00702    } else if(a_method==to_tex_expand_pixels_and_get_part) {
00703       // closest power of two upper than m_w, mh :
00704       unsigned int rw = 2;
00705       while(true) {if(rw>=m_w) break;rw *=2;}
00706       unsigned int rh = 2;
00707       while(true) {if(rh>=m_h) break;rh *=2;}
00708     
00709       // we expand original image pixels to cover a rw*rh image
00710       // and we take a centered part matching rw*rh.
00711 
00712       unsigned int fw = rw/m_w;
00713       if((fw*m_w)!=rw) fw++;    //to cover rw.
00714       unsigned int fh = rh/m_h;
00715       if((fh*m_h)!=rh) fh++;    //to cover rh.
00716       unsigned int factor = mx<unsigned int>(fw,fh);
00717       img<T> tmp(m_n);
00718       if(!expand(factor,tmp)) {
00719         a_res.make_empty();
00720         return false;
00721       }
00722       unsigned int sx = (tmp.width()-rw)/2;
00723       unsigned int sy = (tmp.height()-rh)/2;
00724       return tmp.get_part(sx,sy,rw,rh,a_res);
00725 
00726     } else if(a_method==to_tex_get_part) {
00727   
00728       // closest w,h power of two below m_w,m_h :
00729       unsigned int sw = 2;
00730       while(true) {if((sw*2)>m_w) break;sw *=2;}
00731       unsigned int sh = 2;
00732       while(true) {if((sh*2)>m_h) break;sh *=2;}
00733   
00734       // we take a centered part of original image matching sw*sh.
00735       unsigned int sx = (m_w-sw)/2;
00736       unsigned int sy = (m_h-sh)/2;
00737       return get_part(sx,sy,sw,sh,a_res);
00738 
00739     } else if(a_method==to_tex_contract_pixels_and_get_part) {
00740 
00741       // closest w,h power of two below m_w,m_h :
00742       unsigned int sw = 2;
00743       while(true) {if((sw*2)>m_w) break;sw *=2;}
00744       unsigned int sh = 2;
00745       while(true) {if((sh*2)>m_h) break;sh *=2;}
00746   
00747       unsigned int factor = 1;
00748       while(true) {
00749         unsigned int nw = m_w/factor;
00750         unsigned int nh = m_h/factor;
00751         if((!nw)||(!nh)) {
00752           a_res.make_empty();
00753           return false;
00754         }
00755         if((nw>=sw)&&(nh>=sh)) break;          
00756         factor++;
00757       }
00758       img<T> tmp(m_n);
00759       if(!contract(factor,tmp)) {
00760         a_res.make_empty();
00761         return false;
00762       }
00763       unsigned int sx = (tmp.width()-sw)/2;
00764       unsigned int sy = (tmp.height()-sh)/2;
00765       return tmp.get_part(sx,sy,sw,sh,a_res);
00766 
00767     } else { //unknown method.
00768       a_res.make_empty();
00769       return false;
00770     }
00771   
00772   }
00773 */
00774 public:
00775   static bool concatenate(const std::vector< img<T> >& a_imgs,
00776                                  unsigned int a_cols,unsigned int a_rows,
00777                                  unsigned int a_bw,unsigned int a_bh,
00778                                  T a_bc, //border grey level.
00779                                  img<T>& a_res){
00780     //not tested yet.
00781   
00782     // We assume that size of a_imgs is a_cols*a_rows
00783 
00784     // We should check that all a_imgs are consistents.
00785     
00786     unsigned int num = a_cols*a_rows;
00787     if(!num) {a_res.make_empty();return false;}
00788 
00789     unsigned int a_w = a_imgs[0].m_w;
00790     unsigned int a_h = a_imgs[0].m_h;
00791     unsigned int a_n = a_imgs[0].m_n;
00792 
00793     if(a_res.m_n!=a_n) {
00794       a_res.make_empty();
00795       return false;
00796     }
00797  
00798     for(unsigned int index=1;index<num;index++) {
00799       if(a_imgs[index].m_n!=a_n) {
00800         a_res.make_empty();
00801         return false;
00802       }
00803       if(a_imgs[index].m_w!=a_w) {
00804         a_res.make_empty();
00805         return false;
00806       }
00807       if(a_imgs[index].m_h!=a_h) {
00808         a_res.make_empty();
00809         return false;
00810       }
00811     }
00812   
00813     unsigned wbw = a_w + 2*a_bw;
00814     unsigned hbh = a_h + 2*a_bh;
00815   
00816     unsigned int rw = wbw * a_cols;
00817     unsigned int rh = hbh * a_rows;
00818   
00819     //printf("debug : %d %d\n",rw,rh);
00820   
00821     // on big concatenated image the below may fail :
00822     T* rb = new T[rh*rw*a_n];
00823     if(!rb) {
00824       a_res.make_empty();
00825       return false;
00826     }
00827   
00828     unsigned int wbwn = wbw*a_n;
00829     unsigned int awn = a_w*a_n;
00830     
00831     //copy tiles :  
00832     unsigned int index = 0;
00833     for(unsigned int j=0;j<a_rows;j++) {
00834       for(unsigned int i=0;i<a_cols;i++) {
00835         T* tile = a_imgs[index].buffer();
00836   
00837         for(unsigned int r=0;r<hbh;r++) {
00838           T* pos = rb + (j*hbh+r)*rw*a_n + i*wbw*a_n;
00839           ::memset(pos,a_bc,wbwn*sizeof(T));
00840         }
00841   
00842         for(unsigned int r=0;r<a_h;r++) {
00843           T* pos = rb + (j*hbh+r+a_bh)*rw*a_n + (i*wbw+a_bw)*a_n;
00844           T* ptile = tile+r*awn;        
00845           for(unsigned int c=0;c<awn;c++) *pos++ = *ptile++;
00846         }
00847   
00848         index++;
00849       }
00850     }
00851   
00852     a_res.set(rw,rh,rb,true);
00853     return true;
00854   }
00855 
00856 protected:
00857   unsigned int m_w;
00858   unsigned int m_h;
00859   unsigned int m_n;
00860   T* m_buffer;
00861   bool m_owner;
00862 private:
00863   static void check_instantiation() {
00864     img<float> dummy(3);
00865     //dummy.width();
00866   }
00867 };
00868 
00869 
00870 typedef img<unsigned char> img_byte;
00871 
00872 // NOTE : img_byte is ready for OpenGL glTexImage2D UNSIGNED_BYTE RGB.
00873 //        For glTexImage2D, first row in m_buffer is bottom of image.
00874 
00875 }
00876 
00877 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines