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

    **/
    T& atXYZC(const int x, const int y, const int z, const int c) {
      if (is_empty())
        throw CImgInstanceException(_cimg_instance
                                    "atXYZC(): Empty instance.",
                                    cimg_instance);
      return _atXYZC(x,y,z,c);

Project: CImg
File: CImg.h

    **/
    T& atNX(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].atX(x,y,z,c,out_value);

Project: CImg
File: CImg.h

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

      return CImg<T>(_data + beg,x1 - x0 + 1,1,1,1,true);

Project: CImg
File: CImg.h


    T& _atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) {
      return _data[cimg::cut(pos,0,width() - 1)].atX(x,y,z,c);

Project: CImg
File: CImg.h

    //! Return hyperbolic arcosine of a value.
    inline double acosh(const double x) {
#if cimg_use_cpp11==1 && !defined(_MSC_VER)
      return std::acosh(x);
#else
      return std::log(x + std::sqrt(x*x - 1));
#endif

Project: CImg
File: CImg.h

    //! Compute the histogram of pixel values \overloading.
    CImg<T>& histogram(const unsigned int nb_levels) {
      return get_histogram(nb_levels).move_to(*this);

Project: CImg
File: CImg.h

    //! Return a 3x3 diagonal matrix containing specified coefficients.
    static CImg<T> diagonal(const T& a0, const T& a1, const T& a2) {
      return matrix(a0,0,0,0,a1,0,0,0,a2);

Project: CImg
File: CImg.h

    //! Convert Ascii character to upper case.
    inline char uppercase(const char x) {
      return (char)((x<'a'||x>'z')?x:x - 'a' + 'A');

Project: CImg
File: CImg.h

    **/
    inline bool is_file(const char *const path) {
      if (!path || !*path) return false;
      std::FILE *const file = cimg::std_fopen(path,"rb");
      if (!file) return false;
      cimg::fclose(file);
      return !is_directory(path);

Project: CImg
File: CImg.h

    template<typename tz, typename tc, typename tl>
    CImg<T>& draw_triangle(CImg<tz>& zbuffer,
                           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 (!is_sameXY(zbuffer))
        throw CImgArgumentException(_cimg_instance
                                    "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have "
                                    "different dimensions.",
                                    cimg_instance,
                                    zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data);
      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(zbuffer,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(zbuffer,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);
          tz *ptrz = zbuffer.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;
            if (iz>=*ptrz) {
              *ptrz = (tz)iz;
              const float
                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; ++ptrz;
          }
        }
      }
      return *this;

Project: CImg
File: CImg.h

    // [internal] Return a 40x38 color logo of a 'danger' item.
    static CImg<T> _logo40x38() {
      CImg<T> res(40,38,1,3);
      const unsigned char *ptrs = cimg::logo40x38;
      T *ptr1 = res.data(0,0,0,0), *ptr2 = res.data(0,0,0,1), *ptr3 = res.data(0,0,0,2);
      for (ulongT off = 0; off<(ulongT)res._width*res._height;) {
        const unsigned char n = *(ptrs++), r = *(ptrs++), g = *(ptrs++), b = *(ptrs++);
        for (unsigned int l = 0; l<n; ++off, ++l) { *(ptr1++) = (T)r; *(ptr2++) = (T)g; *(ptr3++) = (T)b; }
      }
      return res;

Project: CImg
File: CImg.h


    const CImg<T>& _save_pfm(std::FILE *const file, const char *const filename) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_pfm(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(file,filename); return *this; }
      if (_depth>1)
        cimg::warn(_cimg_instance
                   "save_pfm(): Instance is volumetric, only the first slice will be saved in file '%s'.",
                   cimg_instance,
                   filename?filename:"(FILE*)");
      if (_spectrum>3)
        cimg::warn(_cimg_instance
                   "save_pfm(): image instance is multispectral, only the three first channels will be saved "
                   "in file '%s'.",
                   cimg_instance,
                   filename?filename:"(FILE*)");

      std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
      const T
        *ptr_r = data(0,0,0,0),
        *ptr_g = (_spectrum>=2)?data(0,0,0,1):0,
        *ptr_b = (_spectrum>=3)?data(0,0,0,2):0;
      const unsigned int buf_size = std::min(1024*1024U,_width*_height*(_spectrum==1?1:3));

      std::fprintf(nfile,"P%c\n%u %u\n1.0\n",
                   (_spectrum==1?'f':'F'),_width,_height);

      switch (_spectrum) {
      case 1 : { // Scalar image
        CImg<floatT> buf(buf_size);
        for (longT to_write = (longT)width()*height(); to_write>0; ) {
          const ulongT N = std::min((ulongT)to_write,(ulongT)buf_size);
          float *ptrd = buf._data;
          for (ulongT i = N; i>0; --i) *(ptrd++) = (float)*(ptr_r++);
          if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size);
          cimg::fwrite(buf._data,N,nfile);
          to_write-=N;
        }
      } break;
      case 2 : { // RG image
        CImg<floatT> buf(buf_size);
        for (longT to_write = (longT)width()*height(); to_write>0; ) {
          const unsigned int N = std::min((unsigned int)to_write,buf_size/3);
          float *ptrd = buf._data;
          for (ulongT i = N; i>0; --i) {
            *(ptrd++) = (float)*(ptr_r++);
            *(ptrd++) = (float)*(ptr_g++);
            *(ptrd++) = 0;
          }
          if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size);
          cimg::fwrite(buf._data,3*N,nfile);
          to_write-=N;
        }
      } break;
      default : { // RGB image
        CImg<floatT> buf(buf_size);
        for (longT to_write = (longT)width()*height(); to_write>0; ) {
          const unsigned int N = std::min((unsigned int)to_write,buf_size/3);
          float *ptrd = buf._data;
          for (ulongT i = N; i>0; --i) {
            *(ptrd++) = (float)*(ptr_r++);
            *(ptrd++) = (float)*(ptr_g++);
            *(ptrd++) = (float)*(ptr_b++);
          }
          if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size);
          cimg::fwrite(buf._data,3*N,nfile);
          to_write-=N;
        }
      }
      }
      if (!file) cimg::fclose(nfile);
      return *this;

Project: CImg
File: CImg.h

    **/
    T& atNXYZ(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].atXYZ(x,y,z,c,out_value);

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h


      unsigned int vector1_v(const mp_func op, const unsigned int arg1) {
        const unsigned int
          siz = _cimg_mp_size(arg1),
          pos = is_comp_vector(arg1)?arg1:vector(siz);
        if (siz>24) CImg<ulongT>::vector((ulongT)mp_vector_map_v,pos,siz,(ulongT)op,arg1).move_to(code);
        else {
          code.insert(siz);
          for (unsigned int k = 1; k<=siz; ++k)
            CImg<ulongT>::vector((ulongT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]);
        }
        return pos;

Project: CImg
File: CImg.h


      static double mp_vector_copy(_cimg_math_parser& mp) {
        std::memcpy(&_mp_arg(1) + 1,&_mp_arg(2) + 1,sizeof(double)*mp.opcode[3]);
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h


      static double mp_normp(_cimg_math_parser& mp) {
        const unsigned int i_end = (unsigned int)mp.opcode[2];
        if (i_end==4) return cimg::abs(_mp_arg(3));
        const double p = (double)mp.opcode[3];
        double res = 0;
        for (unsigned int i = 4; i<i_end; ++i)
          res+=std::pow(cimg::abs(_mp_arg(i)),p);
        res = std::pow(res,1/p);
        return res>0?res:0.;

Project: CImg
File: CImg.h

    //! Load image from a .cimg[z] file \overloading.
    CImg<T>& load_cimg(std::FILE *const file, const char axis='z', const float align=0) {
      CImgList<T> list;
      list.load_cimg(file);
      if (list._width==1) return list[0].move_to(*this);
      return assign(list.get_append(axis,align));

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

    //! Calculate greatest common divisor.
    inline long gcd(long a, long b) {
      while (a) { const long c = a; a = b%a; b = c; }
      return b;

Project: CImg
File: CImg.h

    template<typename tc>
    CImg<T>& draw_point(const int x0, const int y0,
                        const tc *const color, const float opacity=1) {
      return draw_point(x0,y0,0,color,opacity);

Project: CImg
File: CImg.h

    //! Load image using GraphicsMagick's external tool 'gm' \newinstance.
    static CImg<T> get_load_graphicsmagick_external(const char *const filename) {
      return CImg<T>().load_graphicsmagick_external(filename);

Project: CImg
File: CImg.h

    //! Return a reference to the last pixel value \const.
    const T& back() const {
      return *(_data + size() - 1);

Project: CImg
File: CImg.h

     **/
    T median() const {
      if (is_empty())
        throw CImgInstanceException(_cimg_instance
                                    "median(): Empty instance.",
                                    cimg_instance);
      const ulongT s = size();
      switch (s) {
      case 1 : return _data[0];
      case 2 : return cimg::median(_data[0],_data[1]);
      case 3 : return cimg::median(_data[0],_data[1],_data[2]);
      case 5 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4]);
      case 7 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6]);
      case 9 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6],_data[7],_data[8]);
      case 13 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6],_data[7],_data[8],
                                    _data[9],_data[10],_data[11],_data[12]);
      }
      const T res = kth_smallest(s>>1);
      return (s%2)?res:(T)((res + kth_smallest((s>>1) - 1))/2);

Project: CImg
File: CImg.h

    template<typename T>
    inline T sqr(const T& val) {
      return val*val;

Project: CImg
File: CImg.h

    //! Load image from a RGB file \overloading.
    CImg<T>& load_rgb(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) {
      return _load_rgb(file,0,dimw,dimh);

Project: CImg
File: CImg.h

    template<typename tf>
    static CImg<floatT> box3d(CImgList<tf>& primitives,
                              const float size_x=200, const float size_y=100, const float size_z=100) {
      primitives.assign(6,1,4,1,1, 0,3,2,1, 4,5,6,7, 0,1,5,4, 3,7,6,2, 0,4,7,3, 1,2,6,5);
      return CImg<floatT>(8,3,1,1,
                          0.,size_x,size_x,    0.,    0.,size_x,size_x,    0.,
                          0.,    0.,size_y,size_y,    0.,    0.,size_y,size_y,
                          0.,    0.,    0.,    0.,size_z,size_z,size_z,size_z);

Project: CImg
File: CImg.h


      static double mp_gcd(_cimg_math_parser& mp) {
        return cimg::gcd((long)_mp_arg(2),(long)_mp_arg(3));

Project: CImg
File: CImg.h

    **/
    CImg<Tdouble> get_stats(const unsigned int variance_method=1) const {
      if (is_empty()) return CImg<doubleT>();
      const ulongT siz = size();
      const longT off_end = (longT)siz;
      double S = 0, S2 = 0, P = 1;
      longT offm = 0, offM = 0;
      T m = *_data, M = m;

      cimg_pragma_openmp(parallel reduction(+:S,S2) reduction(*:P) cimg_openmp_if_size(siz,131072)) {
        longT loffm = 0, loffM = 0;
        T lm = *_data, lM = lm;
        cimg_pragma_openmp(for)
        for (longT off = 0; off<off_end; ++off) {
          const T val = _data[off];
          const double _val = (double)val;
          if (val<lm) { lm = val; loffm = off; }
          if (val>lM) { lM = val; loffM = off; }
          S+=_val;
          S2+=_val*_val;
          P*=_val;
        }
        cimg_pragma_openmp(critical(get_stats)) {
          if (lm<m || (lm==m && loffm<offm)) { m = lm; offm = loffm; }
          if (lM>M || (lM==M && loffM<offM)) { M = lM; offM = loffM; }
        }
      }

      const double
        mean_value = S/siz,
        _variance_value = variance_method==0?(S2 - S*S/siz)/siz:
        (variance_method==1?(siz>1?(S2 - S*S/siz)/(siz - 1):0):
         variance(variance_method)),
        variance_value = _variance_value>0?_variance_value:0;
      int
        xm = 0, ym = 0, zm = 0, cm = 0,
        xM = 0, yM = 0, zM = 0, cM = 0;
      contains(_data[offm],xm,ym,zm,cm);
      contains(_data[offM],xM,yM,zM,cM);
      return CImg<Tdouble>(1,14).fill((double)m,(double)M,mean_value,variance_value,
                                      (double)xm,(double)ym,(double)zm,(double)cm,
                                      (double)xM,(double)yM,(double)zM,(double)cM,
                                      S,P);

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 = cimg::mod(*ptrd,(T)*(ptrs++));
        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = cimg::mod(*ptrd,(T)*(ptrs++));
      }
      return *this;

Project: CImg
File: CImg.h

      static bool is_float() { return true; }
      static bool is_inf(const float val) {
#ifdef isinf
        return (bool)isinf(val);
#else
        return !is_nan(val) && (val<cimg::type<float>::min() || val>cimg::type<float>::max());
#endif

Project: CImg
File: CImg.h

      void lock(const unsigned int n) { WaitForSingleObject(mutex[n],INFINITE); }

Project: CImg
File: CImg.h

    //! Cumulate image values, optionally along specified axis \newinstance.
    CImg<Tlong> get_cumulate(const char axis=0) const {
      return CImg<Tlong>(*this,false).cumulate(axis);

Project: CImg
File: CImg.h

    //! Access to a pixel value, using Neumann boundary conditions \const.
    const T& atXYZC(const int x, const int y, const int z, const int c) const {
      if (is_empty())
        throw CImgInstanceException(_cimg_instance
                                    "atXYZC(): Empty instance.",
                                    cimg_instance);
      return _atXYZC(x,y,z,c);

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

      static bool is_inf(const bool) { return false; }

Project: CImg
File: CImg.h

    template<typename tp, typename tf, typename tc, typename to>
    const CImg<T>& _display_object3d(CImgDisplay& disp, const char *const title,
				     const CImg<tp>& vertices,
				     const CImgList<tf>& primitives,
				     const CImgList<tc>& colors,
                                     const to& opacities,
				     const bool centering,
				     const int render_static, const int render_motion,
				     const bool is_double_sided, const float focale,
                                     const float light_x, const float light_y, const float light_z,
				     const float specular_lightness, const float specular_shininess,
				     const bool display_axes, float *const pose_matrix,
                                     const bool exit_on_anykey) const {
      typedef typename cimg::superset<tp,float>::type tpfloat;

      // Check input arguments
      if (is_empty()) {
	if (disp) return CImg<T>(disp.width(),disp.height(),1,(colors && colors[0].size()==1)?1:3,0).
		    _display_object3d(disp,title,vertices,primitives,colors,opacities,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);
	else return CImg<T>(1,2,1,1,64,128).resize(cimg_fitscreen(CImgDisplay::screen_width()/2,
                                                                  CImgDisplay::screen_height()/2,1),
                                                   1,(colors && colors[0].size()==1)?1:3,3).
               _display_object3d(disp,title,vertices,primitives,colors,opacities,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);
      } else { if (disp) disp.resize(*this,false); }
      CImg<charT> error_message(1024);
      if (!vertices.is_object3d(primitives,colors,opacities,true,error_message))
        throw CImgArgumentException(_cimg_instance
                                    "display_object3d(): Invalid specified 3D object (%u,%u) (%s).",
                                    cimg_instance,vertices._width,primitives._width,error_message.data());
      if (vertices._width && !primitives) {
        CImgList<tf> nprimitives(vertices._width,1,1,1,1);
        cimglist_for(nprimitives,l) nprimitives(l,0) = (tf)l;
        return _display_object3d(disp,title,vertices,nprimitives,colors,opacities,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);
      }
      if (!disp) {
	disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,3);
        if (!title) disp.set_title("CImg<%s> (%u vertices, %u primitives)",
                                   pixel_type(),vertices._width,primitives._width);
      } else if (title) disp.set_title("%s",title);

      // Init 3D objects and compute object statistics
      CImg<floatT>
        pose,
        rotated_vertices(vertices._width,3),
        bbox_vertices, rotated_bbox_vertices,
        axes_vertices, rotated_axes_vertices,
        bbox_opacities, axes_opacities;
      CImgList<uintT> bbox_primitives, axes_primitives;
      CImgList<tf> reverse_primitives;
      CImgList<T> bbox_colors, bbox_colors2, axes_colors;
      unsigned int ns_width = 0, ns_height = 0;
      int _is_double_sided = (int)is_double_sided;
      bool ndisplay_axes = display_axes;
      const CImg<T>
        background_color(1,1,1,_spectrum,0),
        foreground_color(1,1,1,_spectrum,(T)std::min((int)cimg::type<T>::max(),255));
      float
        Xoff = 0, Yoff = 0, Zoff = 0, sprite_scale = 1,
        xm = 0, xM = vertices?vertices.get_shared_row(0).max_min(xm):0,
        ym = 0, yM = vertices?vertices.get_shared_row(1).max_min(ym):0,
        zm = 0, zM = vertices?vertices.get_shared_row(2).max_min(zm):0;
      const float delta = cimg::max(xM - xm,yM - ym,zM - zm);

      rotated_bbox_vertices = bbox_vertices.assign(8,3,1,1,
                                                   xm,xM,xM,xm,xm,xM,xM,xm,
                                                   ym,ym,yM,yM,ym,ym,yM,yM,
                                                   zm,zm,zm,zm,zM,zM,zM,zM);
      bbox_primitives.assign(6,1,4,1,1, 0,3,2,1, 4,5,6,7, 1,2,6,5, 0,4,7,3, 0,1,5,4, 2,3,7,6);
      bbox_colors.assign(6,_spectrum,1,1,1,background_color[0]);
      bbox_colors2.assign(6,_spectrum,1,1,1,foreground_color[0]);
      bbox_opacities.assign(bbox_colors._width,1,1,1,0.3f);

      rotated_axes_vertices = axes_vertices.assign(7,3,1,1,
                                                   0,20,0,0,22,-6,-6,
                                                   0,0,20,0,-6,22,-6,
                                                   0,0,0,20,0,0,22);
      axes_opacities.assign(3,1,1,1,1);
      axes_colors.assign(3,_spectrum,1,1,1,foreground_color[0]);
      axes_primitives.assign(3,1,2,1,1, 0,1, 0,2, 0,3);

      // Begin user interaction loop
      CImg<T> visu0(*this,false), visu;
      CImg<tpfloat> zbuffer(visu0.width(),visu0.height(),1,1,0);
      bool init_pose = true, clicked = false, redraw = true;
      unsigned int key = 0;
      int
        x0 = 0, y0 = 0, x1 = 0, y1 = 0,
        nrender_static = render_static,
        nrender_motion = render_motion;
      disp.show().flush();

      while (!disp.is_closed() && !key) {

        // Init object pose
        if (init_pose) {
          const float
            ratio = delta>0?(2.f*std::min(disp.width(),disp.height())/(3.f*delta)):1,
            dx = (xM + xm)/2, dy = (yM + ym)/2, dz = (zM + zm)/2;
          if (centering)
            CImg<floatT>(4,3,1,1, ratio,0.,0.,-ratio*dx, 0.,ratio,0.,-ratio*dy, 0.,0.,ratio,-ratio*dz).move_to(pose);
          else CImg<floatT>(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0).move_to(pose);
          if (pose_matrix) {
            CImg<floatT> pose0(pose_matrix,4,3,1,1,false);
            pose0.resize(4,4,1,1,0); pose.resize(4,4,1,1,0);
            pose0(3,3) = pose(3,3) = 1;
            (pose0*pose).get_crop(0,0,3,2).move_to(pose);
            Xoff = pose_matrix[12]; Yoff = pose_matrix[13]; Zoff = pose_matrix[14]; sprite_scale = pose_matrix[15];
          } else { Xoff = Yoff = Zoff = 0; sprite_scale = 1; }
          init_pose = false;
          redraw = true;
        }

        // Rotate and draw 3D object
        if (redraw) {
          const float
            r00 = pose(0,0), r10 = pose(1,0), r20 = pose(2,0), r30 = pose(3,0),
            r01 = pose(0,1), r11 = pose(1,1), r21 = pose(2,1), r31 = pose(3,1),
            r02 = pose(0,2), r12 = pose(1,2), r22 = pose(2,2), r32 = pose(3,2);
          if ((clicked && nrender_motion>=0) || (!clicked && nrender_static>=0))
            cimg_forX(vertices,l) {
              const float x = (float)vertices(l,0), y = (float)vertices(l,1), z = (float)vertices(l,2);
              rotated_vertices(l,0) = r00*x + r10*y + r20*z + r30;
              rotated_vertices(l,1) = r01*x + r11*y + r21*z + r31;
              rotated_vertices(l,2) = r02*x + r12*y + r22*z + r32;
            }
          else cimg_forX(bbox_vertices,l) {
              const float x = bbox_vertices(l,0), y = bbox_vertices(l,1), z = bbox_vertices(l,2);
              rotated_bbox_vertices(l,0) = r00*x + r10*y + r20*z + r30;
              rotated_bbox_vertices(l,1) = r01*x + r11*y + r21*z + r31;
              rotated_bbox_vertices(l,2) = r02*x + r12*y + r22*z + r32;
            }

          // Draw objects
          const bool render_with_zbuffer = !clicked && nrender_static>0;
          visu = visu0;
          if ((clicked && nrender_motion<0) || (!clicked && nrender_static<0))
            visu.draw_object3d(Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff,
                               rotated_bbox_vertices,bbox_primitives,bbox_colors,bbox_opacities,2,false,focale).
              draw_object3d(Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff,
                            rotated_bbox_vertices,bbox_primitives,bbox_colors2,1,false,focale);
          else visu._draw_object3d((void*)0,render_with_zbuffer?zbuffer.fill(0):CImg<tpfloat>::empty(),
                                   Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff,
                                   rotated_vertices,reverse_primitives?reverse_primitives:primitives,
                                   colors,opacities,clicked?nrender_motion:nrender_static,_is_double_sided==1,focale,
                                   width()/2.f + light_x,height()/2.f + light_y,light_z + Zoff,
                                   specular_lightness,specular_shininess,1,sprite_scale);
          // Draw axes
          if (ndisplay_axes) {
            const float
              n = 1e-8f + cimg::hypot(r00,r01,r02),
              _r00 = r00/n, _r10 = r10/n, _r20 = r20/n,
              _r01 = r01/n, _r11 = r11/n, _r21 = r21/n,
              _r02 = r01/n, _r12 = r12/n, _r22 = r22/n,
              Xaxes = 25, Yaxes = visu._height - 38.f;
            cimg_forX(axes_vertices,l) {
              const float
                x = axes_vertices(l,0),
                y = axes_vertices(l,1),
                z = axes_vertices(l,2);
              rotated_axes_vertices(l,0) = _r00*x + _r10*y + _r20*z;
              rotated_axes_vertices(l,1) = _r01*x + _r11*y + _r21*z;
              rotated_axes_vertices(l,2) = _r02*x + _r12*y + _r22*z;
            }
            axes_opacities(0,0) = (rotated_axes_vertices(1,2)>0)?0.5f:1.f;
            axes_opacities(1,0) = (rotated_axes_vertices(2,2)>0)?0.5f:1.f;
            axes_opacities(2,0) = (rotated_axes_vertices(3,2)>0)?0.5f:1.f;
            visu.draw_object3d(Xaxes,Yaxes,0,rotated_axes_vertices,axes_primitives,
                               axes_colors,axes_opacities,1,false,focale).
              draw_text((int)(Xaxes + rotated_axes_vertices(4,0)),
                        (int)(Yaxes + rotated_axes_vertices(4,1)),
                        "X",axes_colors[0]._data,0,axes_opacities(0,0),13).
              draw_text((int)(Xaxes + rotated_axes_vertices(5,0)),
                        (int)(Yaxes + rotated_axes_vertices(5,1)),
                        "Y",axes_colors[1]._data,0,axes_opacities(1,0),13).
              draw_text((int)(Xaxes + rotated_axes_vertices(6,0)),
                        (int)(Yaxes + rotated_axes_vertices(6,1)),
                        "Z",axes_colors[2]._data,0,axes_opacities(2,0),13);
          }
          visu.display(disp);
          if (!clicked || nrender_motion==nrender_static) redraw = false;
        }

        // Handle user interaction
        disp.wait();
        if ((disp.button() || disp.wheel()) && disp.mouse_x()>=0 && disp.mouse_y()>=0) {
          redraw = true;
          if (!clicked) { x0 = x1 = disp.mouse_x(); y0 = y1 = disp.mouse_y(); if (!disp.wheel()) clicked = true; }
          else { x1 = disp.mouse_x(); y1 = disp.mouse_y(); }
          if (disp.button()&1) {
            const float
              R = 0.45f*std::min(disp.width(),disp.height()),
              R2 = R*R,
              u0 = (float)(x0 - disp.width()/2),
              v0 = (float)(y0 - disp.height()/2),
              u1 = (float)(x1 - disp.width()/2),
              v1 = (float)(y1 - disp.height()/2),
              n0 = cimg::hypot(u0,v0),
              n1 = cimg::hypot(u1,v1),
              nu0 = n0>R?(u0*R/n0):u0,
              nv0 = n0>R?(v0*R/n0):v0,
              nw0 = (float)std::sqrt(std::max(0.f,R2 - nu0*nu0 - nv0*nv0)),
              nu1 = n1>R?(u1*R/n1):u1,
              nv1 = n1>R?(v1*R/n1):v1,
              nw1 = (float)std::sqrt(std::max(0.f,R2 - nu1*nu1 - nv1*nv1)),
              u = nv0*nw1 - nw0*nv1,
              v = nw0*nu1 - nu0*nw1,
              w = nv0*nu1 - nu0*nv1,
              n = cimg::hypot(u,v,w),
              alpha = (float)std::asin(n/R2)*180/cimg::PI;
            (CImg<floatT>::rotation_matrix(u,v,w,-alpha)*pose).move_to(pose);
            x0 = x1; y0 = y1;
          }
          if (disp.button()&2) {
            if (focale>0) Zoff-=(y0 - y1)*focale/400;
            else { const float s = std::exp((y0 - y1)/400.f); pose*=s; sprite_scale*=s; }
            x0 = x1; y0 = y1;
          }
          if (disp.wheel()) {
            if (focale>0) Zoff-=disp.wheel()*focale/20;
            else { const float s = std::exp(disp.wheel()/20.f); pose*=s; sprite_scale*=s; }
            disp.set_wheel();
          }
          if (disp.button()&4) { Xoff+=(x1 - x0); Yoff+=(y1 - y0); x0 = x1; y0 = y1; }
          if ((disp.button()&1) && (disp.button()&2)) {
            init_pose = true; disp.set_button(); x0 = x1; y0 = y1;
            pose = CImg<floatT>(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0);
          }
        } else if (clicked) { x0 = x1; y0 = y1; clicked = false; redraw = true; }

        CImg<charT> filename(32);
        switch (key = disp.key()) {
#if cimg_OS!=2
        case cimg::keyCTRLRIGHT :
#endif
        case 0 : case cimg::keyCTRLLEFT : key = 0; break;
        case cimg::keyD: if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            disp.set_fullscreen(false).
              resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false),
                     CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false).
              _is_resized = true;
            disp.set_key(key,false); key = 0;
          } break;
        case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            disp.set_fullscreen(false).
              resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true;
            disp.set_key(key,false); key = 0;
          } break;
        case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            disp.set_fullscreen(false).resize(cimg_fitscreen(_width,_height,_depth),false)._is_resized = true;
            disp.set_key(key,false); key = 0;
          } break;
        case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            if (!ns_width || !ns_height ||
                ns_width>(unsigned int)disp.screen_width() || ns_height>(unsigned int)disp.screen_height()) {
              ns_width = disp.screen_width()*3U/4;
              ns_height = disp.screen_height()*3U/4;
            }
            if (disp.is_fullscreen()) disp.resize(ns_width,ns_height,false);
            else {
              ns_width = disp._width; ns_height = disp._height;
              disp.resize(disp.screen_width(),disp.screen_height(),false);
            }
            disp.toggle_fullscreen()._is_resized = true;
            disp.set_key(key,false); key = 0;
          } break;
        case cimg::keyT : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            // Switch single/double-sided primitives.
            if (--_is_double_sided==-2) _is_double_sided = 1;
            if (_is_double_sided>=0) reverse_primitives.assign();
            else primitives.get_reverse_object3d().move_to(reverse_primitives);
            disp.set_key(key,false); key = 0; redraw = true;
          } break;
        case cimg::keyZ : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Enable/disable Z-buffer
            if (zbuffer) zbuffer.assign();
            else zbuffer.assign(visu0.width(),visu0.height(),1,1,0);
            disp.set_key(key,false); key = 0; redraw = true;
          } break;
        case cimg::keyX : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Show/hide 3D axes
            ndisplay_axes = !ndisplay_axes;
            disp.set_key(key,false); key = 0; redraw = true;
          } break;
        case cimg::keyF1 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to points
            nrender_motion = (nrender_static==0 && nrender_motion!=0)?0:-1; nrender_static = 0;
            disp.set_key(key,false); key = 0; redraw = true;
          } break;
        case cimg::keyF2 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to lines
            nrender_motion = (nrender_static==1 && nrender_motion!=1)?1:-1; nrender_static = 1;
            disp.set_key(key,false); key = 0; redraw = true;
          } break;
        case cimg::keyF3 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to flat
            nrender_motion = (nrender_static==2 && nrender_motion!=2)?2:-1; nrender_static = 2;
            disp.set_key(key,false); key = 0; redraw = true;
          } break;
        case cimg::keyF4 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to flat-shaded
            nrender_motion = (nrender_static==3 && nrender_motion!=3)?3:-1; nrender_static = 3;
            disp.set_key(key,false); key = 0; redraw = true;
          } break;
        case cimg::keyF5 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            // Set rendering mode to gouraud-shaded.
            nrender_motion = (nrender_static==4 && nrender_motion!=4)?4:-1; nrender_static = 4;
            disp.set_key(key,false); key = 0; redraw = true;
          } break;
        case cimg::keyF6 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to phong-shaded
            nrender_motion = (nrender_static==5 && nrender_motion!=5)?5:-1; nrender_static = 5;
            disp.set_key(key,false); key = 0; redraw = true;
          } break;
        case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save snapshot
            static unsigned int snap_number = 0;
            std::FILE *file;
            do {
              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++);
              if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file);
            } while (file);
            (+visu).__draw_text(" Saving snapshot... ",0).display(disp);
            visu.save(filename);
            (+visu).__draw_text(" Snapshot '%s' saved. ",0,filename._data).display(disp);
            disp.set_key(key,false); key = 0;
          } break;
        case cimg::keyG : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .off file
            static unsigned int snap_number = 0;
            std::FILE *file;
            do {
              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.off",snap_number++);
              if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file);
            } while (file);
            (+visu).__draw_text(" Saving object... ",0).display(disp);
            vertices.save_off(reverse_primitives?reverse_primitives:primitives,colors,filename);
            (+visu).__draw_text(" Object '%s' saved. ",0,filename._data).display(disp);
            disp.set_key(key,false); key = 0;
          } break;
        case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .cimg file
            static unsigned int snap_number = 0;
            std::FILE *file;
            do {

#ifdef cimg_use_zlib
              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++);
