Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/img is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef tools_img
0005 #define tools_img
0006 
0007 #ifdef TOOLS_MEM
0008 #include "mem"
0009 #endif
0010 
0011 #include <string> //memcpy
0012 #include <cstring> //memcpy
0013 #include "mnmx"
0014 #include "S_STRING"
0015 
0016 #include <vector> //concatenate
0017 
0018 namespace tools {
0019 
0020 template <class T>
0021 class img {
0022 public:
0023   TOOLS_T_SCLASS(T,tools::img)
0024 public:
0025   img()
0026   :m_w(0),m_h(0),m_n(0)
0027   ,m_buffer(0)
0028   ,m_owner(false)
0029   {
0030 #ifdef TOOLS_MEM
0031     mem::increment(s_class().c_str());
0032 #endif
0033   }
0034   img(unsigned int a_w,unsigned int a_h,unsigned int a_n,T* a_buffer,bool a_owner)
0035   :m_w(a_w),m_h(a_h),m_n(a_n)
0036   ,m_buffer(a_buffer)
0037   ,m_owner(a_owner)
0038   {
0039 #ifdef TOOLS_MEM
0040     mem::increment(s_class().c_str());
0041 #endif
0042   }
0043   virtual ~img() {
0044     if(m_owner) delete [] m_buffer;
0045 #ifdef TOOLS_MEM
0046     mem::decrement(s_class().c_str());
0047 #endif
0048   }
0049 public:
0050   img(const img& a_from)
0051   :m_w(a_from.m_w),m_h(a_from.m_h),m_n(a_from.m_n)
0052   ,m_buffer(0)
0053   ,m_owner(a_from.m_owner)
0054   {
0055 #ifdef TOOLS_MEM
0056     mem::increment(s_class().c_str());
0057 #endif
0058     if(m_owner) {
0059       unsigned int sz = m_w*m_h*m_n;
0060       if(!sz) return;
0061       m_buffer = new T[sz];
0062       if(!m_buffer) {
0063         m_w = 0;m_h = 0;m_n = 0;m_owner = false;
0064         return; //throw
0065       }
0066       ::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
0067     } else {
0068       m_buffer = a_from.m_buffer;
0069     }
0070   }
0071   img& operator=(const img& a_from){
0072     if(&a_from==this) return *this;
0073     if(m_owner) delete [] m_buffer;
0074     m_buffer = 0;
0075     m_w = a_from.m_w;
0076     m_h = a_from.m_h;
0077     m_n = a_from.m_n;
0078     m_owner = a_from.m_owner;
0079     if(m_owner) {
0080       unsigned int sz = m_w*m_h*m_n;
0081       if(!sz) return *this;
0082       m_buffer = new T[sz];
0083       if(!m_buffer) {
0084         m_w = 0;m_h = 0;m_n = 0;m_owner = false;
0085         return *this;  //throw
0086       }
0087       ::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
0088     } else {
0089       m_buffer = a_from.m_buffer;
0090     }
0091     return *this;
0092   }
0093 public:
0094   bool operator==(const img& a_from) const {return equal(a_from);}
0095   bool operator!=(const img& a_from) const {return !operator==(a_from);}
0096 public:
0097   void transfer(img& a_from) {
0098     if(m_owner) delete [] m_buffer;
0099     m_w = a_from.m_w;
0100     m_h = a_from.m_h;
0101     m_n = a_from.m_n;
0102     m_buffer = a_from.m_buffer;
0103     m_owner = a_from.m_owner;
0104     // empty a_from :
0105     a_from.m_w = 0;
0106     a_from.m_h = 0;
0107     a_from.m_buffer = 0;
0108     a_from.m_owner = false;
0109   }
0110 
0111   void clear() {
0112     if(m_owner) delete [] m_buffer;
0113     m_w = 0;
0114     m_h = 0;
0115     m_n = 0;
0116     m_buffer = 0;
0117     m_owner = false;
0118   }
0119   void set(unsigned int a_w,unsigned int a_h,unsigned int a_n,T* a_buffer,bool a_owner) {
0120     if(m_owner) delete [] m_buffer;
0121     m_w = a_w;
0122     m_h = a_h;
0123     m_n = a_n;
0124     m_buffer = a_buffer;
0125     m_owner = a_owner;
0126   }
0127   bool copy(unsigned int a_w,unsigned int a_h,unsigned int a_n,T* a_buffer) {
0128     if(m_owner) delete [] m_buffer;
0129     m_buffer = 0;
0130     m_w = a_w;
0131     m_h = a_h;
0132     m_n = a_n;
0133     unsigned int sz = m_w*m_h*m_n;
0134     if(!sz) {
0135       m_w = 0;m_h = 0;m_n = 0;m_owner = false;
0136       return false;
0137     }
0138     m_buffer = new T[sz];
0139     if(!m_buffer) {
0140       m_w = 0;m_h = 0;m_n = 0;m_owner = false;
0141       return false;
0142     }
0143     ::memcpy(m_buffer,a_buffer,sz*sizeof(T));
0144     m_owner = true;
0145     return true;
0146   }
0147   bool copy(const img& a_from){
0148     if(m_owner) delete [] m_buffer;
0149     m_buffer = 0;
0150     m_w = a_from.m_w;
0151     m_h = a_from.m_h;
0152     m_n = a_from.m_n;
0153     unsigned int sz = m_w*m_h*m_n;
0154     if(!sz) {
0155       m_w = 0;m_h = 0;m_n = 0;m_owner = false;
0156       return false;
0157     }
0158     m_buffer = new T[sz];
0159     if(!m_buffer) {
0160       m_w = 0;m_h = 0;m_n = 0;m_owner = false;
0161       return false;
0162     }
0163     ::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
0164     m_owner = true;
0165     return true;
0166   }
0167   bool allocate(unsigned int a_w,unsigned int a_h,unsigned int a_n){
0168     if(m_owner) delete [] m_buffer;
0169     m_buffer = 0;
0170     unsigned int sz = a_w*a_h*a_n;
0171     if(!sz) {
0172       m_w = 0;m_h = 0;m_n = 0;m_owner = false;
0173       return false;
0174     }
0175     m_w = a_w;
0176     m_h = a_h;
0177     m_n = a_n;
0178     m_buffer = new T[sz];
0179     if(!m_buffer) {
0180       m_w = 0;m_h = 0;m_n = 0;m_owner = false;
0181       return false;
0182     }
0183     m_owner = true;
0184     return true;
0185   }
0186   void make_empty(bool a_delete = true) {
0187     if(m_owner && a_delete) delete [] m_buffer;
0188     m_w = 0;
0189     m_h = 0;
0190     m_n = 0;
0191     m_buffer = 0;
0192     m_owner = false;
0193   }
0194   bool is_empty() const {
0195     if(!m_w) return true;
0196     if(!m_h) return true;
0197     if(!m_n) return true;
0198     if(!m_buffer) return true;
0199     return false;
0200   }
0201   bool equal(const img& a_from) const {
0202     if(m_w!=a_from.m_w) return false;
0203     if(m_h!=a_from.m_h) return false;
0204     if(m_n!=a_from.m_n) return false;
0205     //don't test ownership.
0206     unsigned int sz = m_w*m_h*m_n;
0207     T* pos = m_buffer;
0208     T* fpos = a_from.m_buffer;
0209     for(unsigned int index=0;index<sz;index++,pos++,fpos++) {
0210       if((*pos)!=(*fpos)) return false;
0211     }
0212     return true;
0213   }
0214   unsigned int width() const {return m_w;}
0215   unsigned int height() const {return m_h;}
0216   unsigned int bytes_per_pixel() const {return m_n;}
0217   unsigned int bpp() const {return m_n;}
0218   const T* buffer() const {return m_buffer;}
0219   T* buffer() {return m_buffer;}
0220   bool owner() const {return m_owner;}
0221   unsigned int size() const {return m_w*m_h*m_n*sizeof(T);} //bytes.
0222 public:
0223   bool pixel(unsigned int a_i,unsigned a_j,std::vector<T>& a_pixel) const {
0224     if((!m_w)||(!m_h)||(a_i>=m_w)||(a_j>=m_h)) {
0225       a_pixel.clear();
0226       return false;
0227     }
0228     a_pixel.resize(m_n);
0229     T* pos = m_buffer + a_j * (m_w * m_n) + a_i*m_n;
0230     for(unsigned int ipix=0;ipix<m_n;ipix++) {
0231       a_pixel[ipix] = *(pos+ipix);
0232     }
0233     return true;
0234   }
0235 
0236   bool expand(unsigned int a_factor,img<T>& a_res,bool a_res_force_owner = true) const {
0237     if(a_factor==1) {
0238       if(a_res_force_owner) {
0239         a_res.copy(m_w,m_h,m_n,m_buffer);
0240       } else {
0241         a_res.set(m_w,m_h,m_n,m_buffer,false);
0242       }
0243       return true;
0244     }
0245 
0246     unsigned int nw = m_w*a_factor;
0247     unsigned int nh = m_h*a_factor;
0248     unsigned int sz = nh*nw*m_n;
0249     if(!sz) {
0250       a_res.make_empty();
0251       return false;
0252     }
0253 
0254     T* nb = new T[sz];
0255     if(!nb) {
0256       a_res.make_empty();
0257       return false;
0258     }
0259 
0260     for(unsigned int j=0;j<m_h;j++) {
0261       for(unsigned int i=0;i<m_w;i++) {
0262         //position in the original image.
0263         T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
0264 
0265         for(unsigned int fr=0;fr<a_factor;fr++) {
0266           for(unsigned int fc=0;fc<a_factor;fc++) {
0267             //position in the new image.
0268             T* npos = nb + (j*a_factor+fr) * (nw * m_n) + (i*a_factor+fc)*m_n;
0269             for(unsigned int ipix=0;ipix<m_n;ipix++) {
0270               *(npos+ipix) = *(pos+ipix);
0271             }
0272           }
0273         }
0274 
0275       }
0276     }
0277 
0278     a_res.set(nw,nh,m_n,nb,true);
0279     return true;
0280   }
0281 
0282   bool contract_raw(unsigned int a_w,unsigned int a_h,img<T>& a_res,bool a_force_res_owner = true) const {
0283     if((a_w==m_w)&&(a_h==m_h)) {
0284       if(a_force_res_owner) {
0285         a_res.copy(m_w,m_h,m_n,m_buffer);
0286       } else {
0287         a_res.set(m_w,m_h,m_n,m_buffer,false);
0288       }
0289       return true;
0290     }
0291 
0292     unsigned int sz = a_h*a_w*m_n;
0293     if(!sz) {
0294       a_res.make_empty();
0295       return false;
0296     }
0297 
0298     T* rb = new T[sz];
0299     if(!rb) {
0300       a_res.make_empty();
0301       return false;
0302     }
0303 
0304     double* pixels = new double[m_n]; //for mean value.
0305     if(!pixels) {
0306       delete [] rb;
0307       a_res.make_empty();
0308       return false;
0309     }
0310 
0311     unsigned int wfac = double(m_w)/double(a_w);
0312     unsigned int hfac = double(m_h)/double(a_h);
0313     if(!wfac) wfac = 1;
0314     if(!hfac) hfac = 1;
0315 
0316     unsigned int wfac_hfac = wfac*hfac;
0317 
0318     T* hpos;T* pos;
0319     for(unsigned int j=0;j<a_h;j++) {
0320       for(unsigned int i=0;i<a_w;i++) {
0321 
0322         // take mean value of wfac*hfac pixels :
0323        {for(unsigned int ipix=0;ipix<m_n;ipix++) pixels[ipix] = 0;}
0324 
0325         for(unsigned int fr=0;fr<hfac;fr++) {
0326           hpos = m_buffer + (j*hfac+fr)*(m_w*m_n);
0327           for(unsigned int fc=0;fc<wfac;fc++) {
0328             pos = hpos + (i*wfac+fc)*m_n;
0329             for(unsigned int ipix=0;ipix<m_n;ipix++) {
0330               pixels[ipix] += double(*pos)/double(wfac_hfac);pos++;
0331             }
0332           }
0333         }
0334 
0335         //position in the result image.
0336         T* rpos = rb + j * (a_w * m_n) + i*m_n;
0337        {for(unsigned int ipix=0;ipix<m_n;ipix++) {*rpos = T(pixels[ipix]);rpos++;}}
0338       }
0339     }
0340 
0341     delete [] pixels;
0342 
0343     a_res.set(a_w,a_h,m_n,rb,true);
0344     return true;
0345   }
0346 
0347   bool contract(unsigned int a_w,unsigned int a_h,img<T>& a_res,bool a_force_res_owner = true) const {
0348     //optimized version of contract_raw().
0349 
0350     if((a_w==m_w)&&(a_h==m_h)) {
0351       if(a_force_res_owner) {
0352         a_res.copy(m_w,m_h,m_n,m_buffer);
0353       } else {
0354         a_res.set(m_w,m_h,m_n,m_buffer,false);
0355       }
0356       return true;
0357     }
0358 
0359     size_t sz = a_h*a_w*m_n;
0360     if(!sz) {
0361       a_res.make_empty();
0362       return false;
0363     }
0364 
0365     T* rb = new T[sz];
0366     if(!rb) {
0367       a_res.make_empty();
0368       return false;
0369     }
0370 
0371     double* pixels = new double[m_n]; //for mean value.
0372     if(!pixels) {
0373       delete [] rb;
0374       a_res.make_empty();
0375       return false;
0376     }
0377    {for(unsigned int ipix=0;ipix<m_n;ipix++) pixels[ipix] = 0;}
0378 
0379     unsigned int wfac = (unsigned int)(double(m_w)/double(a_w));
0380     unsigned int hfac = (unsigned int)(double(m_h)/double(a_h));
0381     if(!wfac) wfac = 1;
0382     if(!hfac) hfac = 1;
0383 
0384     double wfac_hfac = wfac*hfac;
0385 
0386     //::printf("debug : %d %d, %d %d\n",a_h,a_w,hfac,wfac);
0387 
0388     T* hpos;T* pos;T* hrpos;T* rpos;T* hhpos;T* _pos;double* ppos;
0389     unsigned int i,j,fr,fc,ipix,i0;
0390     unsigned int astride = a_w * m_n;
0391     unsigned int mstride = m_w * m_n;
0392     unsigned int wfacstride = wfac * m_n;
0393 
0394     for(j=0;j<a_h;j++) {
0395       hrpos = rb + j * astride;
0396       hhpos = m_buffer + j*hfac*mstride;
0397       for(i=0;i<a_w;i++) {
0398 
0399         // take mean value of wfac*hfac pixels :
0400 
0401         i0 = i*wfacstride;
0402 
0403         hpos = hhpos;
0404         for(fr=0;fr<hfac;fr++,hpos+=mstride) {
0405           _pos = hpos + i0;
0406           for(fc=0;fc<wfac;fc++,_pos+=m_n) {
0407             pos = _pos;
0408             ppos = pixels;
0409             for(ipix=0;ipix<m_n;ipix++,pos++,ppos++) {
0410               *ppos += double(*pos)/wfac_hfac;
0411 //              *ppos += double(*pos); //NOTE : doing the wfac_hfac division in the below loop is slower !
0412             }
0413           }
0414         }
0415 
0416         //position in the result image.
0417         rpos = hrpos + i*m_n;
0418         ppos = pixels;
0419         for(ipix=0;ipix<m_n;ipix++,rpos++,ppos++) {
0420           *rpos = T(*ppos);
0421 //          *rpos = T((*ppos)/wfac_hfac); //slower !
0422           *ppos = 0;
0423         }
0424       }
0425     }
0426 
0427     delete [] pixels;
0428 
0429     a_res.set(a_w,a_h,m_n,rb,true);
0430     return true;
0431   }
0432 
0433   bool contract(unsigned int a_factor,img<T>& a_res,bool a_force_res_owner = true) const {
0434     // a_factor pixels are contracted in one.
0435     unsigned int nw = m_w/a_factor;
0436     unsigned int nh = m_h/a_factor;
0437     return contract(nw,nh,a_res,a_force_res_owner);
0438   }
0439 
0440   template <class TTO>
0441   bool convert(img<TTO>& a_res) const {
0442     a_res.make_empty();
0443 
0444     unsigned int sz = m_w*m_h*m_n;
0445     if(!sz) return false;
0446 
0447     TTO* _buffer = new TTO[sz];
0448     if(!_buffer) return false;
0449 
0450     unsigned int i,j,ipix,imn;
0451     unsigned int mwn = m_w*m_n;
0452     T* _pos;T* pos;
0453     TTO* _rpos;TTO* rpos;
0454 
0455     for(j=0;j<m_h;j++) {
0456       _pos = m_buffer + j*mwn;
0457       _rpos = _buffer + j*mwn;
0458       for(i=0;i<m_w;i++) {
0459         imn = i*m_n;
0460         pos = _pos + imn;
0461         rpos = _rpos + imn;
0462         for(ipix=0;ipix<m_n;ipix++,pos++,rpos++) *rpos = *pos;
0463       }
0464     }
0465 
0466     a_res.set(m_w,m_h,m_n,_buffer,true);
0467     return true;
0468   }
0469 
0470   bool get_part(unsigned int a_sx,unsigned int a_sy,unsigned int a_sw,unsigned int a_sh,img<T>& a_res) const {
0471 
0472     if((a_sx>=m_w)||(a_sy>=m_h)){
0473       a_res.make_empty();
0474       return false;
0475     }
0476 
0477     // 012345
0478     unsigned int rw = min_of<unsigned int>(m_w-a_sx,a_sw);
0479     unsigned int rh = min_of<unsigned int>(m_h-a_sy,a_sh);
0480     unsigned int sz = rh*rw*m_n;
0481     if(!sz) {
0482       a_res.make_empty();
0483       return false;
0484     }
0485 
0486     T* rb = new T[sz];
0487     if(!rb) {
0488       a_res.make_empty();
0489       return false;
0490     }
0491 
0492     unsigned int rstride = rw * m_n;
0493     T* rpos = rb;
0494 
0495     unsigned int stride = m_w * m_n;
0496     T* pos = m_buffer+a_sy*stride+a_sx*m_n;
0497 
0498     //T* mx = m_buffer+size();
0499     //T* rmx = rb+sz*sizeof(T);
0500 
0501     for(unsigned int j=0;j<rh;j++,rpos+=rstride,pos+=stride) {//j=0 -> bottom.
0502 /*
0503       if((pos+rstride*sizeof(T))>mx) {
0504         ::printf("debug : get_part : buffer overflow\n");
0505         delete [] rb;
0506         a_res.make_empty();
0507         return false;
0508       }
0509       if((rpos+rstride*sizeof(T))>rmx) {
0510         ::printf("debug : get_part : result buffer overflow\n");
0511         delete [] rb;
0512         a_res.make_empty();
0513         return false;
0514       }
0515 */
0516       ::memcpy(rpos,pos,rstride*sizeof(T));
0517     }
0518 
0519     a_res.set(rw,rh,m_n,rb,true);
0520     return true;
0521   }
0522 
0523   bool to_texture(bool a_expand,
0524                   const T a_pixel[], //size shoulde be a_img.m_n.
0525                   img<T>& a_res,bool a_res_force_owner = true) const {
0526 
0527     //NOTE : pixels of the original image are not expanded or shrinked.
0528 
0529     if((!m_w)||(!m_h)) {
0530       a_res.make_empty();
0531       return false;
0532     }
0533 
0534     // in case (m_w==1)||(m_h==1), expand the pixel
0535     // up to the closest power of 2 ?
0536 
0537     if((m_w==1)||(m_h==1)||a_expand) {
0538       // find closest power of two upper than m_w, m_h :
0539       unsigned int rw = 2;
0540       while(true) {if(rw>=m_w) break;rw *=2;}
0541       unsigned int rh = 2;
0542       while(true) {if(rh>=m_h) break;rh *=2;}
0543 
0544       if((rw==m_w)&&(rh==m_h)) { //exact match.
0545         if(a_res_force_owner) {
0546           a_res.copy(m_w,m_h,m_n,m_buffer);
0547         } else {
0548           a_res.set(m_w,m_h,m_n,m_buffer,false); //WARNING owner=false.
0549         }
0550         return true;
0551       }
0552 
0553       // we expand the image and fill new spaces with a_pixel.
0554 
0555       T* rb = 0;
0556       bool res_set = true;
0557       if(a_res.owner()&&(a_res.size()==(rh*rw*m_n))) {
0558         // a_res has already the right allocation.
0559         rb = a_res.buffer();
0560         res_set = false;
0561       } else {
0562         rb = new T[rh*rw*m_n];
0563         if(!rb) {
0564           a_res.make_empty();
0565           return false;
0566         }
0567       }
0568 
0569       unsigned int num = rw*m_n;
0570 
0571       // initialize with given color :
0572      {T* pos = rb;
0573       for(unsigned int i=0;i<rw;i++,pos+=m_n) {
0574         ::memcpy(pos,a_pixel,m_n*sizeof(T));
0575       }
0576       unsigned int sz = num*sizeof(T);
0577       for(unsigned int j=1;j<rh;j++,pos+=num) {  //j=0 -> bottom.
0578         ::memcpy(pos,rb,sz);
0579       }}
0580 
0581       // center :
0582       unsigned int col = (rw-m_w)/2;
0583       unsigned int row = (rh-m_h)/2;
0584 
0585       unsigned int mnum = m_w*m_n;
0586 
0587       // copy original image in a centered part of the new one :
0588      {T* pos = m_buffer;
0589       T* rpos = rb+row*num+col*m_n;
0590       unsigned int sz = mnum*sizeof(T);
0591       for(unsigned int j=0;j<m_h;j++,pos+=mnum,rpos+=num) {
0592         ::memcpy(rpos,pos,sz);
0593       }}
0594 
0595       if(res_set) a_res.set(rw,rh,m_n,rb,true);
0596 
0597       return true;
0598     } else {
0599       // then m_w>=2 and m_h>=2
0600 
0601       // find closest power of two lower than m_w, m_h :
0602       unsigned int sw = 2;
0603       while(true) {if((sw*2)>m_w) break;sw *=2;}
0604       unsigned int sh = 2;
0605       while(true) {if((sh*2)>m_h) break;sh *=2;}
0606 
0607       if((sw==m_w)&&(sh==m_h)) { //exact match.
0608         if(a_res_force_owner) {
0609           a_res.copy(m_w,m_h,m_n,m_buffer);
0610         } else {
0611           a_res.set(m_w,m_h,m_n,m_buffer,false); //WARNING owner=false.
0612         }
0613         return true;
0614       }
0615 
0616       unsigned int sx = (m_w-sw)/2;
0617       unsigned int sy = (m_h-sh)/2;
0618 
0619       return get_part(sx,sy,sw,sh,a_res);
0620     }
0621 
0622   }
0623 
0624   bool check_gl_limit(unsigned int a_GL_MAX_TEXTURE_SIZE,img<T>& a_res) const {
0625     // if ret true and a_res.is_empty(), "this" does not exceeds the limit.
0626     // if ret true and !a_res.is_empty(), "this" exceeds the limit and a new fitting image is returned in a_res.
0627     // if ret false, "this" exceeds the limit but something went wrong in building a_res.
0628     unsigned int tw = m_w;
0629     unsigned int th = m_h;
0630     if((tw<=a_GL_MAX_TEXTURE_SIZE)&&(th<=a_GL_MAX_TEXTURE_SIZE)) {
0631       a_res.make_empty();
0632       return true;
0633     }
0634     unsigned int fac = 2;
0635     while(true) {
0636       unsigned int pw = tw/fac;
0637       unsigned int ph = th/fac;
0638       if((pw<=a_GL_MAX_TEXTURE_SIZE)&&(ph<=a_GL_MAX_TEXTURE_SIZE)) {
0639         //unsigned int sx = (tw-pw)/2;
0640         //unsigned int sy = (th-ph)/2;
0641         //if(!get_part(sx,sy,pw,ph,a_res)) {
0642         if(!contract(fac,a_res)) {
0643           a_res.make_empty();
0644           return false;
0645         }
0646         return true;
0647       }
0648       fac *= 2;
0649     }
0650     a_res.make_empty();
0651     return false;
0652   }
0653 
0654   bool bw2x(unsigned int a_n,img<T>& a_res) const {
0655     //expect a bw img.
0656     if(m_n!=1) return false;
0657 
0658     a_res.make_empty();
0659     if(a_n<m_n) return false;
0660     unsigned int sz = m_w*m_h*a_n;
0661     if(!sz) return false;
0662 
0663     a_res.m_buffer = new T[sz];
0664     if(!a_res.m_buffer) return false;
0665     a_res.m_owner = true;
0666     a_res.m_w = m_w;
0667     a_res.m_h = m_h;
0668     a_res.m_n = a_n;
0669 
0670     for(unsigned int j=0;j<m_h;j++) {
0671       for(unsigned int i=0;i<m_w;i++) {
0672         //position in the original image.
0673         T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
0674 
0675         T* rpos = a_res.m_buffer + j * (m_w * a_n) + i*a_n;
0676 
0677         for(unsigned int ipix=0;ipix<a_n;ipix++) {
0678           *(rpos+ipix) = *pos;
0679         }
0680 
0681       }
0682     }
0683 
0684     return true;
0685   }
0686 
0687   bool yswap(img<T>& a_res) const {
0688     a_res.make_empty();
0689 
0690     a_res.m_buffer = new T[size()];
0691     if(!a_res.m_buffer) return false;
0692     a_res.m_owner = true;
0693     a_res.m_w = m_w;
0694     a_res.m_h = m_h;
0695     a_res.m_n = m_n;
0696 
0697     unsigned int stride = m_w * m_n;
0698 
0699     for(unsigned int j=0;j<m_h;j++) {
0700       T* pos = m_buffer + j * stride;
0701       T* rpos = a_res.m_buffer + (m_h-j-1) * stride;
0702       ::memcpy(rpos,pos,stride*sizeof(T));
0703     }
0704 
0705     return true;
0706   }
0707 
0708   bool rgba2rgb(img<T>& a_res) const {
0709     if(m_n!=4) return false;
0710 
0711     unsigned int a_n = 3;
0712 
0713     a_res.make_empty();
0714     unsigned int sz = m_w*m_h*a_n;
0715     if(!sz) return false;
0716 
0717     a_res.m_buffer = new T[sz];
0718     if(!a_res.m_buffer) return false;
0719     a_res.m_owner = true;
0720     a_res.m_w = m_w;
0721     a_res.m_h = m_h;
0722     a_res.m_n = a_n;
0723 
0724     for(unsigned int j=0;j<m_h;j++) {
0725       for(unsigned int i=0;i<m_w;i++) {
0726         //position in the original image.
0727         T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
0728 
0729         T* rpos = a_res.m_buffer + j * (m_w * a_n) + i*a_n;
0730 
0731         for(unsigned int ipix=0;ipix<a_n;ipix++) {
0732           *(rpos+ipix) = *(pos+ipix);
0733         }
0734 
0735       }
0736     }
0737 
0738     return true;
0739   }
0740 
0741   bool rgb2rgba(img<T>& a_res,const T& a_pixel) const {
0742     if(m_n!=3) return false;
0743 
0744     unsigned int n = 4;
0745 
0746     a_res.make_empty();
0747     unsigned int sz = m_w*m_h*n;
0748     if(!sz) return false;
0749 
0750     a_res.m_buffer = new T[sz];
0751     if(!a_res.m_buffer) return false;
0752     a_res.m_owner = true;
0753     a_res.m_w = m_w;
0754     a_res.m_h = m_h;
0755     a_res.m_n = n;
0756 
0757     for(unsigned int j=0;j<m_h;j++) {
0758       for(unsigned int i=0;i<m_w;i++) {
0759         //position in the original image.
0760         T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
0761 
0762         T* rpos = a_res.m_buffer + j * (m_w * n) + i*n;
0763 
0764         *(rpos+0) = *(pos+0);
0765         *(rpos+1) = *(pos+1);
0766         *(rpos+2) = *(pos+2);
0767         *(rpos+3) = a_pixel;
0768 
0769       }
0770     }
0771 
0772     return true;
0773   }
0774 
0775   bool rgba2bgra() {
0776     if(m_n!=4) return false;
0777     for(unsigned int j=0;j<m_h;j++) {
0778       for(unsigned int i=0;i<m_w;i++) {
0779         T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
0780         T r = *(pos+0);
0781         T g = *(pos+1);
0782         T b = *(pos+2);
0783         T a = *(pos+3);
0784         *(pos+0) = b;
0785         *(pos+1) = g;
0786         *(pos+2) = r;
0787         *(pos+3) = a;
0788       }
0789     }
0790     return true;
0791   }
0792 
0793 public:
0794   static bool concatenate(const std::vector< img<T> >& a_imgs,
0795                           unsigned int a_cols,unsigned int a_rows,
0796                           unsigned int a_bw,unsigned int a_bh,
0797                           T a_bc, //border grey level.
0798                           img<T>& a_res){
0799     // We assume that a_imgs.size() is a_cols*a_rows and that all images have same (w,h,bpp).
0800 
0801     unsigned int num = a_cols*a_rows;
0802     if(!num) {a_res.make_empty();return false;}
0803 
0804     unsigned int aw = a_imgs[0].m_w;
0805     unsigned int ah = a_imgs[0].m_h;
0806     unsigned int an = a_imgs[0].m_n;
0807 
0808     for(unsigned int index=1;index<num;index++) {
0809       if(a_imgs[index].m_n!=an) {
0810         a_res.make_empty();
0811         return false;
0812       }
0813       if(a_imgs[index].m_w!=aw) {
0814         a_res.make_empty();
0815         return false;
0816       }
0817       if(a_imgs[index].m_h!=ah) {
0818         a_res.make_empty();
0819         return false;
0820       }
0821     }
0822 
0823     unsigned int wbw = aw + 2*a_bw;
0824     unsigned int hbh = ah + 2*a_bh;
0825 
0826     unsigned int rw = wbw * a_cols;
0827     unsigned int rh = hbh * a_rows;
0828     unsigned int rn = an;
0829 
0830     //printf("debug : %d %d\n",rw,rh);
0831 
0832     // on big concatenated image the below may fail :
0833     unsigned int rsz = rh*rw*rn;
0834     T* rb = new T[rsz];
0835     if(!rb) {
0836       a_res.make_empty();
0837       return false;
0838     }
0839 
0840     bool has_border = a_bw||a_bh?true:false;
0841     if(has_border) {
0842       ::memset(rb,a_bc,rsz*sizeof(T));
0843     }
0844 
0845     //optimize :
0846     //unsigned int wbwn = wbw*an;
0847     unsigned int awn = aw*an;
0848     unsigned int rwn = rw*an;
0849     unsigned int i,j,r;
0850     //unsigned int c;
0851     T* pos;T* ptile;T* _pos;
0852 
0853     //copy tiles :
0854     unsigned int index = 0;
0855     for(j=0;j<a_rows;j++) {
0856       for(i=0;i<a_cols;i++) {
0857         // index = a_cols*j+i
0858         const T* tile = a_imgs[index].buffer();
0859 
0860         //if(has_border) {
0861         //  for(unsigned int r=0;r<hbh;r++) {
0862         //    T* pos = rb + (j*hbh+r)*rwn + i*wbwn;
0863         //    ::memset(pos,a_bc,wbwn*sizeof(T));
0864         //  }
0865         //}
0866 
0867         _pos = rb + (j*hbh+a_bh)*rwn + (i*wbw+a_bw)*rn;
0868        {for(r=0;r<ah;r++) {
0869 //          pos = _pos + r*rwn;
0870 //          ptile = tile + r*awn;
0871 //          for(c=0;c<awn;c++,pos++,ptile++) *pos = *ptile;
0872           ::memcpy(_pos+r*rwn,tile+r*awn,awn*sizeof(T)); //optimize. (bof, we do not gain a lot).
0873         }}
0874 
0875         index++;
0876       }
0877     }
0878 
0879     a_res.set(rw,rh,rn,rb,true);
0880     return true;
0881   }
0882 
0883 protected:
0884   unsigned int m_w;
0885   unsigned int m_h;
0886   unsigned int m_n;
0887   T* m_buffer;
0888   bool m_owner;
0889 
0890 private: static void check_instantiation() {img<float> dummy;}
0891 };
0892 
0893 
0894 typedef img<unsigned char> img_byte;
0895 
0896 // NOTE : img_byte is ready for OpenGL glTexImage2D UNSIGNED_BYTE RGB.
0897 //        For glTexImage2D, first row in m_buffer is bottom of image.
0898 
0899 inline void tex_expand_size(unsigned int a_w,unsigned int& a_h,
0900                             unsigned int& a_ew,unsigned int& a_eh){
0901   // find closest power of two upper than a_w, a_h :
0902   a_ew = 2;
0903   while(true) {if(a_ew>=a_w) break;a_ew *=2;}
0904   a_eh = 2;
0905   while(true) {if(a_eh>=a_h) break;a_eh *=2;}
0906 }
0907 
0908 }
0909 
0910 #endif