Commit message: .
CVE: CVE-2019-13568
CWE: CWE-787
Vulnerability description: CImg through 2.6.7 has a heap-based buffer overflow in _load_bmp in CImg.h because of erroneous memory allocation for a malformed BMP image.

Project: CImg
File: CImg.h

    template<typename t>
    CImg<doubleT> _eval(CImg<T> *const output, const char *const expression, const CImg<t>& xyzc,
                        const CImgList<T> *const list_inputs=0, CImgList<T> *const list_outputs=0) const {
      CImg<doubleT> res(1,xyzc.size()/4);
      if (!expression || !*expression) return res.fill(0);
      _cimg_math_parser mp(expression,"eval",*this,output,list_inputs,list_outputs,false);

#if cimg_use_openmp!=0
      cimg_pragma_openmp(parallel if (res._height>=512))
      {
        _cimg_math_parser
          _mp = omp_get_thread_num()?mp:_cimg_math_parser(),
          &lmp = omp_get_thread_num()?_mp:mp;
        cimg_pragma_openmp(for)
          for (int i = 0; i<res.height(); ++i) {
            const unsigned int i4 = 4*i;
            const double
              x = (double)xyzc[i4], y = (double)xyzc[i4 + 1],
              z = (double)xyzc[i4 + 2], c = (double)xyzc[i4 + 3];
            res[i] = lmp(x,y,z,c);
          }
        }
#else
      const t *ps = xyzc._data;
      cimg_for(res,pd,double) {
        const double x = (double)*(ps++), y = (double)*(ps++), z = (double)*(ps++), c = (double)*(ps++);
        *pd = mp(x,y,z,c);
      }
#endif
      mp.end();
      return res;

Project: CImg
File: CImg.h

    //! Convert pixel values from HSI to RGB color spaces \newinstance.
    CImg<Tfloat> get_HSItoRGB() const {
      return CImg< Tuchar>(*this,false).HSItoRGB();

Project: CImg
File: CImg.h


      unsigned int scalar0(const mp_func op) {
        const unsigned int pos = scalar();
        CImg<ulongT>::vector((ulongT)op,pos).move_to(code);
        return pos;

Project: CImg
File: CImg.h

    template<typename T>
    inline T hypot(const T x, const T y, const T z) {
      return std::sqrt(x*x + y*y + z*z);

Project: CImg
File: CImg.h

    //! Fill sequentially all pixel values with specified values \newinstance.
    CImg<T> get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5,
                     const T& val6, const T& val7) const {
      return CImg<T>(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7);

Project: CImg
File: CImg.h


      static double mp_rot3d(_cimg_math_parser& mp) {
        double *ptrd = &_mp_arg(1) + 1;
        const float x = (float)_mp_arg(2), y = (float)_mp_arg(3), z = (float)_mp_arg(4), theta = (float)_mp_arg(5);
        CImg<doubleT>(ptrd,3,3,1,1,true) = CImg<doubleT>::rotation_matrix(x,y,z,theta);
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h

    **/
    CImg<T>& load_inr(const char *const filename, float *const voxel_size=0) {
      return _load_inr(0,filename,voxel_size);

Project: CImg
File: CImg.h

    **/
    CImgList(const unsigned int n, const unsigned int width, const unsigned int height,
             const unsigned int depth, const unsigned int spectrum, const int val0, const int val1, ...):
      _width(0),_allocated_width(0),_data(0) {
#define _CImgList_stdarg(t) { \
	assign(n,width,height,depth,spectrum); \
	const ulongT siz = (ulongT)width*height*depth*spectrum, nsiz = siz*n; \
	T *ptrd = _data->_data; \
	va_list ap; \
	va_start(ap,val1); \
	for (ulongT l = 0, s = 0, i = 0; i<nsiz; ++i) { \
	  *(ptrd++) = (T)(i==0?val0:(i==1?val1:va_arg(ap,t))); \
	  if ((++s)==siz) { ptrd = _data[++l]._data; s = 0; } \
	} \
	va_end(ap); \
      }
      _CImgList_stdarg(int);

Project: CImg
File: CImg.h

  template<typename T>
  inline CImg<T> operator^(const char *const expression, const CImg<T>& img) {
    return img ^ expression;

Project: CImg
File: CImg.h


    CImgDisplay& _assign(const unsigned int dimw, const unsigned int dimh, const char *const ptitle=0,
                         const unsigned int normalization_type=3,
                         const bool fullscreen_flag=false, const bool closed_flag=false) {

      // Allocate space for window title
      const char *const nptitle = ptitle?ptitle:"";
      const unsigned int s = (unsigned int)std::strlen(nptitle) + 1;
      char *const tmp_title = s?new char[s]:0;
      if (s) std::memcpy(tmp_title,nptitle,s*sizeof(char));

      // Destroy previous window if existing
      if (!is_empty()) assign();

      // Set display variables
      _width = std::min(dimw,(unsigned int)screen_width());
      _height = std::min(dimh,(unsigned int)screen_height());
      _normalization = normalization_type<4?normalization_type:3;
      _is_fullscreen = fullscreen_flag;
      _window_x = _window_y = 0;
      _is_closed = closed_flag;
      _is_cursor_visible = true;
      _is_mouse_tracked = false;
      _title = tmp_title;
      flush();
      if (_is_fullscreen) _init_fullscreen();

      // Create event thread
      void *const arg = (void*)(new void*[2]);
      ((void**)arg)[0] = (void*)this;
      ((void**)arg)[1] = (void*)_title;
      _mutex = CreateMutex(0,FALSE,0);
      _is_created = CreateEvent(0,FALSE,FALSE,0);
      _thread = CreateThread(0,0,_events_thread,arg,0,0);
      WaitForSingleObject(_is_created,INFINITE);
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<Tfloat> get_blur_guided(const CImg<t>& guide, const float radius, const float regularization) const {
      if (!is_sameXYZ(guide))
        throw CImgArgumentException(_cimg_instance
                                    "blur_guided(): Invalid size for specified guide image (%u,%u,%u,%u,%p).",
                                    cimg_instance,
                                    guide._width,guide._height,guide._depth,guide._spectrum,guide._data);
      if (is_empty() || !radius) return *this;
      const int _radius = radius>=0?(int)radius:(int)(-radius*cimg::max(_width,_height,_depth)/100);
      float _regularization = regularization;
      if (regularization<0) {
        T edge_min, edge_max = guide.max_min(edge_min);
        if (edge_min==edge_max) return *this;
        _regularization = -regularization*(edge_max - edge_min)/100;
      }
      _regularization = std::max(_regularization,0.01f);
      const unsigned int psize = (unsigned int)(1 + 2*_radius);
      CImg<Tfloat>
        mean_p = get_blur_box(psize,true),
        mean_I = guide.get_blur_box(psize,true).resize(mean_p),
        cov_Ip = get_mul(guide).blur_box(psize,true)-=mean_p.get_mul(mean_I),
        var_I = guide.get_sqr().blur_box(psize,true)-=mean_I.get_sqr(),
        &a = cov_Ip.div(var_I+=_regularization),
        &b = mean_p-=a.get_mul(mean_I);
      a.blur_box(psize,true);
      b.blur_box(psize,true);
      return a.mul(guide)+=b;

Project: CImg
File: CImg.h


    inline void sgels(char & TRANS, int &M, int &N, int &NRHS, float* lapA, int &LDA,
		      float* lapB, int &LDB, float* WORK, int &LWORK, int &INFO){
      sgels_(&TRANS, &M, &N, &NRHS, lapA, &LDA, lapB, &LDB, WORK, &LWORK, &INFO);

Project: CImg
File: CImg.h

    /**
      \param pos1 Starting index of the removal.
      \param pos2 Ending index of the removal.
    **/
    CImgList<T>& remove(const unsigned int pos1, const unsigned int pos2) {
      const unsigned int
        npos1 = pos1<pos2?pos1:pos2,
        tpos2 = pos1<pos2?pos2:pos1,
        npos2 = tpos2<_width?tpos2:_width - 1;
      if (npos1>=_width)
        throw CImgArgumentException(_cimglist_instance
                                    "remove(): Invalid remove request at positions %u->%u.",
                                    cimglist_instance,
                                    npos1,tpos2);
      else {
        if (tpos2>=_width)
          throw CImgArgumentException(_cimglist_instance
                                      "remove(): Invalid remove request at positions %u->%u.",
                                      cimglist_instance,
                                      npos1,tpos2);

        for (unsigned int k = npos1; k<=npos2; ++k) _data[k].assign();
        const unsigned int nb = 1 + npos2 - npos1;
        if (!(_width-=nb)) return assign();
        if (_width>(_allocated_width>>2) || _allocated_width<=16) { // Removing items without reallocation
          if (npos1!=_width)
            std::memmove((void*)(_data + npos1),(void*)(_data + npos2 + 1),sizeof(CImg<T>)*(_width - npos1));
          std::memset((void*)(_data + _width),0,sizeof(CImg<T>)*nb);
        } else { // Removing items with reallocation
          _allocated_width>>=2;
          while (_allocated_width>16 && _width<(_allocated_width>>1)) _allocated_width>>=1;
          CImg<T> *const new_data = new CImg<T>[_allocated_width];
          if (npos1) std::memcpy((void*)new_data,(void*)_data,sizeof(CImg<T>)*npos1);
          if (npos1!=_width)
            std::memcpy((void*)(new_data + npos1),(void*)(_data + npos2 + 1),sizeof(CImg<T>)*(_width - npos1));
          if (_width!=_allocated_width)
            std::memset((void*)(new_data + _width),0,sizeof(CImg<T>)*(_allocated_width - _width));
          std::memset((void*)_data,0,sizeof(CImg<T>)*(_width + nb));
          delete[] _data;
          _data = new_data;

Project: CImg
File: CImg.h

    //! Blur image with a box filter \newinstance.
    CImg<Tfloat> get_blur_box(const float boxsize, const bool boundary_conditions=true) const {
      return CImg<Tfloat>(*this,false).blur_box(boxsize,boundary_conditions);

Project: CImg
File: CImg.h

    //! Round pixel values \newinstance.
    CImg<T> get_round(const double y=1, const unsigned int rounding_type=0) const {
      return (+*this).round(y,rounding_type);

Project: CImg
File: CImg.h


    const CImg<T>& _save_rgb(std::FILE *const file, const char *const filename) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_rgb(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(file,filename); return *this; }
      if (_spectrum!=3)
        cimg::warn(_cimg_instance
                   "save_rgb(): image instance has not exactly 3 channels, for file '%s'.",
                   cimg_instance,
                   filename?filename:"(FILE*)");

      std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
      const ulongT wh = (ulongT)_width*_height;
      unsigned char *const buffer = new unsigned char[3*wh], *nbuffer = buffer;
      const T
        *ptr1 = data(0,0,0,0),
        *ptr2 = _spectrum>1?data(0,0,0,1):0,
        *ptr3 = _spectrum>2?data(0,0,0,2):0;
      switch (_spectrum) {
      case 1 : { // Scalar image
        for (ulongT k = 0; k<wh; ++k) {
          const unsigned char val = (unsigned char)*(ptr1++);
          *(nbuffer++) = val;
          *(nbuffer++) = val;
          *(nbuffer++) = val;
        }
      } break;
      case 2 : { // RG image
        for (ulongT k = 0; k<wh; ++k) {
          *(nbuffer++) = (unsigned char)(*(ptr1++));
          *(nbuffer++) = (unsigned char)(*(ptr2++));
          *(nbuffer++) = 0;
        }
      } break;
      default : { // RGB image
        for (ulongT k = 0; k<wh; ++k) {
          *(nbuffer++) = (unsigned char)(*(ptr1++));
          *(nbuffer++) = (unsigned char)(*(ptr2++));
          *(nbuffer++) = (unsigned char)(*(ptr3++));
        }
      }
      }
      cimg::fwrite(buffer,3*wh,nfile);
      if (!file) cimg::fclose(nfile);
      delete[] buffer;
      return *this;

Project: CImg
File: CImg.h

      return *this;
    }

Project: CImg
File: CImg.h

      static const char* format_s() { return "%g"; }

Project: CImg
File: CImg.h

    //! Convert pixel values from RGB to CMYK color spaces \newinstance.
    CImg<Tfloat> get_RGBtoCMYK() const {
      return CImg<Tfloat>(*this,false).RGBtoCMYK();

Project: CImg
File: CImg.h

    **/
    inline void strwindows_reserved(char *const str, const char c='_') {
      for (char *s = str; *s; ++s) {
        const char i = *s;
        if (i=='<' || i=='>' || i==':' || i=='\"' || i=='/' || i=='\\' || i=='|' || i=='?' || i=='*') *s = c;
      }

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& solve_tridiagonal(const CImg<t>& A) {
      const unsigned int siz = (unsigned int)size();
      if (A._width!=3 || A._height!=siz)
        throw CImgArgumentException(_cimg_instance
                                    "solve_tridiagonal(): Instance and tridiagonal matrix "
                                    "(%u,%u,%u,%u,%p) have incompatible dimensions.",
                                    cimg_instance,
                                    A._width,A._height,A._depth,A._spectrum,A._data);
      typedef _cimg_Ttfloat Ttfloat;
      const Ttfloat epsilon = 1e-4f;
      CImg<Ttfloat> B = A.get_column(1), V(*this,false);
      for (int i = 1; i<(int)siz; ++i) {
        const Ttfloat m = A(0,i)/(B[i - 1]?B[i - 1]:epsilon);
        B[i] -= m*A(2,i - 1);
        V[i] -= m*V[i - 1];
      }
      (*this)[siz - 1] = (T)(V[siz - 1]/(B[siz - 1]?B[siz - 1]:epsilon));
      for (int i = (int)siz - 2; i>=0; --i) (*this)[i] = (T)((V[i] - A(2,i)*(*this)[i + 1])/(B[i]?B[i]:epsilon));
      return *this;

Project: CImg
File: CImg.h

    **/
    const CImg<T>& print(const char *const title=0, const bool display_stats=true) const {

      int xm = 0, ym = 0, zm = 0, vm = 0, xM = 0, yM = 0, zM = 0, vM = 0;
      CImg<doubleT> st;
      if (!is_empty() && display_stats) {
        st = get_stats();
        xm = (int)st[4]; ym = (int)st[5], zm = (int)st[6], vm = (int)st[7];
        xM = (int)st[8]; yM = (int)st[9], zM = (int)st[10], vM = (int)st[11];
      }

      const ulongT siz = size(), msiz = siz*sizeof(T), siz1 = siz - 1,
        mdisp = msiz<8*1024?0U:msiz<8*1024*1024?1U:2U, width1 = _width - 1;

      CImg<charT> _title(64);
      if (!title) cimg_snprintf(_title,_title._width,"CImg<%s>",pixel_type());

      std::fprintf(cimg::output(),"%s%s%s%s: %sthis%s = %p, %ssize%s = (%u,%u,%u,%u) [%lu %s], %sdata%s = (%s*)%p",
                   cimg::t_magenta,cimg::t_bold,title?title:_title._data,cimg::t_normal,
                   cimg::t_bold,cimg::t_normal,(void*)this,
                   cimg::t_bold,cimg::t_normal,_width,_height,_depth,_spectrum,
                   (unsigned long)(mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20))),
                   mdisp==0?"b":(mdisp==1?"Kio":"Mio"),
                   cimg::t_bold,cimg::t_normal,pixel_type(),(void*)begin());
      if (_data)
        std::fprintf(cimg::output(),"..%p (%s) = [ ",(void*)((char*)end() - 1),_is_shared?"shared":"non-shared");
      else std::fprintf(cimg::output()," (%s) = [ ",_is_shared?"shared":"non-shared");

      if (!is_empty()) cimg_foroff(*this,off) {
        std::fprintf(cimg::output(),"%g",(double)_data[off]);
        if (off!=siz1) std::fprintf(cimg::output(),"%s",off%_width==width1?" ; ":" ");
        if (off==7 && siz>16) { off = siz1 - 8; std::fprintf(cimg::output(),"... "); }
      }
      if (!is_empty() && display_stats)
	std::fprintf(cimg::output(),
                     " ], %smin%s = %g, %smax%s = %g, %smean%s = %g, %sstd%s = %g, %scoords_min%s = (%u,%u,%u,%u), "
                     "%scoords_max%s = (%u,%u,%u,%u).\n",
		     cimg::t_bold,cimg::t_normal,st[0],
                     cimg::t_bold,cimg::t_normal,st[1],
                     cimg::t_bold,cimg::t_normal,st[2],
                     cimg::t_bold,cimg::t_normal,std::sqrt(st[3]),
                     cimg::t_bold,cimg::t_normal,xm,ym,zm,vm,
                     cimg::t_bold,cimg::t_normal,xM,yM,zM,vM);
      else std::fprintf(cimg::output(),"%s].\n",is_empty()?"":" ");
      std::fflush(cimg::output());
      return *this;

Project: CImg
File: CImg.h

    //! Fill sequentially all pixel values with specified values \newinstance.
    CImg<T> get_fill(const T& val0, const T& val1) const {
      return CImg<T>(_width,_height,_depth,_spectrum).fill(val0,val1);

Project: CImg
File: CImg.h

      static const char* string() { static const char *const s = "signed char"; return s; }

Project: CImg
File: CImg.h

    //! Resize 3D object \newinstance.
    CImg<Tfloat> get_resize_object3d(const float sx, const float sy=-100, const float sz=-100) const {
      return CImg<Tfloat>(*this,false).resize_object3d(sx,sy,sz);

Project: CImg
File: CImg.h

    //! Test if one of the image list contains the specified referenced value.
    /**
       \param pixel Reference to pixel value to test.
    **/

Project: CImg
File: CImg.h

      return dt;
    }

    // Return a temporary string describing the size of a memory buffer.
    inline const char *strbuffersize(const cimg_ulong size) {
      static CImg<char> res(256);
      cimg::mutex(5);
      if (size<1024LU) cimg_snprintf(res,res._width,"%lu byte%s",(unsigned long)size,size>1?"s":"");
      else if (size<1024*1024LU) { const float nsize = size/1024.f; cimg_snprintf(res,res._width,"%.1f Kio",nsize); }
      else if (size<1024*1024*1024LU) {
        const float nsize = size/(1024*1024.f); cimg_snprintf(res,res._width,"%.1f Mio",nsize);

Project: CImg
File: CImg.h

    **/
    CImg<T>& operator=(const T& value) {
      return fill(value);

Project: CImg
File: CImg.h

    **/
    CImg<T> get_shared_rows(const unsigned int y0, const unsigned int y1,
                             const unsigned int z0=0, const unsigned int c0=0) {
      const unsigned int
        beg = (unsigned int)offset(0,y0,z0,c0),
        end = (unsigned int)offset(0,y1,z0,c0);
      if (beg>end || beg>=size() || end>=size())
        throw CImgArgumentException(_cimg_instance
                                    "get_shared_rows(): Invalid request of a shared-memory subset "
                                    "(0->%u,%u->%u,%u,%u).",
                                    cimg_instance,
                                    _width - 1,y0,y1,z0,c0);

      return CImg<T>(_data + beg,_width,y1 - y0 + 1,1,1,true);

Project: CImg
File: CImg.h


    inline void getrf(int &N, float *lapA, int *IPIV, int &INFO) {
      sgetrf_(&N,&N,lapA,&N,IPIV,&INFO);

Project: CImg
File: CImg.h

      return _load_cimg(0,filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1);
    }

    //! Load a sublist list from a (non compressed) .cimg file \newinstance.
    static CImgList<T> get_load_cimg(const char *const filename,
                                     const unsigned int n0, const unsigned int n1,
                                     const unsigned int x0, const unsigned int y0,
                                     const unsigned int z0, const unsigned int c0,

Project: CImg
File: CImg.h

    //! Load image from a PNM file \newinstance.
    static CImg<T> get_load_pnm(std::FILE *const file) {
      return CImg<T>().load_pnm(file);

Project: CImg
File: CImg.h

    //! Blur image \newinstance.
    CImg<Tfloat> get_blur(const float sigma_x, const float sigma_y, const float sigma_z,
                          const bool boundary_conditions=true, const bool is_gaussian=false) const {
      return CImg<Tfloat>(*this,false).blur(sigma_x,sigma_y,sigma_z,boundary_conditions,is_gaussian);

Project: CImg
File: CImg.h


    static float _matchpatch(const CImg<T>& img1, const CImg<T>& img2, const CImg<uintT>& occ,
                             const unsigned int psizew, const unsigned int psizeh, const unsigned int psizec,
                             const int x1, const int y1,
                             const int x2, const int y2,
                             const int xc, const int yc,
                             const float occ_penalization,
                             const float max_score) { // 2D version
      const T *p1 = img1.data(x1*psizec,y1), *p2 = img2.data(x2*psizec,y2);
      const unsigned int psizewc = psizew*psizec;
      const ulongT
        offx1 = (ulongT)img1._width - psizewc,
        offx2 = (ulongT)img2._width - psizewc;
      float ssd = 0;
      for (unsigned int j = 0; j<psizeh; ++j) {
        for (unsigned int i = 0; i<psizewc; ++i)
          ssd += cimg::sqr((Tfloat)*(p1++) - *(p2++));
        if (ssd>max_score) return max_score;
        p1+=offx1; p2+=offx2;
      }
      return occ_penalization==0?ssd:cimg::sqr(std::sqrt(ssd) + occ_penalization*occ(xc,yc));

Project: CImg
File: CImg.h


    inline int option(const char *const name, const int argc, const char *const *const argv,
                      const int defaut, const char *const usage=0) {
      const char *const s = cimg::option(name,argc,argv,(char*)0);
      const int res = s?std::atoi(s):defaut;
      char *const tmp = new char[256];
      cimg_snprintf(tmp,256,"%d",res);
      cimg::option(name,0,0,tmp,usage);
      delete[] tmp;
      return res;

Project: CImg
File: CImg.h

    **/
    static const CImg<Tuchar>& flag_LUT256() {
      static CImg<Tuchar> colormap;
      cimg::mutex(8);
      if (!colormap) {
        colormap.assign(1,4,1,3,(T)0);
        colormap[0] = colormap[1] = colormap[5] = colormap[9] = colormap[10] = 255;
        colormap.resize(1,256,1,3,0,2);
      }
      cimg::mutex(8,0);
      return colormap;

Project: CImg
File: CImg.h


      static double mp_set_joff(_cimg_math_parser& mp) {
        CImg<T> &img = mp.imgout;
        const int
          ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y],
          oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c];
        const longT
          off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2),
          whds = (longT)img.size();
        const double val = _mp_arg(1);
        if (off>=0 && off<whds) img[off] = (T)val;
        return val;

Project: CImg
File: CImg.h

    template<typename t>
    double MSE(const CImg<t>& img) const {
      if (img.size()!=size())
        throw CImgArgumentException(_cimg_instance
                                    "MSE(): Instance and specified image (%u,%u,%u,%u,%p) have different dimensions.",
                                    cimg_instance,
                                    img._width,img._height,img._depth,img._spectrum,img._data);
      double vMSE = 0;
      const t* ptr2 = img._data;
      cimg_for(*this,ptr1,T) {
        const double diff = (double)*ptr1 - (double)*(ptr2++);
        vMSE+=diff*diff;
      }
      const ulongT siz = img.size();
      if (siz) vMSE/=siz;
      return vMSE;

Project: CImg
File: CImg.h


      static double mp_pow0_25(_cimg_math_parser& mp) {
        const double val = _mp_arg(2);
        return std::sqrt(std::sqrt(val));

Project: CImg
File: CImg.h

    //! Wait for any event occuring either on the display \c disp1, \c disp2 or \c disp3.
    static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3) {
      disp1._is_event = disp2._is_event = disp3._is_event = false;
      while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed) &&
             !disp1._is_event && !disp2._is_event && !disp3._is_event) wait_all();

Project: CImg
File: CImg.h


      static double mp_log10(_cimg_math_parser& mp) {
        return std::log10(_mp_arg(2));

Project: CImg
File: CImg.h

    template<typename tc>
    CImg<T>& draw_grid(const float delta_x,  const float delta_y,
                       const float offsetx, const float offsety,
                       const bool invertx, const bool inverty,
                       const tc *const color, const float opacity=1,
                       const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U) {
      if (is_empty()) return *this;
      CImg<uintT> seqx, seqy;
      if (delta_x!=0) {
        const float dx = delta_x>0?delta_x:_width*-delta_x/100;
        const unsigned int nx = (unsigned int)(_width/dx);
        seqx = CImg<uintT>::sequence(1 + nx,0,(unsigned int)(dx*nx));
        if (offsetx) cimg_foroff(seqx,x) seqx(x) = (unsigned int)cimg::mod(seqx(x) + offsetx,(float)_width);
        if (invertx) cimg_foroff(seqx,x) seqx(x) = _width - 1 - seqx(x);
      }
      if (delta_y!=0) {
        const float dy = delta_y>0?delta_y:_height*-delta_y/100;
        const unsigned int ny = (unsigned int)(_height/dy);
        seqy = CImg<uintT>::sequence(1 + ny,0,(unsigned int)(dy*ny));
        if (offsety) cimg_foroff(seqy,y) seqy(y) = (unsigned int)cimg::mod(seqy(y) + offsety,(float)_height);
        if (inverty) cimg_foroff(seqy,y) seqy(y) = _height - 1 - seqy(y);
     }
      return draw_grid(seqx,seqy,color,opacity,pattern_x,pattern_y);

Project: CImg
File: CImg.h

    //! Fill sequentially all pixel values with specified values \overloading.
    CImg<T>& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5,
                  const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11,
                  const T& val12) {
      if (is_empty()) return *this;
      T *ptrd, *ptre = end() - 12;
      for (ptrd = _data; ptrd<ptre; ) {
        *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4; *(ptrd++) = val5;
        *(ptrd++) = val6; *(ptrd++) = val7; *(ptrd++) = val8; *(ptrd++) = val9; *(ptrd++) = val10; *(ptrd++) = val11;
        *(ptrd++) = val12;
      }
      ptre+=12;
      switch (ptre - ptrd) {
      case 12 : *(--ptre) = val11; // fallthrough
      case 11 : *(--ptre) = val10; // fallthrough
      case 10 : *(--ptre) = val9; // fallthrough
      case 9 : *(--ptre) = val8; // fallthrough
      case 8 : *(--ptre) = val7; // fallthrough
      case 7 : *(--ptre) = val6; // fallthrough
      case 6 : *(--ptre) = val5; // fallthrough
      case 5 : *(--ptre) = val4; // fallthrough
      case 4 : *(--ptre) = val3; // fallthrough
      case 3 : *(--ptre) = val2; // fallthrough
      case 2 : *(--ptre) = val1; // fallthrough
      case 1 : *(--ptre) = val0; // fallthrough
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    explicit CImgList(const CImg<t>& img, const bool is_shared=false):
      _width(0),_allocated_width(0),_data(0) {
      assign(1);
      _data[0].assign(img,is_shared);

Project: CImg
File: CImg.h

    **/
    inline void strunescape(char *const str) {
#define cimg_strunescape(ci,co) case ci : *nd = co; ++ns; break;
      unsigned int val = 0;
      for (char *ns = str, *nd = str; *ns || (bool)(*nd=0); ++nd) if (*ns=='\\') switch (*(++ns)) {
            cimg_strunescape('a','\a');
            cimg_strunescape('b','\b');
            cimg_strunescape('e',0x1B);
            cimg_strunescape('f','\f');
            cimg_strunescape('n','\n');
            cimg_strunescape('r','\r');
            cimg_strunescape('t','\t');
            cimg_strunescape('v','\v');
            cimg_strunescape('\\','\\');
            cimg_strunescape('\'','\'');
            cimg_strunescape('\"','\"');
            cimg_strunescape('\?','\?');
          case 0 : *nd = 0; break;
          case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' :
            cimg_sscanf(ns,"%o",&val); while (*ns>='0' && *ns<='7') ++ns;
            *nd = (char)val; break;
          case 'x' :
            cimg_sscanf(++ns,"%x",&val);
            while ((*ns>='0' && *ns<='9') || (*ns>='a' && *ns<='f') || (*ns>='A' && *ns<='F')) ++ns;
            *nd = (char)val; break;
          default : *nd = *(ns++);
          } else *nd = *(ns++);

Project: CImg
File: CImg.h

    template<typename tc>
    CImg<T>& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float angle,
                          const tc *const color, const float opacity, const unsigned int pattern) {
      if (pattern) _draw_ellipse(x0,y0,r1,r2,angle,color,opacity,pattern,false);
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImgList<T> operator,(const CImg<t>& img) const {
      return (+*this).insert(img);

Project: CImg
File: CImg.h

    template<typename tf, typename tc>
    static CImg<T> get_load_off(CImgList<tf>& primitives, CImgList<tc>& colors, std::FILE *const file) {
      return CImg<T>().load_off(primitives,colors,file);

Project: CImg
File: CImg.h

       \param filename Filename to write data to.
       \param fps Number of desired frames per second.
       \param nb_loops Number of loops (\c 0 for infinite looping).
    **/
    const CImgList<T>& save_gif_external(const char *const filename, const float fps=25,
                                         const unsigned int nb_loops=0) {
      CImg<charT> command(1024), filename_tmp(256), filename_tmp2(256);
      CImgList<charT> filenames;
      std::FILE *file = 0;

#ifdef cimg_use_png
#define _cimg_save_gif_ext "png"
#else
#define _cimg_save_gif_ext "ppm"
#endif

      do {
        cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s",
                      cimg::temporary_path(),cimg_file_separator,cimg::filenamerand());
        cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001." _cimg_save_gif_ext,filename_tmp._data);
        if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file);
      } while (file);
      cimglist_for(*this,l) {
        cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u." _cimg_save_gif_ext,filename_tmp._data,l + 1);
        CImg<charT>::string(filename_tmp2).move_to(filenames);
        if (_data[l]._depth>1 || _data[l]._spectrum!=3) _data[l].get_resize(-100,-100,1,3).save(filename_tmp2);
        else _data[l].save(filename_tmp2);
      }
      cimg_snprintf(command,command._width,"%s -delay %u -loop %u",
                    cimg::imagemagick_path(),(unsigned int)std::max(0.f,cimg::round(100/fps)),nb_loops);
      CImg<ucharT>::string(command).move_to(filenames,0);
      cimg_snprintf(command,command._width,"\"%s\"",
                    CImg<charT>::string(filename)._system_strescape().data());
      CImg<ucharT>::string(command).move_to(filenames);
      CImg<charT> _command = filenames>'x';
      cimg_for(_command,p,char) if (!*p) *p = ' ';
      _command.back() = 0;

      cimg::system(_command);
      file = cimg::std_fopen(filename,"rb");
      if (!file)
        throw CImgIOException(_cimglist_instance
                              "save_gif_external(): Failed to save file '%s' with external command 'magick/convert'.",
                              cimglist_instance,
                              filename);

Project: CImg
File: CImg.h

    template<typename T>
    CImgDisplay& render(const CImg<T>& img) {
      return assign(img);

Project: CImg
File: CImg.h


    CImgDisplay& assign() {
      if (is_empty()) return flush();
      Display *const dpy = cimg::X11_attr().display;
      cimg_lock_display();

      // Remove display window from event thread list.
      unsigned int i;
      for (i = 0; i<cimg::X11_attr().nb_wins && cimg::X11_attr().wins[i]!=this; ++i) {}
      for ( ; i<cimg::X11_attr().nb_wins - 1; ++i) cimg::X11_attr().wins[i] = cimg::X11_attr().wins[i + 1];
      --cimg::X11_attr().nb_wins;

      // Destroy window, image, colormap and title.
      if (_is_fullscreen && !_is_closed) _desinit_fullscreen();
      XDestroyWindow(dpy,_window);
      _window = 0;

#ifdef cimg_use_xshm
      if (_shminfo) {
        XShmDetach(dpy,_shminfo);
        XDestroyImage(_image);
        shmdt(_shminfo->shmaddr);
        shmctl(_shminfo->shmid,IPC_RMID,0);
        delete _shminfo;
        _shminfo = 0;
      } else
#endif
        XDestroyImage(_image);
      _data = 0; _image = 0;
      if (cimg::X11_attr().nb_bits==8) XFreeColormap(dpy,_colormap);
      _colormap = 0;
      XSync(dpy,0);

      // Reset display variables.
      delete[] _title;
      _width = _height = _normalization = _window_width = _window_height = 0;
      _window_x = _window_y = 0;
      _is_fullscreen = false;
      _is_closed = true;
      _min = _max = 0;
      _title = 0;
      flush();

      cimg_unlock_display();
      return *this;

Project: CImg
File: CImg.h


      static double mp_cut(_cimg_math_parser& mp) {
        double val = _mp_arg(2), cmin = _mp_arg(3), cmax = _mp_arg(4);
        return val<cmin?cmin:val>cmax?cmax:val;

Project: CImg
File: CImg.h

    **/
    CImg<T>& XYZtoRGB(const bool use_D65=true) {
      if (_spectrum!=3)
        throw CImgInstanceException(_cimg_instance
                                    "XYZtoRGB(): Instance is not a XYZ image.",
                                    cimg_instance);

      T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
      const longT whd = (longT)width()*height()*depth();
      cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048))
      for (longT N = 0; N<whd; ++N) {
        const Tfloat
          X = (Tfloat)p1[N]*255,
          Y = (Tfloat)p2[N]*255,
          Z = (Tfloat)p3[N]*255;
        if (use_D65) {
          p1[N] = (T)cimg::cut(3.2404542*X - 1.5371385*Y - 0.4985314*Z,0,255);
          p2[N] = (T)cimg::cut(-0.9692660*X + 1.8760108*Y + 0.0415560*Z,0,255);
          p3[N] = (T)cimg::cut(0.0556434*X - 0.2040259*Y + 1.0572252*Z,0,255);
        } else {
          p1[N] = (T)cimg::cut(3.134274799724*X  - 1.617275708956*Y - 0.490724283042*Z,0,255);
          p2[N] = (T)cimg::cut(-0.978795575994*X + 1.916161689117*Y + 0.033453331711*Z,0,255);
          p3[N] = (T)cimg::cut(0.071976988401*X - 0.228984974402*Y + 1.405718224383*Z,0,255);
        }
      }
      return *this;

Project: CImg
File: CImg.h

    inline unsigned int openmp_mode() {
      return openmp_mode(0,false);
    }

Project: CImg
File: CImg.h

    //! Load image from a PANDORE-5 file \newinstance.
    static CImg<T> get_load_pandore(std::FILE *const file) {
      return CImg<T>().load_pandore(file);

Project: CImg
File: CImg.h

    //! Return \c true if input character is blank (space, tab, or non-printable character).
    inline bool is_blank(const char c) {
      return c>=0 && c<=' ';

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& operator^=(const CImg<t>& img) {
      const ulongT siz = size(), isiz = img.size();
      if (siz && isiz) {
        if (is_overlapped(img)) return *this^=+img;
        T *ptrd = _data, *const ptre = _data + siz;
        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
          for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
            *ptrd = (T)((ulongT)*ptrd ^ (ulongT)*(ptrs++));
        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((ulongT)*ptrd ^ (ulongT)*(ptrs++));
      }
      return *this;

Project: CImg
File: CImg.h


      static double mp_image_median(_cimg_math_parser& mp) {
        unsigned int ind = (unsigned int)mp.opcode[2];
        if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
        const CImg<T> &img = ind==~0U?mp.imgout:mp.listout[ind];
        return (double)img.median();

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& index(const CImg<t>& colormap, const float dithering=1, const bool map_indexes=false) {
      return get_index(colormap,dithering,map_indexes).move_to(*this);

Project: CImg
File: CImg.h

    //! Resize image to become a scalar square matrix \newinstance.
    CImg<T> get_matrix() const {
      return (+*this).matrix();

Project: CImg
File: CImg.h

    //! Generate a numbered version of a filename.
    inline char* number_filename(const char *const filename, const int number,
                                 const unsigned int digits, char *const str) {
      if (!filename) { if (str) *str = 0; return 0; }
      char *const format = new char[1024], *const body = new char[1024];
      const char *const ext = cimg::split_filename(filename,body);
      if (*ext) cimg_snprintf(format,1024,"%%s_%%.%ud.%%s",digits);
      else cimg_snprintf(format,1024,"%%s_%%.%ud",digits);
      cimg_sprintf(str,format,body,number,ext);
      delete[] format; delete[] body;
      return str;

Project: CImg
File: CImg.h

    //! Load image from an Ascii file \inplace.
    static CImg<T> get_load_ascii(const char *const filename) {
      return CImg<T>().load_ascii(filename);

Project: CImg
File: CImg.h

    **/
    CImg<T> get_shared_slices(const unsigned int z0, const unsigned int z1, const unsigned int c0=0) {
      const unsigned int
        beg = (unsigned int)offset(0,0,z0,c0),
        end = (unsigned int)offset(0,0,z1,c0);
      if (beg>end || beg>=size() || end>=size())
        throw CImgArgumentException(_cimg_instance
                                    "get_shared_slices(): Invalid request of a shared-memory subset "
                                    "(0->%u,0->%u,%u->%u,%u).",
                                    cimg_instance,
                                    _width - 1,_height - 1,z0,z1,c0);

      return CImg<T>(_data + beg,_width,_height,z1 - z0 + 1,1,true);

Project: CImg
File: CImg.h

    //! Implicitely cast an image into a \c T* \const.
    operator const T*() const {
      return _data;

Project: CImg
File: CImg.h

    //! Load image from a PNM file \newinstance.
    static CImg<T> get_load_pnm(const char *const filename) {
      return CImg<T>().load_pnm(filename);

Project: CImg
File: CImg.h

    **/
    static CImg<T> identity_matrix(const unsigned int N) {
      CImg<T> res(N,N,1,1,0);
      cimg_forX(res,x) res(x,x) = 1;
      return res;

Project: CImg
File: CImg.h

    template<typename tf>
    static CImg<floatT> sphere3d(CImgList<tf>& primitives,
                                 const float radius=50, const unsigned int subdivisions=3) {

      // Create initial icosahedron
      primitives.assign();
      const double tmp = (1 + std::sqrt(5.f))/2, a = 1./std::sqrt(1 + tmp*tmp), b = tmp*a;
      CImgList<floatT> vertices(12,1,3,1,1, b,a,0., -b,a,0., -b,-a,0., b,-a,0., a,0.,b, a,0.,-b,
                                -a,0.,-b, -a,0.,b, 0.,b,a, 0.,-b,a, 0.,-b,-a, 0.,b,-a);
      primitives.assign(20,1,3,1,1, 4,8,7, 4,7,9, 5,6,11, 5,10,6, 0,4,3, 0,3,5, 2,7,1, 2,1,6,
                        8,0,11, 8,11,1, 9,10,3, 9,2,10, 8,4,0, 11,0,5, 4,9,3,
                        5,3,10, 7,8,1, 6,1,11, 7,2,9, 6,10,2);
      // edge - length/2
      float he = (float)a;

      // Recurse subdivisions
      for (unsigned int i = 0; i<subdivisions; ++i) {
        const unsigned int L = primitives._width;
	he/=2;
	const float he2 = he*he;
        for (unsigned int l = 0; l<L; ++l) {
          const unsigned int
            p0 = (unsigned int)primitives(0,0), p1 = (unsigned int)primitives(0,1), p2 = (unsigned int)primitives(0,2);
          const float
            x0 = vertices(p0,0), y0 = vertices(p0,1), z0 = vertices(p0,2),
            x1 = vertices(p1,0), y1 = vertices(p1,1), z1 = vertices(p1,2),
            x2 = vertices(p2,0), y2 = vertices(p2,1), z2 = vertices(p2,2),
            tnx0 = (x0 + x1)/2, tny0 = (y0 + y1)/2, tnz0 = (z0 + z1)/2,
            nn0 = cimg::hypot(tnx0,tny0,tnz0),
            tnx1 = (x0 + x2)/2, tny1 = (y0 + y2)/2, tnz1 = (z0 + z2)/2,
            nn1 = cimg::hypot(tnx1,tny1,tnz1),
            tnx2 = (x1 + x2)/2, tny2 = (y1 + y2)/2, tnz2 = (z1 + z2)/2,
            nn2 = cimg::hypot(tnx2,tny2,tnz2),
            nx0 = tnx0/nn0, ny0 = tny0/nn0, nz0 = tnz0/nn0,
            nx1 = tnx1/nn1, ny1 = tny1/nn1, nz1 = tnz1/nn1,
            nx2 = tnx2/nn2, ny2 = tny2/nn2, nz2 = tnz2/nn2;
          int i0 = -1, i1 = -1, i2 = -1;
          cimglist_for(vertices,p) {
            const float x = (float)vertices(p,0), y = (float)vertices(p,1), z = (float)vertices(p,2);
            if (cimg::sqr(x-nx0) + cimg::sqr(y-ny0) + cimg::sqr(z-nz0)<he2) i0 = p;
            if (cimg::sqr(x-nx1) + cimg::sqr(y-ny1) + cimg::sqr(z-nz1)<he2) i1 = p;
            if (cimg::sqr(x-nx2) + cimg::sqr(y-ny2) + cimg::sqr(z-nz2)<he2) i2 = p;
          }
          if (i0<0) { CImg<floatT>::vector(nx0,ny0,nz0).move_to(vertices); i0 = vertices.width() - 1; }
          if (i1<0) { CImg<floatT>::vector(nx1,ny1,nz1).move_to(vertices); i1 = vertices.width() - 1; }
          if (i2<0) { CImg<floatT>::vector(nx2,ny2,nz2).move_to(vertices); i2 = vertices.width() - 1; }
          primitives.remove(0);
          CImg<tf>::vector(p0,i0,i1).move_to(primitives);
          CImg<tf>::vector((tf)i0,(tf)p1,(tf)i2).move_to(primitives);
          CImg<tf>::vector((tf)i1,(tf)i2,(tf)p2).move_to(primitives);
          CImg<tf>::vector((tf)i1,(tf)i0,(tf)i2).move_to(primitives);
        }
      }
      return (vertices>'x')*=radius;

Project: CImg
File: CImg.h


    Tfloat _linear_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const {
      const float
        nfx = cimg::mod(fx,(float)_width);
      const unsigned int
        x = (unsigned int)nfx;
      const float
        dx = nfx - x;
      const unsigned int
        nx = cimg::mod(x + 1,_width);
      const Tfloat
        Ic = (Tfloat)(*this)(x,y,z,c), In = (Tfloat)(*this)(nx,y,z,c);
      return Ic + dx*(In - Ic);

Project: CImg
File: CImg.h

    template<typename T>
    inline double cbrt(const T& x) {
#if cimg_use_cpp11==1
      return std::cbrt(x);
#else
      return x>=0?std::pow((double)x,1./3):-std::pow(-(double)x,1./3);
#endif

Project: CImg
File: CImg.h

      const CImg<T>& ref;

Project: CImg
File: CImg.h

    char *_message;

Project: CImg
File: CImg.h


    void _assign(const unsigned int dimw, const unsigned int dimh, const char *const ptitle=0,
                 const unsigned int normalization_type=3,
                 const bool fullscreen_flag=false, const bool closed_flag=false) {
      cimg::mutex(14);

      // Allocate space for window title
      const char *const nptitle = ptitle?ptitle:"";
      const unsigned int s = (unsigned int)std::strlen(nptitle) + 1;
      char *const tmp_title = s?new char[s]:0;
      if (s) std::memcpy(tmp_title,nptitle,s*sizeof(char));

      // Destroy previous display window if existing
      if (!is_empty()) assign();

      // Open X11 display and retrieve graphical properties.
      Display* &dpy = cimg::X11_attr().display;
      if (!dpy) {
        dpy = XOpenDisplay(0);
        if (!dpy)
          throw CImgDisplayException(_cimgdisplay_instance
                                     "assign(): Failed to open X11 display.",
                                     cimgdisplay_instance);

        cimg::X11_attr().nb_bits = DefaultDepth(dpy,DefaultScreen(dpy));
        if (cimg::X11_attr().nb_bits!=8 && cimg::X11_attr().nb_bits!=16 &&
            cimg::X11_attr().nb_bits!=24 && cimg::X11_attr().nb_bits!=32)
          throw CImgDisplayException(_cimgdisplay_instance
                                     "assign(): Invalid %u bits screen mode detected "
                                     "(only 8, 16, 24 and 32 bits modes are managed).",
                                     cimgdisplay_instance,
                                     cimg::X11_attr().nb_bits);
        XVisualInfo vtemplate;
        vtemplate.visualid = XVisualIDFromVisual(DefaultVisual(dpy,DefaultScreen(dpy)));
        int nb_visuals;
        XVisualInfo *vinfo = XGetVisualInfo(dpy,VisualIDMask,&vtemplate,&nb_visuals);
        if (vinfo && vinfo->red_mask<vinfo->blue_mask) cimg::X11_attr().is_blue_first = true;
        cimg::X11_attr().byte_order = ImageByteOrder(dpy);
	XFree(vinfo);

        cimg_lock_display();
        cimg::X11_attr().events_thread = new pthread_t;
        pthread_create(cimg::X11_attr().events_thread,0,_events_thread,0);
      } else cimg_lock_display();

      // Set display variables.
      _width = std::min(dimw,(unsigned int)screen_width());
      _height = std::min(dimh,(unsigned int)screen_height());
      _normalization = normalization_type<4?normalization_type:3;
      _is_fullscreen = fullscreen_flag;
      _window_x = _window_y = 0;
      _is_closed = closed_flag;
      _title = tmp_title;
      flush();

      // Create X11 window (and LUT, if 8bits display)
      if (_is_fullscreen) {
        if (!_is_closed) _init_fullscreen();
        const unsigned int sx = screen_width(), sy = screen_height();
        XSetWindowAttributes winattr;
        winattr.override_redirect = 1;
        _window = XCreateWindow(dpy,DefaultRootWindow(dpy),(sx - _width)/2,(sy - _height)/2,_width,_height,0,0,
                                InputOutput,CopyFromParent,CWOverrideRedirect,&winattr);
      } else
        _window = XCreateSimpleWindow(dpy,DefaultRootWindow(dpy),0,0,_width,_height,0,0L,0L);

      XSelectInput(dpy,_window,
		   ExposureMask | StructureNotifyMask | ButtonPressMask | KeyPressMask | PointerMotionMask |
		   EnterWindowMask | LeaveWindowMask | ButtonReleaseMask | KeyReleaseMask);

      XStoreName(dpy,_window,_title?_title:" ");
      if (cimg::X11_attr().nb_bits==8) {
        _colormap = XCreateColormap(dpy,_window,DefaultVisual(dpy,DefaultScreen(dpy)),AllocAll);
        _set_colormap(_colormap,3);
        XSetWindowColormap(dpy,_window,_colormap);
      }

      static const char *const _window_class = cimg_appname;
      XClassHint *const window_class = XAllocClassHint();
      window_class->res_name = (char*)_window_class;
      window_class->res_class = (char*)_window_class;
      XSetClassHint(dpy,_window,window_class);
      XFree(window_class);

      _window_width = _width;
      _window_height = _height;

      // Create XImage
#ifdef cimg_use_xshm
      _shminfo = 0;
      if (XShmQueryExtension(dpy)) {
        _shminfo = new XShmSegmentInfo;
        _image = XShmCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits,
                                 ZPixmap,0,_shminfo,_width,_height);
        if (!_image) { delete _shminfo; _shminfo = 0; }
        else {
          _shminfo->shmid = shmget(IPC_PRIVATE,_image->bytes_per_line*_image->height,IPC_CREAT|0777);
          if (_shminfo->shmid==-1) { XDestroyImage(_image); delete _shminfo; _shminfo = 0; }
          else {
            _shminfo->shmaddr = _image->data = (char*)(_data = shmat(_shminfo->shmid,0,0));
            if (_shminfo->shmaddr==(char*)-1) {
              shmctl(_shminfo->shmid,IPC_RMID,0); XDestroyImage(_image); delete _shminfo; _shminfo = 0;
            } else {
              _shminfo->readOnly = 0;
              cimg::X11_attr().is_shm_enabled = true;
              XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm);
              XShmAttach(dpy,_shminfo);
              XSync(dpy,0);
              XSetErrorHandler(oldXErrorHandler);
              if (!cimg::X11_attr().is_shm_enabled) {
                shmdt(_shminfo->shmaddr); shmctl(_shminfo->shmid,IPC_RMID,0); XDestroyImage(_image);
                delete _shminfo; _shminfo = 0;
              }
            }
          }
        }
      }
      if (!_shminfo)
#endif
        {
          const cimg_ulong buf_size = (cimg_ulong)_width*_height*(cimg::X11_attr().nb_bits==8?1:
                                                                  (cimg::X11_attr().nb_bits==16?2:4));
          _data = std::malloc(buf_size);
          _image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits,
                                ZPixmap,0,(char*)_data,_width,_height,8,0);
        }

      _wm_window_atom = XInternAtom(dpy,"WM_DELETE_WINDOW",0);
      _wm_protocol_atom = XInternAtom(dpy,"WM_PROTOCOLS",0);
      XSetWMProtocols(dpy,_window,&_wm_window_atom,1);

      if (_is_fullscreen) XGrabKeyboard(dpy,_window,1,GrabModeAsync,GrabModeAsync,CurrentTime);
      cimg::X11_attr().wins[cimg::X11_attr().nb_wins++]=this;
      if (!_is_closed) _map_window(); else { _window_x = _window_y = cimg::type<int>::min(); }
      cimg_unlock_display();
      cimg::mutex(14,0);

Project: CImg
File: CImg.h

    //! Fill sequentially all pixel values with specified values \overloading.
    CImg<T>& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5,
                  const T& val6, const T& val7, const T& val8, const T& val9) {
      if (is_empty()) return *this;
      T *ptrd, *ptre = end() - 9;
      for (ptrd = _data; ptrd<ptre; ) {
        *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4;
        *(ptrd++) = val5; *(ptrd++) = val6; *(ptrd++) = val7; *(ptrd++) = val8; *(ptrd++) = val9;
      }
      ptre+=9;
      switch (ptre - ptrd) {
      case 9 : *(--ptre) = val8; // fallthrough
      case 8 : *(--ptre) = val7; // fallthrough
      case 7 : *(--ptre) = val6; // fallthrough
      case 6 : *(--ptre) = val5; // fallthrough
      case 5 : *(--ptre) = val4; // fallthrough
      case 4 : *(--ptre) = val3; // fallthrough
      case 3 : *(--ptre) = val2; // fallthrough
      case 2 : *(--ptre) = val1; // fallthrough
      case 1 : *(--ptre) = val0; // fallthrough
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    CImg<T>& noise(const double sigma, const unsigned int noise_type=0) {
      if (is_empty()) return *this;
      const Tfloat vmin = (Tfloat)cimg::type<T>::min(), vmax = (Tfloat)cimg::type<T>::max();
      Tfloat nsigma = (Tfloat)sigma, m = 0, M = 0;
      if (nsigma==0 && noise_type!=3) return *this;
      if (nsigma<0 || noise_type==2) m = (Tfloat)min_max(M);
      if (nsigma<0) nsigma = (Tfloat)(-nsigma*(M-m)/100.);
      switch (noise_type) {
      case 0 : { // Gaussian noise
        cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),131072)) {
          ulongT rng = (cimg::_rand(),cimg::rng());

#if cimg_use_openmp!=0
          rng+=omp_get_thread_num();
#endif
          cimg_pragma_openmp(for)
            cimg_rofoff(*this,off) {
            Tfloat val = (Tfloat)(_data[off] + nsigma*cimg::grand(&rng));
            if (val>vmax) val = vmax;
            if (val<vmin) val = vmin;
            _data[off] = (T)val;
          }
          cimg::srand(rng);
        }
      } break;
      case 1 : { // Uniform noise
        cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),131072)) {
          ulongT rng = (cimg::_rand(),cimg::rng());

#if cimg_use_openmp!=0
          rng+=omp_get_thread_num();
#endif
          cimg_pragma_openmp(for)
            cimg_rofoff(*this,off) {
            Tfloat val = (Tfloat)(_data[off] + nsigma*cimg::rand(-1,1,&rng));
            if (val>vmax) val = vmax;
            if (val<vmin) val = vmin;
            _data[off] = (T)val;
          }
          cimg::srand(rng);
        }
      } break;
      case 2 : { // Salt & Pepper noise
        if (nsigma<0) nsigma = -nsigma;
        if (M==m) {
          if (cimg::type<T>::is_float()) { --m; ++M; }
          else { m = (Tfloat)cimg::type<T>::min(); M = (Tfloat)cimg::type<T>::max(); }
        }
        cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),131072)) {
          ulongT rng = (cimg::_rand(),cimg::rng());

#if cimg_use_openmp!=0
          rng+=omp_get_thread_num();
#endif
          cimg_pragma_openmp(for)
            cimg_rofoff(*this,off) if (cimg::rand(100,&rng)<nsigma) _data[off] = (T)(cimg::rand(1,&rng)<0.5?M:m);
          cimg::srand(rng);
          }
      } break;
      case 3 : { // Poisson Noise
        cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),131072)) {
          ulongT rng = (cimg::_rand(),cimg::rng());

#if cimg_use_openmp!=0
          rng+=omp_get_thread_num();
#endif
          cimg_pragma_openmp(for)
            cimg_rofoff(*this,off) _data[off] = (T)cimg::prand(_data[off],&rng);
          cimg::srand(rng);
        }
      } break;
      case 4 : { // Rice noise
        const Tfloat sqrt2 = (Tfloat)std::sqrt(2.);
        cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),131072)) {
          ulongT rng = (cimg::_rand(),cimg::rng());

#if cimg_use_openmp!=0
          rng+=omp_get_thread_num();
#endif
          cimg_pragma_openmp(for)
            cimg_rofoff(*this,off) {
            const Tfloat
              val0 = (Tfloat)_data[off]/sqrt2,
              re = (Tfloat)(val0 + nsigma*cimg::grand(&rng)),
              im = (Tfloat)(val0 + nsigma*cimg::grand(&rng));
            Tfloat val = cimg::hypot(re,im);
            if (val>vmax) val = vmax;
            if (val<vmin) val = vmin;
            _data[off] = (T)val;
          }
          cimg::srand(rng);
        }
      } break;
      default :
        throw CImgArgumentException(_cimg_instance
                                    "noise(): Invalid specified noise type %d "
                                    "(should be { 0=gaussian | 1=uniform | 2=salt&Pepper | 3=poisson }).",
                                    cimg_instance,
                                    noise_type);
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T> operator&(const CImg<t>& img) const {
      return (+*this)&=img;

Project: CImg
File: CImg.h

    **/
    CImg<T>& diffusion_tensors(const float sharpness=0.7f, const float anisotropy=0.6f,
                               const float alpha=0.6f, const float sigma=1.1f, const bool is_sqrt=false) {
      CImg<Tfloat> res;
      const float
        nsharpness = std::max(sharpness,1e-5f),
        power1 = (is_sqrt?0.5f:1)*nsharpness,
        power2 = power1/(1e-7f + 1 - anisotropy);
      blur(alpha).normalize(0,(T)255);

      if (_depth>1) { // 3D
        get_structure_tensors().move_to(res).blur(sigma);
        cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 &&
                                                                   _height*_depth>=(cimg_openmp_sizefactor)*256))
        cimg_forYZ(*this,y,z) {
          Tfloat
            *ptrd0 = res.data(0,y,z,0), *ptrd1 = res.data(0,y,z,1), *ptrd2 = res.data(0,y,z,2),
            *ptrd3 = res.data(0,y,z,3), *ptrd4 = res.data(0,y,z,4), *ptrd5 = res.data(0,y,z,5);
          CImg<floatT> val(3), vec(3,3);
          cimg_forX(*this,x) {
            res.get_tensor_at(x,y,z).symmetric_eigen(val,vec);
            const float
              _l1 = val[2], _l2 = val[1], _l3 = val[0],
              l1 = _l1>0?_l1:0, l2 = _l2>0?_l2:0, l3 = _l3>0?_l3:0,
              ux = vec(0,0), uy = vec(0,1), uz = vec(0,2),
              vx = vec(1,0), vy = vec(1,1), vz = vec(1,2),
              wx = vec(2,0), wy = vec(2,1), wz = vec(2,2),
              n1 = (float)std::pow(1 + l1 + l2 + l3,-power1),
              n2 = (float)std::pow(1 + l1 + l2 + l3,-power2);
            *(ptrd0++) = n1*(ux*ux + vx*vx) + n2*wx*wx;
            *(ptrd1++) = n1*(ux*uy + vx*vy) + n2*wx*wy;
            *(ptrd2++) = n1*(ux*uz + vx*vz) + n2*wx*wz;
            *(ptrd3++) = n1*(uy*uy + vy*vy) + n2*wy*wy;
            *(ptrd4++) = n1*(uy*uz + vy*vz) + n2*wy*wz;
            *(ptrd5++) = n1*(uz*uz + vz*vz) + n2*wz*wz;
          }
        }
      } else { // for 2D images
        get_structure_tensors().move_to(res).blur(sigma);
        cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 &&
                                                       _height>=(cimg_openmp_sizefactor)*256))
        cimg_forY(*this,y) {
          Tfloat *ptrd0 = res.data(0,y,0,0), *ptrd1 = res.data(0,y,0,1), *ptrd2 = res.data(0,y,0,2);
          CImg<floatT> val(2), vec(2,2);
          cimg_forX(*this,x) {
            res.get_tensor_at(x,y).symmetric_eigen(val,vec);
            const float
              _l1 = val[1], _l2 = val[0],
              l1 = _l1>0?_l1:0, l2 = _l2>0?_l2:0,
              ux = vec(1,0), uy = vec(1,1),
              vx = vec(0,0), vy = vec(0,1),
              n1 = (float)std::pow(1 + l1 + l2,-power1),
              n2 = (float)std::pow(1 + l1 + l2,-power2);
            *(ptrd0++) = n1*ux*ux + n2*vx*vx;
            *(ptrd1++) = n1*ux*uy + n2*vx*vy;
            *(ptrd2++) = n1*uy*uy + n2*vy*vy;
          }
        }
      }
      return res.move_to(*this);

Project: CImg
File: CImg.h

      void unlock(const unsigned int) {}

Project: CImg
File: CImg.h

    template<typename tc, typename tl>
    CImg<T>& draw_triangle(int x0, int y0, const float z0,
                           int x1, int y1, const float z1,
                           int x2, int y2, const float z2,
                           const CImg<tc>& texture,
                           int tx0, int ty0,
                           int tx1, int ty1,
                           int tx2, int ty2,
                           const CImg<tl>& light,
                           int lx0, int ly0,
                           int lx1, int ly1,
                           int lx2, int ly2,
                           const float opacity=1) {
      if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this;
      if (texture._depth>1 || texture._spectrum<_spectrum)
        throw CImgArgumentException(_cimg_instance
                                    "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
                                    cimg_instance,
                                    texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
      if (light._depth>1 || light._spectrum<_spectrum)
        throw CImgArgumentException(_cimg_instance
                                    "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).",
                                    cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data);
      if (is_overlapped(texture))
        return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,
                             light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
      if (is_overlapped(light))
        return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,texture,tx0,ty0,tx1,ty1,tx2,ty2,
                             +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);

      float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2;
      if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,lx0,lx1,ly0,ly1);
      if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,lx0,lx2,ly0,ly2);
      if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,lx1,lx2,ly1,ly2);
      if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this;

      const int
        w1 = width() - 1, h1 = height() - 1,
        dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1,
        dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1),
        cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1),
        hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2;
      const float
        diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1,
        txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2,
        tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2,
        dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1,
        dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1,
        lxz0 = lx0*iz0, lxz1 = lx1*iz1, lxz2 = lx2*iz2,
        lyz0 = ly0*iz0, lyz1 = ly1*iz1, lyz2 = ly2*iz2,
        dlxz01 = lxz1 - lxz0, dlxz02 = lxz2 - lxz0, dlxz12 = lxz2 - lxz1,
        dlyz01 = lyz1 - lyz0, dlyz02 = lyz2 - lyz0, dlyz12 = lyz2 - lyz1;

      const ulongT
        twhd = (ulongT)texture._width*texture._height*texture._depth,
        lwhd = (ulongT)light._width*light._height*light._depth;
      cimg_init_scanline(opacity);

      for (int y = cy0; y<=cy2; ++y) {
        const int yy0 = y - y0, yy1 = y - y1;
        int
          xm = y<y1?x0 + (dx01*yy0 + hdy01)/dy01:x1 + (dx12*yy1 + hdy12)/dy12,
          xM = x0 + (dx02*yy0 + hdy02)/dy02;
        float
          izm = y<y1?(iz0 + diz01*yy0/dy01):(iz1 + diz12*yy1/dy12),
          izM = iz0 + diz02*yy0/dy02,
          txzm = y<y1?(txz0 + dtxz01*yy0/dy01):(txz1 + dtxz12*yy1/dy12),
          txzM = txz0 + dtxz02*yy0/dy02,
          tyzm = y<y1?(tyz0 + dtyz01*yy0/dy01):(tyz1 + dtyz12*yy1/dy12),
          tyzM = tyz0 + dtyz02*yy0/dy02,
          lxzm = y<y1?(lxz0 + dlxz01*yy0/dy01):(lxz1 + dlxz12*yy1/dy12),
          lxzM = lxz0 + dlxz02*yy0/dy02,
          lyzm = y<y1?(lyz0 + dlyz01*yy0/dy01):(lyz1 + dlyz12*yy1/dy12),
          lyzM = lyz0 + dlyz02*yy0/dy02;
        if (xm>xM) cimg::swap(xm,xM,izm,izM,txzm,txzM,tyzm,tyzM,lxzm,lxzM,lyzm,lyzM);
        if (xM>=0 || xm<=w1) {
          const int
            cxm = cimg::cut(xm,0,w1),
            cxM = cimg::cut(xM,0,w1);
          T *ptrd = data(cxm,y);
          const int dxmM = std::max(1,xM - xm);
          const float
            dizmM = izM - izm,
            dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm,
            dlxzmM = lxzM - lxzm, dlyzmM = lyzM - lyzm;

          for (int x = cxm; x<cxM; ++x) {
            const int xxm = x - xm;
            const float
              iz = izm + dizmM*xxm/dxmM,
              txz = txzm + dtxzmM*xxm/dxmM,
              tyz = tyzm + dtyzmM*xxm/dxmM,
              lxz = lxzm + dlxzmM*xxm/dxmM,
              lyz = lyzm + dlyzmM*xxm/dxmM;
            const int
              tx = (int)cimg::round(txz/iz),
              ty = (int)cimg::round(tyz/iz),
              lx = (int)cimg::round(lxz/iz),
              ly = (int)cimg::round(lyz/iz);
            const tc *const color = &texture._atXY(tx,ty);
            const tl *const lig = &light._atXY(lx,ly);
            cimg_forC(*this,c) {
              const tc col = color[c*twhd];
              const float cbs = cimg::cut((float)lig[c*lwhd],0,2);
              const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval;
              ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity);
            }
            ++ptrd;
          }
        }
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T> & operator=(std::initializer_list<t> values) {
      _cimg_constructor_cpp11(siz>values.size());
      return *this;

Project: CImg
File: CImg.h

      // Insert code instructions for processing scalars.
      unsigned int scalar() { // Insert new scalar in memory
        if (mempos>=mem._width) { mem.resize(-200,1,1,1,0); memtype.resize(mem._width,1,1,1,0); }
        return mempos++;

Project: CImg
File: CImg.h

  template<typename T>
  inline CImg<_cimg_Tfloat> operator*(const char *const expression, const CImg<T>& img) {
    return img*expression;

Project: CImg
File: CImg.h


    inline double grand(cimg_ulong *const p_rng) {
      double x1, w;
      do {
        const double x2 = cimg::rand(-1,1,p_rng);
        x1 = cimg::rand(-1,1,p_rng);
        w = x1*x1 + x2*x2;
      } while (w<=0 || w>=1.);
      return x1*std::sqrt((-2*std::log(w))/w);

Project: CImg
File: CImg.h

      _functor4d_int(const CImg<T>& pref):ref(pref) {}
      float operator()(const float x, const float y, const float z, const unsigned int c) const {
        return (float)ref((int)x,(int)y,(int)z,c);

Project: CImg
File: CImg.h

      void lock(const unsigned int n) { pthread_mutex_lock(&mutex[n]); }

Project: CImg
File: CImg.h

    **/
    CImgDisplay& set_fullscreen(const bool is_fullscreen, const bool force_redraw=true) {
      if (is_empty() || _is_fullscreen==is_fullscreen) return *this;
      return toggle_fullscreen(force_redraw);

Project: CImg
File: CImg.h

    **/
    CImg<T>& ror(const unsigned int n=1) {
      if (is_empty()) return *this;
      cimg_openmp_for(*this,cimg::ror(*ptr,n),32768);
      return *this;

Project: CImg
File: CImg.h


      void set_variable_vector(const unsigned int arg) {
        unsigned int siz = _cimg_mp_size(arg);
        int *ptr = memtype.data(arg + 1);
        while (siz-->0) *(ptr++) = -1;

Project: CImg
File: CImg.h

    **/
    CImg<T> get_column(const int x0) const {
      return get_columns(x0,x0);

Project: CImg
File: CImg.h

    **/
    CImg<Tfloat> operator*(const char *const expression) const {
      return CImg<Tfloat>(*this,false)*=expression;

Project: CImg
File: CImg.h

    template<typename t>
    void _eval(CImg<t>& output, CImg<T> *const img_output, const char *const expression,
               const double x, const double y, const double z, const double c,
               const CImgList<T> *const list_inputs, CImgList<T> *const list_outputs) const {
      if (!expression || !*expression) { output.assign(1); *output = 0; }
      if (!expression[1]) switch (*expression) { // Single-char optimization
        case 'w' : output.assign(1); *output = (t)_width; break;
        case 'h' : output.assign(1); *output = (t)_height; break;
        case 'd' : output.assign(1); *output = (t)_depth; break;
        case 's' : output.assign(1); *output = (t)_spectrum; break;
        case 'r' : output.assign(1); *output = (t)_is_shared; break;
        }
      _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' ||
                                         *expression=='*' || *expression==':'),"eval",
                           *this,img_output,list_inputs,list_outputs,false);
      output.assign(1,std::max(1U,mp.result_dim));
      mp(x,y,z,c,output._data);
      mp.end();

Project: CImg
File: CImg.h

     **/
    CImg<T>& min(const T& value) {
      if (is_empty()) return *this;
      cimg_openmp_for(*this,std::min(*ptr,value),65536);
      return *this;

Project: CImg
File: CImg.h


    CImg<T>& _load_tiff(TIFF *const tif, const unsigned int directory,
                        float *const voxel_size, CImg<charT> *const description) {
      if (!TIFFSetDirectory(tif,directory)) return assign();
      uint16 samplesperpixel = 1, bitspersample = 8, photo = 0;
      uint16 sampleformat = 1;
      uint32 nx = 1, ny = 1;
      const char *const filename = TIFFFileName(tif);
      const bool is_spp = (bool)TIFFGetField(tif,TIFFTAG_SAMPLESPERPIXEL,&samplesperpixel);
      TIFFGetField(tif,TIFFTAG_IMAGEWIDTH,&nx);
      TIFFGetField(tif,TIFFTAG_IMAGELENGTH,&ny);
      TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sampleformat);
      TIFFGetFieldDefaulted(tif,TIFFTAG_BITSPERSAMPLE,&bitspersample);
      TIFFGetField(tif,TIFFTAG_PHOTOMETRIC,&photo);
      if (voxel_size) {
        const char *s_description = 0;
        float vx = 0, vy = 0, vz = 0;
        if (TIFFGetField(tif,TIFFTAG_IMAGEDESCRIPTION,&s_description) && s_description) {
          const char *s_desc = std::strstr(s_description,"VX=");
          if (s_desc && cimg_sscanf(s_desc,"VX=%f VY=%f VZ=%f",&vx,&vy,&vz)==3) { // CImg format
            voxel_size[0] = vx; voxel_size[1] = vy; voxel_size[2] = vz;
          }
          s_desc = std::strstr(s_description,"spacing=");
          if (s_desc && cimg_sscanf(s_desc,"spacing=%f",&vz)==1) { // Fiji format
            voxel_size[2] = vz;
          }
        }
        TIFFGetField(tif,TIFFTAG_XRESOLUTION,voxel_size);
        TIFFGetField(tif,TIFFTAG_YRESOLUTION,voxel_size + 1);
        voxel_size[0] = 1.f/voxel_size[0];
        voxel_size[1] = 1.f/voxel_size[1];
      }
      if (description) {
        const char *s_description = 0;
        if (TIFFGetField(tif,TIFFTAG_IMAGEDESCRIPTION,&s_description) && s_description)
          CImg<charT>::string(s_description).move_to(*description);
      }
      const unsigned int spectrum = !is_spp || photo>=3?(photo>1?3:1):samplesperpixel;
      assign(nx,ny,1,spectrum);

      if ((photo>=3 && sampleformat==1 &&
           (bitspersample==4 || bitspersample==8) &&
           (samplesperpixel==1 || samplesperpixel==3 || samplesperpixel==4)) ||
          (bitspersample==1 && samplesperpixel==1)) {
        // Special case for unsigned color images.
        uint32 *const raster = (uint32*)_TIFFmalloc(nx*ny*sizeof(uint32));
        if (!raster) {
          _TIFFfree(raster); TIFFClose(tif);
          throw CImgException(_cimg_instance
                              "load_tiff(): Failed to allocate memory (%s) for file '%s'.",
                              cimg_instance,
                              cimg::strbuffersize(nx*ny*sizeof(uint32)),filename);
        }
        TIFFReadRGBAImage(tif,nx,ny,raster,0);
        switch (spectrum) {
        case 1 :
          cimg_forXY(*this,x,y)
            (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 -y) + x]);
          break;
        case 3 :
          cimg_forXY(*this,x,y) {
            (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 -y) + x]);
            (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny - 1 -y) + x]);
            (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny - 1 -y) + x]);
          }
          break;
        case 4 :
          cimg_forXY(*this,x,y) {
            (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 - y) + x]);
            (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny - 1 - y) + x]);
            (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny - 1 - y) + x]);
            (*this)(x,y,3) = (T)(float)TIFFGetA(raster[nx*(ny - 1 - y) + x]);
          }
          break;
        }
        _TIFFfree(raster);
      } else { // Other cases
        uint16 config;
        TIFFGetField(tif,TIFFTAG_PLANARCONFIG,&config);
        if (TIFFIsTiled(tif)) {
          uint32 tw = 1, th = 1;
          TIFFGetField(tif,TIFFTAG_TILEWIDTH,&tw);
          TIFFGetField(tif,TIFFTAG_TILELENGTH,&th);
          if (config==PLANARCONFIG_CONTIG) switch (bitspersample) {
            case 8 :
              if (sampleformat==SAMPLEFORMAT_UINT)
                _load_tiff_tiled_contig<unsigned char>(tif,samplesperpixel,nx,ny,tw,th);
              else _load_tiff_tiled_contig<signed char>(tif,samplesperpixel,nx,ny,tw,th);
              break;
            case 16 :
              if (sampleformat==SAMPLEFORMAT_UINT)
                _load_tiff_tiled_contig<unsigned short>(tif,samplesperpixel,nx,ny,tw,th);
              else _load_tiff_tiled_contig<short>(tif,samplesperpixel,nx,ny,tw,th);
              break;
            case 32 :
              if (sampleformat==SAMPLEFORMAT_UINT)
                _load_tiff_tiled_contig<unsigned int>(tif,samplesperpixel,nx,ny,tw,th);
              else if (sampleformat==SAMPLEFORMAT_INT)
                _load_tiff_tiled_contig<int>(tif,samplesperpixel,nx,ny,tw,th);
              else _load_tiff_tiled_contig<float>(tif,samplesperpixel,nx,ny,tw,th);
              break;
            case 64 :
              if (sampleformat==SAMPLEFORMAT_UINT)
                _load_tiff_tiled_contig<uint64T>(tif,samplesperpixel,nx,ny,tw,th);
              else if (sampleformat==SAMPLEFORMAT_INT)
                _load_tiff_tiled_contig<int64T>(tif,samplesperpixel,nx,ny,tw,th);
              else _load_tiff_tiled_contig<double>(tif,samplesperpixel,nx,ny,tw,th);
              break;
            } else switch (bitspersample) {
            case 8 :
              if (sampleformat==SAMPLEFORMAT_UINT)
                _load_tiff_tiled_separate<unsigned char>(tif,samplesperpixel,nx,ny,tw,th);
              else _load_tiff_tiled_separate<signed char>(tif,samplesperpixel,nx,ny,tw,th);
              break;
            case 16 :
              if (sampleformat==SAMPLEFORMAT_UINT)
                _load_tiff_tiled_separate<unsigned short>(tif,samplesperpixel,nx,ny,tw,th);
              else _load_tiff_tiled_separate<short>(tif,samplesperpixel,nx,ny,tw,th);
              break;
            case 32 :
              if (sampleformat==SAMPLEFORMAT_UINT)
                _load_tiff_tiled_separate<unsigned int>(tif,samplesperpixel,nx,ny,tw,th);
              else if (sampleformat==SAMPLEFORMAT_INT)
                _load_tiff_tiled_separate<int>(tif,samplesperpixel,nx,ny,tw,th);
              else _load_tiff_tiled_separate<float>(tif,samplesperpixel,nx,ny,tw,th);
              break;
            case 64 :
              if (sampleformat==SAMPLEFORMAT_UINT)
                _load_tiff_tiled_separate<uint64T>(tif,samplesperpixel,nx,ny,tw,th);
              else if (sampleformat==SAMPLEFORMAT_INT)
                _load_tiff_tiled_separate<int64T>(tif,samplesperpixel,nx,ny,tw,th);
              else _load_tiff_tiled_separate<double>(tif,samplesperpixel,nx,ny,tw,th);
              break;
            }
        } else {
          if (config==PLANARCONFIG_CONTIG) switch (bitspersample) {
            case 8 :
              if (sampleformat==SAMPLEFORMAT_UINT)
                _load_tiff_contig<unsigned char>(tif,samplesperpixel,nx,ny);
              else _load_tiff_contig<signed char>(tif,samplesperpixel,nx,ny);
              break;
            case 16 :
              if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig<unsigned short>(tif,samplesperpixel,nx,ny);
              else _load_tiff_contig<short>(tif,samplesperpixel,nx,ny);
              break;
            case 32 :
              if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig<unsigned int>(tif,samplesperpixel,nx,ny);
              else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_contig<int>(tif,samplesperpixel,nx,ny);
              else _load_tiff_contig<float>(tif,samplesperpixel,nx,ny);
              break;
            case 64 :
              if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig<uint64T>(tif,samplesperpixel,nx,ny);
              else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_contig<int64T>(tif,samplesperpixel,nx,ny);
              else _load_tiff_contig<double>(tif,samplesperpixel,nx,ny);
              break;
            } else switch (bitspersample) {
            case 8 :
              if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate<unsigned char>(tif,samplesperpixel,nx,ny);
              else _load_tiff_separate<signed char>(tif,samplesperpixel,nx,ny);
              break;
            case 16 :
              if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate<unsigned short>(tif,samplesperpixel,nx,ny);
              else _load_tiff_separate<short>(tif,samplesperpixel,nx,ny);
              break;
            case 32 :
              if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate<unsigned int>(tif,samplesperpixel,nx,ny);
              else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_separate<int>(tif,samplesperpixel,nx,ny);
              else _load_tiff_separate<float>(tif,samplesperpixel,nx,ny);
              break;
            case 64 :
              if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate<uint64T>(tif,samplesperpixel,nx,ny);
              else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_separate<int64T>(tif,samplesperpixel,nx,ny);
              else _load_tiff_separate<double>(tif,samplesperpixel,nx,ny);
              break;
            }
        }
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    CImg<T>& operator&=(const char *const expression) {
      return *this&=(+*this)._fill(expression,true,1,0,0,"operator&=",this);

Project: CImg
File: CImg.h

    template<typename t>
    const CImg<T>& SVD(CImg<t>& U, CImg<t>& S, CImg<t>& V, const bool sorting=true,
                       const unsigned int max_iteration=40, const float lambda=0) const {
      typedef _cimg_Ttfloat Ttfloat;

      if (is_empty()) { U.assign(); S.assign(); V.assign(); }
      else {
        U = *this;
	if (lambda!=0) {
	  const unsigned int delta = std::min(U._width,U._height);
	  for (unsigned int i = 0; i<delta; ++i) U(i,i) = (t)(U(i,i) + lambda);
	}
        if (S.size()<_width) S.assign(1,_width);
        if (V._width<_width || V._height<_height) V.assign(_width,_width);
        CImg<t> rv1(_width);
        Ttfloat anorm = 0, c, f, g = 0, h, s, scale = 0;
        int l = 0, nm = 0;

        cimg_forX(U,i) {
          l = i + 1; rv1[i] = scale*g; g = s = scale = 0;
          if (i<height()) {
            for (int k = i; k<height(); ++k) scale+=cimg::abs(U(i,k));
            if (scale) {
              for (int k = i; k<height(); ++k) { U(i,k)/=scale; s+=U(i,k)*U(i,k); }
              f = U(i,i); g = (Ttfloat)((f>=0?-1:1)*std::sqrt(s)); h=f*g-s; U(i,i) = f-g;
              for (int j = l; j<width(); ++j) {
                s = 0;
                for (int k=i; k<height(); ++k) s+=U(i,k)*U(j,k);
                f = s/h;
                for (int k = i; k<height(); ++k) U(j,k)+=f*U(i,k);
              }
              for (int k = i; k<height(); ++k) U(i,k)*=scale;
            }
          }
          S[i]=scale*g;

          g = s = scale = 0;
          if (i<height() && i!=width() - 1) {
            for (int k = l; k<width(); ++k) scale+=cimg::abs(U(k,i));
            if (scale) {
              for (int k = l; k<width(); ++k) { U(k,i)/= scale; s+=U(k,i)*U(k,i); }
              f = U(l,i); g = (Ttfloat)((f>=0?-1:1)*std::sqrt(s)); h = f*g-s; U(l,i) = f-g;
              for (int k = l; k<width(); ++k) rv1[k]=U(k,i)/h;
              for (int j = l; j<height(); ++j) {
                s = 0;
                for (int k = l; k<width(); ++k) s+=U(k,j)*U(k,i);
                for (int k = l; k<width(); ++k) U(k,j)+=s*rv1[k];
              }
              for (int k = l; k<width(); ++k) U(k,i)*=scale;
            }
          }
          anorm = (Ttfloat)std::max((float)anorm,(float)(cimg::abs(S[i]) + cimg::abs(rv1[i])));
        }

        for (int i = width() - 1; i>=0; --i) {
          if (i<width()-1) {
            if (g) {
              for (int j = l; j<width(); ++j) V(i,j) =(U(j,i)/U(l,i))/g;
              for (int j = l; j<width(); ++j) {
                s = 0;
                for (int k = l; k<width(); ++k) s+=U(k,i)*V(j,k);
                for (int k = l; k<width(); ++k) V(j,k)+=s*V(i,k);
              }
            }
            for (int j = l; j<width(); ++j) V(j,i) = V(i,j) = (t)0.;
          }
          V(i,i) = (t)1.; g = rv1[i]; l = i;
        }

        for (int i = std::min(width(),height()) - 1; i>=0; --i) {
          l = i + 1; g = S[i];
          for (int j = l; j<width(); ++j) U(j,i) = 0;
          if (g) {
            g = 1/g;
            for (int j = l; j<width(); ++j) {
              s = 0; for (int k = l; k<height(); ++k) s+=U(i,k)*U(j,k);
              f = (s/U(i,i))*g;
              for (int k = i; k<height(); ++k) U(j,k)+=f*U(i,k);
            }
            for (int j = i; j<height(); ++j) U(i,j)*= g;
          } else for (int j = i; j<height(); ++j) U(i,j) = 0;
          ++U(i,i);
        }

        for (int k = width() - 1; k>=0; --k) {
          for (unsigned int its = 0; its<max_iteration; ++its) {
            bool flag = true;
            for (l = k; l>=1; --l) {
              nm = l - 1;
              if ((cimg::abs(rv1[l]) + anorm)==anorm) { flag = false; break; }
              if ((cimg::abs(S[nm]) + anorm)==anorm) break;
            }
            if (flag) {
              c = 0; s = 1;
              for (int i = l; i<=k; ++i) {
                f = s*rv1[i]; rv1[i] = c*rv1[i];
                if ((cimg::abs(f) + anorm)==anorm) break;
                g = S[i]; h = cimg::_hypot(f,g); S[i] = h; h = 1/h; c = g*h; s = -f*h;
                cimg_forY(U,j) { const t y = U(nm,j), z = U(i,j); U(nm,j) = y*c + z*s; U(i,j) = z*c - y*s; }
              }
            }

            const t z = S[k];
            if (l==k) { if (z<0) { S[k] = -z; cimg_forX(U,j) V(k,j) = -V(k,j); } break; }
            nm = k - 1;
            t x = S[l], y = S[nm];
            g = rv1[nm]; h = rv1[k];
            f = ((y - z)*(y + z)+(g - h)*(g + h))/std::max((Ttfloat)1e-25,(Ttfloat)2*h*y);
            g = cimg::_hypot(f,(Ttfloat)1);
            f = ((x - z)*(x + z)+h*((y/(f + (f>=0?g:-g))) - h))/std::max((Ttfloat)1e-25,(Ttfloat)x);
            c = s = 1;
            for (int j = l; j<=nm; ++j) {
              const int i = j + 1;
              g = rv1[i]; h = s*g; g = c*g;
              t y1 = S[i];
              t z1 = cimg::_hypot(f,h);
              rv1[j] = z1; c = f/std::max((Ttfloat)1e-25,(Ttfloat)z1); s = h/std::max((Ttfloat)1e-25,(Ttfloat)z1);
              f = x*c + g*s; g = g*c - x*s; h = y1*s; y1*=c;
              cimg_forX(U,jj) { const t x2 = V(j,jj), z2 = V(i,jj); V(j,jj) = x2*c + z2*s; V(i,jj) = z2*c - x2*s; }
              z1 = cimg::_hypot(f,h); S[j] = z1;
              if (z1) { z1 = 1/std::max((Ttfloat)1e-25,(Ttfloat)z1); c = f*z1; s = h*z1; }
              f = c*g + s*y1; x = c*y1 - s*g;
              cimg_forY(U,jj) { const t y2 = U(j,jj), z2 = U(i,jj); U(j,jj) = y2*c + z2*s; U(i,jj) = z2*c - y2*s; }
            }
            rv1[l] = 0; rv1[k] = f; S[k] = x;
          }
        }

        if (sorting) {
          CImg<intT> permutations;
          CImg<t> tmp(_width);
          S.sort(permutations,false);
          cimg_forY(U,k) {
            cimg_forY(permutations,y) tmp(y) = U(permutations(y),k);
            std::memcpy(U.data(0,k),tmp._data,sizeof(t)*_width);
          }
          cimg_forY(V,k) {
            cimg_forY(permutations,y) tmp(y) = V(permutations(y),k);
            std::memcpy(V.data(0,k),tmp._data,sizeof(t)*_width);
          }
        }
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<_cimg_Ttfloat> get_solve_tridiagonal(const CImg<t>& A) const {
      return CImg<_cimg_Ttfloat>(*this,false).solve_tridiagonal(A);

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& distance_dijkstra(const T& value, const CImg<t>& metric,
                               const bool is_high_connectivity=false) {
      return get_distance_dijkstra(value,metric,is_high_connectivity).move_to(*this);

Project: CImg
File: CImg.h


    //! Return a reference to the minimum pixel value of the instance list.
    /**
    **/
    T& min() {
      bool is_all_empty = true;
      T *ptr_min = 0;
      cimglist_for(*this,l) if (!_data[l].is_empty()) {
        ptr_min = _data[l]._data;
        is_all_empty = false;
        break;
      }
      if (is_all_empty)
        throw CImgInstanceException(_cimglist_instance
                                    "min(): %s.",
                                    _data?"List of empty images":"Empty instance",
                                    cimglist_instance);
      T min_value = *ptr_min;
      cimglist_for(*this,l) {
        const CImg<T>& img = _data[l];

Project: CImg
File: CImg.h

    **/
    inline double atof(const char *const str) {
      double x = 0, y = 1;
      return str && cimg_sscanf(str,"%lf/%lf",&x,&y)>0?x/y:0;

Project: CImg
File: CImg.h

    //! Crop image region \overloading.
    CImg<T>& crop(const int x0, const int y0, const int z0,
                  const int x1, const int y1, const int z1,
                  const unsigned int boundary_conditions=0) {
      return crop(x0,y0,z0,0,x1,y1,z1,_spectrum - 1,boundary_conditions);

Project: CImg
File: CImg.h


    T _cubic_atXYZ_c(const float fx, const float fy, const float fz, const int c) const {
      return cimg::type<T>::cut(_cubic_atXYZ(fx,fy,fz,c));

Project: CImg
File: CImg.h

    //! Wait for any event occuring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp7.
    static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5,
                     CImgDisplay& disp6, CImgDisplay& disp7) {
      disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event =
        disp6._is_event = disp7._is_event = false;
      while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed ||
              !disp6._is_closed || !disp7._is_closed) &&
             !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event &&
             !disp6._is_event && !disp7._is_event) wait_all();

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& atan2(const CImg<t>& img) {
      const ulongT siz = size(), isiz = img.size();
      if (siz && isiz) {
        if (is_overlapped(img)) return atan2(+img);
        T *ptrd = _data, *const ptre = _data + siz;
        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
          for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
            *ptrd = (T)std::atan2((double)*ptrd,(double)*(ptrs++));
        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)std::atan2((double)*ptrd,(double)*(ptrs++));
      }
      return *this;

Project: CImg
File: CImg.h

    //! Convert pixel values from XYZ to xyY color spaces.
    CImg<T>& XYZtoxyY() {
      if (_spectrum!=3)
        throw CImgInstanceException(_cimg_instance
                                    "XYZtoxyY(): Instance is not a XYZ image.",
                                    cimg_instance);

      T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
      const longT whd = (longT)width()*height()*depth();
      cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,4096))
      for (longT N = 0; N<whd; ++N) {
        const Tfloat
          X = (Tfloat)p1[N],
          Y = (Tfloat)p2[N],
          Z = (Tfloat)p3[N],
          sum = X + Y + Z,
          nsum = sum>0?sum:1;
        p1[N] = (T)(X/nsum);
        p2[N] = (T)(Y/nsum);
        p3[N] = (T)Y;
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename T>
    inline void getrf(int &N, T *lapA, int *IPIV, int &INFO) {
      dgetrf_(&N,&N,lapA,&N,IPIV,&INFO);

Project: CImg
File: CImg.h

      ~_functor2d_expr() { mp->end(); delete mp; }
      _functor2d_expr(const char *const expr):mp(0) {
        mp = new _cimg_math_parser(expr,0,CImg<T>::const_empty(),0);

Project: CImg
File: CImg.h

    template<typename T>
    inline T ror(const T& a, const unsigned int n=1) {
      return n?(T)((a>>n)|(a<<((sizeof(T)<<3) - n))):a;

Project: CImg
File: CImg.h

    //! Access to a pixel value \const.
    const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c,
                        const ulongT wh, const ulongT whd=0) const {
      cimg::unused(wh,whd);
      return (*this)(x,y,z,c);

Project: CImg
File: CImg.h

    //! Fill sequentially all pixel values with specified values \overloading.
    CImg<T>& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5,
                  const T& val6, const T& val7, const T& val8, const T& val9, const T& val10) {
      if (is_empty()) return *this;
      T *ptrd, *ptre = end() - 10;
      for (ptrd = _data; ptrd<ptre; ) {
        *(ptrd++) = val0; *(ptrd++) = val1; *(ptrd++) = val2; *(ptrd++) = val3; *(ptrd++) = val4;
        *(ptrd++) = val5; *(ptrd++) = val6; *(ptrd++) = val7; *(ptrd++) = val8; *(ptrd++) = val9;
        *(ptrd++) = val10;
      }
      ptre+=10;
      switch (ptre - ptrd) {
      case 10 : *(--ptre) = val9; // fallthrough
      case 9 : *(--ptre) = val8; // fallthrough
      case 8 : *(--ptre) = val7; // fallthrough
      case 7 : *(--ptre) = val6; // fallthrough
      case 6 : *(--ptre) = val5; // fallthrough
      case 5 : *(--ptre) = val4; // fallthrough
      case 4 : *(--ptre) = val3; // fallthrough
      case 3 : *(--ptre) = val2; // fallthrough
      case 2 : *(--ptre) = val1; // fallthrough
      case 1 : *(--ptre) = val0; // fallthrough
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename tp, typename tf, typename tc>
    const CImg<T>& display_object3d(const char *const title,
				    const CImg<tp>& vertices,
                                    const CImgList<tf>& primitives,
                                    const CImgList<tc>& colors,
                                    const bool centering=true,
                                    const int render_static=4, const int render_motion=1,
                                    const bool is_double_sided=true, const float focale=700,
                                    const float light_x=0, const float light_y=0, const float light_z=-5e8f,
                                    const float specular_lightness=0.2f, const float specular_shininess=0.1f,
                                    const bool display_axes=true, float *const pose_matrix=0,
                                    const bool exit_on_anykey=false) const {
      return display_object3d(title,vertices,primitives,colors,CImgList<floatT>(),centering,
                              render_static,render_motion,is_double_sided,focale,
                              light_x,light_y,light_z,specular_lightness,specular_shininess,
                              display_axes,pose_matrix,exit_on_anykey);

Project: CImg
File: CImg.h

    template<typename t>
    bool is_sameYZC(const CImg<t>& img) const {
      return is_sameYZC(img._height,img._depth,img._spectrum);

Project: CImg
File: CImg.h

    }
    inline bool abs(const bool a) {
      return a;

Project: CImg
File: CImg.h

    template<typename t, typename to>
    CImg<T>& distance_dijkstra(const T& value, const CImg<t>& metric, const bool is_high_connectivity,
                               CImg<to>& return_path) {
      return get_distance_dijkstra(value,metric,is_high_connectivity,return_path).move_to(*this);

Project: CImg
File: CImg.h


      static double mp_log(_cimg_math_parser& mp) {
        return std::log(_mp_arg(2));

Project: CImg
File: CImg.h

    //! Save image as a .cpp source file \overloading.
    const CImg<T>& save_cpp(std::FILE *const file) const {
      return _save_cpp(file,0);

Project: CImg
File: CImg.h

    //! Crop image region \overloading.
    CImg<T>& crop(const int x0, const int x1, const unsigned int boundary_conditions=0) {
      return crop(x0,0,0,0,x1,_height - 1,_depth - 1,_spectrum - 1,boundary_conditions);

Project: CImg
File: CImg.h

    //! Access to a pixel value at a specified offset, using Dirichlet boundary conditions \const.
    T at(const int offset, const T& out_value) const {
      return (offset<0 || offset>=(int)size())?out_value:(*this)[offset];

Project: CImg
File: CImg.h

    //! Access to a pixel value, using Dirichlet boundary conditions for the X,Y and Z-coordinates \const.
    T atXYZ(const int x, const int y, const int z, const int c, const T& out_value) const {
      return (x<0 || y<0 || z<0 || x>=width() || y>=height() || z>=depth())?out_value:(*this)(x,y,z,c);

Project: CImg
File: CImg.h

    //! Wait for any event occuring on the display \c disp1.
    static void wait(CImgDisplay& disp1) {
      disp1._is_event = false;
      while (!disp1._is_closed && !disp1._is_event) wait_all();

Project: CImg
File: CImg.h

      static unsigned char inf() { return max(); }
      static unsigned char cut(const double val) {

Project: CImg
File: CImg.h

    //! Return a shared-memory version of the image instance \const.
    const CImg<T> get_shared() const {
      return CImg<T>(_data,_width,_height,_depth,_spectrum,true);

Project: CImg
File: CImg.h


      static double mp_vector_resize(_cimg_math_parser& mp) {
        double *const ptrd = &_mp_arg(1) + 1;
        const unsigned int p1 = (unsigned int)mp.opcode[2], p2 = (unsigned int)mp.opcode[4];
        const int
          interpolation = (int)_mp_arg(5),
          boundary_conditions = (int)_mp_arg(6);
        if (p2) { // Resize vector
          const double *const ptrs = &_mp_arg(3) + 1;
          CImg<doubleT>(ptrd,p1,1,1,1,true) = CImg<doubleT>(ptrs,p2,1,1,1,true).
            get_resize(p1,1,1,1,interpolation,boundary_conditions);
        } else { // Resize scalar
          const double value = _mp_arg(3);
          CImg<doubleT>(ptrd,p1,1,1,1,true) = CImg<doubleT>(1,1,1,1,value).resize(p1,1,1,1,interpolation,
                                                                                  boundary_conditions);
        }
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h

    **/
    CImg<T>& quantize(const unsigned int nb_levels, const bool keep_range=true) {
      if (!nb_levels)
        throw CImgArgumentException(_cimg_instance
                                    "quantize(): Invalid quantization request with 0 values.",
                                    cimg_instance);

      if (is_empty()) return *this;
      Tfloat m, M = (Tfloat)max_min(m), range = M - m;
      if (range>0) {
        if (keep_range)
          cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768))
          cimg_rofoff(*this,off) {
            const unsigned int val = (unsigned int)((_data[off] - m)*nb_levels/range);
            _data[off] = (T)(m + std::min(val,nb_levels - 1)*range/nb_levels);
          } else
          cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768))
          cimg_rofoff(*this,off) {
            const unsigned int val = (unsigned int)((_data[off] - m)*nb_levels/range);
            _data[off] = (T)std::min(val,nb_levels - 1);
          }
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    const CImg<T>& _save_tiff(TIFF *tif, const unsigned int directory, const unsigned int z, const t& pixel_t,
                              const unsigned int compression_type, const float *const voxel_size,
                              const char *const description) const {
      if (is_empty() || !tif || pixel_t) return *this;
      const char *const filename = TIFFFileName(tif);
      uint32 rowsperstrip = (uint32)-1;
      uint16 spp = _spectrum, bpp = sizeof(t)*8, photometric;
      if (spp==3 || spp==4) photometric = PHOTOMETRIC_RGB;
      else photometric = PHOTOMETRIC_MINISBLACK;
      TIFFSetDirectory(tif,directory);
      TIFFSetField(tif,TIFFTAG_IMAGEWIDTH,_width);
      TIFFSetField(tif,TIFFTAG_IMAGELENGTH,_height);
      if (voxel_size) {
        const float vx = voxel_size[0], vy = voxel_size[1], vz = voxel_size[2];
        TIFFSetField(tif,TIFFTAG_RESOLUTIONUNIT,RESUNIT_NONE);
        TIFFSetField(tif,TIFFTAG_XRESOLUTION,1.f/vx);
        TIFFSetField(tif,TIFFTAG_YRESOLUTION,1.f/vy);
        CImg<charT> s_description(256);
        cimg_snprintf(s_description,s_description._width,"VX=%g VY=%g VZ=%g spacing=%g",vx,vy,vz,vz);
        TIFFSetField(tif,TIFFTAG_IMAGEDESCRIPTION,s_description.data());
      }
      if (description) TIFFSetField(tif,TIFFTAG_IMAGEDESCRIPTION,description);
      TIFFSetField(tif,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
      TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,spp);
      if (cimg::type<t>::is_float()) TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,3);
      else if (cimg::type<t>::min()==0) TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,1);
      else TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,2);
      double valm, valM = max_min(valm);
      TIFFSetField(tif,TIFFTAG_SMINSAMPLEVALUE,valm);
      TIFFSetField(tif,TIFFTAG_SMAXSAMPLEVALUE,valM);
      TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,bpp);
      TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
      TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,photometric);
      TIFFSetField(tif,TIFFTAG_COMPRESSION,compression_type==2?COMPRESSION_JPEG:
                   compression_type==1?COMPRESSION_LZW:COMPRESSION_NONE);
      rowsperstrip = TIFFDefaultStripSize(tif,rowsperstrip);
      TIFFSetField(tif,TIFFTAG_ROWSPERSTRIP,rowsperstrip);
      TIFFSetField(tif,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB);
      TIFFSetField(tif,TIFFTAG_SOFTWARE,"CImg");

      t *const buf = (t*)_TIFFmalloc(TIFFStripSize(tif));
      if (buf) {
        for (unsigned int row = 0; row<_height; row+=rowsperstrip) {
          uint32 nrow = (row + rowsperstrip>_height?_height - row:rowsperstrip);
          tstrip_t strip = TIFFComputeStrip(tif,row,0);
          tsize_t i = 0;
          for (unsigned int rr = 0; rr<nrow; ++rr)
            for (unsigned int cc = 0; cc<_width; ++cc)
              for (unsigned int vv = 0; vv<spp; ++vv)
                buf[i++] = (t)(*this)(cc,row + rr,z,vv);
          if (TIFFWriteEncodedStrip(tif,strip,buf,i*sizeof(t))<0)
            throw CImgIOException(_cimg_instance
                                  "save_tiff(): Invalid strip writing when saving file '%s'.",
                                  cimg_instance,
                                  filename?filename:"(FILE*)");
        }
        _TIFFfree(buf);
      }
      TIFFWriteDirectory(tif);
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImgList<t>& move_to(CImgList<t>& list, const unsigned int pos=~0U) {
      const unsigned int npos = pos>list._width?list._width:pos;
      move_to(list.insert(1,npos)[npos]);
      return list;

Project: CImg
File: CImg.h

    **/
    int mouse_y() const {
      return _mouse_y;

Project: CImg
File: CImg.h

    template<typename t>
    CImgList<T>& assign(const unsigned int n, const CImg<t>& img, const bool is_shared=false) {
      assign(n);
      cimglist_apply(*this,assign)(img,is_shared);
      return *this;

Project: CImg
File: CImg.h

    //! Equalize histogram of pixel values \newinstance.
    CImg<T> get_equalize(const unsigned int nblevels) const {
      return (+*this).equalize(nblevels);

Project: CImg
File: CImg.h

      _functor3d_float(const CImg<T>& pref):ref(pref) {}
      float operator()(const float x, const float y, const float z) const {
        return (float)ref._linear_atXYZ(x,y,z);

Project: CImg
File: CImg.h


      static double mp_asinh(_cimg_math_parser& mp) {
        return cimg::asinh(_mp_arg(2));

Project: CImg
File: CImg.h

      static T cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(T)val; }

Project: CImg
File: CImg.h


    CImg<T>& _load_jpeg(std::FILE *const file, const char *const filename) {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "load_jpeg(): Specified filename is (null).",
                                    cimg_instance);

#ifndef cimg_use_jpeg
      if (file)
        throw CImgIOException(_cimg_instance
                              "load_jpeg(): Unable to load data from '(FILE*)' unless libjpeg is enabled.",
                              cimg_instance);
      else return load_other(filename);
#else

      std::FILE *const nfile = file?file:cimg::fopen(filename,"rb");
      struct jpeg_decompress_struct cinfo;
      struct _cimg_error_mgr jerr;
      cinfo.err = jpeg_std_error(&jerr.original);
      jerr.original.error_exit = _cimg_jpeg_error_exit;
      if (setjmp(jerr.setjmp_buffer)) { // JPEG error
        if (!file) cimg::fclose(nfile);
        throw CImgIOException(_cimg_instance
                             "load_jpeg(): Error message returned by libjpeg: %s.",
                             cimg_instance,jerr.message);
      }

      jpeg_create_decompress(&cinfo);
      jpeg_stdio_src(&cinfo,nfile);
      jpeg_read_header(&cinfo,TRUE);
      jpeg_start_decompress(&cinfo);

      if (cinfo.output_components!=1 && cinfo.output_components!=3 && cinfo.output_components!=4) {
        if (!file) {
          cimg::fclose(nfile);
          return load_other(filename);
        } else
          throw CImgIOException(_cimg_instance
                                "load_jpeg(): Failed to load JPEG data from file '%s'.",
                                cimg_instance,filename?filename:"(FILE*)");
      }
      CImg<ucharT> buffer(cinfo.output_width*cinfo.output_components);
      JSAMPROW row_pointer[1];
      try { assign(cinfo.output_width,cinfo.output_height,1,cinfo.output_components); }
      catch (...) { if (!file) cimg::fclose(nfile); throw; }
      T *ptr_r = _data, *ptr_g = _data + 1UL*_width*_height, *ptr_b = _data + 2UL*_width*_height,
        *ptr_a = _data + 3UL*_width*_height;
      while (cinfo.output_scanline<cinfo.output_height) {
        *row_pointer = buffer._data;
        if (jpeg_read_scanlines(&cinfo,row_pointer,1)!=1) {
          cimg::warn(_cimg_instance
                     "load_jpeg(): Incomplete data in file '%s'.",
                     cimg_instance,filename?filename:"(FILE*)");
          break;
        }
        const unsigned char *ptrs = buffer._data;
        switch (_spectrum) {
        case 1 : {
          cimg_forX(*this,x) *(ptr_r++) = (T)*(ptrs++);
        } break;
        case 3 : {
          cimg_forX(*this,x) {
            *(ptr_r++) = (T)*(ptrs++);
            *(ptr_g++) = (T)*(ptrs++);
            *(ptr_b++) = (T)*(ptrs++);
          }
        } break;
        case 4 : {
          cimg_forX(*this,x) {
            *(ptr_r++) = (T)*(ptrs++);
            *(ptr_g++) = (T)*(ptrs++);
            *(ptr_b++) = (T)*(ptrs++);
            *(ptr_a++) = (T)*(ptrs++);
          }
        } break;
        }
      }
      jpeg_finish_decompress(&cinfo);
      jpeg_destroy_decompress(&cinfo);
      if (!file) cimg::fclose(nfile);
      return *this;
#endif

Project: CImg
File: CImg.h


    static void wait_all() {
      WaitForSingleObject(cimg::Win32_attr().wait_event,INFINITE);

Project: CImg
File: CImg.h

     **/
    CImg<T>& max(const T& value) {
      if (is_empty()) return *this;
      cimg_openmp_for(*this,std::max(*ptr,value),65536);
      return *this;

Project: CImg
File: CImg.h

    **/
    CImgDisplay& set_wheel() {
      _wheel = 0;
      _is_event = true;
#if cimg_display==1
      pthread_cond_broadcast(&cimg::X11_attr().wait_event);
#elif cimg_display==2
      SetEvent(cimg::Win32_attr().wait_event);
#endif
      return *this;

Project: CImg
File: CImg.h

    template<typename tc>
    CImg<T>& draw_mandelbrot(const int x0, const int y0, const int x1, const int y1,
                             const CImg<tc>& colormap, const float opacity=1,
                             const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2,
                             const unsigned int iteration_max=255,
                             const bool is_normalized_iteration=false,
                             const bool is_julia_set=false,
                             const double param_r=0, const double param_i=0) {
      if (is_empty()) return *this;
      CImg<tc> palette;
      if (colormap) palette.assign(colormap._data,colormap.size()/colormap._spectrum,1,1,colormap._spectrum,true);
      if (palette && palette._spectrum!=_spectrum)
        throw CImgArgumentException(_cimg_instance
                                    "draw_mandelbrot(): Instance and specified colormap (%u,%u,%u,%u,%p) have "
                                    "incompatible dimensions.",
                                    cimg_instance,
                                    colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data);

      const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f), ln2 = (float)std::log(2.);
      const int
        _x0 = cimg::cut(x0,0,width() - 1),
        _y0 = cimg::cut(y0,0,height() - 1),
        _x1 = cimg::cut(x1,0,width() - 1),
        _y1 = cimg::cut(y1,0,height() - 1);

      cimg_pragma_openmp(parallel for cimg_openmp_collapse(2)
                         cimg_openmp_if((1 + _x1 - _x0)*(1 + _y1 - _y0)>=(cimg_openmp_sizefactor)*2048))
      for (int q = _y0; q<=_y1; ++q)
        for (int p = _x0; p<=_x1; ++p) {
          unsigned int iteration = 0;
          const double x = z0r + p*(z1r-z0r)/_width, y = z0i + q*(z1i-z0i)/_height;
          double zr, zi, cr, ci;
          if (is_julia_set) { zr = x; zi = y; cr = param_r; ci = param_i; }
          else { zr = param_r; zi = param_i; cr = x; ci = y; }
          for (iteration=1; zr*zr + zi*zi<=4 && iteration<=iteration_max; ++iteration) {
            const double temp = zr*zr - zi*zi + cr;
            zi = 2*zr*zi + ci;
            zr = temp;
          }
          if (iteration>iteration_max) {
            if (palette) {
              if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette(0,c);
              else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(palette(0,c)*nopacity + (*this)(p,q,0,c)*copacity);
            } else {
              if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)0;
              else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)((*this)(p,q,0,c)*copacity);
            }
          } else if (is_normalized_iteration) {
            const float
              normz = (float)cimg::abs(zr*zr + zi*zi),
              niteration = (float)(iteration + 1 - std::log(std::log(normz))/ln2);
            if (palette) {
              if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette._linear_atX(niteration,c);
              else cimg_forC(*this,c)
                     (*this)(p,q,0,c) = (T)(palette._linear_atX(niteration,c)*nopacity + (*this)(p,q,0,c)*copacity);
            } else {
              if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)niteration;
              else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(niteration*nopacity + (*this)(p,q,0,c)*copacity);
            }
          } else {
            if (palette) {
              if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette._atX(iteration,c);
              else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(palette(iteration,c)*nopacity + (*this)(p,q,0,c)*copacity);
            } else {
              if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)iteration;
              else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(iteration*nopacity + (*this)(p,q,0,c)*copacity);
            }
          }
        }
      return *this;

Project: CImg
File: CImg.h


      static double mp_list_height(_cimg_math_parser& mp) {
        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
        return (double)mp.listin[ind]._height;

Project: CImg
File: CImg.h

     **/
    CImg<T> get_matrix_at(const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) const {
      const int n = (int)cimg::round(std::sqrt((double)_spectrum));
      const T *ptrs = data(x,y,z,0);
      const ulongT whd = (ulongT)_width*_height*_depth;
      CImg<T> res(n,n);
      T *ptrd = res._data;
      cimg_forC(*this,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
      return res;

Project: CImg
File: CImg.h

    **/
    T& atNXY(const int pos, const int x, const int y, const int z, const int c, const T& out_value) {
      return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atXY(x,y,z,c,out_value);

Project: CImg
File: CImg.h

    **/
    CImg<T>& assign(const unsigned int size_x, const unsigned int size_y,
                    const unsigned int size_z, const unsigned int size_c,
                    const char *const values, const bool repeat_values) {
      return assign(size_x,size_y,size_z,size_c).fill(values,repeat_values);

Project: CImg
File: CImg.h


      unsigned int scalar3(const mp_func op,
                           const unsigned int arg1, const unsigned int arg2, const unsigned int arg3) {
        const unsigned int pos =
          arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1:
          arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2:
          arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3:scalar();
        CImg<ulongT>::vector((ulongT)op,pos,arg1,arg2,arg3).move_to(code);
        return pos;

Project: CImg
File: CImg.h

      static char max() { return (char)((unsigned char)-1>>1); }

Project: CImg
File: CImg.h

    **/
    bool is_fullscreen() const {
      return _is_fullscreen;

Project: CImg
File: CImg.h


      static double mp_bitwise_left_shift(_cimg_math_parser& mp) {
        return (double)((longT)_mp_arg(2)<<(unsigned int)_mp_arg(3));

Project: CImg
File: CImg.h

    //! Convert pixel values from CMYK to RGB color spaces \newinstance.
    CImg<Tuchar> get_CMYKtoRGB() const {
      return CImg<Tuchar>(*this,false).CMYKtoRGB();

Project: CImg
File: CImg.h


    T _cubic_atXY_c(const float fx, const float fy, const int z, const int c) const {
      return cimg::type<T>::cut(_cubic_atXY(fx,fy,z,c));

Project: CImg
File: CImg.h

    **/
    CImg<T>& resize(const int size_x, const int size_y=-100,
                    const int size_z=-100, const int size_c=-100,
                    const int interpolation_type=1, const unsigned int boundary_conditions=0,
                    const float centering_x = 0, const float centering_y = 0,
                    const float centering_z = 0, const float centering_c = 0) {
      if (!size_x || !size_y || !size_z || !size_c) return assign();
      const unsigned int
        _sx = (unsigned int)(size_x<0?-size_x*width()/100:size_x),
        _sy = (unsigned int)(size_y<0?-size_y*height()/100:size_y),
        _sz = (unsigned int)(size_z<0?-size_z*depth()/100:size_z),
        _sc = (unsigned int)(size_c<0?-size_c*spectrum()/100:size_c),
        sx = _sx?_sx:1, sy = _sy?_sy:1, sz = _sz?_sz:1, sc = _sc?_sc:1;
      if (sx==_width && sy==_height && sz==_depth && sc==_spectrum) return *this;
      if (is_empty()) return assign(sx,sy,sz,sc,(T)0);
      if (interpolation_type==-1 && sx*sy*sz*sc==size()) {
	_width = sx; _height = sy; _depth = sz; _spectrum = sc;
	return *this;
      }
      return get_resize(sx,sy,sz,sc,interpolation_type,boundary_conditions,
                        centering_x,centering_y,centering_z,centering_c).move_to(*this);

Project: CImg
File: CImg.h

      return remove(pos,pos);
    }

Project: CImg
File: CImg.h

     **/
    double sum() const {
      double res = 0;
      cimg_for(*this,ptrs,T) res+=(double)*ptrs;
      return res;

Project: CImg
File: CImg.h

    template<typename T, typename t>
    inline T cut(const T& val, const t& val_min, const t& val_max) {
      return val<val_min?(T)val_min:val>val_max?(T)val_max:val;

Project: CImg
File: CImg.h

    **/
    CImg<T>& vanvliet(const float sigma, const unsigned int order, const char axis='x',
                      const bool boundary_conditions=true) {
      if (is_empty()) return *this;
      if (!cimg::type<T>::is_float())
        return CImg<Tfloat>(*this,false).vanvliet(sigma,order,axis,boundary_conditions).move_to(*this);
      const char naxis = cimg::lowercase(axis);
      const float nsigma = sigma>=0?sigma:-sigma*(naxis=='x'?_width:naxis=='y'?_height:naxis=='z'?_depth:_spectrum)/100;
      if (is_empty() || (nsigma<0.5f && !order)) return *this;
      const double
	nnsigma = nsigma<0.5f?0.5f:nsigma,
	m0 = 1.16680, m1 = 1.10783, m2 = 1.40586,
        m1sq = m1 * m1, m2sq = m2 * m2,
	q = (nnsigma<3.556?-0.2568 + 0.5784*nnsigma + 0.0561*nnsigma*nnsigma:2.5091 + 0.9804*(nnsigma - 3.556)),
	qsq = q * q,
	scale = (m0 + q) * (m1sq + m2sq + 2 * m1 * q + qsq),
	b1 = -q * (2 * m0 * m1 + m1sq + m2sq + (2 * m0 + 4 * m1) * q + 3 * qsq) / scale,
	b2 = qsq * (m0 + 2 * m1 + 3 * q) / scale,
	b3 = -qsq * q / scale,
	B = ( m0 * (m1sq + m2sq) ) / scale;
      double filter[4];
      filter[0] = B; filter[1] = -b1; filter[2] = -b2; filter[3] = -b3;
      switch (naxis) {
      case 'x' : {
        cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 &&
                                                                   _height*_depth*_spectrum>=16))
	cimg_forYZC(*this,y,z,c)
	  _cimg_recursive_apply(data(0,y,z,c),filter,_width,1U,order,boundary_conditions);
      } break;
      case 'y' : {
        cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 &&
                                                                   _height*_depth*_spectrum>=16))
	cimg_forXZC(*this,x,z,c)
	  _cimg_recursive_apply(data(x,0,z,c),filter,_height,(ulongT)_width,order,boundary_conditions);
      } break;
      case 'z' : {
        cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 &&
                                                                   _height*_depth*_spectrum>=16))
	cimg_forXYC(*this,x,y,c)
	  _cimg_recursive_apply(data(x,y,0,c),filter,_depth,(ulongT)_width*_height,
				order,boundary_conditions);
      } break;
      default : {
        cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 &&
                                                                   _height*_depth*_spectrum>=16))
	cimg_forXYZ(*this,x,y,z)
	  _cimg_recursive_apply(data(x,y,z,0),filter,_spectrum,(ulongT)_width*_height*_depth,
				order,boundary_conditions);
      }
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    T& atXYZC(const int x, const int y, const int z, const int c, const T& out_value) {
      return (x<0 || y<0 || z<0 || c<0 || x>=width() || y>=height() || z>=depth() || c>=spectrum())?
        (cimg::temporary(out_value)=out_value):(*this)(x,y,z,c);

Project: CImg
File: CImg.h

    }
    inline cimg_int64 mod(const cimg_int64 x, const cimg_int64 m) {
      return x>=0?x%m:(x%m?m + x%m:0);

Project: CImg
File: CImg.h

    // Conversion functions to get more precision when trying to store unsigned ints values as floats.
    inline unsigned int float2uint(const float f) {
      int tmp = 0;
      std::memcpy(&tmp,&f,sizeof(float));
      if (tmp>=0) return (unsigned int)f;
      unsigned int u;
      // use memcpy instead of assignment to avoid undesired optimizations by C++-compiler.
      std::memcpy(&u,&f,sizeof(float));
      return ((u)<<1)>>1; // set sign bit to 0

Project: CImg
File: CImg.h

    //! Load a list from a .cimg file.
    /**
      \param filename Filename to read data from.

Project: CImg
File: CImg.h

    template<typename t>
    CImg<_cimg_Tt> get_div(const CImg<t>& img) const {
      return CImg<_cimg_Tt>(*this,false).div(img);

Project: CImg
File: CImg.h

    **/
    CImg<T>& load_ffmpeg_external(const char *const filename, const char axis='z', const float align=0) {
      return get_load_ffmpeg_external(filename,axis,align).move_to(*this);

Project: CImg
File: CImg.h

    **/
    iterator end() {
      return _data + size();

Project: CImg
File: CImg.h

    //! Crop image region \newinstance.
    CImg<T> get_crop(const int x0, const int y0, const int z0, const int c0,
                     const int x1, const int y1, const int z1, const int c1,
                     const unsigned int boundary_conditions=0) const {
      if (is_empty())
        throw CImgInstanceException(_cimg_instance
                                    "crop(): Empty instance.",
                                    cimg_instance);
      const int
        nx0 = x0<x1?x0:x1, nx1 = x0^x1^nx0,
        ny0 = y0<y1?y0:y1, ny1 = y0^y1^ny0,
        nz0 = z0<z1?z0:z1, nz1 = z0^z1^nz0,
        nc0 = c0<c1?c0:c1, nc1 = c0^c1^nc0;
      CImg<T> res(1U + nx1 - nx0,1U + ny1 - ny0,1U + nz1 - nz0,1U + nc1 - nc0);
      if (nx0<0 || nx1>=width() || ny0<0 || ny1>=height() || nz0<0 || nz1>=depth() || nc0<0 || nc1>=spectrum())
        switch (boundary_conditions) {
        case 3 : { // Mirror
          const int w2 = 2*width(), h2 = 2*height(), d2 = 2*depth(), s2 = 2*spectrum();
          cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 &&
                                                                     _height*_depth*_spectrum>=4))
          cimg_forXYZC(res,x,y,z,c) {
            const int
              mx = cimg::mod(nx0 + x,w2),
              my = cimg::mod(ny0 + y,h2),
              mz = cimg::mod(nz0 + z,d2),
              mc = cimg::mod(nc0 + c,s2);
            res(x,y,z,c) = (*this)(mx<width()?mx:w2 - mx - 1,
                                   my<height()?my:h2 - my - 1,
                                   mz<depth()?mz:d2 - mz - 1,
                                   mc<spectrum()?mc:s2 - mc - 1);
          }
        } break;
        case 2 : { // Periodic
          cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 &&
                                                                     _height*_depth*_spectrum>=4))
          cimg_forXYZC(res,x,y,z,c) {
            res(x,y,z,c) = (*this)(cimg::mod(nx0 + x,width()),cimg::mod(ny0 + y,height()),
                                   cimg::mod(nz0 + z,depth()),cimg::mod(nc0 + c,spectrum()));
          }
        } break;
        case 1 : // Neumann
          cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 &&
                                                                     _height*_depth*_spectrum>=4))
          cimg_forXYZC(res,x,y,z,c) res(x,y,z,c) = _atXYZC(nx0 + x,ny0 + y,nz0 + z,nc0 + c);
          break;
        default : // Dirichlet
          res.fill((T)0).draw_image(-nx0,-ny0,-nz0,-nc0,*this);
        }
      else res.draw_image(-nx0,-ny0,-nz0,-nc0,*this);
      return res;

Project: CImg
File: CImg.h

    //! Convert pixel values from HSV to RGB color spaces.
    CImg<T>& HSVtoRGB() {
      if (_spectrum!=3)
        throw CImgInstanceException(_cimg_instance
                                    "HSVtoRGB(): Instance is not a HSV image.",
                                    cimg_instance);

      T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
      const longT whd = (longT)width()*height()*depth();
      cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256))
      for (longT N = 0; N<whd; ++N) {
        Tfloat
          H = cimg::mod((Tfloat)p1[N]/60,(Tfloat)6),
          S = (Tfloat)p2[N],
          V = (Tfloat)p3[N],
          C = V*S,
          X = C*(1 - cimg::abs(cimg::mod(H,(Tfloat)2) - 1)),
          m = V - C;
        Tfloat R, G, B;
        switch ((int)H) {
        case 0 : R = C; G = X; B = 0; break;
        case 1 : R = X; G = C; B = 0; break;
        case 2 : R = 0; G = C; B = X; break;
        case 3 : R = 0; G = X; B = C; break;
        case 4 : R = X; G = 0; B = C; break;
        default : R = C; G = 0; B = X;
        }
        p1[N] = (T)((R + m)*255);
        p2[N] = (T)((G + m)*255);
        p3[N] = (T)((B + m)*255);
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    bool is_empty() const {
      return !(_width && _height);

Project: CImg
File: CImg.h

    //! Save image as a JPEG file \overloading.
    const CImg<T>& save_jpeg(std::FILE *const file, const unsigned int quality=100) const {
      return _save_jpeg(file,0,quality);

Project: CImg
File: CImg.h

    template<> struct type<bool> {

Project: CImg
File: CImg.h

    //! Convert pixel values from CMYK to CMY color spaces.
    CImg<T>& CMYKtoCMY() {
      return get_CMYKtoCMY().move_to(*this);

Project: CImg
File: CImg.h

    template<typename T>
    CImgDisplay& display(const CImg<T>& img) {
      if (!img)
        throw CImgArgumentException(_cimgdisplay_instance
                                    "display(): Empty specified image.",
                                    cimgdisplay_instance);
      if (is_empty()) return assign(img);
      return render(img).paint();

Project: CImg
File: CImg.h

    template<typename t>
    CImgList<T>& assign(const CImgList<t>& list, const bool is_shared=false) {
      cimg::unused(is_shared);
      assign(list._width);
      cimglist_for(*this,l) _data[l].assign(list[l],false);
      return *this;

Project: CImg
File: CImg.h

      \param fps Number of frames per second.
      \param codec Type of compression.
      \param bitrate Output bitrate
    **/
    const CImgList<T>& save_ffmpeg_external(const char *const filename, const unsigned int fps=25,
                                            const char *const codec=0, const unsigned int bitrate=2048) const {
      if (!filename)
        throw CImgArgumentException(_cimglist_instance
                                    "save_ffmpeg_external(): Specified filename is (null).",
                                    cimglist_instance);
      if (is_empty()) { cimg::fempty(0,filename); return *this; }

      const char
        *const ext = cimg::split_filename(filename),
        *const _codec = codec?codec:!cimg::strcasecmp(ext,"flv")?"flv":"mpeg2video";

      CImg<charT> command(1024), filename_tmp(256), filename_tmp2(256);
      CImgList<charT> filenames;
      std::FILE *file = 0;
      cimglist_for(*this,l) if (!_data[l].is_sameXYZ(_data[0]))
        throw CImgInstanceException(_cimglist_instance
                                    "save_ffmpeg_external(): Invalid instance dimensions for file '%s'.",
                                    cimglist_instance,
                                    filename);
      do {
        cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s",
                      cimg::temporary_path(),cimg_file_separator,cimg::filenamerand());
        cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001.ppm",filename_tmp._data);
        if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file);
      } while (file);
      cimglist_for(*this,l) {
        cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u.ppm",filename_tmp._data,l + 1);
        CImg<charT>::string(filename_tmp2).move_to(filenames);
        if (_data[l]._depth>1 || _data[l]._spectrum!=3) _data[l].get_resize(-100,-100,1,3).save_pnm(filename_tmp2);
        else _data[l].save_pnm(filename_tmp2);
      }
      cimg_snprintf(command,command._width,"%s -i \"%s_%%6d.ppm\" -vcodec %s -b %uk -r %u -y \"%s\"",
                    cimg::ffmpeg_path(),
                    CImg<charT>::string(filename_tmp)._system_strescape().data(),
                    _codec,bitrate,fps,
                    CImg<charT>::string(filename)._system_strescape().data());
      cimg::system(command);
      file = cimg::std_fopen(filename,"rb");
      if (!file)
        throw CImgIOException(_cimglist_instance
                              "save_ffmpeg_external(): Failed to save file '%s' with external command 'ffmpeg'.",
                              cimglist_instance,
                              filename);

Project: CImg
File: CImg.h

    template<typename t>
    static float ___draw_object3d(const CImg<t>& opacities, const unsigned int n_primitive) {
      return n_primitive<opacities._width?(float)opacities[n_primitive]:1.f;

Project: CImg
File: CImg.h

    **/
    const CImg<T>& save_imagemagick_external(const char *const filename, const unsigned int quality=100) const {
      if (!filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_imagemagick_external(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(0,filename); return *this; }
      if (_depth>1)
        cimg::warn(_cimg_instance
                   "save_other(): File '%s', saving a volumetric image with an external call to "
                   "ImageMagick only writes the first image slice.",
                   cimg_instance,filename);
#ifdef cimg_use_png
#define _cimg_sie_ext1 "png"
#define _cimg_sie_ext2 "png"
#else
#define _cimg_sie_ext1 "pgm"
#define _cimg_sie_ext2 "ppm"
#endif
      CImg<charT> command(1024), filename_tmp(256);
      std::FILE *file;
      do {
        cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s",cimg::temporary_path(),
                      cimg_file_separator,cimg::filenamerand(),_spectrum==1?_cimg_sie_ext1:_cimg_sie_ext2);
        if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file);
      } while (file);
#ifdef cimg_use_png
      save_png(filename_tmp);
#else
      save_pnm(filename_tmp);
#endif
      cimg_snprintf(command,command._width,"%s -quality %u \"%s\" \"%s\"",
                    cimg::imagemagick_path(),quality,
                    CImg<charT>::string(filename_tmp)._system_strescape().data(),
                    CImg<charT>::string(filename)._system_strescape().data());
      cimg::system(command);
      file = cimg::std_fopen(filename,"rb");
      if (!file)
        throw CImgIOException(_cimg_instance
                              "save_imagemagick_external(): Failed to save file '%s' with "
                              "external command 'magick/convert'.",
                              cimg_instance,
                              filename);

      if (file) cimg::fclose(file);
      std::remove(filename_tmp);
      return *this;

Project: CImg
File: CImg.h

    **/
    CImg<T>& load_pandore(const char *const filename) {
      return _load_pandore(0,filename);

Project: CImg
File: CImg.h

      static const char* format_s() { return cimg_fuint64; }

Project: CImg
File: CImg.h


    static int screen_height() {
      Display *const dpy = cimg::X11_attr().display;
      int res = 0;
      if (!dpy) {
        Display *const _dpy = XOpenDisplay(0);
        if (!_dpy)
          throw CImgDisplayException("CImgDisplay::screen_height(): Failed to open X11 display.");
        res = DisplayHeight(_dpy,DefaultScreen(_dpy));
        XCloseDisplay(_dpy);
      } else {

#ifdef cimg_use_xrandr
        if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution)
          res = cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].height;
        else res = DisplayHeight(dpy,DefaultScreen(dpy));
#else
        res = DisplayHeight(dpy,DefaultScreen(dpy));
#endif
      }
      return res;

Project: CImg
File: CImg.h

    template<typename t>
    bool is_sameXZ(const CImg<t>& img) const {
      return is_sameXZ(img._width,img._depth);

Project: CImg
File: CImg.h


    inline double _fibonacci(int exp) {
      double
        base = (1 + std::sqrt(5.))/2,
        result = 1/std::sqrt(5.);
      while (exp) {
        if (exp&1) result*=base;
        exp>>=1;
        base*=base;
      }
      return result;

Project: CImg
File: CImg.h


      static double mp_acos(_cimg_math_parser& mp) {
        return std::acos(_mp_arg(2));

Project: CImg
File: CImg.h

    **/
    const CImg<T>& save_graphicsmagick_external(const char *const filename, const unsigned int quality=100) const {
      if (!filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_graphicsmagick_external(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(0,filename); return *this; }
      if (_depth>1)
        cimg::warn(_cimg_instance
                   "save_other(): File '%s', saving a volumetric image with an external call to "
                   "GraphicsMagick only writes the first image slice.",
                   cimg_instance,filename);

#ifdef cimg_use_png
#define _cimg_sge_ext1 "png"
#define _cimg_sge_ext2 "png"
#else
#define _cimg_sge_ext1 "pgm"
#define _cimg_sge_ext2 "ppm"
#endif
      CImg<charT> command(1024), filename_tmp(256);
      std::FILE *file;
      do {
        cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s",
                      cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),
                      _spectrum==1?_cimg_sge_ext1:_cimg_sge_ext2);
        if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file);
      } while (file);

#ifdef cimg_use_png
      save_png(filename_tmp);
#else
      save_pnm(filename_tmp);
#endif
      cimg_snprintf(command,command._width,"%s convert -quality %u \"%s\" \"%s\"",
                    cimg::graphicsmagick_path(),quality,
                    CImg<charT>::string(filename_tmp)._system_strescape().data(),
                    CImg<charT>::string(filename)._system_strescape().data());
      cimg::system(command);
      file = cimg::std_fopen(filename,"rb");
      if (!file)
        throw CImgIOException(_cimg_instance
                              "save_graphicsmagick_external(): Failed to save file '%s' with external command 'gm'.",
                              cimg_instance,
                              filename);

      if (file) cimg::fclose(file);
      std::remove(filename_tmp);
      return *this;

Project: CImg
File: CImg.h

    }
    inline int mod(const unsigned int x, const unsigned int m) {
      return (int)(x%m);

Project: CImg
File: CImg.h

    template<typename t>
    CImgDisplay& operator=(const CImg<t>& img) {
      return display(img);

Project: CImg
File: CImg.h


      unsigned int scalar1(const mp_func op, const unsigned int arg1) {
        const unsigned int pos =
          arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1) && op!=mp_copy?arg1:scalar();
        CImg<ulongT>::vector((ulongT)op,pos,arg1).move_to(code);
        return pos;

Project: CImg
File: CImg.h

    //! Load image from a PFM file \newinstance.
    static CImg<T> get_load_pfm(const char *const filename) {
      return CImg<T>().load_pfm(filename);

Project: CImg
File: CImg.h

    **/
    operator bool() const {
      return !is_empty();

Project: CImg
File: CImg.h

    **/
    bool is_nan() const {
      if (cimg::type<T>::is_float()) cimg_for(*this,p,T) if (cimg::type<T>::is_nan((float)*p)) return true;
      return false;

Project: CImg
File: CImg.h

      static T inf() { return max(); }

Project: CImg
File: CImg.h

      static signed char max() { return (signed char)((unsigned char)-1>>1); }

Project: CImg
File: CImg.h

    //! Compute distance to a specified value \newinstance.
    CImg<Tfloat> get_distance(const T& value, const unsigned int metric=2) const {
      return CImg<Tfloat>(*this,false).distance((Tfloat)value,metric);

Project: CImg
File: CImg.h

    **/
    CImg<T>& operator>>=(const char *const expression) {
      return *this>>=(+*this)._fill(expression,true,1,0,0,"operator>>=",this);

Project: CImg
File: CImg.h

    **/
    static CImg<T> string(const char *const str, const bool is_last_zero=true, const bool is_shared=false) {
      if (!str) return CImg<T>();
      return CImg<T>(str,(unsigned int)std::strlen(str) + (is_last_zero?1:0),1,1,1,is_shared);

Project: CImg
File: CImg.h


    inline void gesvd(char &JOB, int &M, int &N, float *lapA, int &MN,
                      float *lapS, float *lapU, float *lapV, float *WORK, int &LWORK, int &INFO) {
      sgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO);

Project: CImg
File: CImg.h


      unsigned int vector(const unsigned int siz) { // Insert new vector of specified size in memory
        if (mempos + siz>=mem._width) {
          mem.resize(2*mem._width + siz,1,1,1,0);
          memtype.resize(mem._width,1,1,1,0);
        }
        const unsigned int pos = mempos++;
        mem[pos] = cimg::type<double>::nan();
        memtype[pos] = siz + 1;
        mempos+=siz;
        return pos;

Project: CImg
File: CImg.h

       \param reinit_path Force path to be recalculated (may take some time).
       \return Path containing the program files.
    **/
#if cimg_OS==2
    inline const char* programfiles_path(const char *const user_path, const bool reinit_path) {
      static CImg<char> s_path;
      cimg::mutex(7);
      if (reinit_path) s_path.assign();
      if (user_path) {
        if (!s_path) s_path.assign(1024);
        std::strncpy(s_path,user_path,1023);
      } else if (!s_path) {
        s_path.assign(MAX_PATH);
        *s_path = 0;
        // Note: in the following line, 0x26 = CSIDL_PROGRAM_FILES (not defined on every compiler).
#if !defined(__INTEL_COMPILER)
        if (!SHGetSpecialFolderPathA(0,s_path,0x0026,false)) {
          const char *const pfPath = std::getenv("PROGRAMFILES");
          if (pfPath) std::strncpy(s_path,pfPath,MAX_PATH - 1);
          else std::strcpy(s_path,"C:\\PROGRA~1");
        }
#else
        std::strcpy(s_path,"C:\\PROGRA~1");
#endif

Project: CImg
File: CImg.h


    static void _load_inr_header(std::FILE *file, int out[8], float *const voxel_size) {
      CImg<charT> item(1024), tmp1(64), tmp2(64);
      *item = *tmp1 = *tmp2 = 0;
      out[0] = std::fscanf(file,"%63s",item._data);
      out[0] = out[1] = out[2] = out[3] = out[5] = 1; out[4] = out[6] = out[7] = -1;
      if (cimg::strncasecmp(item,"#INRIMAGE-4#{",13)!=0)
        throw CImgIOException("CImg<%s>::load_inr(): INRIMAGE-4 header not found.",
                              pixel_type());

      while (std::fscanf(file," %63[^\n]%*c",item._data)!=EOF && std::strncmp(item,"##}",3)) {
        cimg_sscanf(item," XDIM%*[^0-9]%d",out);
        cimg_sscanf(item," YDIM%*[^0-9]%d",out + 1);
        cimg_sscanf(item," ZDIM%*[^0-9]%d",out + 2);
        cimg_sscanf(item," VDIM%*[^0-9]%d",out + 3);
        cimg_sscanf(item," PIXSIZE%*[^0-9]%d",out + 6);
        if (voxel_size) {
          cimg_sscanf(item," VX%*[^0-9.+-]%f",voxel_size);
          cimg_sscanf(item," VY%*[^0-9.+-]%f",voxel_size + 1);
          cimg_sscanf(item," VZ%*[^0-9.+-]%f",voxel_size + 2);
        }
        if (cimg_sscanf(item," CPU%*[ =]%s",tmp1._data)) out[7] = cimg::strncasecmp(tmp1,"sun",3)?0:1;
        switch (cimg_sscanf(item," TYPE%*[ =]%s %s",tmp1._data,tmp2._data)) {
        case 0 : break;
        case 2 :
          out[5] = cimg::strncasecmp(tmp1,"unsigned",8)?1:0;
          std::strncpy(tmp1,tmp2,tmp1._width - 1); // fallthrough
        case 1 :
          if (!cimg::strncasecmp(tmp1,"int",3) || !cimg::strncasecmp(tmp1,"fixed",5))  out[4] = 0;
          if (!cimg::strncasecmp(tmp1,"float",5) || !cimg::strncasecmp(tmp1,"double",6)) out[4] = 1;
          if (!cimg::strncasecmp(tmp1,"packed",6)) out[4] = 2;
          if (out[4]>=0) break; // fallthrough
        default :
          throw CImgIOException("CImg<%s>::load_inr(): Invalid pixel type '%s' defined in header.",
                                pixel_type(),
                                tmp2._data);
        }
      }
      if (out[0]<0 || out[1]<0 || out[2]<0 || out[3]<0)
        throw CImgIOException("CImg<%s>::load_inr(): Invalid dimensions (%d,%d,%d,%d) defined in header.",
                              pixel_type(),
                              out[0],out[1],out[2],out[3]);
      if (out[4]<0 || out[5]<0)
        throw CImgIOException("CImg<%s>::load_inr(): Incomplete pixel type defined in header.",
                              pixel_type());
      if (out[6]<0)
        throw CImgIOException("CImg<%s>::load_inr(): Incomplete PIXSIZE field defined in header.",
                              pixel_type());
      if (out[7]<0)
        throw CImgIOException("CImg<%s>::load_inr(): Big/Little Endian coding type undefined in header.",
                              pixel_type());

Project: CImg
File: CImg.h

    //! Load gzipped image file, using external tool 'gunzip' \newinstance.
    static CImg<T> get_load_gzip_external(const char *const filename) {
      return CImg<T>().load_gzip_external(filename);

Project: CImg
File: CImg.h


      static double mp_echo(_cimg_math_parser& mp) {
        const unsigned int nb_args = (unsigned int)(mp.opcode[2] - 3)/2;
        CImgList<charT> _str;
        CImg<charT> it;
        for (unsigned int n = 0; n<nb_args; ++n) {
          const unsigned int siz = (unsigned int)mp.opcode[4 + 2*n];
          if (siz) { // Vector argument -> string
            const double *ptr = &_mp_arg(3 + 2*n) + 1;
            unsigned int l = 0;
            while (l<siz && ptr[l]) ++l;
            CImg<doubleT>(ptr,l,1,1,1,true).move_to(_str);
          } else { // Scalar argument -> number
            it.assign(256);
            cimg_snprintf(it,it._width,"%.17g",_mp_arg(3 + 2*n));
            CImg<charT>::string(it,false,true).move_to(_str);
          }
        }
        CImg(1,1,1,1,0).move_to(_str);
        const CImg<charT> str = _str>'x';
        std::fprintf(cimg::output(),"\n%s",str._data);
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h

    //! Load image from a camera stream, using OpenCV \newinstance.
    static CImg<T> get_load_camera(const unsigned int camera_index=0,
                                   const unsigned int capture_width=0, const unsigned int capture_height=0,
                                   const unsigned int skip_frames=0, const bool release_camera=true) {
      return CImg<T>().load_camera(camera_index,capture_width,capture_height,skip_frames,release_camera);

Project: CImg
File: CImg.h

    **/
    CImg<ucharT> get_serialize(const bool is_compressed=false) const {
      return CImgList<T>(*this,true).get_serialize(is_compressed);

Project: CImg
File: CImg.h

    **/
    static CImg<T> matrix(const T& a0) {
      return vector(a0);

Project: CImg
File: CImg.h

      _cimg_math_parser *mp;

Project: CImg
File: CImg.h

    //! Compute the structure tensor field of an image \newinstance.
    CImg<Tfloat> get_structure_tensors(const bool is_fwbw_scheme=false) const {
      if (is_empty()) return *this;
      CImg<Tfloat> res;
      if (_depth>1) { // 3D
        res.assign(_width,_height,_depth,6,0);
        if (!is_fwbw_scheme) { // Classical central finite differences
          cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1048576 &&
                                                         _spectrum>=2))
          cimg_forC(*this,c) {
            Tfloat
              *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2),
              *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5);
            CImg_3x3x3(I,Tfloat);
            cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) {
              const Tfloat
                ix = (Incc - Ipcc)/2,
                iy = (Icnc - Icpc)/2,
                iz = (Iccn - Iccp)/2;
              *(ptrd0++)+=ix*ix;
              *(ptrd1++)+=ix*iy;
              *(ptrd2++)+=ix*iz;
              *(ptrd3++)+=iy*iy;
              *(ptrd4++)+=iy*iz;
              *(ptrd5++)+=iz*iz;
            }
          }
        } else { // Forward/backward finite differences
          cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1048576 &&
                                                         _spectrum>=2))
          cimg_forC(*this,c) {
            Tfloat
              *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2),
              *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5);
            CImg_3x3x3(I,Tfloat);
            cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) {
              const Tfloat
                ixf = Incc - Iccc, ixb = Iccc - Ipcc,
                iyf = Icnc - Iccc, iyb = Iccc - Icpc,
                izf = Iccn - Iccc, izb = Iccc - Iccp;
              *(ptrd0++)+=(ixf*ixf + ixb*ixb)/2;
              *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4;
              *(ptrd2++)+=(ixf*izf + ixf*izb + ixb*izf + ixb*izb)/4;
              *(ptrd3++)+=(iyf*iyf + iyb*iyb)/2;
              *(ptrd4++)+=(iyf*izf + iyf*izb + iyb*izf + iyb*izb)/4;
              *(ptrd5++)+=(izf*izf + izb*izb)/2;
            }
          }
        }
      } else { // 2D
        res.assign(_width,_height,_depth,3,0);
        if (!is_fwbw_scheme) { // Classical central finite differences
          cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*1048576 &&
                                                         _depth*_spectrum>=2))
          cimg_forC(*this,c) {
            Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2);
            CImg_3x3(I,Tfloat);
            cimg_for3x3(*this,x,y,0,c,I,Tfloat) {
              const Tfloat
                ix = (Inc - Ipc)/2,
                iy = (Icn - Icp)/2;
              *(ptrd0++)+=ix*ix;
              *(ptrd1++)+=ix*iy;
              *(ptrd2++)+=iy*iy;
            }
          }
        } else { // Forward/backward finite differences (version 2)
          cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*1048576 &&
                                                         _depth*_spectrum>=2))
          cimg_forC(*this,c) {
            Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2);
            CImg_3x3(I,Tfloat);
            cimg_for3x3(*this,x,y,0,c,I,Tfloat) {
              const Tfloat
                ixf = Inc - Icc, ixb = Icc - Ipc,
                iyf = Icn - Icc, iyb = Icc - Icp;
              *(ptrd0++)+=(ixf*ixf + ixb*ixb)/2;
              *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4;
              *(ptrd2++)+=(iyf*iyf + iyb*iyb)/2;
            }
          }
        }
      }
      return res;

Project: CImg
File: CImg.h

    **/
    static const CImg<Tuchar>& default_LUT256() {
      static CImg<Tuchar> colormap;
      cimg::mutex(8);
      if (!colormap) {
        colormap.assign(1,256,1,3);
        for (unsigned int index = 0, r = 16; r<256; r+=32)
          for (unsigned int g = 16; g<256; g+=32)
            for (unsigned int b = 32; b<256; b+=64) {
              colormap(0,index,0) = (Tuchar)r;
              colormap(0,index,1) = (Tuchar)g;
              colormap(0,index++,2) = (Tuchar)b;
            }
      }
      cimg::mutex(8,0);
      return colormap;

Project: CImg
File: CImg.h

    //! Dilate image by a rectangular structuring element of specified size \newinstance.
    CImg<T> get_dilate(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) const {
      return (+*this).dilate(sx,sy,sz);

Project: CImg
File: CImg.h

    **/
    bool is_sameXYZ(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z) const {
      return is_sameXY(size_x,size_y) && _depth==size_z;

Project: CImg
File: CImg.h

    inline int _vsnprintf(char *const s, const size_t size, const char *const format, va_list ap) {
      int result = -1;
      cimg::mutex(6);
      if (size) result = _vsnprintf_s(s,size,_TRUNCATE,format,ap);
      if (result==-1) result = _vscprintf(format,ap);
      cimg::mutex(6,0);
      return result;
    }

Project: CImg
File: CImg.h

    //! Convert pixel values from RGB to HSI color spaces.
    CImg<T>& RGBtoHSI() {
      if (_spectrum!=3)
        throw CImgInstanceException(_cimg_instance
                                    "RGBtoHSI(): Instance is not a RGB image.",
                                    cimg_instance);

      T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
      const longT whd = (longT)width()*height()*depth();
      cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256))
      for (longT N = 0; N<whd; ++N) {
        const Tfloat
          R = (Tfloat)p1[N],
          G = (Tfloat)p2[N],
          B = (Tfloat)p3[N],
          m = cimg::min(R,G,B),
          M = cimg::max(R,G,B),
          C = M - m,
          sum = R + G + B,
          H = 60*(C==0?0:M==R?cimg::mod((G - B)/C,(Tfloat)6):M==G?(B - R)/C + 2:(R - G)/C + 4),
          S = sum<=0?0:1 - 3*m/sum,
          I = sum/(3*255);
        p1[N] = (T)H;
        p2[N] = (T)S;
        p3[N] = (T)I;
      }
      return *this;

Project: CImg
File: CImg.h

      static const char* string() { static const char *const s = "long double"; return s; }

Project: CImg
File: CImg.h

    template<typename tp, typename tc, typename tt, typename tx>
    const CImg<T>& texturize_object3d(CImgList<tp>& primitives, CImgList<tc>& colors,
                                      const CImg<tt>& texture, const CImg<tx>& coords=CImg<tx>::const_empty()) const {
      if (is_empty()) return *this;
      if (_height!=3)
        throw CImgInstanceException(_cimg_instance
                                    "texturize_object3d(): image instance is not a set of 3D points.",
                                    cimg_instance);
      if (coords && (coords._width!=_width || coords._height!=2))
        throw CImgArgumentException(_cimg_instance
                                    "texturize_object3d(): Invalid specified texture coordinates (%u,%u,%u,%u,%p).",
                                    cimg_instance,
                                    coords._width,coords._height,coords._depth,coords._spectrum,coords._data);
      CImg<intT> _coords;
      if (!coords) { // If no texture coordinates specified, do a default XY-projection
        _coords.assign(_width,2);
        float
          xmin, xmax = (float)get_shared_row(0).max_min(xmin),
          ymin, ymax = (float)get_shared_row(1).max_min(ymin),
          dx = xmax>xmin?xmax-xmin:1,
          dy = ymax>ymin?ymax-ymin:1;
        cimg_forX(*this,p) {
          _coords(p,0) = (int)(((*this)(p,0) - xmin)*texture._width/dx);
          _coords(p,1) = (int)(((*this)(p,1) - ymin)*texture._height/dy);
        }
      } else _coords = coords;

      int texture_ind = -1;
      cimglist_for(primitives,l) {
        CImg<tp> &p = primitives[l];
        const unsigned int siz = p.size();
        switch (siz) {
        case 1 : { // Point
          const unsigned int i0 = (unsigned int)p[0];
          const int x0 = _coords(i0,0), y0 = _coords(i0,1);
          texture.get_vector_at(x0<=0?0:x0>=texture.width()?texture.width() - 1:x0,
                                y0<=0?0:y0>=texture.height()?texture.height() - 1:y0).move_to(colors[l]);
        } break;
        case 2 : case 6 : { // Line
          const unsigned int i0 = (unsigned int)p[0], i1 = (unsigned int)p[1];
          const int
            x0 = _coords(i0,0), y0 = _coords(i0,1),
            x1 = _coords(i1,0), y1 = _coords(i1,1);
          if (texture_ind<0) colors[texture_ind=l].assign(texture,false);
          else colors[l].assign(colors[texture_ind],true);
          CImg<tp>::vector(i0,i1,x0,y0,x1,y1).move_to(p);
        } break;
        case 3 : case 9 : { // Triangle
          const unsigned int i0 = (unsigned int)p[0], i1 = (unsigned int)p[1], i2 = (unsigned int)p[2];
          const int
            x0 = _coords(i0,0), y0 = _coords(i0,1),
            x1 = _coords(i1,0), y1 = _coords(i1,1),
            x2 = _coords(i2,0), y2 = _coords(i2,1);
          if (texture_ind<0) colors[texture_ind=l].assign(texture,false);
          else colors[l].assign(colors[texture_ind],true);
          CImg<tp>::vector(i0,i1,i2,x0,y0,x1,y1,x2,y2).move_to(p);
        } break;
        case 4 : case 12 : { // Quadrangle
          const unsigned int
            i0 = (unsigned int)p[0], i1 = (unsigned int)p[1], i2 = (unsigned int)p[2], i3 = (unsigned int)p[3];
          const int
            x0 = _coords(i0,0), y0 = _coords(i0,1),
            x1 = _coords(i1,0), y1 = _coords(i1,1),
            x2 = _coords(i2,0), y2 = _coords(i2,1),
            x3 = _coords(i3,0), y3 = _coords(i3,1);
          if (texture_ind<0) colors[texture_ind=l].assign(texture,false);
          else colors[l].assign(colors[texture_ind],true);
          CImg<tp>::vector(i0,i1,i2,i3,x0,y0,x1,y1,x2,y2,x3,y3).move_to(p);
        } break;
        }
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    CImgList<Tfloat> get_FFT(const bool is_inverse=false) const {
      CImgList<Tfloat> res(*this,CImg<Tfloat>());
      CImg<Tfloat>::FFT(res[0],res[1],is_inverse);
      return res;

Project: CImg
File: CImg.h

      bool is_exit = false;
      return _display(disp,title,0,display_info,axis,align,XYZ,exit_on_anykey,0,true,is_exit);
    }

    const CImgList<T>& _display(CImgDisplay &disp, const char *const title, const CImgList<charT> *const titles,
                                const bool display_info, const char axis, const float align, unsigned int *const XYZ,
                                const bool exit_on_anykey, const unsigned int orig, const bool is_first_call,
                                bool &is_exit) const {
      if (is_empty())
        throw CImgInstanceException(_cimglist_instance
                                    "display(): Empty instance.",
                                    cimglist_instance);
      if (!disp) {
        if (axis=='x') {
          unsigned int sum_width = 0, max_height = 0;
          cimglist_for(*this,l) {
            const CImg<T> &img = _data[l];
            const unsigned int
              w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false),
              h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true);
            sum_width+=w;
            if (h>max_height) max_height = h;
          }
          disp.assign(cimg_fitscreen(sum_width,max_height,1),title?title:titles?titles->__display()._data:0,1);
        } else {
          unsigned int max_width = 0, sum_height = 0;
          cimglist_for(*this,l) {
            const CImg<T> &img = _data[l];
            const unsigned int
              w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false),
              h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true);
            if (w>max_width) max_width = w;
            sum_height+=h;
          }
          disp.assign(cimg_fitscreen(max_width,sum_height,1),title?title:titles?titles->__display()._data:0,1);
        }
        if (!title && !titles) disp.set_title("CImgList<%s> (%u)",pixel_type(),_width);
      } else if (title) disp.set_title("%s",title);
      else if (titles) disp.set_title("%s",titles->__display()._data);
      const CImg<char> dtitle = CImg<char>::string(disp.title());
      if (display_info) print(disp.title());
      disp.show().flush();

      if (_width==1) {
        const unsigned int dw = disp._width, dh = disp._height;
        if (!is_first_call)
          disp.resize(cimg_fitscreen(_data[0]._width,_data[0]._height,_data[0]._depth),false);
        disp.set_title("%s (%ux%ux%ux%u)",
                       dtitle.data(),_data[0]._width,_data[0]._height,_data[0]._depth,_data[0]._spectrum);
        _data[0]._display(disp,0,false,XYZ,exit_on_anykey,!is_first_call);
        if (disp.key()) is_exit = true;
        disp.resize(cimg_fitscreen(dw,dh,1),false).set_title("%s",dtitle.data());
      } else {
        bool disp_resize = !is_first_call;
        while (!disp.is_closed() && !is_exit) {
          const CImg<intT> s = _select(disp,0,true,axis,align,exit_on_anykey,orig,disp_resize,!is_first_call,true);
          disp_resize = true;
          if (s[0]<0 && !disp.wheel()) { // No selections done
            if (disp.button()&2) { disp.flush(); break; }
            is_exit = true;
          } else if (disp.wheel()) { // Zoom in/out
            const int wheel = disp.wheel();
            disp.set_wheel();
            if (!is_first_call && wheel<0) break;
            if (wheel>0 && _width>=4) {
              const unsigned int
                delta = std::max(1U,(unsigned int)cimg::round(0.3*_width)),
                ind0 = (unsigned int)std::max(0,s[0] - (int)delta),
                ind1 = (unsigned int)std::min(width() - 1,s[0] + (int)delta);
              if ((ind0!=0 || ind1!=_width - 1) && ind1 - ind0>=3) {
                const CImgList<T> sublist = get_shared_images(ind0,ind1);
                CImgList<charT> t_sublist;
                if (titles) t_sublist = titles->get_shared_images(ind0,ind1);
                sublist._display(disp,0,titles?&t_sublist:0,false,axis,align,XYZ,exit_on_anykey,
                                 orig + ind0,false,is_exit);
              }
            }
          } else if (s[0]!=0 || s[1]!=width() - 1) {
            const CImgList<T> sublist = get_shared_images(s[0],s[1]);
            CImgList<charT> t_sublist;
            if (titles) t_sublist = titles->get_shared_images(s[0],s[1]);
            sublist._display(disp,0,titles?&t_sublist:0,false,axis,align,XYZ,exit_on_anykey,
                             orig + s[0],false,is_exit);
          }
          disp.set_title("%s",dtitle.data());

Project: CImg
File: CImg.h


      static double mp_ioff(_cimg_math_parser& mp) {
        const unsigned int
          boundary_conditions = (unsigned int)_mp_arg(3);
        const CImg<T> &img = mp.imgin;
        const longT
          off = (longT)_mp_arg(2),
          whds = (longT)img.size();
        if (off>=0 && off<whds) return (double)img[off];
        if (img._data) switch (boundary_conditions) {
          case 3 : { // Mirror
            const longT whds2 = 2*whds, moff = cimg::mod(off,whds2);
            return (double)img[moff<whds?moff:whds2 - moff - 1];
          }
          case 2 : // Periodic
            return (double)img[cimg::mod(off,whds)];
          case 1 : // Neumann
            return (double)img[off<0?0:whds - 1];
          default : // Dirichlet
            return 0;
          }
        return 0;

Project: CImg
File: CImg.h

      return CImgList<T>().load_yuv(file,size_x,size_y,chroma_subsampling,
                                    first_frame,last_frame,step_frame,yuv2rgb);
    }

    CImgList<T>& _load_yuv(std::FILE *const file, const char *const filename,
			   const unsigned int size_x, const unsigned int size_y,
                           const unsigned int chroma_subsampling,
			   const unsigned int first_frame, const unsigned int last_frame,
			   const unsigned int step_frame, const bool yuv2rgb) {
      if (!filename && !file)
        throw CImgArgumentException(_cimglist_instance
                                    "load_yuv(): Specified filename is (null).",
                                    cimglist_instance);
      if (chroma_subsampling!=420 && chroma_subsampling!=422 && chroma_subsampling!=444)
        throw CImgArgumentException(_cimglist_instance
                                    "load_yuv(): Specified chroma subsampling '%u' is invalid, for file '%s'.",
                                    cimglist_instance,
                                    chroma_subsampling,filename?filename:"(FILE*)");
      const unsigned int
        cfx = chroma_subsampling==420 || chroma_subsampling==422?2:1,
        cfy = chroma_subsampling==420?2:1,
	nfirst_frame = first_frame<last_frame?first_frame:last_frame,
	nlast_frame = first_frame<last_frame?last_frame:first_frame,
	nstep_frame = step_frame?step_frame:1;

      if (!size_x || !size_y || size_x%cfx || size_y%cfy)
        throw CImgArgumentException(_cimglist_instance
                                    "load_yuv(): Specified dimensions (%u,%u) are invalid, for file '%s'.",
                                    cimglist_instance,
                                    size_x,size_y,filename?filename:"(FILE*)");

      CImg<ucharT> YUV(size_x,size_y,1,3), UV(size_x/cfx,size_y/cfy,1,2);
      std::FILE *const nfile = file?file:cimg::fopen(filename,"rb");
      bool stop_flag = false;
      int err;
      if (nfirst_frame) {
        err = cimg::fseek(nfile,(uint64T)nfirst_frame*(YUV._width*YUV._height + 2*UV._width*UV._height),SEEK_CUR);
        if (err) {
          if (!file) cimg::fclose(nfile);
          throw CImgIOException(_cimglist_instance
                                "load_yuv(): File '%s' doesn't contain frame number %u.",
                                cimglist_instance,
                                filename?filename:"(FILE*)",nfirst_frame);
        }
      }
      unsigned int frame;
      for (frame = nfirst_frame; !stop_flag && frame<=nlast_frame; frame+=nstep_frame) {
        YUV.get_shared_channel(0).fill(0);
        // *TRY* to read the luminance part, do not replace by cimg::fread!
        err = (int)std::fread((void*)(YUV._data),1,(size_t)YUV._width*YUV._height,nfile);
        if (err!=(int)(YUV._width*YUV._height)) {
          stop_flag = true;
          if (err>0)
            cimg::warn(_cimglist_instance
                       "load_yuv(): File '%s' contains incomplete data or given image dimensions "
                       "(%u,%u) are incorrect.",
                       cimglist_instance,
                       filename?filename:"(FILE*)",size_x,size_y);
        } else {
          UV.fill(0);
          // *TRY* to read the luminance part, do not replace by cimg::fread!
          err = (int)std::fread((void*)(UV._data),1,(size_t)UV.size(),nfile);
          if (err!=(int)(UV.size())) {
            stop_flag = true;
            if (err>0)
              cimg::warn(_cimglist_instance
                         "load_yuv(): File '%s' contains incomplete data or given image dimensions "
                         "(%u,%u) are incorrect.",
                         cimglist_instance,
                         filename?filename:"(FILE*)",size_x,size_y);
          } else {
            const ucharT *ptrs1 = UV._data, *ptrs2 = UV.data(0,0,0,1);
            ucharT *ptrd1 = YUV.data(0,0,0,1), *ptrd2 = YUV.data(0,0,0,2);
            const unsigned int wd = YUV._width;
            switch (chroma_subsampling) {
            case 420 :
              cimg_forY(UV,y) {
                cimg_forX(UV,x) {
                  const ucharT U = *(ptrs1++), V = *(ptrs2++);
                  ptrd1[wd] = U; *(ptrd1)++ = U;
                  ptrd1[wd] = U; *(ptrd1)++ = U;
                  ptrd2[wd] = V; *(ptrd2)++ = V;
                  ptrd2[wd] = V; *(ptrd2)++ = V;
                }
                ptrd1+=wd; ptrd2+=wd;
              }
              break;
            case 422 :
              cimg_forXY(UV,x,y) {
                const ucharT U = *(ptrs1++), V = *(ptrs2++);
                *(ptrd1++) = U; *(ptrd1++) = U;
                *(ptrd2++) = V; *(ptrd2++) = V;
              }
              break;
            default :
              YUV.draw_image(0,0,0,1,UV);
            }
            if (yuv2rgb) YUV.YCbCrtoRGB();
            insert(YUV);
            if (nstep_frame>1) cimg::fseek(nfile,(uint64T)(nstep_frame - 1)*(size_x*size_y + size_x*size_y/2),SEEK_CUR);
          }
        }
      }
      if (is_empty())
        throw CImgIOException(_cimglist_instance
                              "load_yuv() : Missing data in file '%s'.",
                              cimglist_instance,
                              filename?filename:"(FILE*)");
      if (stop_flag && nlast_frame!=~0U && frame!=nlast_frame)
        cimg::warn(_cimglist_instance
                   "load_yuv(): Frame %d not reached since only %u frames were found in file '%s'.",
                   cimglist_instance,
                   nlast_frame,frame - 1,filename?filename:"(FILE*)");

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& draw_image(const int x0, const int y0, const int z0, const int c0,
                        const CImg<t>& sprite, const float opacity=1) {
      if (is_empty() || !sprite) return *this;
      if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,opacity);
      if (x0==0 && y0==0 && z0==0 && c0==0 && is_sameXYZC(sprite) && opacity>=1 && !is_shared())
        return assign(sprite,false);
      const bool bx = (x0<0), by = (y0<0), bz = (z0<0), bc = (c0<0);
      const int
        lX = sprite.width() - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0) + (bx?x0:0),
        lY = sprite.height() - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0) + (by?y0:0),
        lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0),
        lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0);
      const t
        *ptrs = sprite._data +
        (bx?-x0:0) +
        (by?-y0*(ulongT)sprite.width():0) +
        (bz?-z0*(ulongT)sprite.width()*sprite.height():0) +
        (bc?-c0*(ulongT)sprite.width()*sprite.height()*sprite.depth():0);
      const ulongT
        offX = (ulongT)_width - lX,
        soffX = (ulongT)sprite._width - lX,
        offY = (ulongT)_width*(_height - lY),
        soffY = (ulongT)sprite._width*(sprite._height - lY),
        offZ = (ulongT)_width*_height*(_depth - lZ),
        soffZ = (ulongT)sprite._width*sprite._height*(sprite._depth - lZ);
      const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f);
      if (lX>0 && lY>0 && lZ>0 && lC>0) {
        T *ptrd = data(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,c0<0?0:c0);
        for (int v = 0; v<lC; ++v) {
          for (int z = 0; z<lZ; ++z) {
            for (int y = 0; y<lY; ++y) {
              if (opacity>=1) for (int x = 0; x<lX; ++x) *(ptrd++) = (T)*(ptrs++);
              else for (int x = 0; x<lX; ++x) { *ptrd = (T)(nopacity*(*(ptrs++)) + *ptrd*copacity); ++ptrd; }
              ptrd+=offX; ptrs+=soffX;
            }
            ptrd+=offY; ptrs+=soffY;
          }
          ptrd+=offZ; ptrs+=soffZ;
        }
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<t> _permute_axes(const char *const order, const t&) const {
      if (is_empty() || !order) return CImg<t>(*this,false);
      CImg<t> res;
      const T* ptrs = _data;
      unsigned char s_code[4] = { 0,1,2,3 }, n_code[4] = { 0 };
      for (unsigned int l = 0; order[l]; ++l) {
        int c = cimg::lowercase(order[l]);
        if (c!='x' && c!='y' && c!='z' && c!='c') { *s_code = 4; break; }
        else { ++n_code[c%=4]; s_code[l] = c; }
      }
      if (*order && *s_code<4 && *n_code<=1 && n_code[1]<=1 && n_code[2]<=1 && n_code[3]<=1) {
        const unsigned int code = (s_code[0]<<12) | (s_code[1]<<8) | (s_code[2]<<4) | (s_code[3]);
        ulongT wh, whd;
        switch (code) {
        case 0x0123 : // xyzc
          return +*this;
        case 0x0132 : // xycz
          res.assign(_width,_height,_spectrum,_depth);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(x,y,c,z,wh,whd) = (t)*(ptrs++);
          break;
        case 0x0213 : // xzyc
          res.assign(_width,_depth,_height,_spectrum);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(x,z,y,c,wh,whd) = (t)*(ptrs++);
          break;
        case 0x0231 : // xzcy
          res.assign(_width,_depth,_spectrum,_height);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(x,z,c,y,wh,whd) = (t)*(ptrs++);
          break;
        case 0x0312 : // xcyz
          res.assign(_width,_spectrum,_height,_depth);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(x,c,y,z,wh,whd) = (t)*(ptrs++);
          break;
        case 0x0321 : // xczy
          res.assign(_width,_spectrum,_depth,_height);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(x,c,z,y,wh,whd) = (t)*(ptrs++);
          break;
        case 0x1023 : // yxzc
          res.assign(_height,_width,_depth,_spectrum);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(y,x,z,c,wh,whd) = (t)*(ptrs++);
          break;
        case 0x1032 : // yxcz
          res.assign(_height,_width,_spectrum,_depth);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(y,x,c,z,wh,whd) = (t)*(ptrs++);
          break;
        case 0x1203 : // yzxc
          res.assign(_height,_depth,_width,_spectrum);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(y,z,x,c,wh,whd) = (t)*(ptrs++);
          break;
        case 0x1230 : // yzcx
          res.assign(_height,_depth,_spectrum,_width);
          switch (_width) {
          case 1 : {
            t *ptr_r = res.data(0,0,0,0);
            for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) {
              *(ptr_r++) = (t)*(ptrs++);
            }
          } break;
          case 2 : {
            t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1);
            for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) {
              *(ptr_r++) = (t)ptrs[0];
              *(ptr_g++) = (t)ptrs[1];
              ptrs+=2;
            }
          } break;
          case 3 : { // Optimization for the classical conversion from interleaved RGB to planar RGB
            t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), *ptr_b = res.data(0,0,0,2);
            for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) {
              *(ptr_r++) = (t)ptrs[0];
              *(ptr_g++) = (t)ptrs[1];
              *(ptr_b++) = (t)ptrs[2];
              ptrs+=3;
            }
          } break;
          case 4 : { // Optimization for the classical conversion from interleaved RGBA to planar RGBA
            t
              *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1),
              *ptr_b = res.data(0,0,0,2), *ptr_a = res.data(0,0,0,3);
            for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) {
              *(ptr_r++) = (t)ptrs[0];
              *(ptr_g++) = (t)ptrs[1];
              *(ptr_b++) = (t)ptrs[2];
              *(ptr_a++) = (t)ptrs[3];
              ptrs+=4;
            }
          } break;
          default : {
            wh = (ulongT)res._width*res._height; whd = wh*res._depth;
            cimg_forXYZC(*this,x,y,z,c) res(y,z,c,x,wh,whd) = *(ptrs++);
            return res;
          }
          }
          break;
        case 0x1302 : // ycxz
          res.assign(_height,_spectrum,_width,_depth);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(y,c,x,z,wh,whd) = (t)*(ptrs++);
          break;
        case 0x1320 : // yczx
          res.assign(_height,_spectrum,_depth,_width);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(y,c,z,x,wh,whd) = (t)*(ptrs++);
          break;
        case 0x2013 : // zxyc
          res.assign(_depth,_width,_height,_spectrum);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(z,x,y,c,wh,whd) = (t)*(ptrs++);
          break;
        case 0x2031 : // zxcy
          res.assign(_depth,_width,_spectrum,_height);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(z,x,c,y,wh,whd) = (t)*(ptrs++);
          break;
        case 0x2103 : // zyxc
          res.assign(_depth,_height,_width,_spectrum);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(z,y,x,c,wh,whd) = (t)*(ptrs++);
          break;
        case 0x2130 : // zycx
          res.assign(_depth,_height,_spectrum,_width);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(z,y,c,x,wh,whd) = (t)*(ptrs++);
          break;
        case 0x2301 : // zcxy
          res.assign(_depth,_spectrum,_width,_height);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(z,c,x,y,wh,whd) = (t)*(ptrs++);
          break;
        case 0x2310 : // zcyx
          res.assign(_depth,_spectrum,_height,_width);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(z,c,y,x,wh,whd) = (t)*(ptrs++);
          break;
        case 0x3012 : // cxyz
          res.assign(_spectrum,_width,_height,_depth);
          switch (_spectrum) {
          case 1 : {
            const T *ptr_r = data(0,0,0,0);
            t *ptrd = res._data;
            for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) *(ptrd++) = (t)*(ptr_r++);
          } break;
          case 2 : {
            const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1);
            t *ptrd = res._data;
            for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) {
              ptrd[0] = (t)*(ptr_r++);
              ptrd[1] = (t)*(ptr_g++);
              ptrd+=2;
            }
          } break;
          case 3 : { // Optimization for the classical conversion from planar RGB to interleaved RGB
            const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2);
            t *ptrd = res._data;
            for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) {
              ptrd[0] = (t)*(ptr_r++);
              ptrd[1] = (t)*(ptr_g++);
              ptrd[2] = (t)*(ptr_b++);
              ptrd+=3;
            }
          } break;
          case 4 : { // Optimization for the classical conversion from planar RGBA to interleaved RGBA
            const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3);
            t *ptrd = res._data;
            for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) {
              ptrd[0] = (t)*(ptr_r++);
              ptrd[1] = (t)*(ptr_g++);
              ptrd[2] = (t)*(ptr_b++);
              ptrd[3] = (t)*(ptr_a++);
              ptrd+=4;
            }
          } break;
          default : {
            wh = (ulongT)res._width*res._height; whd = wh*res._depth;
            cimg_forXYZC(*this,x,y,z,c) res(c,x,y,z,wh,whd) = (t)*(ptrs++);
          }
          }
          break;
        case 0x3021 : // cxzy
          res.assign(_spectrum,_width,_depth,_height);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(c,x,z,y,wh,whd) = (t)*(ptrs++);
          break;
        case 0x3102 : // cyxz
          res.assign(_spectrum,_height,_width,_depth);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(c,y,x,z,wh,whd) = (t)*(ptrs++);
          break;
        case 0x3120 : // cyzx
          res.assign(_spectrum,_height,_depth,_width);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(c,y,z,x,wh,whd) = (t)*(ptrs++);
          break;
        case 0x3201 : // czxy
          res.assign(_spectrum,_depth,_width,_height);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(c,z,x,y,wh,whd) = (t)*(ptrs++);
          break;
        case 0x3210 : // czyx
          res.assign(_spectrum,_depth,_height,_width);
          wh = (ulongT)res._width*res._height; whd = wh*res._depth;
          cimg_forXYZC(*this,x,y,z,c) res(c,z,y,x,wh,whd) = (t)*(ptrs++);
          break;
        }
      }
      if (!res)
        throw CImgArgumentException(_cimg_instance
                                    "permute_axes(): Invalid specified permutation '%s'.",
                                    cimg_instance,
                                    order);
      return res;

Project: CImg
File: CImg.h

    **/
    CImg<T>& load_imagemagick_external(const char *const filename) {
      if (!filename)
        throw CImgArgumentException(_cimg_instance
                                    "load_imagemagick_external(): Specified filename is (null).",
                                    cimg_instance);
      cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists
      CImg<charT> command(1024), filename_tmp(256);
      std::FILE *file = 0;
      const CImg<charT> s_filename = CImg<charT>::string(filename)._system_strescape();
#if cimg_OS==1
      if (!cimg::system("which convert")) {
        cimg_snprintf(command,command._width,"%s%s \"%s\" pnm:-",
                      cimg::imagemagick_path(),
                      !cimg::strcasecmp(cimg::split_filename(filename),"pdf")?" -density 400x400":"",
                      s_filename.data());
        file = popen(command,"r");
        if (file) {
          const unsigned int omode = cimg::exception_mode();
          cimg::exception_mode(0);
          try { load_pnm(file); } catch (...) {
            pclose(file);
            cimg::exception_mode(omode);
            throw CImgIOException(_cimg_instance
                                  "load_imagemagick_external(): Failed to load file '%s' with "
                                  "external command 'magick/convert'.",
                                  cimg_instance,
                                  filename);
          }
          pclose(file);
          return *this;
        }
      }
#endif
      do {
        cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.pnm",
                      cimg::temporary_path(),cimg_file_separator,cimg::filenamerand());
        if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file);
      } while (file);
      cimg_snprintf(command,command._width,"%s%s \"%s\" \"%s\"",
                    cimg::imagemagick_path(),
                    !cimg::strcasecmp(cimg::split_filename(filename),"pdf")?" -density 400x400":"",
                    s_filename.data(),CImg<charT>::string(filename_tmp)._system_strescape().data());
      cimg::system(command,cimg::imagemagick_path());
      if (!(file=cimg::std_fopen(filename_tmp,"rb"))) {
        cimg::fclose(cimg::fopen(filename,"r"));
        throw CImgIOException(_cimg_instance
                              "load_imagemagick_external(): Failed to load file '%s' with "
                              "external command 'magick/convert'.",
                              cimg_instance,
                              filename);

      } else cimg::fclose(file);
      load_pnm(filename_tmp);
      std::remove(filename_tmp);
      return *this;

Project: CImg
File: CImg.h

    **/
    CImgList(const unsigned int n, const unsigned int width, const unsigned int height,
             const unsigned int depth, const unsigned int spectrum, const T& val):
      _width(0),_allocated_width(0),_data(0) {
      assign(n);
      cimglist_apply(*this,assign)(width,height,depth,spectrum,val);

Project: CImg
File: CImg.h

    **/
    CImg<T>& draw_plasma(const float alpha=1, const float beta=0, const unsigned int scale=8) {
      if (is_empty()) return *this;
      const int w = width(), h = height();
      const Tfloat m = (Tfloat)cimg::type<T>::min(), M = (Tfloat)cimg::type<T>::max();
      ulongT rng = (cimg::_rand(),cimg::rng());
      cimg_forZC(*this,z,c) {
        CImg<T> ref = get_shared_slice(z,c);
        for (int delta = 1<<std::min(scale,31U); delta>1; delta>>=1) {
          const int delta2 = delta>>1;
          const float r = alpha*delta + beta;

          // Square step.
          for (int y0 = 0; y0<h; y0+=delta)
            for (int x0 = 0; x0<w; x0+=delta) {
              const int x1 = (x0 + delta)%w, y1 = (y0 + delta)%h, xc = (x0 + delta2)%w, yc = (y0 + delta2)%h;
              const Tfloat val = (Tfloat)(0.25f*(ref(x0,y0) + ref(x0,y1) + ref(x0,y1) + ref(x1,y1)) +
                                          r*cimg::rand(-1,1,&rng));
              ref(xc,yc) = (T)(val<m?m:val>M?M:val);
            }

          // Diamond steps.
          for (int y = -delta2; y<h; y+=delta)
            for (int x0=0; x0<w; x0+=delta) {
              const int y0 = cimg::mod(y,h), x1 = (x0 + delta)%w, y1 = (y + delta)%h,
                xc = (x0 + delta2)%w, yc = (y + delta2)%h;
              const Tfloat val = (Tfloat)(0.25f*(ref(xc,y0) + ref(x0,yc) + ref(xc,y1) + ref(x1,yc)) +
                                          r*cimg::rand(-1,1,&rng));
              ref(xc,yc) = (T)(val<m?m:val>M?M:val);
            }
          for (int y0 = 0; y0<h; y0+=delta)
            for (int x = -delta2; x<w; x+=delta) {
              const int x0 = cimg::mod(x,w), x1 = (x + delta)%w, y1 = (y0 + delta)%h,
                xc = (x + delta2)%w, yc = (y0 + delta2)%h;
              const Tfloat val = (Tfloat)(0.25f*(ref(xc,y0) + ref(x0,yc) + ref(xc,y1) + ref(x1,yc)) +
                                          r*cimg::rand(-1,1,&rng));
              ref(xc,yc) = (T)(val<m?m:val>M?M:val);
            }
          for (int y = -delta2; y<h; y+=delta)
            for (int x = -delta2; x<w; x+=delta) {
              const int x0 = cimg::mod(x,w), y0 = cimg::mod(y,h), x1 = (x + delta)%w, y1 = (y + delta)%h,
                xc = (x + delta2)%w, yc = (y + delta2)%h;
              const Tfloat val = (Tfloat)(0.25f*(ref(xc,y0) + ref(x0,yc) + ref(xc,y1) + ref(x1,yc)) +
                                          r*cimg::rand(-1,1,&rng));
                ref(xc,yc) = (T)(val<m?m:val>M?M:val);
            }
        }
      }
      cimg::srand(rng);
      return *this;

Project: CImg
File: CImg.h

    //! Convert pixel values from CMY to CMYK color spaces.
    CImg<T>& CMYtoCMYK() {
      return get_CMYtoCMYK().move_to(*this);

Project: CImg
File: CImg.h

    //! Access to a pixel value, using Neumann boundary conditions for the X,Y and Z-coordinates \const.
    const T& atXYZ(const int x, const int y, const int z, const int c=0) const {
      if (is_empty())
        throw CImgInstanceException(_cimg_instance
                                    "atXYZ(): Empty instance.",
                                    cimg_instance);
      return _atXYZ(x,y,z,c);

Project: CImg
File: CImg.h

    //! Append two images along specified axis \specialization.
    CImg<T>& append(const CImg<T>& img, const char axis='x', const float align=0) {
      if (is_empty()) return assign(img,false);
      if (!img) return *this;
      return CImgList<T>(*this,img,true).get_append(axis,align).move_to(*this);

Project: CImg
File: CImg.h

    //! Load image from a TIFF file \newinstance.
    static CImg<T> get_load_tiff(const char *const filename,
				 const unsigned int first_frame=0, const unsigned int last_frame=~0U,
				 const unsigned int step_frame=1,
                                 float *const voxel_size=0,
                                 CImg<charT> *const description=0) {
      return CImg<T>().load_tiff(filename,first_frame,last_frame,step_frame,voxel_size,description);

Project: CImg
File: CImg.h

    **/
    bool is_resized() const {
      return _is_resized;

Project: CImg
File: CImg.h

      // If 'N' is not zero, it also restricts the vectors to be of size N only.
      void check_type(const unsigned int arg, const unsigned int n_arg,
                      const unsigned int mode, const unsigned int N,
                      char *const ss, char *const se, const char saved_char) {
        const bool
          is_scalar = _cimg_mp_is_scalar(arg),
          is_vector = _cimg_mp_is_vector(arg) && (!N || _cimg_mp_size(arg)==N);
        bool cond = false;
        if (mode&1) cond|=is_scalar;
        if (mode&2) cond|=is_vector;
        if (!cond) {
          const char *s_arg;
          if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand ":"Right-hand ";
          else s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ":
                 n_arg==4?"Fourth ":n_arg==5?"Fifth ":n_arg==6?"Sixth ":n_arg==7?"Seventh ":n_arg==8?"Eighth":
                 n_arg==9?"Ninth":"One of the ";
          CImg<charT> sb_type(32);
          if (mode==1) cimg_snprintf(sb_type,sb_type._width,"'scalar'");
          else if (mode==2) {
            if (N) cimg_snprintf(sb_type,sb_type._width,"'vector%u'",N);
            else cimg_snprintf(sb_type,sb_type._width,"'vector'");
          } else {
            if (N) cimg_snprintf(sb_type,sb_type._width,"'scalar' or 'vector%u'",N);
            else cimg_snprintf(sb_type,sb_type._width,"'scalar' or 'vector'");
          }
          *se = saved_char;
          char *const s0 = ss - 4>expr._data?ss - 4:expr._data;
          cimg::strellipsize(s0,64);
          throw CImgArgumentException("[" cimg_appname "_math_parser] "
                                      "CImg<%s>::%s: %s%s %s%s has invalid type '%s' (should be %s), "
                                      "in expression '%s%s%s'.",
                                      pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
                                      s_arg,*s_op=='F'?(*s_arg?"argument":"Argument"):(*s_arg?"operand":"Operand"),
                                      s_type(arg)._data,sb_type._data,
                                      s0!=expr._data?"...":"",s0,se<&expr.back()?"...":"");
        }

Project: CImg
File: CImg.h

    //! Wait for any event occuring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp8.
    static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5,
                     CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8) {
      disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event =
        disp6._is_event = disp7._is_event = disp8._is_event = false;
      while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed ||
              !disp6._is_closed || !disp7._is_closed || !disp8._is_closed) &&
             !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event &&
             !disp6._is_event && !disp7._is_event && !disp8._is_event) wait_all();

Project: CImg
File: CImg.h

    /**
       \param[out] max_val Value of the maximum value found.
    **/
    template<typename t>
    T& min_max(t& max_val) {
      bool is_all_empty = true;
      T *ptr_min = 0;
      cimglist_for(*this,l) if (!_data[l].is_empty()) {
        ptr_min = _data[l]._data;
        is_all_empty = false;
        break;
      }
      if (is_all_empty)
        throw CImgInstanceException(_cimglist_instance
                                    "min_max(): %s.",
                                    _data?"List of empty images":"Empty instance",
                                    cimglist_instance);
      T min_value = *ptr_min, max_value = min_value;
      cimglist_for(*this,l) {
        const CImg<T>& img = _data[l];
        cimg_for(img,ptrs,T) {
          const T val = *ptrs;
          if (val<min_value) { min_value = val; ptr_min = ptrs; }
          if (val>max_value) max_value = val;
        }

Project: CImg
File: CImg.h

    //! Return a reference to an empty list \const.
    static const CImgList<T>& const_empty() {
      static const CImgList<T> _empty;
      return _empty;

Project: CImg
File: CImg.h

    //! Replace the image by an identity matrix \newinstance.
    CImg<T> get_identity_matrix() const {
      return identity_matrix(std::max(_width,_height));

Project: CImg
File: CImg.h

    template<typename tp, typename tc, typename to>
    CImg<T>& CImg3dtoobject3d(CImgList<tp>& primitives,
                              CImgList<tc>& colors,
                              CImgList<to>& opacities,
                              const bool full_check=true) {
      return get_CImg3dtoobject3d(primitives,colors,opacities,full_check).move_to(*this);

Project: CImg
File: CImg.h

      static const char* format() { return "%s"; }

Project: CImg
File: CImg.h

    template<typename tp, typename tc, typename to>
    CImg<floatT> get_object3dtoCImg3d(const CImgList<tp>& primitives,
                                      const CImgList<tc>& colors,
                                      const to& opacities,
                                      const bool full_check=true) const {
      CImg<charT> error_message(1024);
      if (!is_object3d(primitives,colors,opacities,full_check,error_message))
        throw CImgInstanceException(_cimg_instance
                                    "object3dtoCImg3d(): Invalid specified 3D object (%u,%u) (%s).",
                                    cimg_instance,_width,primitives._width,error_message.data());
      CImg<floatT> res(1,_size_object3dtoCImg3d(primitives,colors,opacities));
      float *ptrd = res._data;

      // Put magick number.
      *(ptrd++) = 'C' + 0.5f; *(ptrd++) = 'I' + 0.5f; *(ptrd++) = 'm' + 0.5f;
      *(ptrd++) = 'g' + 0.5f; *(ptrd++) = '3' + 0.5f; *(ptrd++) = 'd' + 0.5f;

      // Put number of vertices and primitives.
      *(ptrd++) = cimg::uint2float(_width);
      *(ptrd++) = cimg::uint2float(primitives._width);

      // Put vertex data.
      if (is_empty() || !primitives) return res;
      const T *ptrx = data(0,0), *ptry = data(0,1), *ptrz = data(0,2);
      cimg_forX(*this,p) {
        *(ptrd++) = (float)*(ptrx++);
        *(ptrd++) = (float)*(ptry++);
        *(ptrd++) = (float)*(ptrz++);
      }

      // Put primitive data.
      cimglist_for(primitives,p) {
        *(ptrd++) = (float)primitives[p].size();
        const tp *ptrp = primitives[p]._data;
        cimg_foroff(primitives[p],i) *(ptrd++) = cimg::uint2float((unsigned int)*(ptrp++));
      }

      // Put color/texture data.
      const unsigned int csiz = std::min(colors._width,primitives._width);
      for (int c = 0; c<(int)csiz; ++c) {
        const CImg<tc>& color = colors[c];
        const tc *ptrc = color._data;
        if (color.size()==3) { *(ptrd++) = (float)*(ptrc++); *(ptrd++) = (float)*(ptrc++); *(ptrd++) = (float)*ptrc; }
        else {
          *(ptrd++) = -128.f;
          int shared_ind = -1;
          if (color.is_shared()) for (int i = 0; i<c; ++i) if (ptrc==colors[i]._data) { shared_ind = i; break; }
          if (shared_ind<0) {
            *(ptrd++) = (float)color._width;
            *(ptrd++) = (float)color._height;
            *(ptrd++) = (float)color._spectrum;
            cimg_foroff(color,l) *(ptrd++) = (float)*(ptrc++);
          } else {
            *(ptrd++) = (float)shared_ind;
            *(ptrd++) = 0;
            *(ptrd++) = 0;
          }
        }
      }
      const int csiz2 = primitives.width() - colors.width();
      for (int c = 0; c<csiz2; ++c) { *(ptrd++) = 200.f; *(ptrd++) = 200.f; *(ptrd++) = 200.f; }

      // Put opacity data.
      ptrd = _object3dtoCImg3d(opacities,ptrd);
      const float *ptre = res.end();
      while (ptrd<ptre) *(ptrd++) = 1.f;
      return res;

Project: CImg
File: CImg.h

    **/
    CImg<T>& assign(const unsigned int size_x, const unsigned int size_y,
                    const unsigned int size_z, const unsigned int size_c,
                    const int value0, const int value1, ...) {
      assign(size_x,size_y,size_z,size_c);
      _CImg_stdarg(*this,value0,value1,(size_t)size_x*size_y*size_z*size_c,int);
      return *this;

Project: CImg
File: CImg.h


    static longT _distance_sep_edt(const longT i, const longT u, const longT *const g) {
      return (u*u - i*i + g[u] - g[i])/(2*(u - i));

Project: CImg
File: CImg.h

    template<typename tf, typename tp, typename tff>
    CImg<T>& append_object3d(CImgList<tf>& primitives, const CImg<tp>& obj_vertices,
                             const CImgList<tff>& obj_primitives) {
      if (!obj_vertices || !obj_primitives) return *this;
      if (obj_vertices._height!=3 || obj_vertices._depth>1 || obj_vertices._spectrum>1)
        throw CImgInstanceException(_cimg_instance
                                    "append_object3d(): Specified vertice image (%u,%u,%u,%u,%p) is not a "
                                    "set of 3D vertices.",
                                    cimg_instance,
                                    obj_vertices._width,obj_vertices._height,
                                    obj_vertices._depth,obj_vertices._spectrum,obj_vertices._data);

      if (is_empty()) { primitives.assign(obj_primitives); return assign(obj_vertices); }
      if (_height!=3 || _depth>1 || _spectrum>1)
        throw CImgInstanceException(_cimg_instance
                                    "append_object3d(): Instance is not a set of 3D vertices.",
                                    cimg_instance);

      const unsigned int P = _width;
      append(obj_vertices,'x');
      const unsigned int N = primitives._width;
      primitives.insert(obj_primitives);
      for (unsigned int i = N; i<primitives._width; ++i) {
        CImg<tf> &p = primitives[i];
        switch (p.size()) {
        case 1 : p[0]+=P; break; // Point
        case 5 : p[0]+=P; p[1]+=P; break; // Sphere
        case 2 : case 6 : p[0]+=P; p[1]+=P; break; // Segment
        case 3 : case 9 : p[0]+=P; p[1]+=P; p[2]+=P; break; // Triangle
        case 4 : case 12 : p[0]+=P; p[1]+=P; p[2]+=P; p[3]+=P; break; // Rectangle
        }
      }
      return *this;

Project: CImg
File: CImg.h

      static char inf() { return max(); }
      static char cut(const double val) {

Project: CImg
File: CImg.h

    template<typename t>
    CImgList<t>& move_to(CImgList<t>& list) {
      list.assign(_width);
      bool is_one_shared_element = false;
      cimglist_for(*this,l) is_one_shared_element|=_data[l]._is_shared;
      if (is_one_shared_element) cimglist_for(*this,l) list[l].assign(_data[l]);
      else cimglist_for(*this,l) _data[l].move_to(list[l]);
      assign();
      return list;

Project: CImg
File: CImg.h


    void _desinit_fullscreen() {
      if (!_is_fullscreen) return;
      if (_background_window) DestroyWindow(_background_window);
      _background_window = 0;
      if (_curr_mode.dmSize) ChangeDisplaySettings(&_curr_mode,0);
      _is_fullscreen = false;

Project: CImg
File: CImg.h

    // Convert a continuous cv::Mat<uchar> to a CImg<uchar>.
    static CImg<ucharT> _cvmat2cimg(const cv::Mat &src) {
      if (src.channels()==1) return CImg<ucharT>(src.ptr(),src.cols,src.rows,1,1);
      else if (src.channels()==3) { // BGR
        CImg<ucharT> res(src.cols,src.rows,1,src.channels());
        const unsigned char *ptrs = src.ptr();
        unsigned char *pR = res.data(), *pG = res.data(0,0,0,1), *pB = res.data(0,0,0,2);
        cimg_forXY(res,x,y) { *(pB++) = *(ptrs++); *(pG++) = *(ptrs++); *(pR++) = *(ptrs++); }
        return res;
      }
      return CImg<ucharT>(src.ptr(),src.channels(),src.cols,src.rows,1,true).get_permute_axes("yzcx");

Project: CImg
File: CImg.h

    **/
    CImgList<T> operator+() const {
      return CImgList<T>(*this,false);

Project: CImg
File: CImg.h

      return empty.eval(expression,x,y,z,c);
    }

    template<typename t>

Project: CImg
File: CImg.h

    **/
    CImg<T>& assign(const CImgDisplay &disp) {
      disp.snapshot(*this);
      return *this;

Project: CImg
File: CImg.h

    **/
    static const CImg<Tuchar>& lines_LUT256() {
      static const unsigned char pal[] = {
        0,255,255,0,0,28,125,125,235,210,186,182,36,0,125,255,
        53,32,255,210,89,186,65,45,125,210,210,97,130,194,0,125,
        206,53,190,89,255,146,20,190,154,73,255,36,130,215,0,138,
        101,210,61,194,206,0,77,45,255,154,174,0,190,239,89,125,
        16,36,158,223,117,0,97,69,223,255,40,239,0,0,255,0,
        97,170,93,255,138,40,117,210,0,170,53,158,186,255,0,121,
        227,121,186,40,20,190,89,255,77,57,130,142,255,73,186,85,
        210,8,32,166,243,130,210,40,255,45,61,142,223,49,121,255,
        20,162,158,73,89,255,53,138,210,190,57,235,36,73,255,49,
        210,0,210,85,57,97,255,121,85,174,40,255,162,178,0,121,
        166,125,53,146,166,255,97,121,65,89,235,231,12,170,36,190,
        85,255,166,97,198,77,20,146,109,166,255,28,40,202,121,81,
        247,0,210,255,49,0,65,255,36,166,93,77,255,85,251,0,
        170,178,0,182,255,0,162,16,154,142,162,223,223,0,0,81,
        215,4,215,162,215,125,77,206,121,36,125,231,101,16,255,121,
        0,57,190,215,65,125,89,142,255,101,73,53,146,223,125,125,
        0,255,0,255,0,206,93,138,49,255,0,202,154,85,45,219,
        251,53,0,255,40,130,219,158,16,117,186,130,202,49,65,239,
        89,202,49,28,247,134,150,0,255,117,202,4,215,81,186,57,
        202,89,73,210,40,93,45,251,206,28,223,142,40,134,162,125,
        32,247,97,170,0,255,57,134,73,247,162,0,251,40,142,142,
        8,166,206,81,154,194,93,89,125,243,28,109,227,0,190,65,
        194,186,0,255,53,45,109,186,186,0,255,130,49,170,69,210,
        154,0,109,227,45,255,125,105,81,81,255,0,219,134,170,85,
        146,28,170,89,223,97,8,210,255,158,49,40,125,174,174,125,
        0,227,166,28,219,130,0,93,239,0,85,255,81,178,125,49,
        89,255,53,206,73,113,146,255,0,150,36,219,162,0,210,125,
        69,134,255,85,40,89,235,49,215,121,0,206,36,223,174,69,
        40,182,178,130,69,45,255,210,85,77,215,0,231,146,0,194,
        125,174,0,255,40,89,121,206,57,0,206,170,231,150,81,0,
        125,255,4,174,4,190,121,255,4,166,109,130,49,239,170,93,
        16,174,210,0,255,16,105,158,93,255,0,125,0,255,158,85,
        0,255,0,0,255,170,166,61,121,28,198,215,45,243,61,97,
        255,53,81,130,109,255,8,117,235,121,40,178,174,0,182,49,
        162,121,255,69,206,0,219,125,0,101,255,239,121,32,210,130,
        36,231,32,125,81,142,215,158,4,178,255,0,40,251,125,125,
        219,89,130,0,166,255,24,65,194,125,255,125,77,125,93,125,
        202,24,138,174,178,32,255,85,194,40,85,36,174,174,125,210,
        85,255,53,16,93,206,40,130,170,202,93,255,0,24,117,255,
        97,113,105,81,255,186,194,57,69,206,57,53,223,190,4,255,
        85,97,130,255,85,0,125,223,85,219,0,215,146,77,40,239,
        89,36,142,154,227,0,255,85,162,0,162,0,235,178,45,166,
        0,247,255,20,69,210,89,142,53,255,40,146,166,255,69,0,
        174,154,142,130,162,0,215,255,0,89,40,255,166,61,146,69,
        162,40,255,32,121,255,117,178,0,186,206,0,57,215,215,81,
        158,77,166,210,77,89,210,0,24,202,150,186,0,255,20,97,
        57,170,235,251,16,73,142,251,93,0,202,0,255,121,219,4,
        73,219,8,162,206,16,219,93,117,0,255,8,130,174,223,45 };
      static const CImg<Tuchar> colormap(pal,1,256,1,3,false);
      return colormap;

Project: CImg
File: CImg.h

    //! Wait for any event occuring either on the display \c disp1, \c disp2, \c disp3 or \c disp4.
    static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4) {
      disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = false;
      while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed) &&
             !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event) wait_all();

Project: CImg
File: CImg.h

      static bool cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(bool)val; }

Project: CImg
File: CImg.h

    **/
    CImg<T>& equalize(const unsigned int nb_levels, const T& min_value, const T& max_value) {
      if (!nb_levels || is_empty()) return *this;
      const T
        vmin = min_value<max_value?min_value:max_value,
        vmax = min_value<max_value?max_value:min_value;
      CImg<ulongT> hist = get_histogram(nb_levels,vmin,vmax);
      ulongT cumul = 0;
      cimg_forX(hist,pos) { cumul+=hist[pos]; hist[pos] = cumul; }
      if (!cumul) cumul = 1;
      cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),1048576))
      cimg_rofoff(*this,off) {
        const int pos = (int)((_data[off] - vmin)*(nb_levels - 1.)/(vmax - vmin));
        if (pos>=0 && pos<(int)nb_levels) _data[off] = (T)(vmin + (vmax - vmin)*hist[pos]/cumul);
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    CImgDisplay(const CImgDisplay& disp):
      _width(0),_height(0),_normalization(0),
      _min(0),_max(0),
      _is_fullscreen(false),
      _title(0),
      _window_width(0),_window_height(0),_button(0),
      _keys(new unsigned int[128]),_released_keys(new unsigned int[128]),
      _window_x(0),_window_y(0),_mouse_x(-1),_mouse_y(-1),_wheel(0),
      _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) {
      assign(disp);

Project: CImg
File: CImg.h

    //! Convert pixel values from RGB to XYZ color spaces \newinstance.
    CImg<Tfloat> get_RGBtoXYZ(const bool use_D65=true) const {
      return CImg<Tfloat>(*this,false).RGBtoXYZ(use_D65);

Project: CImg
File: CImg.h

       \param user_path Specified path, or \c 0 to get the path currently used.
       \param reinit_path Force path to be recalculated (may take some time).
       \return Path containing the \c gzip binary.
    **/
    inline const char *gzip_path(const char *const user_path, const bool reinit_path) {
      static CImg<char> s_path;
      cimg::mutex(7);
      if (reinit_path) s_path.assign();
      if (user_path) {
        if (!s_path) s_path.assign(1024);
        std::strncpy(s_path,user_path,1023);
      } else if (!s_path) {
        s_path.assign(1024);
        bool path_found = false;
        std::FILE *file = 0;
#if cimg_OS==2
        if (!path_found) {
          std::strcpy(s_path,".\\gzip.exe");
          if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
        }
        if (!path_found) std::strcpy(s_path,"gzip.exe");
#else
        if (!path_found) {
          std::strcpy(s_path,"./gzip");
          if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
        }
        if (!path_found) std::strcpy(s_path,"gzip");
#endif
        winformat_string(s_path);

Project: CImg
File: CImg.h

    template<> struct type<signed char> {

Project: CImg
File: CImg.h

    **/
    CImg<T>& assign() {
      if (!_is_shared) delete[] _data;
      _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0;
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& discard(const CImg<t>& values, const char axis=0) {
      if (is_empty() || !values) return *this;
      return get_discard(values,axis).move_to(*this);

Project: CImg
File: CImg.h

    //! Return pixel value with Neumann boundary conditions for the coordinate (\c pos) \const.
    T atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) const {
      if (is_empty())
        throw CImgInstanceException(_cimglist_instance
                                    "atN(): Empty instance.",
                                    cimglist_instance);
      return _atN(pos,x,y,z,c);

Project: CImg
File: CImg.h

      static float inf() { return (float)cimg::type<double>::inf(); }

Project: CImg
File: CImg.h

    template<typename t1, typename t2, typename t3, typename t4, typename t5, typename t6, typename t7>
    CImgList(const CImg<t1>& img1, const CImg<t2>& img2, const CImg<t3>& img3, const CImg<t4>& img4,
             const CImg<t5>& img5, const CImg<t6>& img6, const CImg<t7>& img7, const bool is_shared=false):
      _width(0),_allocated_width(0),_data(0) {
      assign(7);
      _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared);
      _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared);
      _data[6].assign(img7,is_shared);

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& max(const CImg<t>& img) {
      const ulongT siz = size(), isiz = img.size();
      if (siz && isiz) {
        if (is_overlapped(img)) return max(+img);
        T *ptrd = _data, *const ptre = _data + siz;
        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
          for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
            *ptrd = std::max((T)*(ptrs++),*ptrd);
        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = std::max((T)*(ptrs++),*ptrd);
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename T>
    static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg<T>& img) {
      cimg::unused(x0,y0,x1,y1,&img);
      _no_display_exception();

Project: CImg
File: CImg.h


      static double mp_list_set_Joff_v(_cimg_math_parser& mp) {
        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
        CImg<T> &img = mp.listout[ind];
        const int
          ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y],
          oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c];
        const longT
          off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3),
          whd = (longT)img.width()*img.height()*img.depth();
        const double *ptrs = &_mp_arg(1) + 1;
        if (off>=0 && off<whd) {
          const unsigned int vsiz = (unsigned int)mp.opcode[4];
          T *ptrd = &img[off];
          cimg_for_inC(img,0,vsiz - 1,c) { *ptrd = (T)*(ptrs++); ptrd+=whd; }
        }
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h

    **/
    bool is_empty() const {
      return (!_data || !_width);

Project: CImg
File: CImg.h

      static unsigned int max() { return (unsigned int)-1; }

Project: CImg
File: CImg.h

    //! Load image from a PFM file \overloading.
    CImg<T>& load_pfm(std::FILE *const file) {
      return _load_pfm(file,0);

Project: CImg
File: CImg.h

    **/
    CImg<T>& ror(const char *const expression) {
      return ror((+*this)._fill(expression,true,1,0,0,"ror",this));