#else
              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++);
#endif
              if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file);
            } while (file);
            (+visu).__draw_text(" Saving object... ",0).display(disp);
            vertices.get_object3dtoCImg3d(reverse_primitives?reverse_primitives:primitives,colors,opacities).
              save(filename);
            (+visu).__draw_text(" Object '%s' saved. ",0,filename._data).display(disp);
            disp.set_key(key,false); key = 0;
          } break;

#ifdef cimg_use_board
        case cimg::keyP : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .EPS file
            static unsigned int snap_number = 0;
            std::FILE *file;
            do {
              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.eps",snap_number++);
              if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file);
            } while (file);
            (+visu).__draw_text(" Saving EPS snapshot... ",0).display(disp);
            LibBoard::Board board;
            (+visu)._draw_object3d(&board,zbuffer.fill(0),
                                   Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff,
                                   rotated_vertices,reverse_primitives?reverse_primitives:primitives,
                                   colors,opacities,clicked?nrender_motion:nrender_static,
                                   _is_double_sided==1,focale,
                                   visu.width()/2.f + light_x,visu.height()/2.f + light_y,light_z + Zoff,
                                   specular_lightness,specular_shininess,1,
                                   sprite_scale);
            board.saveEPS(filename);
            (+visu).__draw_text(" Object '%s' saved. ",0,filename._data).display(disp);
            disp.set_key(key,false); key = 0;
          } break;
        case cimg::keyV : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .SVG file
            static unsigned int snap_number = 0;
            std::FILE *file;
            do {
              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.svg",snap_number++);
              if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file);
            } while (file);
            (+visu).__draw_text(" Saving SVG snapshot... ",0,13).display(disp);
            LibBoard::Board board;
            (+visu)._draw_object3d(&board,zbuffer.fill(0),
                                   Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff,
                                   rotated_vertices,reverse_primitives?reverse_primitives:primitives,
                                   colors,opacities,clicked?nrender_motion:nrender_static,
                                   _is_double_sided==1,focale,
                                   visu.width()/2.f + light_x,visu.height()/2.f + light_y,light_z + Zoff,
                                   specular_lightness,specular_shininess,1,
                                   sprite_scale);
            board.saveSVG(filename);
            (+visu).__draw_text(" Object '%s' saved. ",0,filename._data).display(disp);
            disp.set_key(key,false); key = 0;
          } break;
#endif
        }
        if (disp.is_resized()) {
          disp.resize(false); visu0 = get_resize(disp,1);
          if (zbuffer) zbuffer.assign(disp.width(),disp.height());
          redraw = true;
        }
        if (!exit_on_anykey && key && key!=cimg::keyESC &&
            (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) {
          key = 0;
        }
      }
      if (pose_matrix) {
        std::memcpy(pose_matrix,pose._data,12*sizeof(float));
        pose_matrix[12] = Xoff; pose_matrix[13] = Yoff; pose_matrix[14] = Zoff; pose_matrix[15] = sprite_scale;
      }
      disp.set_button().set_key(key);
      return *this;

Project: CImg
File: CImg.h

    **/
    bool contains(const T& pixel) const {
      const T *const ppixel = &pixel;
      return !is_empty() && ppixel>=_data && ppixel<_data + size();

Project: CImg
File: CImg.h


      static double mp_kth(_cimg_math_parser& mp) {
        const unsigned int i_end = (unsigned int)mp.opcode[2];
        CImg<doubleT> vals(i_end - 4);
        double *p = vals.data();
        for (unsigned int i = 4; i<i_end; ++i) *(p++) = _mp_arg(i);
        int ind = (int)cimg::round(_mp_arg(3));
        if (ind<0) ind+=vals.width() + 1;
        ind = std::max(1,std::min(vals.width(),ind));
        return vals.kth_smallest(ind - 1);

Project: CImg
File: CImg.h


      static double mp_fsize(_cimg_math_parser& mp) {
        const double *ptrs = &_mp_arg(2) + 1;
        const ulongT siz = (ulongT)mp.opcode[3];
        CImg<charT> ss(siz + 1);
        cimg_forX(ss,i) ss[i] = (char)ptrs[i];
        ss.back() = 0;
        return (double)cimg::fsize(ss);

Project: CImg
File: CImg.h


      unsigned int vector(const unsigned int siz, const double value) { // Insert new initialized vector
        const unsigned int pos = vector(siz);
        double *ptr = &mem[pos] + 1;
        for (unsigned int i = 0; i<siz; ++i) *(ptr++) = value;
        return pos;

Project: CImg
File: CImg.h

    //! Rotate image with arbitrary angle \newinstance.
    CImg<T> get_rotate(const float angle, const unsigned int interpolation=1,
                       const unsigned int boundary_conditions=0) const {
      if (is_empty()) return *this;
      CImg<T> res;
      const float nangle = cimg::mod(angle,360.f);
      if (boundary_conditions!=1 && cimg::mod(nangle,90.f)==0) { // Optimized version for orthogonal angles
        const int wm1 = width() - 1, hm1 = height() - 1;
        const int iangle = (int)nangle/90;
        switch (iangle) {
        case 1 : { // 90 deg
          res.assign(_height,_width,_depth,_spectrum);
          T *ptrd = res._data;
          cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(y,hm1 - x,z,c);
        } break;
        case 2 : { // 180 deg
          res.assign(_width,_height,_depth,_spectrum);
          T *ptrd = res._data;
          cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(wm1 - x,hm1 - y,z,c);
        } break;
        case 3 : { // 270 deg
          res.assign(_height,_width,_depth,_spectrum);
          T *ptrd = res._data;
          cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(wm1 - y,x,z,c);
        } break;
        default : // 0 deg
          return *this;
        }
      } else { // Generic angle
        const float
          rad = (float)(nangle*cimg::PI/180.),
          ca = (float)std::cos(rad), sa = (float)std::sin(rad),
          ux = cimg::abs((_width - 1)*ca), uy = cimg::abs((_width - 1)*sa),
          vx = cimg::abs((_height - 1)*sa), vy = cimg::abs((_height - 1)*ca),
          w2 = 0.5f*(_width - 1), h2 = 0.5f*(_height - 1);
        res.assign((int)cimg::round(1 + ux + vx),(int)cimg::round(1 + uy + vy),_depth,_spectrum);
        const float rw2 = 0.5f*(res._width - 1), rh2 = 0.5f*(res._height - 1);
        _rotate(res,nangle,interpolation,boundary_conditions,w2,h2,rw2,rh2);
      }
      return res;

Project: CImg
File: CImg.h

    **/
    static void FFT(CImg<T>& real, CImg<T>& imag, const bool is_inverse=false,
                    const unsigned int nb_threads=0) {
      if (!real)
        throw CImgInstanceException("CImgList<%s>::FFT(): Empty specified real part.",
                                    pixel_type());
      if (!imag) imag.assign(real._width,real._height,real._depth,real._spectrum,(T)0);
      if (!real.is_sameXYZC(imag))
        throw CImgInstanceException("CImgList<%s>::FFT(): Specified real part (%u,%u,%u,%u,%p) and "
                                    "imaginary part (%u,%u,%u,%u,%p) have different dimensions.",
                                    pixel_type(),
                                    real._width,real._height,real._depth,real._spectrum,real._data,
                                    imag._width,imag._height,imag._depth,imag._spectrum,imag._data);
      cimg::unused(nb_threads);
#ifdef cimg_use_fftw3
      cimg::mutex(12);
#ifndef cimg_use_fftw3_singlethread
      fftw_plan_with_nthreads(nb_threads?nb_threads:cimg::nb_cpus());
#endif
      fftw_complex *data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*real._width*real._height*real._depth);
      if (!data_in)
        throw CImgInstanceException("CImgList<%s>::FFT(): Failed to allocate memory (%s) "
                                    "for computing FFT of image (%u,%u,%u,%u).",
                                    pixel_type(),
                                    cimg::strbuffersize(sizeof(fftw_complex)*real._width*
                                                        real._height*real._depth*real._spectrum),
                                    real._width,real._height,real._depth,real._spectrum);
      double *const ptrf = (double*)data_in;
      fftw_plan data_plan =
        real._depth>1?fftw_plan_dft_3d(real._depth,real._height,real._width,data_in,data_in,
                                       is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE):
        real._height>1?fftw_plan_dft_2d(real._height,real._width,data_in,data_in,
                                        is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE):
        fftw_plan_dft_1d(real._width,data_in,data_in,
                         is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE);
      cimg_forC(real,c) {
        CImg<T> realc = real.get_shared_channel(c), imagc = imag.get_shared_channel(c);
        cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000))
          cimg_rofoff(realc,i) { const ulongT i2 = 2*i; ptrf[i2] = (double)realc[i]; ptrf[i2 + 1] = (double)imagc[i]; }
        fftw_execute(data_plan);
        if (is_inverse) {
          const double a = 1.0/(real.width()*real.height()*real.depth());
          cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000))
            cimg_rofoff(realc,i) { const ulongT i2 = 2*i; realc[i] = (T)(a*ptrf[i2]); imagc[i] = (T)(a*ptrf[i2 + 1]); }
        } else
          cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000))
            cimg_rofoff(realc,i) { const ulongT i2 = 2*i; realc[i] = (T)ptrf[i2]; imagc[i] = (T)ptrf[i2 + 1]; }
      }
      fftw_destroy_plan(data_plan);
      fftw_free(data_in);
#ifndef cimg_use_fftw3_singlethread
      fftw_cleanup_threads();
