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 #include <string> //memcpy
0008 #include <cstring> //memcpy
0009 #include "mnmx"
0010 #include "S_STRING"
0011 
0012 #include <vector> //concatenate
0013 
0014 namespace tools {
0015 
0016 template <class T>
0017 class img {
0018 public:
0019   TOOLS_T_SCLASS(T,tools::img)
0020 public:
0021   img()
0022   :m_w(0),m_h(0),m_n(0)
0023   ,m_buffer(0)
0024   ,m_owner(false)
0025   {
0026   }
0027   img(unsigned int a_w,unsigned int a_h,unsigned int a_n,T* a_buffer,bool a_owner)
0028   :m_w(a_w),m_h(a_h),m_n(a_n)
0029   ,m_buffer(a_buffer)
0030   ,m_owner(a_owner)
0031   {
0032   }
0033   virtual ~img() {
0034     if(m_owner) delete [] m_buffer;
0035   }
0036 public:
0037   img(const img& a_from)
0038   :m_w(a_from.m_w),m_h(a_from.m_h),m_n(a_from.m_n)
0039   ,m_buffer(0)
0040   ,m_owner(a_from.m_owner)
0041   {
0042     if(m_owner) {
0043       unsigned int sz = m_w*m_h*m_n;
0044       if(!sz) return;
0045       m_buffer = new T[sz];
0046       if(!m_buffer) {
0047         m_w = 0;m_h = 0;m_n = 0;m_owner = false;
0048         return; //throw
0049       }
0050       ::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
0051     } else {
0052       m_buffer = a_from.m_buffer;
0053     }
0054   }
0055   img& operator=(const img& a_from){
0056     if(&a_from==this) return *this;
0057     if(m_owner) delete [] m_buffer;
0058     m_buffer = 0;
0059     m_w = a_from.m_w;
0060     m_h = a_from.m_h;
0061     m_n = a_from.m_n;
0062     m_owner = a_from.m_owner;
0063     if(m_owner) {
0064       unsigned int sz = m_w*m_h*m_n;
0065       if(!sz) return *this;
0066       m_buffer = new T[sz];
0067       if(!m_buffer) {
0068         m_w = 0;m_h = 0;m_n = 0;m_owner = false;
0069         return *this;  //throw
0070       }
0071       ::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
0072     } else {
0073       m_buffer = a_from.m_buffer;
0074     }
0075     return *this;
0076   }
0077 public:
0078   bool operator==(const img& a_from) const {return equal(a_from);}
0079   bool operator!=(const img& a_from) const {return !operator==(a_from);}
0080 public:
0081   void set(unsigned int a_w,unsigned int a_h,unsigned int a_n,T* a_buffer,bool a_owner) {
0082     if(m_owner) delete [] m_buffer;
0083     m_w = a_w;
0084     m_h = a_h;
0085     m_n = a_n;
0086     m_buffer = a_buffer;
0087     m_owner = a_owner;
0088   }
0089   bool copy(unsigned int a_w,unsigned int a_h,unsigned int a_n,T* a_buffer) {
0090     if(m_owner) delete [] m_buffer;
0091     m_buffer = 0;
0092     m_w = a_w;
0093     m_h = a_h;
0094     m_n = a_n;
0095     unsigned int sz = m_w*m_h*m_n;
0096     if(!sz) {
0097       m_w = 0;m_h = 0;m_n = 0;m_owner = false;
0098       return false;
0099     }
0100     m_buffer = new T[sz];
0101     if(!m_buffer) {
0102       m_w = 0;m_h = 0;m_n = 0;m_owner = false;
0103       return false;
0104     }
0105     ::memcpy(m_buffer,a_buffer,sz*sizeof(T));
0106     m_owner = true;
0107     return true;
0108   }
0109   void make_empty(bool a_delete = true) {
0110     if(m_owner && a_delete) delete [] m_buffer;
0111     m_w = 0;
0112     m_h = 0;
0113     m_n = 0;
0114     m_buffer = 0;
0115     m_owner = false;
0116   }
0117   bool is_empty() const {
0118     if(!m_w) return true;
0119     if(!m_h) return true;
0120     if(!m_n) return true;
0121     if(!m_buffer) return true;
0122     return false;
0123   }
0124   bool equal(const img& a_from) const {
0125     if(m_w!=a_from.m_w) return false;
0126     if(m_h!=a_from.m_h) return false;
0127     if(m_n!=a_from.m_n) return false;
0128     //don't test ownership.
0129     unsigned int sz = m_w*m_h*m_n;
0130     T* pos = m_buffer;
0131     T* fpos = a_from.m_buffer;
0132     for(unsigned int index=0;index<sz;index++,pos++,fpos++) {
0133       if((*pos)!=(*fpos)) return false;
0134     }
0135     return true;
0136   }
0137   unsigned int width() const {return m_w;}
0138   unsigned int height() const {return m_h;}
0139   unsigned int bytes_per_pixel() const {return m_n;}
0140   const T* buffer() const {return m_buffer;}
0141   T* buffer() {return m_buffer;}
0142   bool owner() const {return m_owner;}
0143   unsigned int size() const {return m_w*m_h*m_n*sizeof(T);} //bytes.
0144 public:
0145   bool pixel(unsigned int a_i,unsigned a_j,std::vector<T>& a_pixel) const {
0146     if((!m_w)||(!m_h)||(a_i>=m_w)||(a_j>=m_h)) {
0147       a_pixel.clear();
0148       return false;
0149     }
0150     a_pixel.resize(m_n);
0151     T* pos = m_buffer + a_j * (m_w * m_n) + a_i*m_n;
0152     for(unsigned int ipix=0;ipix<m_n;ipix++) {
0153       a_pixel[ipix] = *(pos+ipix);
0154     }
0155     return true;
0156   }
0157 
0158   bool contract(unsigned int a_w,unsigned int a_h,img<T>& a_res,bool a_force_res_owner = true) const {
0159     //optimized version of contract_raw().
0160 
0161     if((a_w==m_w)&&(a_h==m_h)) {
0162       if(a_force_res_owner) {
0163         a_res.copy(m_w,m_h,m_n,m_buffer);
0164       } else {
0165         a_res.set(m_w,m_h,m_n,m_buffer,false);
0166       }
0167       return true;
0168     }
0169 
0170     size_t sz = a_h*a_w*m_n;
0171     if(!sz) {
0172       a_res.make_empty();
0173       return false;
0174     }
0175 
0176     T* rb = new T[sz];
0177     if(!rb) {
0178       a_res.make_empty();
0179       return false;
0180     }
0181 
0182     double* pixels = new double[m_n]; //for mean value.
0183     if(!pixels) {
0184       delete [] rb;
0185       a_res.make_empty();
0186       return false;
0187     }
0188    {for(unsigned int ipix=0;ipix<m_n;ipix++) pixels[ipix] = 0;}
0189 
0190     unsigned int wfac = (unsigned int)(double(m_w)/double(a_w));
0191     unsigned int hfac = (unsigned int)(double(m_h)/double(a_h));
0192     if(!wfac) wfac = 1;
0193     if(!hfac) hfac = 1;
0194 
0195     double wfac_hfac = wfac*hfac;
0196 
0197     T* hpos;T* pos;T* hrpos;T* rpos;T* hhpos;T* _pos;double* ppos;
0198     unsigned int i,j,fr,fc,ipix,i0;
0199     unsigned int astride = a_w * m_n;
0200     unsigned int mstride = m_w * m_n;
0201     unsigned int wfacstride = wfac * m_n;
0202 
0203     for(j=0;j<a_h;j++) {
0204       hrpos = rb + j * astride;
0205       hhpos = m_buffer + j*hfac*mstride;
0206       for(i=0;i<a_w;i++) {
0207 
0208         // take mean value of wfac*hfac pixels :
0209 
0210         i0 = i*wfacstride;
0211 
0212         hpos = hhpos;
0213         for(fr=0;fr<hfac;fr++,hpos+=mstride) {
0214           _pos = hpos + i0;
0215           for(fc=0;fc<wfac;fc++,_pos+=m_n) {
0216             pos = _pos;
0217             ppos = pixels;
0218             for(ipix=0;ipix<m_n;ipix++,pos++,ppos++) {
0219               *ppos += double(*pos)/wfac_hfac;
0220             }
0221           }
0222         }
0223 
0224         //position in the result image.
0225         rpos = hrpos + i*m_n;
0226         ppos = pixels;
0227         for(ipix=0;ipix<m_n;ipix++,rpos++,ppos++) {
0228           *rpos = T(*ppos);
0229           *ppos = 0;
0230         }
0231       }
0232     }
0233 
0234     delete [] pixels;
0235 
0236     a_res.set(a_w,a_h,m_n,rb,true);
0237     return true;
0238   }
0239 
0240   bool contract(unsigned int a_factor,img<T>& a_res,bool a_force_res_owner = true) const {
0241     // a_factor pixels are contracted in one.
0242     unsigned int nw = m_w/a_factor;
0243     unsigned int nh = m_h/a_factor;
0244     return contract(nw,nh,a_res,a_force_res_owner);
0245   }
0246 
0247   bool get_part(unsigned int a_sx,unsigned int a_sy,unsigned int a_sw,unsigned int a_sh,img<T>& a_res) const {
0248 
0249     if((a_sx>=m_w)||(a_sy>=m_h)){
0250       a_res.make_empty();
0251       return false;
0252     }
0253 
0254     // 012345
0255     unsigned int rw = min_of<unsigned int>(m_w-a_sx,a_sw);
0256     unsigned int rh = min_of<unsigned int>(m_h-a_sy,a_sh);
0257     unsigned int sz = rh*rw*m_n;
0258     if(!sz) {
0259       a_res.make_empty();
0260       return false;
0261     }
0262 
0263     T* rb = new T[sz];
0264     if(!rb) {
0265       a_res.make_empty();
0266       return false;
0267     }
0268 
0269     unsigned int rstride = rw * m_n;
0270     T* rpos = rb;
0271 
0272     unsigned int stride = m_w * m_n;
0273     T* pos = m_buffer+a_sy*stride+a_sx*m_n;
0274 
0275     for(unsigned int j=0;j<rh;j++,rpos+=rstride,pos+=stride) {//j=0 -> bottom.
0276       ::memcpy(rpos,pos,rstride*sizeof(T));
0277     }
0278 
0279     a_res.set(rw,rh,m_n,rb,true);
0280     return true;
0281   }
0282 
0283   bool to_texture(bool a_expand,
0284                   const T a_pixel[], //size shoulde be a_img.m_n.
0285                   img<T>& a_res,bool a_res_force_owner = true) const {
0286 
0287     //NOTE : pixels of the original image are not expanded or shrinked.
0288 
0289     if((!m_w)||(!m_h)) {
0290       a_res.make_empty();
0291       return false;
0292     }
0293 
0294     // in case (m_w==1)||(m_h==1), expand the pixel
0295     // up to the closest power of 2 ?
0296 
0297     if((m_w==1)||(m_h==1)||a_expand) {
0298       // find closest power of two upper than m_w, m_h :
0299       unsigned int rw = 2;
0300       while(true) {if(rw>=m_w) break;rw *=2;}
0301       unsigned int rh = 2;
0302       while(true) {if(rh>=m_h) break;rh *=2;}
0303 
0304       if((rw==m_w)&&(rh==m_h)) { //exact match.
0305         if(a_res_force_owner) {
0306           a_res.copy(m_w,m_h,m_n,m_buffer);
0307         } else {
0308           a_res.set(m_w,m_h,m_n,m_buffer,false); //WARNING owner=false.
0309         }
0310         return true;
0311       }
0312 
0313       // we expand the image and fill new spaces with a_pixel.
0314 
0315       T* rb = 0;
0316       bool res_set = true;
0317       if(a_res.owner()&&(a_res.size()==(rh*rw*m_n))) {
0318         // a_res has already the right allocation.
0319         rb = a_res.buffer();
0320         res_set = false;
0321       } else {
0322         rb = new T[rh*rw*m_n];
0323         if(!rb) {
0324           a_res.make_empty();
0325           return false;
0326         }
0327       }
0328 
0329       unsigned int num = rw*m_n;
0330 
0331       // initialize with given color :
0332      {T* pos = rb;
0333       for(unsigned int i=0;i<rw;i++,pos+=m_n) {
0334         ::memcpy(pos,a_pixel,m_n*sizeof(T));
0335       }
0336       unsigned int sz = num*sizeof(T);
0337       for(unsigned int j=1;j<rh;j++,pos+=num) {  //j=0 -> bottom.
0338         ::memcpy(pos,rb,sz);
0339       }}
0340 
0341       // center :
0342       unsigned int col = (rw-m_w)/2;
0343       unsigned int row = (rh-m_h)/2;
0344 
0345       unsigned int mnum = m_w*m_n;
0346 
0347       // copy original image in a centered part of the new one :
0348      {T* pos = m_buffer;
0349       T* rpos = rb+row*num+col*m_n;
0350       unsigned int sz = mnum*sizeof(T);
0351       for(unsigned int j=0;j<m_h;j++,pos+=mnum,rpos+=num) {
0352         ::memcpy(rpos,pos,sz);
0353       }}
0354 
0355       if(res_set) a_res.set(rw,rh,m_n,rb,true);
0356 
0357       return true;
0358     } else {
0359       // then m_w>=2 and m_h>=2
0360 
0361       // find closest power of two lower than m_w, m_h :
0362       unsigned int sw = 2;
0363       while(true) {if((sw*2)>m_w) break;sw *=2;}
0364       unsigned int sh = 2;
0365       while(true) {if((sh*2)>m_h) break;sh *=2;}
0366 
0367       if((sw==m_w)&&(sh==m_h)) { //exact match.
0368         if(a_res_force_owner) {
0369           a_res.copy(m_w,m_h,m_n,m_buffer);
0370         } else {
0371           a_res.set(m_w,m_h,m_n,m_buffer,false); //WARNING owner=false.
0372         }
0373         return true;
0374       }
0375 
0376       unsigned int sx = (m_w-sw)/2;
0377       unsigned int sy = (m_h-sh)/2;
0378 
0379       return get_part(sx,sy,sw,sh,a_res);
0380     }
0381 
0382   }
0383 
0384   bool check_gl_limit(unsigned int a_GL_MAX_TEXTURE_SIZE,img<T>& a_res) const {
0385     // if ret true and a_res.is_empty(), "this" does not exceeds the limit.
0386     // if ret true and !a_res.is_empty(), "this" exceeds the limit and a new fitting image is returned in a_res.
0387     // if ret false, "this" exceeds the limit but something went wrong in building a_res.
0388     unsigned int tw = m_w;
0389     unsigned int th = m_h;
0390     if((tw<=a_GL_MAX_TEXTURE_SIZE)&&(th<=a_GL_MAX_TEXTURE_SIZE)) {
0391       a_res.make_empty();
0392       return true;
0393     }
0394     unsigned int fac = 2;
0395     while(true) {
0396       unsigned int pw = tw/fac;
0397       unsigned int ph = th/fac;
0398       if((pw<=a_GL_MAX_TEXTURE_SIZE)&&(ph<=a_GL_MAX_TEXTURE_SIZE)) {
0399         if(!contract(fac,a_res)) {
0400           a_res.make_empty();
0401           return false;
0402         }
0403         return true;
0404       }
0405       fac *= 2;
0406     }
0407     a_res.make_empty();
0408     return false;
0409   }
0410 
0411   bool bw2x(unsigned int a_n,img<T>& a_res) const {
0412     //expect a bw img.
0413     if(m_n!=1) return false;
0414 
0415     a_res.make_empty();
0416     if(a_n<m_n) return false;
0417     unsigned int sz = m_w*m_h*a_n;
0418     if(!sz) return false;
0419 
0420     a_res.m_buffer = new T[sz];
0421     if(!a_res.m_buffer) return false;
0422     a_res.m_owner = true;
0423     a_res.m_w = m_w;
0424     a_res.m_h = m_h;
0425     a_res.m_n = a_n;
0426 
0427     for(unsigned int j=0;j<m_h;j++) {
0428       for(unsigned int i=0;i<m_w;i++) {
0429         //position in the original image.
0430         T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
0431 
0432         T* rpos = a_res.m_buffer + j * (m_w * a_n) + i*a_n;
0433 
0434         for(unsigned int ipix=0;ipix<a_n;ipix++) {
0435           *(rpos+ipix) = *pos;
0436         }
0437 
0438       }
0439     }
0440 
0441     return true;
0442   }
0443 
0444   bool rgb2rgba(img<T>& a_res,const T& a_pixel) const {
0445     if(m_n!=3) return false;
0446 
0447     unsigned int n = 4;
0448 
0449     a_res.make_empty();
0450     unsigned int sz = m_w*m_h*n;
0451     if(!sz) return false;
0452 
0453     a_res.m_buffer = new T[sz];
0454     if(!a_res.m_buffer) return false;
0455     a_res.m_owner = true;
0456     a_res.m_w = m_w;
0457     a_res.m_h = m_h;
0458     a_res.m_n = n;
0459 
0460     for(unsigned int j=0;j<m_h;j++) {
0461       for(unsigned int i=0;i<m_w;i++) {
0462         //position in the original image.
0463         T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
0464 
0465         T* rpos = a_res.m_buffer + j * (m_w * n) + i*n;
0466 
0467         *(rpos+0) = *(pos+0);
0468         *(rpos+1) = *(pos+1);
0469         *(rpos+2) = *(pos+2);
0470         *(rpos+3) = a_pixel;
0471 
0472       }
0473     }
0474 
0475     return true;
0476   }
0477 
0478 protected:
0479   unsigned int m_w;
0480   unsigned int m_h;
0481   unsigned int m_n;
0482   T* m_buffer;
0483   bool m_owner;
0484 
0485 private: static void check_instantiation() {img<float> dummy;}
0486 };
0487 
0488 // NOTE : img_byte is ready for OpenGL glTexImage2D UNSIGNED_BYTE RGB.
0489 //        For glTexImage2D, first row in m_buffer is bottom of image.
0490 typedef img<unsigned char> img_byte;
0491 
0492 }
0493 
0494 #endif