#endif
      cimg::mutex(12,0);
#else
      if (real._depth>1) FFT(real,imag,'z',is_inverse);
      if (real._height>1) FFT(real,imag,'y',is_inverse);
      if (real._width>1) FFT(real,imag,'x',is_inverse);
#endif

Project: CImg
File: CImg.h

    **/
    int spectrum() const {
      return (int)_spectrum;

Project: CImg
File: CImg.h

    template<typename tp, typename tf, typename tc, typename to, typename tz>
    CImg<T>& draw_object3d(const float x0, const float y0, const float z0,
                           const CImg<tp>& vertices, const CImgList<tf>& primitives,
                           const CImgList<tc>& colors, const CImg<to>& opacities,
                           const unsigned int render_type,
                           const bool is_double_sided, const float focale,
                           const float lightx, const float lighty, const float lightz,
                           const float specular_lightness, const float specular_shininess,
                           const float g_opacity, CImg<tz>& zbuffer) {
      return _draw_object3d(0,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities,
                            render_type,is_double_sided,focale,lightx,lighty,lightz,
                            specular_lightness,specular_shininess,g_opacity,1);

Project: CImg
File: CImg.h

      static float max() { return FLT_MAX; }

Project: CImg
File: CImg.h

    //! Loadimage from an Ascii file \newinstance.
    static CImg<T> get_load_ascii(std::FILE *const file) {
      return CImg<T>().load_ascii(file);

Project: CImg
File: CImg.h

    **/
    inline bool is_directory(const char *const path) {
      if (!path || !*path) return false;
#if cimg_OS==1
      struct stat st_buf;
      return (!stat(path,&st_buf) && S_ISDIR(st_buf.st_mode));
#elif cimg_OS==2
      const unsigned int res = (unsigned int)GetFileAttributesA(path);
      return res==INVALID_FILE_ATTRIBUTES?false:(res&16);
#else
      return false;
#endif

Project: CImg
File: CImg.h

    **/
    T& front() {
      return *_data;

Project: CImg
File: CImg.h

      static cimg_int64 max() { return (cimg_int64)((cimg_uint64)-1>>1); }

Project: CImg
File: CImg.h

    **/
    const CImg<T>& save_analyze(const char *const filename, const float *const voxel_size=0) const {
      if (!filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_analyze(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(0,filename); return *this; }

      std::FILE *file;
      CImg<charT> hname(1024), iname(1024);
      const char *const ext = cimg::split_filename(filename);
      short datatype = -1;
      if (!*ext) {
        cimg_snprintf(hname,hname._width,"%s.hdr",filename);
        cimg_snprintf(iname,iname._width,"%s.img",filename);
      }
      if (!cimg::strncasecmp(ext,"hdr",3)) {
        std::strcpy(hname,filename);
        std::strncpy(iname,filename,iname._width - 1);
        cimg_sprintf(iname._data + std::strlen(iname) - 3,"img");
      }
      if (!cimg::strncasecmp(ext,"img",3)) {
        std::strcpy(hname,filename);
        std::strncpy(iname,filename,iname._width - 1);
        cimg_sprintf(hname._data + std::strlen(iname) - 3,"hdr");
      }
      if (!cimg::strncasecmp(ext,"nii",3)) {
        std::strncpy(hname,filename,hname._width - 1); *iname = 0;
      }

      CImg<charT> header(*iname?348:352,1,1,1,0);
      int *const iheader = (int*)header._data;
      *iheader = 348;
      std::strcpy(header._data + 4,"CImg");
      std::strcpy(header._data + 14," ");
      ((short*)&(header[36]))[0] = 4096;
      ((char*)&(header[38]))[0] = 114;
      ((short*)&(header[40]))[0] = 4;
      ((short*)&(header[40]))[1] = (short)_width;
      ((short*)&(header[40]))[2] = (short)_height;
      ((short*)&(header[40]))[3] = (short)_depth;
      ((short*)&(header[40]))[4] = (short)_spectrum;
      if (!cimg::strcasecmp(pixel_type(),"bool")) datatype = 2;
      if (!cimg::strcasecmp(pixel_type(),"unsigned char")) datatype = 2;
      if (!cimg::strcasecmp(pixel_type(),"char")) datatype = 2;
      if (!cimg::strcasecmp(pixel_type(),"unsigned short")) datatype = 4;
      if (!cimg::strcasecmp(pixel_type(),"short")) datatype = 4;
      if (!cimg::strcasecmp(pixel_type(),"unsigned int")) datatype = 8;
      if (!cimg::strcasecmp(pixel_type(),"int")) datatype = 8;
      if (!cimg::strcasecmp(pixel_type(),"unsigned int64")) datatype = 8;
      if (!cimg::strcasecmp(pixel_type(),"int64")) datatype = 8;
      if (!cimg::strcasecmp(pixel_type(),"float")) datatype = 16;
      if (!cimg::strcasecmp(pixel_type(),"double")) datatype = 64;
      if (datatype<0)
        throw CImgIOException(_cimg_instance
                              "save_analyze(): Unsupported pixel type '%s' for file '%s'.",
                              cimg_instance,
                              pixel_type(),filename);

      ((short*)&(header[70]))[0] = datatype;
      ((short*)&(header[72]))[0] = sizeof(T);
      ((float*)&(header[108]))[0] = (float)(*iname?0:header.width());
      ((float*)&(header[112]))[0] = 1;
      ((float*)&(header[76]))[0] = 0;
      if (voxel_size) {
        ((float*)&(header[76]))[1] = voxel_size[0];
        ((float*)&(header[76]))[2] = voxel_size[1];
        ((float*)&(header[76]))[3] = voxel_size[2];
      } else ((float*)&(header[76]))[1] = ((float*)&(header[76]))[2] = ((float*)&(header[76]))[3] = 1;
      file = cimg::fopen(hname,"wb");
      cimg::fwrite(header._data,header.width(),file);
      if (*iname) { cimg::fclose(file); file = cimg::fopen(iname,"wb"); }
      cimg::fwrite(_data,size(),file);
      cimg::fclose(file);
      return *this;

Project: CImg
File: CImg.h

    **/
    CImg<T>& pseudoinvert() {
      return get_pseudoinvert().move_to(*this);

Project: CImg
File: CImg.h

    **/
    inline cimg_ulong toc() {
      return cimg::tictoc(false);

Project: CImg
File: CImg.h

       \param[out] c C-coordinate of the pixel value, if test succeeds.
       \note If true, set coordinates (n,x,y,z,c).
    **/
    template<typename t>
    bool contains(const T& pixel, t& n, t& x, t&y, t& z, t& c) const {

Project: CImg
File: CImg.h

    **/
    CImg<T>& fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const int a0, ...) {
      const ulongT wh = (ulongT)_width*_height;
      if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,int);
      return *this;

Project: CImg
File: CImg.h

    **/
    float frames_per_second() {
      if (!_fps_timer) _fps_timer = cimg::time();
      const float delta = (cimg::time() - _fps_timer)/1000.f;
      ++_fps_frames;
      if (delta>=1) {
        _fps_fps = _fps_frames/delta;
        _fps_frames = 0;
        _fps_timer = cimg::time();
      }
      return _fps_fps;

Project: CImg
File: CImg.h

    //! Threshold pixel values \newinstance.
    CImg<T> get_threshold(const T& value, const bool soft_threshold=false, const bool strict_threshold=false) const {
      return (+*this).threshold(value,soft_threshold,strict_threshold);

Project: CImg
File: CImg.h

    //! Test if image spectrum is equal to specified value.
    bool is_sameC(const unsigned int size_c) const {
      return _spectrum==size_c;

Project: CImg
File: CImg.h

    **/
    CImg<T> get_channel(const int c0) const {
      return get_channels(c0,c0);

Project: CImg
File: CImg.h

    template<typename t>
    CImg<_cimg_Tt> operator-(const t value) const {
      return CImg<_cimg_Tt>(*this,false)-=value;

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h


      static double mp_bool(_cimg_math_parser& mp) {
        return (double)(bool)_mp_arg(2);

Project: CImg
File: CImg.h

    **/
    CImg<T>& unroll(const char axis) {
      const unsigned int siz = (unsigned int)size();
      if (siz) switch (cimg::lowercase(axis)) {
      case 'x' : _width = siz; _height = _depth = _spectrum = 1; break;
      case 'y' : _height = siz; _width = _depth = _spectrum = 1; break;
      case 'z' : _depth = siz; _width = _height = _spectrum = 1; break;
      default : _spectrum = siz; _width = _height = _depth = 1;
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    ~CImg() {
      if (!_is_shared) delete[] _data;

Project: CImg
File: CImg.h


    T& _atXY(const int x, const int y, const int z=0, const int c=0) {
      return (*this)(cimg::cut(x,0,width() - 1),
                     cimg::cut(y,0,height() - 1),z,c);

Project: CImg
File: CImg.h

    //! Return base-2 logarithm of a value.
    inline double log2(const double x) {
#if cimg_use_cpp11==1 && !defined(_MSC_VER)
      return std::log2(x);
#else
      const double base2 = std::log(2.);
      return std::log(x)/base2;
#endif

Project: CImg
File: CImg.h

    **/
    const CImg<T>& save_pnm(const char *const filename, const unsigned int bytes_per_pixel=0) const {
      return _save_pnm(0,filename,bytes_per_pixel);

Project: CImg
File: CImg.h

    template<typename tf>
    static CImg<floatT> isoline3d(CImgList<tf>& primitives, const char *const expression, const float isovalue,
                                  const float x0, const float y0, const float x1, const float y1,
                                  const int size_x=256, const int size_y=256) {
      const _functor2d_expr func(expression);
      return isoline3d(primitives,func,isovalue,x0,y0,x1,y1,size_x,size_y);

Project: CImg
File: CImg.h

    //! Test if list contains image with specified index.
    /**
       \param n Index of the checked image.
    **/

Project: CImg
File: CImg.h

    }

    //! Return a reference to the minimum pixel value of the instance list and return the minimum value as well \const.
    template<typename t>
    const T& max_min(t& min_val) const {
      bool is_all_empty = true;
      T *ptr_max = 0;
      cimglist_for(*this,l) if (!_data[l].is_empty()) {
        ptr_max = _data[l]._data;
        is_all_empty = false;
        break;
      }
      if (is_all_empty)
        throw CImgInstanceException(_cimglist_instance
                                    "max_min(): %s.",
                                    _data?"List of empty images":"Empty instance",
                                    cimglist_instance);
      T min_value = *ptr_max, 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>max_value) { max_value = val; ptr_max = ptrs; }
          if (val<min_value) min_value = val;
        }

Project: CImg
File: CImg.h

    **/
    static unsigned int keycode(const char *const keycode) {
#define _cimg_keycode(k) if (!cimg::strcasecmp(keycode,#k)) return cimg::key##k;
      _cimg_keycode(ESC); _cimg_keycode(F1); _cimg_keycode(F2); _cimg_keycode(F3);
      _cimg_keycode(F4); _cimg_keycode(F5); _cimg_keycode(F6); _cimg_keycode(F7);
      _cimg_keycode(F8); _cimg_keycode(F9); _cimg_keycode(F10); _cimg_keycode(F11);
      _cimg_keycode(F12); _cimg_keycode(PAUSE); _cimg_keycode(1); _cimg_keycode(2);
      _cimg_keycode(3); _cimg_keycode(4); _cimg_keycode(5); _cimg_keycode(6);
      _cimg_keycode(7); _cimg_keycode(8); _cimg_keycode(9); _cimg_keycode(0);
      _cimg_keycode(BACKSPACE); _cimg_keycode(INSERT); _cimg_keycode(HOME);
      _cimg_keycode(PAGEUP); _cimg_keycode(TAB); _cimg_keycode(Q); _cimg_keycode(W);
      _cimg_keycode(E); _cimg_keycode(R); _cimg_keycode(T); _cimg_keycode(Y);
      _cimg_keycode(U); _cimg_keycode(I); _cimg_keycode(O); _cimg_keycode(P);
      _cimg_keycode(DELETE); _cimg_keycode(END); _cimg_keycode(PAGEDOWN);
      _cimg_keycode(CAPSLOCK); _cimg_keycode(A); _cimg_keycode(S); _cimg_keycode(D);
      _cimg_keycode(F); _cimg_keycode(G); _cimg_keycode(H); _cimg_keycode(J);
      _cimg_keycode(K); _cimg_keycode(L); _cimg_keycode(ENTER);
      _cimg_keycode(SHIFTLEFT); _cimg_keycode(Z); _cimg_keycode(X); _cimg_keycode(C);
      _cimg_keycode(V); _cimg_keycode(B); _cimg_keycode(N); _cimg_keycode(M);
      _cimg_keycode(SHIFTRIGHT); _cimg_keycode(ARROWUP); _cimg_keycode(CTRLLEFT);
      _cimg_keycode(APPLEFT); _cimg_keycode(ALT); _cimg_keycode(SPACE); _cimg_keycode(ALTGR);
      _cimg_keycode(APPRIGHT); _cimg_keycode(MENU); _cimg_keycode(CTRLRIGHT);
      _cimg_keycode(ARROWLEFT); _cimg_keycode(ARROWDOWN); _cimg_keycode(ARROWRIGHT);
      _cimg_keycode(PAD0); _cimg_keycode(PAD1); _cimg_keycode(PAD2);
      _cimg_keycode(PAD3); _cimg_keycode(PAD4); _cimg_keycode(PAD5);
      _cimg_keycode(PAD6); _cimg_keycode(PAD7); _cimg_keycode(PAD8);
      _cimg_keycode(PAD9); _cimg_keycode(PADADD); _cimg_keycode(PADSUB);
      _cimg_keycode(PADMUL); _cimg_keycode(PADDIV);
      return 0;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& min(const CImg<t>& img) {
      const ulongT siz = size(), isiz = img.size();
      if (siz && isiz) {
        if (is_overlapped(img)) return min(+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::min((T)*(ptrs++),*ptrd);
        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = std::min((T)*(ptrs++),*ptrd);
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    CImgDisplay& close() {
      return assign();

Project: CImg
File: CImg.h


      static double mp_vector_map_vs(_cimg_math_parser& mp) { // Operator(vector,scalar)
        unsigned int
          siz = (unsigned int)mp.opcode[2],
          ptrs = (unsigned int)mp.opcode[4] + 1;
        double *ptrd = &_mp_arg(1) + 1;
        mp_func op = (mp_func)mp.opcode[3];
        CImg<ulongT> l_opcode(1,4);
        l_opcode[3] = mp.opcode[5]; // Scalar argument2
        l_opcode.swap(mp.opcode);
        ulongT &argument1 = mp.opcode[2];
        while (siz-->0) { argument1 = ptrs++; *(ptrd++) = (*op)(mp); }
        l_opcode.swap(mp.opcode);
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h

      static bool is_inf(const cimg_uint64) { return false; }

Project: CImg
File: CImg.h

    **/
    CImg<T>& load_medcon_external(const char *const filename) {
      if (!filename)
        throw CImgArgumentException(_cimg_instance
                                    "load_medcon_external(): Specified filename is (null).",
                                    cimg_instance);
      cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists
      CImg<charT> command(1024), filename_tmp(256), body(256);
      cimg::fclose(cimg::fopen(filename,"r"));
      std::FILE *file = 0;
      do {
        cimg_snprintf(filename_tmp,filename_tmp._width,"%s.hdr",cimg::filenamerand());
        if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file);
      } while (file);
      cimg_snprintf(command,command._width,"%s -w -c anlz -o \"%s\" -f \"%s\"",
                    cimg::medcon_path(),
                    CImg<charT>::string(filename_tmp)._system_strescape().data(),
                    CImg<charT>::string(filename)._system_strescape().data());
      cimg::system(command);
      cimg::split_filename(filename_tmp,body);

      cimg_snprintf(command,command._width,"%s.hdr",body._data);
      file = cimg::std_fopen(command,"rb");
      if (!file) {
        cimg_snprintf(command,command._width,"m000-%s.hdr",body._data);
        file = cimg::std_fopen(command,"rb");
        if (!file) {
          throw CImgIOException(_cimg_instance
                                "load_medcon_external(): Failed to load file '%s' with external command 'medcon'.",
                                cimg_instance,
                                filename);
        }
      }
      cimg::fclose(file);
      load_analyze(command);
      std::remove(command);
      cimg::split_filename(command,body);
      cimg_snprintf(command,command._width,"%s.img",body._data);
      std::remove(command);
      return *this;

Project: CImg
File: CImg.h

    **/
    CImg<T>& fillY(const unsigned int x, const unsigned int z, const unsigned int c, const int a0, ...) {
      if (x<_width && z<_depth && c<_spectrum) _cimg_fill1(x,0,z,c,_width,_height,int);
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<ulongT> get_label(const CImg<t>& connectivity_mask,
                           const Tfloat tolerance=0) const {
      int nb = 0;
      cimg_for(connectivity_mask,ptr,t) if (*ptr) ++nb;
      CImg<intT> dx(nb,1,1,1,0), dy(nb,1,1,1,0), dz(nb,1,1,1,0);
      nb = 0;
      cimg_forXYZ(connectivity_mask,x,y,z) if ((x || y || z) &&
                                               connectivity_mask(x,y,z)) {
        dx[nb] = x; dy[nb] = y; dz[nb++] = z;
      }
      return _label(nb,dx,dy,dz,tolerance);

Project: CImg
File: CImg.h


      static double mp_vector_init(_cimg_math_parser& mp) {
        unsigned int
          ptrs = 4U,
          ptrd = (unsigned int)mp.opcode[1] + 1,
          siz = (unsigned int)mp.opcode[3];
        switch (mp.opcode[2] - 4) {
        case 0 : std::memset(mp.mem._data + ptrd,0,siz*sizeof(double)); break; // 0 values given
        case 1 : { const double val = _mp_arg(ptrs); while (siz-->0) mp.mem[ptrd++] = val; } break;
        default : while (siz-->0) { mp.mem[ptrd++] = _mp_arg(ptrs++); if (ptrs>=mp.opcode[2]) ptrs = 4U; }
        }
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h

    //! Convert pixel values from xyY to RGB color spaces.
    CImg<T>& xyYtoRGB(const bool use_D65=true) {
      return xyYtoXYZ().XYZtoRGB(use_D65);

Project: CImg
File: CImg.h


      static double mp_do(_cimg_math_parser& mp) {
        const ulongT
          mem_body = mp.opcode[1],
          mem_cond = mp.opcode[2];
        const CImg<ulongT>
          *const p_body = ++mp.p_code,
          *const p_cond = p_body + mp.opcode[3],
          *const p_end = p_cond + mp.opcode[4];
        const unsigned int vsiz = (unsigned int)mp.opcode[5];
        if (mp.opcode[6]) { // Set default value for result and condition if necessary
          if (vsiz) CImg<doubleT>(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type<double>::nan());
          else mp.mem[mem_body] = cimg::type<double>::nan();
        }
        if (mp.opcode[7]) mp.mem[mem_cond] = 0;

        const unsigned int _break_type = mp.break_type;
        mp.break_type = 0;
        do {
          for (mp.p_code = p_body; mp.p_code<p_cond; ++mp.p_code) { // Evaluate body
            mp.opcode._data = mp.p_code->_data;
            const ulongT target = mp.opcode[1];
            mp.mem[target] = _cimg_mp_defunc(mp);
          }
          if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0;
          for (mp.p_code = p_cond; mp.p_code<p_end; ++mp.p_code) { // Evaluate condition
            mp.opcode._data = mp.p_code->_data;
            const ulongT target = mp.opcode[1];
            mp.mem[target] = _cimg_mp_defunc(mp);
          }
          if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0;
        } while (mp.mem[mem_cond]);
        mp.break_type = _break_type;
        mp.p_code = p_end - 1;
        return mp.mem[mem_body];

Project: CImg
File: CImg.h

    CImgAbortException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgAbortException",true); }
    CImgAbortException(const CImgAbortException& e):std::exception(e) {
      const size_t size = std::strlen(e._message);
      _message = new char[size + 1];
      std::strncpy(_message,e._message,size);
      _message[size] = 0;

Project: CImg
File: CImg.h

    //! Mirror image content along specified axis \newinstance.
    CImg<T> get_mirror(const char axis) const {
      return (+*this).mirror(axis);

Project: CImg
File: CImg.h

    //! Return a \c 1x13 image containing specified values.
    static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3,
                          const T& a4, const T& a5, const T& a6, const T& a7,
                          const T& a8, const T& a9, const T& a10, const T& a11,
			  const T& a12) {
      CImg<T> r(1,13); T *ptr = r._data;
      *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
      *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7;
      *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11;
      *(ptr++) = a12;
      return r;

Project: CImg
File: CImg.h


      static double mp_std(_cimg_math_parser& mp) {
        const unsigned int i_end = (unsigned int)mp.opcode[2];
        CImg<doubleT> vals(i_end - 3);
        double *p = vals.data();
        for (unsigned int i = 3; i<i_end; ++i) *(p++) = _mp_arg(i);
        return std::sqrt(vals.variance());

Project: CImg
File: CImg.h


      unsigned int scalar5(const mp_func op,
                           const unsigned int arg1, const unsigned int arg2, const unsigned int arg3,
                           const unsigned int arg4, const unsigned int arg5) {
        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:
          arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4:
          arg5!=~0U && arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5:scalar();
        CImg<ulongT>::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5).move_to(code);
        return pos;

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 T& val8, const T& val9, const T& val10, const T& val11) const {
      return CImg<T>(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,
                                                           val11);

Project: CImg
File: CImg.h

    //! Access pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y,\c z) \const.
    T atNXYZ(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const {
      return (pos<0 || pos>=width())?out_value:_data[pos].atXYZ(x,y,z,c,out_value);

Project: CImg
File: CImg.h

    **/
    CImgDisplay& set_key() {
      std::memset((void*)_keys,0,128*sizeof(unsigned int));
      std::memset((void*)_released_keys,0,128*sizeof(unsigned int));
      _is_keyESC = _is_keyF1 = _is_keyF2 = _is_keyF3 = _is_keyF4 = _is_keyF5 = _is_keyF6 = _is_keyF7 = _is_keyF8 =
        _is_keyF9 = _is_keyF10 = _is_keyF11 = _is_keyF12 = _is_keyPAUSE = _is_key1 = _is_key2 = _is_key3 = _is_key4 =
        _is_key5 = _is_key6 = _is_key7 = _is_key8 = _is_key9 = _is_key0 = _is_keyBACKSPACE = _is_keyINSERT =
        _is_keyHOME = _is_keyPAGEUP = _is_keyTAB = _is_keyQ = _is_keyW = _is_keyE = _is_keyR = _is_keyT = _is_keyY =
        _is_keyU = _is_keyI = _is_keyO = _is_keyP = _is_keyDELETE = _is_keyEND = _is_keyPAGEDOWN = _is_keyCAPSLOCK =
        _is_keyA = _is_keyS = _is_keyD = _is_keyF = _is_keyG = _is_keyH = _is_keyJ = _is_keyK = _is_keyL =
        _is_keyENTER = _is_keySHIFTLEFT = _is_keyZ = _is_keyX = _is_keyC = _is_keyV = _is_keyB = _is_keyN =
        _is_keyM = _is_keySHIFTRIGHT = _is_keyARROWUP = _is_keyCTRLLEFT = _is_keyAPPLEFT = _is_keyALT = _is_keySPACE =
        _is_keyALTGR = _is_keyAPPRIGHT = _is_keyMENU = _is_keyCTRLRIGHT = _is_keyARROWLEFT = _is_keyARROWDOWN =
        _is_keyARROWRIGHT = _is_keyPAD0 = _is_keyPAD1 = _is_keyPAD2 = _is_keyPAD3 = _is_keyPAD4 = _is_keyPAD5 =
        _is_keyPAD6 = _is_keyPAD7 = _is_keyPAD8 = _is_keyPAD9 = _is_keyPADADD = _is_keyPADSUB = _is_keyPADMUL =
        _is_keyPADDIV = false;
      _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


      static double mp_tan(_cimg_math_parser& mp) {
        return std::tan(_mp_arg(2));

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

    /**
      \param title Label set to the information displayed.
      \param display_stats Tells if image statistics must be computed and displayed.
    **/
    const CImgList<T>& print(const char *const title=0, const bool display_stats=true) const {
      unsigned int msiz = 0;
      cimglist_for(*this,l) msiz+=_data[l].size();
      msiz*=sizeof(T);
      const unsigned int mdisp = msiz<8*1024?0U:msiz<8*1024*1024?1U:2U;
      CImg<charT> _title(64);
      if (!title) cimg_snprintf(_title,_title._width,"CImgList<%s>",pixel_type());
      std::fprintf(cimg::output(),"%s%s%s%s: %sthis%s = %p, %ssize%s = %u/%u [%u %s], %sdata%s = (CImg<%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,_allocated_width,
                   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.\n",(void*)((char*)end() - 1));
      else std::fprintf(cimg::output(),".\n");

      char tmp[16] = { 0 };
      cimglist_for(*this,ll) {
        cimg_snprintf(tmp,sizeof(tmp),"[%d]",ll);
        std::fprintf(cimg::output(),"  ");
        _data[ll].print(tmp,display_stats);
        if (ll==3 && width()>8) { ll = width() - 5; std::fprintf(cimg::output(),"  ...\n"); }

Project: CImg
File: CImg.h

    template<typename t>
    CImgList<_cimg_Tt> operator,(const CImg<t>& img) const {
      return CImgList<_cimg_Tt>(*this,img);

Project: CImg
File: CImg.h


      static double mp_find_seq(_cimg_math_parser& mp) {
        const bool is_forward = (bool)_mp_arg(6);
        const ulongT
          siz1 = (ulongT)mp.opcode[3],
          siz2 = (ulongT)mp.opcode[5];
        longT ind = (longT)(mp.opcode[7]!=_cimg_mp_slot_nan?_mp_arg(7):is_forward?0:siz1 - 1);
        if (ind<0 || ind>=(longT)siz1) return -1.;
        const double
          *const ptr1b = &_mp_arg(2) + 1,
          *const ptr1e = ptr1b + siz1,
          *const ptr2b = &_mp_arg(4) + 1,
          *const ptr2e = ptr2b + siz2,
          *ptr1 = ptr1b + ind,
          *p1 = 0,
          *p2 = 0;

        // Forward search.
        if (is_forward) {
          do {
            while (ptr1<ptr1e && *ptr1!=*ptr2b) ++ptr1;
            if (ptr1>=ptr1e) return -1.;
            p1 = ptr1 + 1;
            p2 = ptr2b + 1;
            while (p1<ptr1e && p2<ptr2e && *p1==*p2) { ++p1; ++p2; }
          } while (p2<ptr2e && ++ptr1<ptr1e);
          return p2<ptr2e?-1.:(double)(ptr1 - ptr1b);
        }

        // Backward search.
        do {
          while (ptr1>=ptr1b && *ptr1!=*ptr2b) --ptr1;
          if (ptr1<ptr1b) return -1.;
          p1 = ptr1 + 1;
          p2 = ptr2b + 1;
          while (p1<ptr1e && p2<ptr2e && *p1==*p2) { ++p1; ++p2; }
        } while (p2<ptr2e && --ptr1>=ptr1b);
        return p2<ptr2e?-1.:(double)(ptr1 - ptr1b);

Project: CImg
File: CImg.h


      static double mp_polygon(_cimg_math_parser& mp) {
        const unsigned int i_end = (unsigned int)mp.opcode[2];
        unsigned int ind = (unsigned int)mp.opcode[3];
        if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(3),mp.listin.width());
        CImg<T> &img = ind==~0U?mp.imgout:mp.listout[ind];
        bool is_invalid_arguments = i_end<=4, is_outlined = false;
        if (!is_invalid_arguments) {
          int nbv = (int)_mp_arg(4);
          if (!nbv) is_invalid_arguments = true;
          else {
            if (nbv<0) { nbv = -nbv; is_outlined = true; }
            CImg<intT> points(nbv,2,1,1,0);
            CImg<T> color(img._spectrum,1,1,1,0);
            float opacity = 1;
            unsigned int i = 5, pattern=~0U;
            cimg_foroff(points,k) if (i<i_end) points(k/2,k%2) = (int)cimg::round(_mp_arg(i++));
            else { is_invalid_arguments = true; break; }
            if (!is_invalid_arguments) {
              if (i<i_end) opacity = (float)_mp_arg(i++);
              if (is_outlined && i<i_end) pattern = (unsigned int)_mp_arg(i++);
              cimg_forX(color,k) if (i<i_end) color[k] = (T)_mp_arg(i++);
              else { color.resize(k,1,1,1,-1); break; }
              color.resize(img._spectrum,1,1,1,0,2);
              if (is_outlined) img.draw_polygon(points,color._data,opacity,pattern);
              else img.draw_polygon(points,color._data,opacity);
            }
          }
        }
        if (is_invalid_arguments) {
          CImg<doubleT> args(i_end - 4);
          cimg_forX(args,k) args[k] = _mp_arg(4 + k);
          if (ind==~0U)
            throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'polygon()': "
                                        "Invalid arguments '%s'. ",
                                        mp.imgin.pixel_type(),args.value_string()._data);
          else
            throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'polygon()': "
                                        "Invalid arguments '#%u%s%s'. ",
                                        mp.imgin.pixel_type(),ind,args._width?",":"",args.value_string()._data);
        }
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h

      \param file File to write data to.
      \param chroma_subsampling Type of chroma subsampling. Can be <tt>{ 420 | 422 | 444 }</tt>.
      \param is_rgb Tells if the RGB to YUV conversion must be done for saving.
    **/
    const CImgList<T>& save_yuv(std::FILE *const file,

Project: CImg
File: CImg.h


      static double mp_if(_cimg_math_parser& mp) {
        const bool is_cond = (bool)_mp_arg(2);
        const ulongT
          mem_left = mp.opcode[3],
          mem_right = mp.opcode[4];
        const CImg<ulongT>
          *const p_right = ++mp.p_code + mp.opcode[5],
          *const p_end = p_right + mp.opcode[6];
        const unsigned int vtarget = (unsigned int)mp.opcode[1], vsiz = (unsigned int)mp.opcode[7];
        if (is_cond) for ( ; mp.p_code<p_right; ++mp.p_code) {
            mp.opcode._data = mp.p_code->_data;
            const ulongT target = mp.opcode[1];
            mp.mem[target] = _cimg_mp_defunc(mp);
          }
        else for (mp.p_code = p_right; mp.p_code<p_end; ++mp.p_code) {
            mp.opcode._data = mp.p_code->_data;
            const ulongT target = mp.opcode[1];
            mp.mem[target] = _cimg_mp_defunc(mp);
          }
        if (mp.p_code==mp.p_break) --mp.p_code;
        else mp.p_code = p_end - 1;
        if (vsiz) std::memcpy(&mp.mem[vtarget] + 1,&mp.mem[is_cond?mem_left:mem_right] + 1,sizeof(double)*vsiz);
        return mp.mem[is_cond?mem_left:mem_right];

Project: CImg
File: CImg.h


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

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

    **/
    static CImgDisplay& empty() {
      static CImgDisplay _empty;
      return _empty.assign();

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& operator/=(const CImg<t>& img) {
      return (*this*img.get_invert()).move_to(*this);

Project: CImg
File: CImg.h


      static double mp_matrix_svd(_cimg_math_parser& mp) {
        double *ptrd = &_mp_arg(1) + 1;
        const double *ptr1 = &_mp_arg(2) + 1;
        const unsigned int
          k = (unsigned int)mp.opcode[3],
          l = (unsigned int)mp.opcode[4];
        CImg<doubleT> U, S, V;
        CImg<doubleT>(ptr1,k,l,1,1,true).SVD(U,S,V);
        CImg<doubleT>(ptrd,1,k,1,1,true) = S;
        CImg<doubleT>(ptrd + k,k,l,1,1,true) = U;
        CImg<doubleT>(ptrd + k + k*l,k,k,1,1,true) = V;
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h

    ~CImgException() throw() { delete[] _message; }
    CImgException& operator=(const CImgException& e) {
      const size_t size = std::strlen(e._message);
      _message = new char[size + 1];
      std::strncpy(_message,e._message,size);
      _message[size] = 0;
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& draw_image(const int x0,
                        const CImg<t>& sprite, const float opacity=1) {
      return draw_image(x0,0,sprite,opacity);

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

     **/
    T& at(const int offset) {
      if (is_empty())
        throw CImgInstanceException(_cimg_instance
                                    "at(): Empty instance.",
                                    cimg_instance);
      return _at(offset);

Project: CImg
File: CImg.h

    template<typename T1, typename T2>
    inline void swap(T1& a1, T1& b1, T2& a2, T2& b2) {
      cimg::swap(a1,b1); cimg::swap(a2,b2);

Project: CImg
File: CImg.h


      static double mp_image_display(_cimg_math_parser& mp) {
        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width());
        cimg::mutex(6);
        CImg<T> &img = mp.listout[ind];
        CImg<charT> title(256);
        std::fputc('\n',cimg::output());
        cimg_snprintf(title,title._width,"[ Image #%u ]",ind);
        img.display(title);
        cimg::mutex(6,0);
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h

    //! Convert pixel values from xyY to RGB color spaces \newinstance.
    CImg<Tuchar> get_xyYtoRGB(const bool use_D65=true) const {
      return CImg<Tuchar>(*this,false).xyYtoRGB(use_D65);

Project: CImg
File: CImg.h

    **/
    unsigned int normalization() const {
      return _normalization;

Project: CImg
File: CImg.h

    **/
    bool& is_key(const char *const keycode) {
      static bool f = false;
      f = false;
#define _cimg_iskey_test2(k) if (!cimg::strcasecmp(keycode,#k)) return _is_key##k;
      _cimg_iskey_test2(ESC); _cimg_iskey_test2(F1); _cimg_iskey_test2(F2); _cimg_iskey_test2(F3);
      _cimg_iskey_test2(F4); _cimg_iskey_test2(F5); _cimg_iskey_test2(F6); _cimg_iskey_test2(F7);
      _cimg_iskey_test2(F8); _cimg_iskey_test2(F9); _cimg_iskey_test2(F10); _cimg_iskey_test2(F11);
      _cimg_iskey_test2(F12); _cimg_iskey_test2(PAUSE); _cimg_iskey_test2(1); _cimg_iskey_test2(2);
      _cimg_iskey_test2(3); _cimg_iskey_test2(4); _cimg_iskey_test2(5); _cimg_iskey_test2(6);
      _cimg_iskey_test2(7); _cimg_iskey_test2(8); _cimg_iskey_test2(9); _cimg_iskey_test2(0);
      _cimg_iskey_test2(BACKSPACE); _cimg_iskey_test2(INSERT); _cimg_iskey_test2(HOME);
      _cimg_iskey_test2(PAGEUP); _cimg_iskey_test2(TAB); _cimg_iskey_test2(Q); _cimg_iskey_test2(W);
      _cimg_iskey_test2(E); _cimg_iskey_test2(R); _cimg_iskey_test2(T); _cimg_iskey_test2(Y);
      _cimg_iskey_test2(U); _cimg_iskey_test2(I); _cimg_iskey_test2(O); _cimg_iskey_test2(P);
      _cimg_iskey_test2(DELETE); _cimg_iskey_test2(END); _cimg_iskey_test2(PAGEDOWN);
      _cimg_iskey_test2(CAPSLOCK); _cimg_iskey_test2(A); _cimg_iskey_test2(S); _cimg_iskey_test2(D);
      _cimg_iskey_test2(F); _cimg_iskey_test2(G); _cimg_iskey_test2(H); _cimg_iskey_test2(J);
      _cimg_iskey_test2(K); _cimg_iskey_test2(L); _cimg_iskey_test2(ENTER);
      _cimg_iskey_test2(SHIFTLEFT); _cimg_iskey_test2(Z); _cimg_iskey_test2(X); _cimg_iskey_test2(C);
      _cimg_iskey_test2(V); _cimg_iskey_test2(B); _cimg_iskey_test2(N); _cimg_iskey_test2(M);
      _cimg_iskey_test2(SHIFTRIGHT); _cimg_iskey_test2(ARROWUP); _cimg_iskey_test2(CTRLLEFT);
      _cimg_iskey_test2(APPLEFT); _cimg_iskey_test2(ALT); _cimg_iskey_test2(SPACE); _cimg_iskey_test2(ALTGR);
      _cimg_iskey_test2(APPRIGHT); _cimg_iskey_test2(MENU); _cimg_iskey_test2(CTRLRIGHT);
      _cimg_iskey_test2(ARROWLEFT); _cimg_iskey_test2(ARROWDOWN); _cimg_iskey_test2(ARROWRIGHT);
      _cimg_iskey_test2(PAD0); _cimg_iskey_test2(PAD1); _cimg_iskey_test2(PAD2);
      _cimg_iskey_test2(PAD3); _cimg_iskey_test2(PAD4); _cimg_iskey_test2(PAD5);
      _cimg_iskey_test2(PAD6); _cimg_iskey_test2(PAD7); _cimg_iskey_test2(PAD8);
      _cimg_iskey_test2(PAD9); _cimg_iskey_test2(PADADD); _cimg_iskey_test2(PADSUB);
      _cimg_iskey_test2(PADMUL); _cimg_iskey_test2(PADDIV);
      return f;

Project: CImg
File: CImg.h


    CImgDisplay& show_mouse() {
      if (is_empty()) return *this;
      Display *const dpy = cimg::X11_attr().display;
      cimg_lock_display();
      XUndefineCursor(dpy,_window);
      cimg_unlock_display();
      return *this;

Project: CImg
File: CImg.h

    template<typename tc, typename t>
    CImg<T>& draw_text(const int x0, const int y0,
                       const char *const text,
                       const int, const tc *const background_color,
                       const float opacity, const CImgList<t>& font, ...) {
      if (!font) return *this;
      CImg<charT> tmp(2048);
      std::va_list ap; va_start(ap,font);
      cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap);
      return _draw_text(x0,y0,tmp,(tc*)0,background_color,opacity,font,false);

Project: CImg
File: CImg.h


    T _cubic_atX_c(const float fx, const int y, const int z, const int c) const {
      return cimg::type<T>::cut(_cubic_atX(fx,y,z,c));

Project: CImg
File: CImg.h

    //! Convert pixel values from Lab to RGB color spaces \newinstance.
    CImg<Tuchar> get_LabtoRGB(const bool use_D65=true) const {
      return CImg<Tuchar>(*this,false).LabtoRGB(use_D65);

Project: CImg
File: CImg.h


      static double mp_srand0(_cimg_math_parser& mp) {
        cimg::srand(&mp.rng);

#if cimg_use_openmp!=0
        mp.rng+=omp_get_thread_num();
#endif
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h

    //! Return a \c 1x8 image containing specified values.
    static CImg<T> vector(const T& a0, const T& a1, const T& a2, const T& a3,
			  const T& a4, const T& a5, const T& a6, const T& a7) {
      CImg<T> r(1,8); T *ptr = r._data;
      *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3;
      *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7;
      return r;

Project: CImg
File: CImg.h

    **/
    unsigned int size() const {
      return _width;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<_cimg_Tt> operator%(const CImg<t>& img) const {
      return CImg<_cimg_Tt>(*this,false)%=img;

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

    template<typename t>
    CImgList<T>& operator=(const CImgList<t>& list) {
      return assign(list);

Project: CImg
File: CImg.h

    //! Load image from a RGBA file \overloading.
    CImg<T>& load_rgba(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) {
      return _load_rgba(file,0,dimw,dimh);

Project: CImg
File: CImg.h


      static double mp_vector_eq(_cimg_math_parser& mp) {
        const double
          *ptr1 = &_mp_arg(2) + 1,
          *ptr2 = &_mp_arg(4) + 1;
        unsigned int p1 = (unsigned int)mp.opcode[3], p2 = (unsigned int)mp.opcode[5], n;
        const int N = (int)_mp_arg(6);
        const bool case_sensitive = (bool)_mp_arg(7);
        bool still_equal = true;
        double value;
        if (!N) return true;

        // Compare all values.
        if (N<0) {
          if (p1>0 && p2>0) { // Vector == vector
            if (p1!=p2) return false;
            if (case_sensitive)
              while (still_equal && p1--) still_equal = *(ptr1++)==*(ptr2++);
            else
              while (still_equal && p1--)
                still_equal = cimg::lowercase(*(ptr1++))==cimg::lowercase(*(ptr2++));
            return still_equal;
          } else if (p1>0 && !p2) { // Vector == scalar
            value = _mp_arg(4);
            if (!case_sensitive) value = cimg::lowercase(value);
            while (still_equal && p1--) still_equal = *(ptr1++)==value;
            return still_equal;
          } else if (!p1 && p2>0) { // Scalar == vector
            value = _mp_arg(2);
            if (!case_sensitive) value = cimg::lowercase(value);
            while (still_equal && p2--) still_equal = *(ptr2++)==value;
            return still_equal;
          } else { // Scalar == scalar
            if (case_sensitive) return _mp_arg(2)==_mp_arg(4);
            else return cimg::lowercase(_mp_arg(2))==cimg::lowercase(_mp_arg(4));
          }
        }

        // Compare only first N values.
        if (p1>0 && p2>0) { // Vector == vector
          n = cimg::min((unsigned int)N,p1,p2);
          if (case_sensitive)
            while (still_equal && n--) still_equal = *(ptr1++)==(*ptr2++);
          else
            while (still_equal && n--) still_equal = cimg::lowercase(*(ptr1++))==cimg::lowercase(*(ptr2++));
          return still_equal;
        } else if (p1>0 && !p2) { // Vector == scalar
          n = std::min((unsigned int)N,p1);
          value = _mp_arg(4);
          if (!case_sensitive) value = cimg::lowercase(value);
          while (still_equal && n--) still_equal = *(ptr1++)==value;
          return still_equal;
        } else if (!p1 && p2>0) { // Scalar == vector
          n = std::min((unsigned int)N,p2);
          value = _mp_arg(2);
          if (!case_sensitive) value = cimg::lowercase(value);
          while (still_equal && n--) still_equal = *(ptr2++)==value;
          return still_equal;
        }  // Scalar == scalar
        if (case_sensitive) return _mp_arg(2)==_mp_arg(4);
        return cimg::lowercase(_mp_arg(2))==cimg::lowercase(_mp_arg(4));

Project: CImg
File: CImg.h

      CImgDisplay disp;
      return _select(disp,title,feature_type,axis,align,exit_on_anykey,0,false,false,false);
    }

    CImg<intT> _select(CImgDisplay &disp, const char *const title, const bool feature_type,
                       const char axis, const float align, const bool exit_on_anykey,
                       const unsigned int orig, const bool resize_disp,
                       const bool exit_on_rightbutton, const bool exit_on_wheel) const {
      if (is_empty())
        throw CImgInstanceException(_cimglist_instance
                                    "select(): Empty instance.",
                                    cimglist_instance);

      // Create image correspondence table and get list dimensions for visualization.
      CImgList<uintT> _indices;
      unsigned int max_width = 0, max_height = 0, sum_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;
        if (h>max_height) max_height = h;
        sum_width+=w; sum_height+=h;
        if (axis=='x') CImg<uintT>(w,1,1,1,(unsigned int)l).move_to(_indices);
        else CImg<uintT>(h,1,1,1,(unsigned int)l).move_to(_indices);
      }
      const CImg<uintT> indices0 = _indices>'x';

      // Create display window.
      if (!disp) {
        if (axis=='x') disp.assign(cimg_fitscreen(sum_width,max_height,1),title?title:0,1);
        else disp.assign(cimg_fitscreen(max_width,sum_height,1),title?title:0,1);
        if (!title) disp.set_title("CImgList<%s> (%u)",pixel_type(),_width);
      } else {
        if (title) disp.set_title("%s",title);
        disp.move_inside_screen();
      }
      if (resize_disp) {
        if (axis=='x') disp.resize(cimg_fitscreen(sum_width,max_height,1),false);
        else disp.resize(cimg_fitscreen(max_width,sum_height,1),false);
      }

      const unsigned int old_normalization = disp.normalization();
      bool old_is_resized = disp.is_resized();
      disp._normalization = 0;
      disp.show().set_key(0).show_mouse();
      static const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 };

      // Enter event loop.
      CImg<ucharT> visu0, visu;
      CImg<uintT> indices;
      CImg<intT> positions(_width,4,1,1,-1);
      int oindex0 = -1, oindex1 = -1, index0 = -1, index1 = -1;
      bool is_clicked = false, is_selected = false, text_down = false, update_display = true;
      unsigned int key = 0;

      while (!is_selected && !disp.is_closed() && !key) {

        // Create background image.
        if (!visu0) {
          visu0.assign(disp._width,disp._height,1,3,0); visu.assign();
          (indices0.get_resize(axis=='x'?visu0._width:visu0._height,1)).move_to(indices);
          unsigned int _ind = 0;
          const CImg<T> onexone(1,1,1,1,(T)0);
          if (axis=='x')
            cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width,4))
            cimglist_for(*this,ind) {
              unsigned int x0 = 0;
              while (x0<visu0._width && indices[x0++]!=(unsigned int)ind) {}
              unsigned int x1 = x0;
              while (x1<visu0._width && indices[x1++]==(unsigned int)ind) {}
              const CImg<T> &src = _data[ind]?_data[ind]:onexone;
              CImg<ucharT> res;
              src._get_select(disp,old_normalization,src._width/2,src._height/2,src._depth/2).
                move_to(res);
              const unsigned int h = CImgDisplay::_fitscreen(res._width,res._height,1,128,-85,true);
              res.resize(x1 - x0,std::max(32U,h*disp._height/max_height),1,res._spectrum==1?3:-100);
              positions(ind,0) = positions(ind,2) = (int)x0;
              positions(ind,1) = positions(ind,3) = (int)(align*(visu0.height() - res.height()));
              positions(ind,2)+=res._width;
              positions(ind,3)+=res._height - 1;
              visu0.draw_image(positions(ind,0),positions(ind,1),res);
            }
          else
            cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width,4))
            cimglist_for(*this,ind) {
              unsigned int y0 = 0;
              while (y0<visu0._height && indices[y0++]!=(unsigned int)ind) {}
              unsigned int y1 = y0;
              while (y1<visu0._height && indices[y1++]==(unsigned int)ind) {}
              const CImg<T> &src = _data[ind]?_data[ind]:onexone;
              CImg<ucharT> res;
              src._get_select(disp,old_normalization,(src._width - 1)/2,(src._height - 1)/2,(src._depth - 1)/2).
                move_to(res);
              const unsigned int w = CImgDisplay::_fitscreen(res._width,res._height,1,128,-85,false);
              res.resize(std::max(32U,w*disp._width/max_width),y1 - y0,1,res._spectrum==1?3:-100);
              positions(ind,0) = positions(ind,2) = (int)(align*(visu0.width() - res.width()));
              positions(ind,1) = positions(ind,3) = (int)y0;
              positions(ind,2)+=res._width - 1;
              positions(ind,3)+=res._height;
              visu0.draw_image(positions(ind,0),positions(ind,1),res);
            }
          if (axis=='x') --positions(_ind,2); else --positions(_ind,3);
          update_display = true;
        }

        if (!visu || oindex0!=index0 || oindex1!=index1) {
          if (index0>=0 && index1>=0) {
            visu.assign(visu0,false);
            const int indm = std::min(index0,index1), indM = std::max(index0,index1);
            for (int ind = indm; ind<=indM; ++ind) if (positions(ind,0)>=0) {
                visu.draw_rectangle(positions(ind,0),positions(ind,1),positions(ind,2),positions(ind,3),
                                    background_color,0.2f);
                if ((axis=='x' && positions(ind,2) - positions(ind,0)>=8) ||
                    (axis!='x' && positions(ind,3) - positions(ind,1)>=8))
                  visu.draw_rectangle(positions(ind,0),positions(ind,1),positions(ind,2),positions(ind,3),
                                      foreground_color,0.9f,0xAAAAAAAA);
              }
            if (is_clicked) visu.__draw_text(" Images #%u - #%u, Size = %u ",(int)text_down,
                                             orig + indm,orig + indM,indM - indm + 1);
            else visu.__draw_text(" Image #%u (%u,%u,%u,%u) ",(int)text_down,
                                  orig + index0,
                                  _data[index0]._width,
                                  _data[index0]._height,
                                  _data[index0]._depth,
                                  _data[index0]._spectrum);
            update_display = true;
          } else visu.assign();
        }
        if (!visu) { visu.assign(visu0,true); update_display = true; }
        if (update_display) { visu.display(disp); update_display = false; }
        disp.wait();

        // Manage user events.
        const int xm = disp.mouse_x(), ym = disp.mouse_y();
        int index = -1;

        if (xm>=0) {
          index = (int)indices(axis=='x'?xm:ym);
          if (disp.button()&1) {
            if (!is_clicked) { is_clicked = true; oindex0 = index0; index0 = index; }
            oindex1 = index1; index1 = index;
            if (!feature_type) is_selected = true;
          } else {
            if (!is_clicked) { oindex0 = oindex1 = index0; index0 = index1 = index; }
            else is_selected = true;
          }
        } else {
          if (is_clicked) {
            if (!(disp.button()&1)) { is_clicked = is_selected = false; index0 = index1 = -1; }
            else index1 = -1;
          } else index0 = index1 = -1;
        }

        if (disp.button()&4) { is_clicked = is_selected = false; index0 = index1 = -1; }
        if (disp.button()&2 && exit_on_rightbutton) { is_selected = true; index1 = index0 = -1; }
        if (disp.wheel() && exit_on_wheel) is_selected = true;

        CImg<charT> filename(32);
        switch (key = disp.key()) {
#if cimg_OS!=2
        case cimg::keyCTRLRIGHT :
#endif
        case 0 : case cimg::keyCTRLLEFT : key = 0; break;
        case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            disp.set_fullscreen(false).
              resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false),
                     CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false).
              _is_resized = true;
            disp.set_key(key,false); key = 0; visu0.assign();
          } break;
        case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            disp.set_fullscreen(false).
              resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true;
            disp.set_key(key,false); key = 0; visu0.assign();
          } break;
        case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            disp.set_fullscreen(false).
              resize(cimg_fitscreen(axis=='x'?sum_width:max_width,axis=='x'?max_height:sum_height,1),false).
              _is_resized = true;
            disp.set_key(key,false); key = 0; visu0.assign();
          } break;
        case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true;
            disp.set_key(key,false); key = 0; visu0.assign();
          } break;
        case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            static unsigned int snap_number = 0;
            std::FILE *file;
            do {
              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++);
              if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file);
            } while (file);
            if (visu0) {
              (+visu0).__draw_text(" Saving snapshot... ",(int)text_down).display(disp);
              visu0.save(filename);
              (+visu0).__draw_text(" Snapshot '%s' saved. ",(int)text_down,filename._data).display(disp);
            }
            disp.set_key(key,false).wait(); key = 0;
          } break;
        case cimg::keyO :
          if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            static unsigned int snap_number = 0;
            std::FILE *file;
            do {
#ifdef cimg_use_zlib
              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++);
#else
              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++);
#endif
              if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file);
            } while (file);
            (+visu0).__draw_text(" Saving instance... ",(int)text_down).display(disp);
            save(filename);
            (+visu0).__draw_text(" Instance '%s' saved. ",(int)text_down,filename._data).display(disp);
            disp.set_key(key,false).wait(); key = 0;
          } break;
        }
        if (disp.is_resized()) { disp.resize(false); visu0.assign(); }
        if (ym>=0 && ym<13) { if (!text_down) { visu.assign(); text_down = true; }}
        else if (ym>=visu.height() - 13) { if (text_down) { visu.assign(); text_down = false; }}
        if (!exit_on_anykey && key && key!=cimg::keyESC &&
            (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) {
          key = 0;
        }
      }
      CImg<intT> res(1,2,1,1,-1);
      if (is_selected) {
        if (feature_type) res.fill(std::min(index0,index1),std::max(index0,index1));
        else res.fill(index0);
      }
      if (!(disp.button()&2)) disp.set_button();
      disp._normalization = old_normalization;

Project: CImg
File: CImg.h

    template<typename t>
    const T& max_min(t& min_val) const {
      if (is_empty())
        throw CImgInstanceException(_cimg_instance
                                    "max_min(): Empty instance.",
                                    cimg_instance);
      const T *ptr_max = _data;
      T max_value = *ptr_max, min_value = max_value;
      cimg_for(*this,ptrs,T) {
        const T val = *ptrs;
        if (val>max_value) { max_value = val; ptr_max = ptrs; }
        if (val<min_value) min_value = val;
      }
      min_val = (t)min_value;
      return *ptr_max;

Project: CImg
File: CImg.h

    //! Equalize histogram of pixel values \overloading.
    CImg<T>& equalize(const unsigned int nb_levels) {
      if (!nb_levels || is_empty()) return *this;
      T vmax = 0, vmin = min_max(vmax);
      return equalize(nb_levels,vmin,vmax);

Project: CImg
File: CImg.h

    **/
    CImgList<T>& operator=(const char *const filename) {
      return assign(filename);

Project: CImg
File: CImg.h


      static double mp_minus(_cimg_math_parser& mp) {
        return -_mp_arg(2);

Project: CImg
File: CImg.h

    //! Rotate image with arbitrary angle, around a center point \newinstance.
    CImg<T> get_rotate(const float angle, const float cx, const float cy,
                       const unsigned int interpolation, const unsigned int boundary_conditions=0) const {
      if (is_empty()) return *this;
      CImg<T> res(_width,_height,_depth,_spectrum);
      _rotate(res,angle,interpolation,boundary_conditions,cx,cy,cx,cy);
      return res;

Project: CImg
File: CImg.h

      static long double max() { return LDBL_MAX; }

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T> get_warp(const CImg<t>& p_warp, const unsigned int mode=0,
                     const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const {
      if (is_empty() || !p_warp) return *this;
      if (mode && !is_sameXYZ(p_warp))
        throw CImgArgumentException(_cimg_instance
                                    "warp(): Instance and specified relative warping field (%u,%u,%u,%u,%p) "
                                    "have different XYZ dimensions.",
                                    cimg_instance,
                                    p_warp._width,p_warp._height,p_warp._depth,p_warp._spectrum,p_warp._data);

      CImg<T> res(p_warp._width,p_warp._height,p_warp._depth,_spectrum);

      if (p_warp._spectrum==1) { // 1D warping
        if (mode>=3) { // Forward-relative warp
          res.fill((T)0);
          if (interpolation>=1) // Linear interpolation
            cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
            cimg_forYZC(res,y,z,c) {
              const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c);
              cimg_forX(res,x) res.set_linear_atX(*(ptrs++),x + (float)*(ptrs0++),y,z,c);
            }
          else // Nearest-neighbor interpolation
            cimg_forYZC(res,y,z,c) {
              const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c);
              cimg_forX(res,x) {
                const int X = x + (int)cimg::round(*(ptrs0++));
                if (X>=0 && X<width()) res(X,y,z,c) = *(ptrs++);
              }
            }
        } else if (mode==2) { // Forward-absolute warp
          res.fill((T)0);
          if (interpolation>=1) // Linear interpolation
            cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
            cimg_forYZC(res,y,z,c) {
              const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c);
              cimg_forX(res,x) res.set_linear_atX(*(ptrs++),(float)*(ptrs0++),y,z,c);
            }
          else // Nearest-neighbor interpolation
            cimg_forYZC(res,y,z,c) {
              const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c);
              cimg_forX(res,x) {
                const int X = (int)cimg::round(*(ptrs0++));
                if (X>=0 && X<width()) res(X,y,z,c) = *(ptrs++);
              }
            }
        } else if (mode==1) { // Backward-relative warp
          if (interpolation==2) // Cubic interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const float w2 = 2.f*width();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const float mx = cimg::mod(x - (float)*(ptrs0++),w2);
                  *(ptrd++) = _cubic_atX_c(mx<width()?mx:w2 - mx - 1,y,z,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _cubic_atX_pc(x - (float)*(ptrs0++),y,z,c);
              }
              break;
            case 1 : // Neumann
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _cubic_atX_c(x - (float)*(ptrs0++),y,z,c);
              }
              break;
            default : // Dirichlet
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = cubic_atX_c(x - (float)*(ptrs0++),y,z,c,(T)0);
              }
            }
          else if (interpolation==1) // Linear interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const float w2 = 2.f*width();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const float mx = cimg::mod(x - (float)*(ptrs0++),w2);
                  *(ptrd++) = (T)_linear_atX(mx<width()?mx:w2 - mx - 1,y,z,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)_linear_atX_p(x - (float)*(ptrs0++),y,z,c);
              }
              break;
            case 1 : // Neumann
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)_linear_atX(x - (float)*(ptrs0++),y,z,c);
              }
              break;
            default : // Dirichlet
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)linear_atX(x - (float)*(ptrs0++),y,z,c,(T)0);
              }
            }
          else // Nearest-neighbor interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const int w2 = 2*width();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const int mx = cimg::mod(x - (int)cimg::round(*(ptrs0++)),w2);
                  *(ptrd++) = (*this)(mx<width()?mx:w2 - mx - 1,y,z,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (*this)(cimg::mod(x - (int)cimg::round(*(ptrs0++)),width()),y,z,c);
              }
              break;
            case 1 : // Neumann
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _atX(x - (int)cimg::round(*(ptrs0++)),y,z,c);
              }
              break;
            default : // Dirichlet
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = atX(x - (int)cimg::round(*(ptrs0++)),y,z,c,(T)0);
              }
            }
        }
        else { // Backward-absolute warp
          if (interpolation==2) // Cubic interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const float w2 = 2.f*width();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
                cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const float mx = cimg::mod((float)*(ptrs0++),w2);
                  *(ptrd++) = _cubic_atX_c(mx<width()?mx:w2 - mx - 1,0,0,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _cubic_atX_pc((float)*(ptrs0++),0,0,c);
              }
              break;
            case 1 : // Neumann
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _cubic_atX_c((float)*(ptrs0++),0,0,c);
              }
              break;
            default : // Dirichlet
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = cubic_atX_c((float)*(ptrs0++),0,0,c,(T)0);
              }
            }
          else if (interpolation==1) // Linear interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const float w2 = 2.f*width();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
                cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const float mx = cimg::mod((float)*(ptrs0++),w2);
                  *(ptrd++) = (T)_linear_atX(mx<width()?mx:w2 - mx - 1,0,0,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)_linear_atX_p((float)*(ptrs0++),0,0,c);
              }
              break;
            case 1 : // Neumann
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)_linear_atX((float)*(ptrs0++),0,0,c);
              }
              break;
            default : // Dirichlet
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)linear_atX((float)*(ptrs0++),0,0,c,(T)0);
              }
            }
          else // Nearest-neighbor interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const int w2 = 2*width();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
                cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const int mx = cimg::mod((int)cimg::round(*(ptrs0++)),w2);
                  *(ptrd++) = (*this)(mx<width()?mx:w2 - mx - 1,0,0,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (*this)(cimg::mod((int)cimg::round(*(ptrs0++)),width()),0,0,c);
              }
              break;
            case 1 : // Neumann
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _atX((int)cimg::round(*(ptrs0++)),0,0,c);
              }
              break;
            default : // Dirichlet
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = atX((int)cimg::round(*(ptrs0++)),0,0,c,(T)0);
              }
            }
        }

      } else if (p_warp._spectrum==2) { // 2D warping
        if (mode>=3) { // Forward-relative warp
          res.fill((T)0);
          if (interpolation>=1) // Linear interpolation
            cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
            cimg_forYZC(res,y,z,c) {
              const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c);
              cimg_forX(res,x) res.set_linear_atXY(*(ptrs++),x + (float)*(ptrs0++),y + (float)*(ptrs1++),z,c);
            }
          else // Nearest-neighbor interpolation
            cimg_forYZC(res,y,z,c) {
              const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c);
              cimg_forX(res,x) {
                const int X = x + (int)cimg::round(*(ptrs0++)), Y = y + (int)cimg::round(*(ptrs1++));
                if (X>=0 && X<width() && Y>=0 && Y<height()) res(X,Y,z,c) = *(ptrs++);
              }
            }
        } else if (mode==2) { // Forward-absolute warp
          res.fill((T)0);
          if (interpolation>=1) // Linear interpolation
            cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
            cimg_forYZC(res,y,z,c) {
              const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c);
              cimg_forX(res,x) res.set_linear_atXY(*(ptrs++),(float)*(ptrs0++),(float)*(ptrs1++),z,c);
            }
          else // Nearest-neighbor interpolation
            cimg_forYZC(res,y,z,c) {
              const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c);
              cimg_forX(res,x) {
                const int X = (int)cimg::round(*(ptrs0++)), Y = (int)cimg::round(*(ptrs1++));
                if (X>=0 && X<width() && Y>=0 && Y<height()) res(X,Y,z,c) = *(ptrs++);
              }
            }
        } else if (mode==1) { // Backward-relative warp
          if (interpolation==2) // Cubic interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const float w2 = 2.f*width(), h2 = 2.f*height();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const float
                    mx = cimg::mod(x - (float)*(ptrs0++),w2),
                    my = cimg::mod(y - (float)*(ptrs1++),h2);
                  *(ptrd++) = _cubic_atXY_c(mx<width()?mx:w2 - mx - 1,my<height()?my:h2 - my - 1,z,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _cubic_atXY_pc(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z,c);
              }
              break;
            case 1 : // Neumann
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _cubic_atXY_c(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z,c);
              }
              break;
            default : // Dirichlet
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = cubic_atXY_c(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z,c,(T)0);
              }
            }
          else if (interpolation==1) // Linear interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const float w2 = 2.f*width(), h2 = 2.f*height();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const float
                    mx = cimg::mod(x - (float)*(ptrs0++),w2),
                    my = cimg::mod(y - (float)*(ptrs1++),h2);
                  *(ptrd++) = (T)_linear_atXY(mx<width()?mx:w2 - mx - 1,my<height()?my:h2 - my - 1,z,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)_linear_atXY_p(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z,c);
              }
              break;
            case 1 : // Neumann
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)_linear_atXY(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z,c);
              }
              break;
            default : // Dirichlet
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)linear_atXY(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z,c,(T)0);
              }
            }
          else // Nearest-neighbor interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const int w2 = 2*width(), h2 = 2*height();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const int
                    mx = cimg::mod(x - (int)cimg::round(*(ptrs0++)),w2),
                    my = cimg::mod(y - (int)cimg::round(*(ptrs1++)),h2);
                  *(ptrd++) = (*this)(mx<width()?mx:w2 - mx - 1,my<height()?my:h2 - my - 1,z,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (*this)(cimg::mod(x - (int)cimg::round(*(ptrs0++)),width()),
                                                     cimg::mod(y - (int)cimg::round(*(ptrs1++)),height()),z,c);
              }
              break;
            case 1 : // Neumann
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _atXY(x - (int)cimg::round(*(ptrs0++)),
                                                   y - (int)cimg::round(*(ptrs1++)),z,c);
              }
              break;
            default : // Dirichlet
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = atXY(x - (int)cimg::round(*(ptrs0++)),
                                                  y - (int)cimg::round(*(ptrs1++)),z,c,(T)0);
              }
            }
        } else { // Backward-absolute warp
          if (interpolation==2) // Cubic interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const float w2 = 2.f*width(), h2 = 2.f*height();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const float
                    mx = cimg::mod((float)*(ptrs0++),w2),
                    my = cimg::mod((float)*(ptrs1++),h2);
                  *(ptrd++) = _cubic_atXY_c(mx<width()?mx:w2 - mx - 1,my<height()?my:h2 - my - 1,0,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _cubic_atXY_pc((float)*(ptrs0++),(float)*(ptrs1++),0,c);
              }
              break;
            case 1 : // Neumann
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _cubic_atXY_c((float)*(ptrs0++),(float)*(ptrs1++),0,c);
              }
              break;
            default : // Dirichlet
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = cubic_atXY_c((float)*(ptrs0++),(float)*(ptrs1++),0,c,(T)0);
              }
            }
          else if (interpolation==1) // Linear interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const float w2 = 2.f*width(), h2 = 2.f*height();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const float
                    mx = cimg::mod((float)*(ptrs0++),w2),
                    my = cimg::mod((float)*(ptrs1++),h2);
                  *(ptrd++) = (T)_linear_atXY(mx<width()?mx:w2 - mx - 1,my<height()?my:h2 - my - 1,0,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)_linear_atXY_p((float)*(ptrs0++),(float)*(ptrs1++),0,c);
              }
              break;
            case 1 : // Neumann
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)_linear_atXY((float)*(ptrs0++),(float)*(ptrs1++),0,c);
              }
              break;
            default : // Dirichlet
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)linear_atXY((float)*(ptrs0++),(float)*(ptrs1++),0,c,(T)0);
              }
            }
          else // Nearest-neighbor interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const int w2 = 2*width(), h2 = 2*height();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const int
                    mx = cimg::mod((int)cimg::round(*(ptrs0++)),w2),
                    my = cimg::mod((int)cimg::round(*(ptrs1++)),h2);
                  *(ptrd++) = (*this)(mx<width()?mx:w2 - mx - 1,my<height()?my:h2 - my - 1,0,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (*this)(cimg::mod((int)cimg::round(*(ptrs0++)),width()),
                                                     cimg::mod((int)cimg::round(*(ptrs1++)),height()),0,c);
              }
              break;
            case 1 : // Neumann
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _atXY((int)cimg::round(*(ptrs0++)),
                                                   (int)cimg::round(*(ptrs1++)),0,c);
              }
              break;
            default : // Dirichlet
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = atXY((int)cimg::round(*(ptrs0++)),
                                                  (int)cimg::round(*(ptrs1++)),0,c,(T)0);
              }
            }
        }

      } else { // 3D warping
        if (mode>=3) { // Forward-relative warp
          res.fill((T)0);
          if (interpolation>=1) // Linear interpolation
            cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
            cimg_forYZC(res,y,z,c) {
              const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
              const T *ptrs = data(0,y,z,c);
              cimg_forX(res,x) res.set_linear_atXYZ(*(ptrs++),x + (float)*(ptrs0++),y + (float)*(ptrs1++),
                                                    z + (float)*(ptrs2++),c);
            }
          else // Nearest-neighbor interpolation
            cimg_forYZC(res,y,z,c) {
              const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
              const T *ptrs = data(0,y,z,c);
              cimg_forX(res,x) {
                const int
                  X = x + (int)cimg::round(*(ptrs0++)),
                  Y = y + (int)cimg::round(*(ptrs1++)),
                  Z = z + (int)cimg::round(*(ptrs2++));
                if (X>=0 && X<width() && Y>=0 && Y<height() && Z>=0 && Z<depth()) res(X,Y,Z,c) = *(ptrs++);
              }
            }
        } else if (mode==2) { // Forward-absolute warp
          res.fill((T)0);
          if (interpolation>=1) // Linear interpolation
            cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
            cimg_forYZC(res,y,z,c) {
              const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
              const T *ptrs = data(0,y,z,c);
              cimg_forX(res,x) res.set_linear_atXYZ(*(ptrs++),(float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++),c);
            }
          else // Nearest-neighbor interpolation
            cimg_forYZC(res,y,z,c) {
              const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
              const T *ptrs = data(0,y,z,c);
              cimg_forX(res,x) {
                const int
                  X = (int)cimg::round(*(ptrs0++)),
                  Y = (int)cimg::round(*(ptrs1++)),
                  Z = (int)cimg::round(*(ptrs2++));
                if (X>=0 && X<width() && Y>=0 && Y<height() && Z>=0 && Z<depth()) res(X,Y,Z,c) = *(ptrs++);
              }
            }
        } else if (mode==1) { // Backward-relative warp
          if (interpolation==2) // Cubic interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const float w2 = 2.f*width(), h2 = 2.f*height(), d2 = 2.f*depth();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const float
                    mx = cimg::mod(x - (float)*(ptrs0++),w2),
                    my = cimg::mod(y - (float)*(ptrs1++),h2),
                    mz = cimg::mod(z - (float)*(ptrs2++),d2);
                  *(ptrd++) = _cubic_atXYZ_c(mx<width()?mx:w2 - mx - 1,
                                             my<height()?my:h2 - my - 1,
                                             mz<depth()?mz:d2 - mz - 1,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x)
                  *(ptrd++) = _cubic_atXYZ_pc(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z - (float)*(ptrs2++),c);
              }
              break;
            case 1 : // Neumann
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x)
                  *(ptrd++) = _cubic_atXYZ_c(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z - (float)*(ptrs2++),c);
              }
              break;
            default : // Dirichlet
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x)
                  *(ptrd++) = cubic_atXYZ_c(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z - (float)*(ptrs2++),c,(T)0);
              }
            }
          else if (interpolation==1) // Linear interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const float w2 = 2.f*width(), h2 = 2.f*height(), d2 = 2.f*depth();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const float
                    mx = cimg::mod(x - (float)*(ptrs0++),w2),
                    my = cimg::mod(y - (float)*(ptrs1++),h2),
                    mz = cimg::mod(z - (float)*(ptrs2++),d2);
                  *(ptrd++) = (T)_linear_atXYZ(mx<width()?mx:w2 - mx - 1,
                                               my<height()?my:h2 - my - 1,
                                               mz<depth()?mz:d2 - mz - 1,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)_linear_atXYZ_p(x - (float)*(ptrs0++),y - (float)*(ptrs1++),
                                                                z - (float)*(ptrs2++),c);
              }
              break;
            case 1 : // Neumann
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x)
                  *(ptrd++) = (T)_linear_atXYZ(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z - (float)*(ptrs2++),c);
              }
              break;
            default : // Dirichlet
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x)
                  *(ptrd++) = (T)linear_atXYZ(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z - (float)*(ptrs2++),c,(T)0);
              }
            }
          else // Nearest neighbor interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const int w2 = 2*width(), h2 = 2*height(), d2 = 2*depth();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const int
                    mx = cimg::mod(x - (int)cimg::round(*(ptrs0++)),w2),
                    my = cimg::mod(y - (int)cimg::round(*(ptrs1++)),h2),
                    mz = cimg::mod(z - (int)cimg::round(*(ptrs2++)),d2);
                  *(ptrd++) = (*this)(mx<width()?mx:w2 - mx - 1,
                                      my<height()?my:h2 - my - 1,
                                      mz<depth()?mz:d2 - mz - 1,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (*this)(cimg::mod(x - (int)cimg::round(*(ptrs0++)),width()),
                                                     cimg::mod(y - (int)cimg::round(*(ptrs1++)),height()),
                                                     cimg::mod(z - (int)cimg::round(*(ptrs2++)),depth()),c);
              }
              break;
            case 1 : // Neumann
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _atXYZ(x - (int)cimg::round(*(ptrs0++)),
                                                    y - (int)cimg::round(*(ptrs1++)),
                                                    z - (int)cimg::round(*(ptrs2++)),c);
              }
              break;
            default : // Dirichlet
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = atXYZ(x - (int)cimg::round(*(ptrs0++)),
                                                   y - (int)cimg::round(*(ptrs1++)),
                                                   z - (int)cimg::round(*(ptrs2++)),c,(T)0);
              }
            }
        } else { // Backward-absolute warp
          if (interpolation==2) // Cubic interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const float w2 = 2.f*width(), h2 = 2.f*height(), d2 = 2.f*depth();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const float
                    mx = cimg::mod((float)*(ptrs0++),w2),
                    my = cimg::mod((float)*(ptrs1++),h2),
                    mz = cimg::mod((float)*(ptrs2++),d2);
                  *(ptrd++) = _cubic_atXYZ_c(mx<width()?mx:w2 - mx - 1,
                                             my<height()?my:h2 - my - 1,
                                             mz<depth()?mz:d2 - mz - 1,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _cubic_atXYZ_pc((float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++),c);
              }
              break;
            case 1 : // Neumann
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _cubic_atXYZ_c((float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++),c);
              }
              break;
            default : // Dirichlet
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = cubic_atXYZ_c((float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++),
                                                           c,(T)0);
              }
            }
          else if (interpolation==1) // Linear interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const float w2 = 2.f*width(), h2 = 2.f*height(), d2 = 2.f*depth();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const float
                    mx = cimg::mod((float)*(ptrs0++),w2),
                    my = cimg::mod((float)*(ptrs1++),h2),
                    mz = cimg::mod((float)*(ptrs2++),d2);
                  *(ptrd++) = (T)_linear_atXYZ(mx<width()?mx:w2 - mx - 1,
                                               my<height()?my:h2 - my - 1,
                                               mz<depth()?mz:d2 - mz - 1,c);
                }
              }
            } break;
            case 2 :// Periodic
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)_linear_atXYZ_p((float)*(ptrs0++),(float)*(ptrs1++),
                                                                (float)*(ptrs2++),c);
              }
              break;
            case 1 : // Neumann
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)_linear_atXYZ((float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++),c);
              }
              break;
            default : // Dirichlet
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1048576))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (T)linear_atXYZ((float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++),
                                                             c,(T)0);
              }
            }
          else // Nearest-neighbor interpolation
            switch (boundary_conditions) {
            case 3 : { // Mirror
              const int w2 = 2*width(), h2 = 2*height(), d2 = 2*depth();
              cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096))
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) {
                  const int
                    mx = cimg::mod((int)cimg::round(*(ptrs0++)),w2),
                    my = cimg::mod((int)cimg::round(*(ptrs1++)),h2),
                    mz = cimg::mod((int)cimg::round(*(ptrs2++)),d2);
                  *(ptrd++) = (*this)(mx<width()?mx:w2 - mx - 1,
                                      my<height()?my:h2 - my - 1,
                                      mz<depth()?mz:d2 - mz - 1,c);
                }
              }
            } break;
            case 2 : // Periodic
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = (*this)(cimg::mod((int)cimg::round(*(ptrs0++)),width()),
                                                     cimg::mod((int)cimg::round(*(ptrs1++)),height()),
                                                     cimg::mod((int)cimg::round(*(ptrs2++)),depth()),c);
              }
              break;
            case 1 : // Neumann
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = _atXYZ((int)cimg::round(*(ptrs0++)),
                                                    (int)cimg::round(*(ptrs1++)),
                                                    (int)cimg::round(*(ptrs2++)),c);
              }
              break;
            default : // Dirichlet
              cimg_forYZC(res,y,z,c) {
                const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2);
                T *ptrd = res.data(0,y,z,c);
                cimg_forX(res,x) *(ptrd++) = atXYZ((int)cimg::round(*(ptrs0++)),
                                                   (int)cimg::round(*(ptrs1++)),
                                                   (int)cimg::round(*(ptrs2++)),c,(T)0);
              }
            }
        }
      }
      return res;

Project: CImg
File: CImg.h

    //! Evaluate math formula \const.
    double eval(const char *const expression,
                const double x=0, const double y=0, const double z=0, const double c=0,
                const CImgList<T> *const list_inputs=0, CImgList<T> *const list_outputs=0) const {
      return _eval(0,expression,x,y,z,c,list_inputs,list_outputs);

Project: CImg
File: CImg.h

    **/
    inline std::FILE *fopen(const char *const path, const char *const mode) {
      if (!path)
        throw CImgArgumentException("cimg::fopen(): Specified file path is (null).");
      if (!mode)
        throw CImgArgumentException("cimg::fopen(): File '%s', specified mode is (null).",
                                    path);
      std::FILE *res = 0;
      if (*path=='-' && (!path[1] || path[1]=='.')) {
        res = (*mode=='r')?cimg::_stdin():cimg::_stdout();
#if cimg_OS==2
        if (*mode && mode[1]=='b') { // Force stdin/stdout to be in binary mode
#ifdef __BORLANDC__
          if (setmode(_fileno(res),0x8000)==-1) res = 0;
#else
          if (_setmode(_fileno(res),0x8000)==-1) res = 0;
#endif
        }
#endif
      } else res = cimg::std_fopen(path,mode);
      if (!res) throw CImgIOException("cimg::fopen(): Failed to open file '%s' with mode '%s'.",
                                      path,mode);
      return res;

Project: CImg
File: CImg.h

    **/
    CImgList<T>& assign(const unsigned int n, const unsigned int width, const unsigned int height,
                        const unsigned int depth, const unsigned int spectrum,
                        const double val0, const double val1, ...) {
      _CImgList_stdarg(double);
      return *this;

Project: CImg
File: CImg.h


    inline float rol(const float a, const unsigned int n=1) {
      return (float)rol((int)a,n);

Project: CImg
File: CImg.h

    //! Convert C-string to upper case.
    inline void uppercase(char *const str) {
      if (str) for (char *ptr = str; *ptr; ++ptr) *ptr = uppercase(*ptr);

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& blur_bilateral(const CImg<t>& guide,
                            const float sigma_s, const float sigma_r,
                            const float sampling_s=0, const float sampling_r=0) {
      const float _sigma_s = sigma_s>=0?sigma_s:-sigma_s*cimg::max(_width,_height,_depth)/100;
      return blur_bilateral(guide,_sigma_s,_sigma_s,_sigma_s,sigma_r,sampling_s,sampling_s,sampling_s,sampling_r);

Project: CImg
File: CImg.h

       res1 = cimg::eval("cos(x)^2 + sin(y)^2",2,2),  // will return '1'
       res2 = cimg::eval(0,1,1);                    // will return '1' too
       \endcode
    **/

Project: CImg
File: CImg.h

    //! Resize image to become a diagonal matrix \newinstance.
    CImg<T> get_diagonal() const {
      if (is_empty()) return *this;
      const unsigned int siz = (unsigned int)size();
      CImg<T> res(siz,siz,1,1,0);
      cimg_foroff(*this,off) res((unsigned int)off,(unsigned int)off) = (*this)[off];
      return res;

Project: CImg
File: CImg.h

      static bool is_float() { return true; }
      static bool is_inf(const double val) {
#ifdef isinf
        return (bool)isinf(val);
#else
        return !is_nan(val) && (val<cimg::type<double>::min() || val>cimg::type<double>::max());
#endif

Project: CImg
File: CImg.h

    //! Access to pixel value with Neumann boundary conditions for the 2 coordinates (\c pos, \c x) \const.
    T atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) const {
      if (is_empty())
        throw CImgInstanceException(_cimglist_instance
                                    "atNX(): Empty instance.",
                                    cimglist_instance);

      return _atNX(pos,x,y,z,c);

Project: CImg
File: CImg.h

#endif
      X11_info():nb_wins(0),events_thread(0),display(0),
                 nb_bits(0),is_blue_first(false),is_shm_enabled(false),byte_order(false) {
#ifdef __FreeBSD__
        XInitThreads();
#endif
        wins = new CImgDisplay*[1024];
        pthread_mutex_init(&wait_event_mutex,0);
        pthread_cond_init(&wait_event,0);

#ifdef cimg_use_xrandr
        resolutions = 0;
        curr_rotation = 0;
        curr_resolution = nb_resolutions = 0;
#endif

Project: CImg
File: CImg.h

    **/
    const CImg<T>& save_other(const char *const filename, const unsigned int quality=100) const {
      if (!filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_other(): 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 or GraphicsMagick only writes the first image slice.",
                   cimg_instance,filename);

      const unsigned int omode = cimg::exception_mode();
      bool is_saved = true;
      cimg::exception_mode(0);
      try { save_magick(filename); }
      catch (CImgException&) {
        try { save_imagemagick_external(filename,quality); }
        catch (CImgException&) {
          try { save_graphicsmagick_external(filename,quality); }
          catch (CImgException&) {
            is_saved = false;
          }
        }
      }
      cimg::exception_mode(omode);
      if (!is_saved)
        throw CImgIOException(_cimg_instance
                              "save_other(): Failed to save file '%s'. Format is not natively supported, "
                              "and no external commands succeeded.",
                              cimg_instance,
                              filename);
      return *this;

Project: CImg
File: CImg.h

    /**
      \param list List to insert.
    **/

Project: CImg
File: CImg.h

    **/
    CImg<T>& fill(const T& val0, const T& val1) {
      if (is_empty()) return *this;
      T *ptrd, *ptre = end() - 1;
      for (ptrd = _data; ptrd<ptre; ) { *(ptrd++) = val0; *(ptrd++) = val1; }
      if (ptrd!=ptre + 1) *(ptrd++) = val0;
      return *this;

Project: CImg
File: CImg.h

    **/
    static const CImg<Tuchar>& cube_LUT256() {
      static CImg<Tuchar> colormap;
      cimg::mutex(8);
      if (!colormap) {
        colormap.assign(1,8,1,3,(T)0);
        colormap[1] = colormap[3] = colormap[5] = colormap[7] =
          colormap[10] = colormap[11] = colormap[12] = colormap[13] =
          colormap[20] = colormap[21] = colormap[22] = colormap[23] = 255;
        colormap.resize(1,256,1,3,3);
      }
      cimg::mutex(8,0);
      return colormap;

Project: CImg
File: CImg.h


    CImgDisplay& hide_mouse() {
      if (is_empty()) return *this;
      _is_cursor_visible = false;
      return *this;

Project: CImg
File: CImg.h

    **/
    CImg<T> get_projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0) const {
      if (is_empty() || _depth<2) return +*this;
      const unsigned int
        _x0 = (x0>=_width)?_width - 1:x0,
        _y0 = (y0>=_height)?_height - 1:y0,
        _z0 = (z0>=_depth)?_depth - 1:z0;
      const CImg<T>
        img_xy = get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1),
        img_zy = get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1).permute_axes("xzyc").
        resize(_depth,_height,1,-100,-1),
        img_xz = get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1).resize(_width,_depth,1,-100,-1);
      return CImg<T>(_width + _depth,_height + _depth,1,_spectrum,cimg::min(img_xy.min(),img_zy.min(),img_xz.min())).
        draw_image(0,0,img_xy).draw_image(img_xy._width,0,img_zy).
        draw_image(0,img_xy._height,img_xz);

Project: CImg
File: CImg.h

    // Compute SSD between two patches in different images.
    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 psized, const unsigned int psizec,
                             const int x1, const int y1, const int z1,
                             const int x2, const int y2, const int z2,
                             const int xc, const int yc, const int zc,
                             const float occ_penalization,
                             const float max_score) { // 3D version
      const T *p1 = img1.data(x1*psizec,y1,z1), *p2 = img2.data(x2*psizec,y2,z2);
      const unsigned int psizewc = psizew*psizec;
      const ulongT
        offx1 = (ulongT)img1._width - psizewc,
        offx2 = (ulongT)img2._width - psizewc,
        offy1 = (ulongT)img1._width*img1._height - (ulongT)psizeh*img1._width,
        offy2 = (ulongT)img2._width*img2._height - (ulongT)psizeh*img2._width;
      float ssd = 0;
      for (unsigned int k = 0; k<psized; ++k) {
        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;
        }
        p1+=offy1; p2+=offy2;
      }
      return occ_penalization==0?ssd:cimg::sqr(std::sqrt(ssd) + occ_penalization*occ(xc,yc,zc));

Project: CImg
File: CImg.h

    template<typename tf>
    CImg<floatT> get_isosurface3d(CImgList<tf>& primitives, const float isovalue,
                                  const int size_x=-100, const int size_y=-100, const int size_z=-100) const {
      if (_spectrum>1)
        throw CImgInstanceException(_cimg_instance
                                    "get_isosurface3d(): Instance is not a scalar image.",
                                    cimg_instance);
      primitives.assign();
      if (is_empty()) return *this;
      CImg<floatT> vertices;
      if ((size_x==-100 && size_y==-100 && size_z==-100) || (size_x==width() && size_y==height() && size_z==depth())) {
        const _functor3d_int func(*this);
        vertices = isosurface3d(primitives,func,isovalue,0,0,0,width() - 1.f,height() - 1.f,depth() - 1.f,
                                width(),height(),depth());
      } else {
        const _functor3d_float func(*this);
        vertices = isosurface3d(primitives,func,isovalue,0,0,0,width() - 1.f,height() - 1.f,depth() - 1.f,
                                size_x,size_y,size_z);
      }
      return vertices;

Project: CImg
File: CImg.h

    CImg<typename CImg<t>::Tuint>
    get_index(const CImg<t>& colormap, const float dithering=1, const bool map_indexes=true) const {
      if (colormap._spectrum!=_spectrum)
        throw CImgArgumentException(_cimg_instance
                                    "index(): Instance and specified colormap (%u,%u,%u,%u,%p) "
                                    "have incompatible dimensions.",
                                    cimg_instance,
                                    colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data);

      typedef typename CImg<t>::Tuint tuint;
      if (is_empty()) return CImg<tuint>();
      const ulongT
        whd = (ulongT)_width*_height*_depth,
        pwhd = (ulongT)colormap._width*colormap._height*colormap._depth;
      CImg<tuint> res(_width,_height,_depth,map_indexes?_spectrum:1);
      if (dithering>0) { // Dithered versions
        tuint *ptrd = res._data;
        const float ndithering = cimg::cut(dithering,0,1)/16;
        Tfloat valm = 0, valM = (Tfloat)max_min(valm);
        if (valm==valM && valm>=0 && valM<=255) { valm = 0; valM = 255; }
        CImg<Tfloat> cache = get_crop(-1,0,0,0,_width,1,0,_spectrum - 1);
        Tfloat *cache_current = cache.data(1,0,0,0), *cache_next = cache.data(1,1,0,0);
        const ulongT cwhd = (ulongT)cache._width*cache._height*cache._depth;
        switch (_spectrum) {
        case 1 : { // Optimized for scalars
          cimg_forYZ(*this,y,z) {
            if (y<height() - 2) {
              Tfloat *ptrc0 = cache_next; const T *ptrs0 = data(0,y + 1,z,0);
              cimg_forX(*this,x) *(ptrc0++) = (Tfloat)*(ptrs0++);
            }
            Tfloat *ptrs0 = cache_current, *ptrsn0 = cache_next;
            cimg_forX(*this,x) {
              const Tfloat _val0 = (Tfloat)*ptrs0, val0 = _val0<valm?valm:_val0>valM?valM:_val0;
              Tfloat distmin = cimg::type<Tfloat>::max(); const t *ptrmin0 = colormap._data;
              for (const t *ptrp0 = colormap._data, *ptrp_end = ptrp0 + pwhd; ptrp0<ptrp_end; ) {
                const Tfloat pval0 = (Tfloat)*(ptrp0++) - val0, dist = pval0*pval0;
                if (dist<distmin) { ptrmin0 = ptrp0 - 1; distmin = dist; }
              }
              const Tfloat err0 = ((*(ptrs0++)=val0) - (Tfloat)*ptrmin0)*ndithering;
              *ptrs0+=7*err0; *(ptrsn0 - 1)+=3*err0; *(ptrsn0++)+=5*err0; *ptrsn0+=err0;
              if (map_indexes) *(ptrd++) = (tuint)*ptrmin0; else *(ptrd++) = (tuint)(ptrmin0 - colormap._data);
            }
            cimg::swap(cache_current,cache_next);
          }
        } break;
        case 2 : { // Optimized for 2D vectors
          tuint *ptrd1 = ptrd + whd;
          cimg_forYZ(*this,y,z) {
            if (y<height() - 2) {
              Tfloat *ptrc0 = cache_next, *ptrc1 = ptrc0 + cwhd;
              const T *ptrs0 = data(0,y + 1,z,0), *ptrs1 = ptrs0 + whd;
              cimg_forX(*this,x) { *(ptrc0++) = (Tfloat)*(ptrs0++); *(ptrc1++) = (Tfloat)*(ptrs1++); }
            }
            Tfloat
              *ptrs0 = cache_current, *ptrs1 = ptrs0 + cwhd,
              *ptrsn0 = cache_next, *ptrsn1 = ptrsn0 + cwhd;
            cimg_forX(*this,x) {
              const Tfloat
                _val0 = (Tfloat)*ptrs0, val0 = _val0<valm?valm:_val0>valM?valM:_val0,
                _val1 = (Tfloat)*ptrs1, val1 = _val1<valm?valm:_val1>valM?valM:_val1;
              Tfloat distmin = cimg::type<Tfloat>::max(); const t *ptrmin0 = colormap._data;
              for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp_end = ptrp1; ptrp0<ptrp_end; ) {
                const Tfloat
                  pval0 = (Tfloat)*(ptrp0++) - val0, pval1 = (Tfloat)*(ptrp1++) - val1,
                  dist = pval0*pval0 + pval1*pval1;
                if (dist<distmin) { ptrmin0 = ptrp0 - 1; distmin = dist; }
              }
              const t *const ptrmin1 = ptrmin0 + pwhd;
              const Tfloat
                err0 = ((*(ptrs0++)=val0) - (Tfloat)*ptrmin0)*ndithering,
                err1 = ((*(ptrs1++)=val1) - (Tfloat)*ptrmin1)*ndithering;
              *ptrs0+=7*err0; *ptrs1+=7*err1;
              *(ptrsn0 - 1)+=3*err0; *(ptrsn1 - 1)+=3*err1;
              *(ptrsn0++)+=5*err0; *(ptrsn1++)+=5*err1;
              *ptrsn0+=err0; *ptrsn1+=err1;
              if (map_indexes) { *(ptrd++) = (tuint)*ptrmin0; *(ptrd1++) = (tuint)*ptrmin1; }
              else *(ptrd++) = (tuint)(ptrmin0 - colormap._data);
            }
            cimg::swap(cache_current,cache_next);
          }
        } break;
        case 3 : { // Optimized for 3D vectors (colors)
          tuint *ptrd1 = ptrd + whd, *ptrd2 = ptrd1 + whd;
          cimg_forYZ(*this,y,z) {
            if (y<height() - 2) {
              Tfloat *ptrc0 = cache_next, *ptrc1 = ptrc0 + cwhd, *ptrc2 = ptrc1 + cwhd;
              const T *ptrs0 = data(0,y + 1,z,0), *ptrs1 = ptrs0 + whd, *ptrs2 = ptrs1 + whd;
              cimg_forX(*this,x) {
                *(ptrc0++) = (Tfloat)*(ptrs0++); *(ptrc1++) = (Tfloat)*(ptrs1++); *(ptrc2++) = (Tfloat)*(ptrs2++);
              }
            }
            Tfloat
              *ptrs0 = cache_current, *ptrs1 = ptrs0 + cwhd, *ptrs2 = ptrs1 + cwhd,
              *ptrsn0 = cache_next, *ptrsn1 = ptrsn0 + cwhd, *ptrsn2 = ptrsn1 + cwhd;
            cimg_forX(*this,x) {
              const Tfloat
                _val0 = (Tfloat)*ptrs0, val0 = _val0<valm?valm:_val0>valM?valM:_val0,
                _val1 = (Tfloat)*ptrs1, val1 = _val1<valm?valm:_val1>valM?valM:_val1,
                _val2 = (Tfloat)*ptrs2, val2 = _val2<valm?valm:_val2>valM?valM:_val2;
              Tfloat distmin = cimg::type<Tfloat>::max(); const t *ptrmin0 = colormap._data;
              for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd,
                     *ptrp_end = ptrp1; ptrp0<ptrp_end; ) {
                const Tfloat
                  pval0 = (Tfloat)*(ptrp0++) - val0,
                  pval1 = (Tfloat)*(ptrp1++) - val1,
                  pval2 = (Tfloat)*(ptrp2++) - val2,
                  dist = pval0*pval0 + pval1*pval1 + pval2*pval2;
                if (dist<distmin) { ptrmin0 = ptrp0 - 1; distmin = dist; }
              }
              const t *const ptrmin1 = ptrmin0 + pwhd, *const ptrmin2 = ptrmin1 + pwhd;
              const Tfloat
                err0 = ((*(ptrs0++)=val0) - (Tfloat)*ptrmin0)*ndithering,
                err1 = ((*(ptrs1++)=val1) - (Tfloat)*ptrmin1)*ndithering,
                err2 = ((*(ptrs2++)=val2) - (Tfloat)*ptrmin2)*ndithering;

              *ptrs0+=7*err0; *ptrs1+=7*err1; *ptrs2+=7*err2;
              *(ptrsn0 - 1)+=3*err0; *(ptrsn1 - 1)+=3*err1; *(ptrsn2 - 1)+=3*err2;
              *(ptrsn0++)+=5*err0; *(ptrsn1++)+=5*err1; *(ptrsn2++)+=5*err2;
              *ptrsn0+=err0; *ptrsn1+=err1; *ptrsn2+=err2;

              if (map_indexes) {
                *(ptrd++) = (tuint)*ptrmin0; *(ptrd1++) = (tuint)*ptrmin1; *(ptrd2++) = (tuint)*ptrmin2;
              } else *(ptrd++) = (tuint)(ptrmin0 - colormap._data);
            }
            cimg::swap(cache_current,cache_next);
          }
        } break;
        default : // Generic version
          cimg_forYZ(*this,y,z) {
            if (y<height() - 2) {
              Tfloat *ptrc = cache_next;
              cimg_forC(*this,c) {
                Tfloat *_ptrc = ptrc; const T *_ptrs = data(0,y + 1,z,c);
                cimg_forX(*this,x) *(_ptrc++) = (Tfloat)*(_ptrs++);
                ptrc+=cwhd;
              }
            }
            Tfloat *ptrs = cache_current, *ptrsn = cache_next;
            cimg_forX(*this,x) {
              Tfloat distmin = cimg::type<Tfloat>::max(); const t *ptrmin = colormap._data;
              for (const t *ptrp = colormap._data, *ptrp_end = ptrp + pwhd; ptrp<ptrp_end; ++ptrp) {
                Tfloat dist = 0; Tfloat *_ptrs = ptrs; const t *_ptrp = ptrp;
                cimg_forC(*this,c) {
                  const Tfloat _val = *_ptrs, val = _val<valm?valm:_val>valM?valM:_val;
                  dist+=cimg::sqr((*_ptrs=val) - (Tfloat)*_ptrp); _ptrs+=cwhd; _ptrp+=pwhd;
                }
                if (dist<distmin) { ptrmin = ptrp; distmin = dist; }
              }
              const t *_ptrmin = ptrmin; Tfloat *_ptrs = ptrs++, *_ptrsn = (ptrsn++) - 1;
              cimg_forC(*this,c) {
                const Tfloat err = (*(_ptrs++) - (Tfloat)*_ptrmin)*ndithering;
                *_ptrs+=7*err; *(_ptrsn++)+=3*err; *(_ptrsn++)+=5*err; *_ptrsn+=err;
                _ptrmin+=pwhd; _ptrs+=cwhd - 1; _ptrsn+=cwhd - 2;
              }
              if (map_indexes) {
                tuint *_ptrd = ptrd++;
                cimg_forC(*this,c) { *_ptrd = (tuint)*ptrmin; _ptrd+=whd; ptrmin+=pwhd; }
              }
              else *(ptrd++) = (tuint)(ptrmin - colormap._data);
            }
            cimg::swap(cache_current,cache_next);
          }
        }
      } else { // Non-dithered versions
        switch (_spectrum) {
        case 1 : { // Optimized for scalars
          cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*64 &&
                                                                     _height*_depth>=16 && pwhd>=16))
          cimg_forYZ(*this,y,z) {
            tuint *ptrd = res.data(0,y,z);
            for (const T *ptrs0 = data(0,y,z), *ptrs_end = ptrs0 + _width; ptrs0<ptrs_end; ) {
              const Tfloat val0 = (Tfloat)*(ptrs0++);
              Tfloat distmin = cimg::type<Tfloat>::max(); const t *ptrmin0 = colormap._data;
              for (const t *ptrp0 = colormap._data, *ptrp_end = ptrp0 + pwhd; ptrp0<ptrp_end; ) {
                const Tfloat pval0 = (Tfloat)*(ptrp0++) - val0, dist = pval0*pval0;
                if (dist<distmin) { ptrmin0 = ptrp0 - 1; distmin = dist; }
              }
              if (map_indexes) *(ptrd++) = (tuint)*ptrmin0; else *(ptrd++) = (tuint)(ptrmin0 - colormap._data);
            }
          }
        } break;
        case 2 : { // Optimized for 2D vectors
          cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*64 &&
                                                                     _height*_depth>=16 && pwhd>=16))
          cimg_forYZ(*this,y,z) {
            tuint *ptrd = res.data(0,y,z), *ptrd1 = ptrd + whd;
            for (const T *ptrs0 = data(0,y,z), *ptrs1 = ptrs0 + whd, *ptrs_end = ptrs0 + _width; ptrs0<ptrs_end; ) {
              const Tfloat val0 = (Tfloat)*(ptrs0++), val1 = (Tfloat)*(ptrs1++);
              Tfloat distmin = cimg::type<Tfloat>::max(); const t *ptrmin0 = colormap._data;
              for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp_end = ptrp1; ptrp0<ptrp_end; ) {
                const Tfloat
                  pval0 = (Tfloat)*(ptrp0++) - val0, pval1 = (Tfloat)*(ptrp1++) - val1,
                  dist = pval0*pval0 + pval1*pval1;
                if (dist<distmin) { ptrmin0 = ptrp0 - 1; distmin = dist; }
              }
              if (map_indexes) { *(ptrd++) = (tuint)*ptrmin0; *(ptrd1++) = (tuint)*(ptrmin0 + pwhd); }
              else *(ptrd++) = (tuint)(ptrmin0 - colormap._data);
            }
          }
        } break;
        case 3 : { // Optimized for 3D vectors (colors)
          cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*64 &&
                                                                     _height*_depth>=16 && pwhd>=16))
          cimg_forYZ(*this,y,z) {
            tuint *ptrd = res.data(0,y,z), *ptrd1 = ptrd + whd, *ptrd2 = ptrd1 + whd;
            for (const T *ptrs0 = data(0,y,z), *ptrs1 = ptrs0 + whd, *ptrs2 = ptrs1 + whd,
                   *ptrs_end = ptrs0 + _width; ptrs0<ptrs_end; ) {
              const Tfloat val0 = (Tfloat)*(ptrs0++), val1 = (Tfloat)*(ptrs1++), val2 = (Tfloat)*(ptrs2++);
              Tfloat distmin = cimg::type<Tfloat>::max(); const t *ptrmin0 = colormap._data;
              for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd,
                     *ptrp_end = ptrp1; ptrp0<ptrp_end; ) {
                const Tfloat
                  pval0 = (Tfloat)*(ptrp0++) - val0,
                  pval1 = (Tfloat)*(ptrp1++) - val1,
                  pval2 = (Tfloat)*(ptrp2++) - val2,
                  dist = pval0*pval0 + pval1*pval1 + pval2*pval2;
                if (dist<distmin) { ptrmin0 = ptrp0 - 1; distmin = dist; }
              }
              if (map_indexes) {
                *(ptrd++) = (tuint)*ptrmin0;
                *(ptrd1++) = (tuint)*(ptrmin0 + pwhd);
                *(ptrd2++) = (tuint)*(ptrmin0 + 2*pwhd);
              } else *(ptrd++) = (tuint)(ptrmin0 - colormap._data);
            }
          }
        } break;
        default : // Generic version
          cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*64 &&
                                                                     _height*_depth>=16 && pwhd>=16))
          cimg_forYZ(*this,y,z) {
            tuint *ptrd = res.data(0,y,z);
            for (const T *ptrs = data(0,y,z), *ptrs_end = ptrs + _width; ptrs<ptrs_end; ++ptrs) {
              Tfloat distmin = cimg::type<Tfloat>::max(); const t *ptrmin = colormap._data;
              for (const t *ptrp = colormap._data, *ptrp_end = ptrp + pwhd; ptrp<ptrp_end; ++ptrp) {
                Tfloat dist = 0; const T *_ptrs = ptrs; const t *_ptrp = ptrp;
                cimg_forC(*this,c) { dist+=cimg::sqr((Tfloat)*_ptrs - (Tfloat)*_ptrp); _ptrs+=whd; _ptrp+=pwhd; }
                if (dist<distmin) { ptrmin = ptrp; distmin = dist; }
              }
              if (map_indexes) {
                tuint *_ptrd = ptrd++;
                cimg_forC(*this,c) { *_ptrd = (tuint)*ptrmin; _ptrd+=whd; ptrmin+=pwhd; }
              }
              else *(ptrd++) = (tuint)(ptrmin - colormap._data);
            }
          }
        }
      }
      return res;

Project: CImg
File: CImg.h

#else
    T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) {
      return _data + x + (ulongT)y*_width + (ulongT)z*_width*_height + (ulongT)c*_width*_height*_depth;

Project: CImg
File: CImg.h

    //! Unroll pixel values along specified axis \newinstance.
    CImg<T> get_unroll(const char axis) const {
      return (+*this).unroll(axis);

Project: CImg
File: CImg.h

    **/
    inline void info() {
      std::fprintf(cimg::output(),"\n %s%sCImg Library %u.%u.%u%s, compiled %s ( %s ) with the following flags:\n\n",
                   cimg::t_red,cimg::t_bold,cimg_version/100,(cimg_version/10)%10,cimg_version%10,
                   cimg::t_normal,cimg_date,cimg_time);

      std::fprintf(cimg::output(),"  > Operating System:       %s%-13s%s %s('cimg_OS'=%d)%s\n",
                   cimg::t_bold,
                   cimg_OS==1?"Unix":(cimg_OS==2?"Windows":"Unknow"),
                   cimg::t_normal,cimg::t_green,
                   cimg_OS,
                   cimg::t_normal);

      std::fprintf(cimg::output(),"  > CPU endianness:         %s%s Endian%s\n",
                   cimg::t_bold,
                   cimg::endianness()?"Big":"Little",
                   cimg::t_normal);

      std::fprintf(cimg::output(),"  > Verbosity mode:         %s%-13s%s %s('cimg_verbosity'=%d)%s\n",
                   cimg::t_bold,
                   cimg_verbosity==0?"Quiet":
                   cimg_verbosity==1?"Console":
                   cimg_verbosity==2?"Dialog":
                   cimg_verbosity==3?"Console+Warnings":"Dialog+Warnings",
                   cimg::t_normal,cimg::t_green,
                   cimg_verbosity,
                   cimg::t_normal);

      std::fprintf(cimg::output(),"  > Stricts warnings:       %s%-13s%s %s('cimg_strict_warnings' %s)%s\n",
                   cimg::t_bold,
#ifdef cimg_strict_warnings
                   "Yes",cimg::t_normal,cimg::t_green,"defined",
#else
                   "No",cimg::t_normal,cimg::t_green,"undefined",
#endif
                   cimg::t_normal);

      std::fprintf(cimg::output(),"  > Support for C++11:      %s%-13s%s %s('cimg_use_cpp11'=%d)%s\n",
                   cimg::t_bold,
                   cimg_use_cpp11?"Yes":"No",
                   cimg::t_normal,cimg::t_green,
                   (int)cimg_use_cpp11,
                   cimg::t_normal);

      std::fprintf(cimg::output(),"  > Using VT100 messages:   %s%-13s%s %s('cimg_use_vt100' %s)%s\n",
                   cimg::t_bold,
#ifdef cimg_use_vt100
                   "Yes",cimg::t_normal,cimg::t_green,"defined",
#else
                   "No",cimg::t_normal,cimg::t_green,"undefined",
#endif
                   cimg::t_normal);

      std::fprintf(cimg::output(),"  > Display type:           %s%-13s%s %s('cimg_display'=%d)%s\n",
                   cimg::t_bold,
                   cimg_display==0?"No display":cimg_display==1?"X11":cimg_display==2?"Windows GDI":"Unknown",
                   cimg::t_normal,cimg::t_green,
                   (int)cimg_display,
                   cimg::t_normal);

#if cimg_display==1
      std::fprintf(cimg::output(),"  > Using XShm for X11:     %s%-13s%s %s('cimg_use_xshm' %s)%s\n",
                   cimg::t_bold,
#ifdef cimg_use_xshm
                   "Yes",cimg::t_normal,cimg::t_green,"defined",
#else
                   "No",cimg::t_normal,cimg::t_green,"undefined",
#endif
                   cimg::t_normal);

      std::fprintf(cimg::output(),"  > Using XRand for X11:    %s%-13s%s %s('cimg_use_xrandr' %s)%s\n",
                   cimg::t_bold,
#ifdef cimg_use_xrandr
                   "Yes",cimg::t_normal,cimg::t_green,"defined",
#else
                   "No",cimg::t_normal,cimg::t_green,"undefined",
#endif
                   cimg::t_normal);
#endif
      std::fprintf(cimg::output(),"  > Using OpenMP:           %s%-13s%s %s('cimg_use_openmp' %s)%s\n",
                   cimg::t_bold,
#if cimg_use_openmp!=0
                   "Yes",cimg::t_normal,cimg::t_green,"defined",
#else
                   "No",cimg::t_normal,cimg::t_green,"undefined",
#endif
                   cimg::t_normal);
      std::fprintf(cimg::output(),"  > Using PNG library:      %s%-13s%s %s('cimg_use_png' %s)%s\n",
                   cimg::t_bold,
#ifdef cimg_use_png
                   "Yes",cimg::t_normal,cimg::t_green,"defined",
#else
                   "No",cimg::t_normal,cimg::t_green,"undefined",
#endif
                   cimg::t_normal);
      std::fprintf(cimg::output(),"  > Using JPEG library:     %s%-13s%s %s('cimg_use_jpeg' %s)%s\n",
                   cimg::t_bold,
#ifdef cimg_use_jpeg
                   "Yes",cimg::t_normal,cimg::t_green,"defined",
#else
                   "No",cimg::t_normal,cimg::t_green,"undefined",
#endif
                   cimg::t_normal);

      std::fprintf(cimg::output(),"  > Using TIFF library:     %s%-13s%s %s('cimg_use_tiff' %s)%s\n",
                   cimg::t_bold,
#ifdef cimg_use_tiff
                   "Yes",cimg::t_normal,cimg::t_green,"defined",
#else
                   "No",cimg::t_normal,cimg::t_green,"undefined",
#endif
                   cimg::t_normal);

      std::fprintf(cimg::output(),"  > Using Magick++ library: %s%-13s%s %s('cimg_use_magick' %s)%s\n",
                   cimg::t_bold,
#ifdef cimg_use_magick
                   "Yes",cimg::t_normal,cimg::t_green,"defined",
#else
                   "No",cimg::t_normal,cimg::t_green,"undefined",
#endif
                   cimg::t_normal);

      std::fprintf(cimg::output(),"  > Using FFTW3 library:    %s%-13s%s %s('cimg_use_fftw3' %s)%s\n",
                   cimg::t_bold,
#ifdef cimg_use_fftw3
                   "Yes",cimg::t_normal,cimg::t_green,"defined",
#else
                   "No",cimg::t_normal,cimg::t_green,"undefined",
#endif
                   cimg::t_normal);

      std::fprintf(cimg::output(),"  > Using LAPACK library:   %s%-13s%s %s('cimg_use_lapack' %s)%s\n",
                   cimg::t_bold,
#ifdef cimg_use_lapack
                   "Yes",cimg::t_normal,cimg::t_green,"defined",
#else
                   "No",cimg::t_normal,cimg::t_green,"undefined",
#endif
                   cimg::t_normal);

      char *const tmp = new char[1024];
      cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::imagemagick_path());
      std::fprintf(cimg::output(),"  > Path of ImageMagick:    %s%-13s%s\n",
                   cimg::t_bold,
                   tmp,
                   cimg::t_normal);

      cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::graphicsmagick_path());
      std::fprintf(cimg::output(),"  > Path of GraphicsMagick: %s%-13s%s\n",
                   cimg::t_bold,
                   tmp,
                   cimg::t_normal);

      cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::medcon_path());
      std::fprintf(cimg::output(),"  > Path of 'medcon':       %s%-13s%s\n",
                   cimg::t_bold,
                   tmp,
                   cimg::t_normal);

      cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::temporary_path());
      std::fprintf(cimg::output(),"  > Temporary path:         %s%-13s%s\n",
                   cimg::t_bold,
                   tmp,
                   cimg::t_normal);

      std::fprintf(cimg::output(),"\n");
      delete[] tmp;

Project: CImg
File: CImg.h


      static double mp_self_modulo(_cimg_math_parser& mp) {
        double &val = _mp_arg(1);
        return val = cimg::mod(val,_mp_arg(2));

Project: CImg
File: CImg.h

    **/
    explicit CImg(const char *const filename):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
      assign(filename);

Project: CImg
File: CImg.h

    template<typename to>
    float* _object3dtoCImg3d(const CImg<to>& opacities, float *ptrd) const {
      const to *ptro = opacities._data;
      cimg_foroff(opacities,o) *(ptrd++) = (float)*(ptro++);
      return ptrd;

Project: CImg
File: CImg.h


    CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *const title=0,
                        const unsigned int normalization_type=3,
                        const bool fullscreen_flag=false, const bool closed_flag=false) {
      if (!dimw || !dimh) return assign();
      _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag);
      _min = _max = 0;
      std::memset(_data,0,sizeof(unsigned int)*_width*_height);
      return paint();

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 T& val8, const T& val9, const T& val10, const T& val11,
                     const T& val12, const T& val13, const T& val14) const {
      return CImg<T>(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,
                                                           val11,val12,val13,val14);

Project: CImg
File: CImg.h

    }

    //! Insert a copy of the image list \c list into the current image list, starting from position \c pos \newinstance.

Project: CImg
File: CImg.h


      static double mp_floor(_cimg_math_parser& mp) {
        return std::floor(_mp_arg(2));

Project: CImg
File: CImg.h


      static double mp_date(_cimg_math_parser& mp) {
        const unsigned int
          siz_out = (unsigned int)mp.opcode[2],
          siz_arg1 = (unsigned int)mp.opcode[4],
          siz_arg2 = (unsigned int)mp.opcode[6];
        double *ptr_out = &_mp_arg(1) + (siz_out?1:0);
        const double
          *ptr_arg1 = siz_arg1==~0U?0:&_mp_arg(3) + (siz_arg1?1:0),
          *ptr_arg2 = siz_arg2==~0U?0:&_mp_arg(5) + 1;

        if (!ptr_arg2) { // No filename specified
          if (!siz_arg1) return cimg::date((unsigned int)*ptr_arg1);
          if (siz_arg1==~0U) for (unsigned int k = 0; k<siz_out; ++k) ptr_out[k] = k;
          else for (unsigned int k = 0; k<siz_out; ++k) ptr_out[k] = ptr_arg1[k];
          cimg::date(ptr_out,siz_out);
          return cimg::type<double>::nan();
        }

        // Filename specified.
        CImg<charT> ss(siz_arg2 + 1);
        cimg_forX(ss,i) ss[i] = (char)ptr_arg2[i];
        ss.back() = 0;
        if (!siz_arg1) return cimg::fdate(ss,(unsigned int)*ptr_arg1);
        for (unsigned int k = 0; k<siz_out; ++k) ptr_out[k] = ptr_arg1[k];
        cimg::fdate(ss,ptr_out,siz_out);
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h

    **/
    CImg<T>& RGBtoXYZ(const bool use_D65=true) {
      if (_spectrum!=3)
        throw CImgInstanceException(_cimg_instance
                                    "RGBtoXYZ(): 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,2048))
      for (longT N = 0; N<whd; ++N) {
        const Tfloat
          R = (Tfloat)p1[N]/255,
          G = (Tfloat)p2[N]/255,
          B = (Tfloat)p3[N]/255;
        if (use_D65) { // D65
          p1[N] = (T)(0.4124564*R + 0.3575761*G + 0.1804375*B);
          p2[N] = (T)(0.2126729*R + 0.7151522*G + 0.0721750*B);
          p3[N] = (T)(0.0193339*R + 0.1191920*G + 0.9503041*B);
        } else { // D50
          p1[N] = (T)(0.43603516*R + 0.38511658*G + 0.14305115*B);
          p2[N] = (T)(0.22248840*R + 0.71690369*G + 0.06060791*B);
          p3[N] = (T)(0.01391602*R + 0.09706116*G + 0.71392822*B);
        }
      }
      return *this;

Project: CImg
File: CImg.h

       \param align Alignment setting when images have not all the same size.
       \param exit_on_anykey Exit function when any key is pressed.
       \return A one-column vector containing the selected image indexes.
    **/
    CImg<intT> get_select(CImgDisplay &disp, const bool feature_type=true,

Project: CImg
File: CImg.h

    //! Crop image region \newinstance.
    CImg<T> get_crop(const int x0, const int y0,
                     const int x1, const int y1,
                     const unsigned int boundary_conditions=0) const {
      return get_crop(x0,y0,0,0,x1,y1,_depth - 1,_spectrum - 1,boundary_conditions);

Project: CImg
File: CImg.h

    //! Return the basename of a filename.
    inline const char* basename(const char *const s, const char separator=cimg_file_separator)  {
      const char *p = 0, *np = s;
      while (np>=s && (p=np)) np = std::strchr(np,separator) + 1;
      return p;

Project: CImg
File: CImg.h

    //! Save image as an Ascii file \overloading.
    const CImg<T>& save_ascii(std::FILE *const file) const {
      return _save_ascii(file,0);

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

    **/
    CImg<T>& cumulate(const char axis=0) {
      switch (cimg::lowercase(axis)) {
      case 'x' :
        cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 &&
                                                                   _height*_depth*_spectrum>=16))
        cimg_forYZC(*this,y,z,c) {
          T *ptrd = data(0,y,z,c);
          Tlong cumul = (Tlong)0;
          cimg_forX(*this,x) { cumul+=(Tlong)*ptrd; *(ptrd++) = (T)cumul; }
        }
        break;
      case 'y' : {
        const ulongT w = (ulongT)_width;
        cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*512 &&
                                                                   _width*_depth*_spectrum>=16))
        cimg_forXZC(*this,x,z,c) {
          T *ptrd = data(x,0,z,c);
          Tlong cumul = (Tlong)0;
          cimg_forY(*this,y) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=w; }
        }
      } break;
      case 'z' : {
        const ulongT wh = (ulongT)_width*_height;
        cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_depth>=(cimg_openmp_sizefactor)*512 &&
                                                                   _width*_depth*_spectrum>=16))
        cimg_forXYC(*this,x,y,c) {
          T *ptrd = data(x,y,0,c);
          Tlong cumul = (Tlong)0;
          cimg_forZ(*this,z) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=wh; }
        }
      } break;
      case 'c' : {
        const ulongT whd = (ulongT)_width*_height*_depth;
        cimg_pragma_openmp(parallel for cimg_openmp_collapse(3)
                           cimg_openmp_if(_spectrum>=(cimg_openmp_sizefactor)*512 && _width*_height*_depth>=16))
        cimg_forXYZ(*this,x,y,z) {
          T *ptrd = data(x,y,z,0);
          Tlong cumul = (Tlong)0;
          cimg_forC(*this,c) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=whd; }
        }
      } break;
      default : { // Global cumulation
        Tlong cumul = (Tlong)0;
        cimg_for(*this,ptrd,T) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; }
      }
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename t1, typename t2>
    CImg<T>& draw_quiver(const CImg<t1>& flow,
                         const t2 *const color, const float opacity=1,
                         const unsigned int sampling=25, const float factor=-20,
                         const bool is_arrow=true, const unsigned int pattern=~0U) {
      return draw_quiver(flow,CImg<t2>(color,_spectrum,1,1,1,true),opacity,sampling,factor,is_arrow,pattern);

Project: CImg
File: CImg.h


      unsigned int scalar7(const mp_func op,
                           const unsigned int arg1, const unsigned int arg2, const unsigned int arg3,
                           const unsigned int arg4, const unsigned int arg5, const unsigned int arg6,
                           const unsigned int arg7) {
        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:
          arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4:
          arg5!=~0U && arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5:
          arg6!=~0U && arg6>_cimg_mp_slot_c && _cimg_mp_is_comp(arg6)?arg6:
          arg7!=~0U && arg7>_cimg_mp_slot_c && _cimg_mp_is_comp(arg7)?arg7:scalar();
        CImg<ulongT>::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5,arg6,arg7).move_to(code);
        return pos;

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

     **/
    static CImg<T> rotation_matrix(const float x, const float y, const float z, const float w,
                                   const bool is_quaternion=false) {
      double X, Y, Z, W, N;
      if (is_quaternion) {
        N = std::sqrt((double)x*x + (double)y*y + (double)z*z + (double)w*w);
        if (N>0) { X = x/N; Y = y/N; Z = z/N; W = w/N; }
        else { X = Y = Z = 0; W = 1; }
        return CImg<T>::matrix((T)(X*X + Y*Y - Z*Z - W*W),(T)(2*Y*Z - 2*X*W),(T)(2*X*Z + 2*Y*W),
                               (T)(2*X*W + 2*Y*Z),(T)(X*X - Y*Y + Z*Z - W*W),(T)(2*Z*W - 2*X*Y),
                               (T)(2*Y*W - 2*X*Z),(T)(2*X*Y + 2*Z*W),(T)(X*X - Y*Y - Z*Z + W*W));
      }
      N = cimg::hypot((double)x,(double)y,(double)z);
      if (N>0) { X = x/N; Y = y/N; Z = z/N; }
      else { X = Y = 0; Z = 1; }
      const double ang = w*cimg::PI/180, c = std::cos(ang), omc = 1 - c, s = std::sin(ang);
      return CImg<T>::matrix((T)(X*X*omc + c),(T)(X*Y*omc - Z*s),(T)(X*Z*omc + Y*s),
                             (T)(X*Y*omc + Z*s),(T)(Y*Y*omc + c),(T)(Y*Z*omc - X*s),
                             (T)(X*Z*omc - Y*s),(T)(Y*Z*omc + X*s),(T)(Z*Z*omc + c));

Project: CImg
File: CImg.h

    **/
    CImg<T>& cut(const T& min_value, const T& max_value) {
      if (is_empty()) return *this;
      const T a = min_value<max_value?min_value:max_value, b = min_value<max_value?max_value:min_value;
      cimg_openmp_for(*this,cimg::cut(*ptr,a,b),32768);
      return *this;

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

#endif
    }

    //! Load a multi-page TIFF file \newinstance.
    static CImgList<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,

Project: CImg
File: CImg.h

    **/
    const CImg<T>& save_raw(std::FILE *const file, const bool is_multiplexed=false) const {
      return _save_raw(file,0,is_multiplexed);

Project: CImg
File: CImg.h


    T _atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) const {
      return _data[cimg::cut(pos,0,width() - 1)](x,y,z,c);

Project: CImg
File: CImg.h

    **/
    CImg<T> operator|(const char *const expression) const {
      return (+*this)|=expression;

Project: CImg
File: CImg.h


      static double mp_while(_cimg_math_parser& mp) {
        const ulongT
          mem_body = mp.opcode[1],
          mem_cond = mp.opcode[2];
        const CImg<ulongT>
          *const p_cond = ++mp.p_code,
          *const p_body = p_cond + mp.opcode[3],
          *const p_end = p_body + mp.opcode[4];
        const unsigned int vsiz = (unsigned int)mp.opcode[5];
        bool is_cond = false;
        if (mp.opcode[6]) { // Set default value for result and condition if necessary
          if (vsiz) CImg<doubleT>(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type<double>::nan());
          else mp.mem[mem_body] = cimg::type<double>::nan();
        }
        if (mp.opcode[7]) mp.mem[mem_cond] = 0;
        const unsigned int _break_type = mp.break_type;
        mp.break_type = 0;
        do {
          for (mp.p_code = p_cond; mp.p_code<p_body; ++mp.p_code) { // Evaluate condition
            mp.opcode._data = mp.p_code->_data;
            const ulongT target = mp.opcode[1];
            mp.mem[target] = _cimg_mp_defunc(mp);
          }
          if (mp.break_type==1) break;
          is_cond = (bool)mp.mem[mem_cond];
          if (is_cond && !mp.break_type) // Evaluate body
            for (mp.p_code = p_body; mp.p_code<p_end; ++mp.p_code) {
              mp.opcode._data = mp.p_code->_data;
              const ulongT target = mp.opcode[1];
              mp.mem[target] = _cimg_mp_defunc(mp);
            }
          if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0;
        } while (is_cond);

        mp.break_type = _break_type;
        mp.p_code = p_end - 1;
        return mp.mem[mem_body];

Project: CImg
File: CImg.h

    inline int _vsnprintf(char *const s, const size_t size, const char* format, va_list ap) {
      cimg::mutex(6);
      const int result = std::vsnprintf(s,size,format,ap);
      cimg::mutex(6,0);
      return result;
    }

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

                       first_frame,last_frame,step_frame,yuv2rgb);
    }

    //! Load a list from an image sequence YUV file \newinstance.
    static CImgList<T> get_load_yuv(std::FILE *const file,
                                    const unsigned int size_x, const unsigned int size_y=1,
                                    const unsigned int chroma_subsampling=444,
                                    const unsigned int first_frame=0, const unsigned int last_frame=~0U,