Commit message: Fix other issues in 'CImg<T>::load_bmp()'.
CVE: CVE-2018-7641
CWE: CWE-125
Vulnerability description: An issue was discovered in CImg v.220. A heap-based buffer over-read in load_bmp in CImg.h occurs when loading a crafted bmp image, a different vulnerability than CVE-2018-7588. This is in a "32 bits colors" case, aka case 32.

Project: CImg
File: CImg.h

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

      T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
      const ulongT whd = (ulongT)_width*_height*_depth;
      cimg_pragma_openmp(parallel for cimg_openmp_if(whd>=16384))
      for (ulongT N = 0; N<whd; ++N) {
        const Tfloat
          Y = (Tfloat)p1[N],
          U = (Tfloat)p2[N],
          V = (Tfloat)p3[N],
          R = (Y + 1.140f*V)*255,
          G = (Y - 0.395f*U - 0.581f*V)*255,
          B = (Y + 2.032f*U)*255;
        p1[N] = (T)cimg::cut(R,0,255),
        p2[N] = (T)cimg::cut(G,0,255),
        p3[N] = (T)cimg::cut(B,0,255);
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename T>
    CImgDisplay& display(const CImgList<T>& list, const char axis='x', const float align=0) {
      if (list._width==1) {
        const CImg<T>& img = list[0];
        if (img._depth==1 && (img._spectrum==1 || img._spectrum>=3) && _normalization!=1) return display(img);
      }
      CImgList<typename CImg<T>::ucharT> visu(list._width);
      unsigned int dims = 0;
      cimglist_for(list,l) {
        const CImg<T>& img = list._data[l];
        img.__get_select(*this,_normalization,(img._width - 1)/2,(img._height - 1)/2,
                         (img._depth - 1)/2).move_to(visu[l]);
        dims = std::max(dims,visu[l]._spectrum);
      }
      cimglist_for(list,l) if (visu[l]._spectrum<dims) visu[l].resize(-100,-100,-100,dims,1);
      visu.get_append(axis,align).display(*this);
      return *this;

Project: CImg
File: CImg.h

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

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>=(int)_width)?out_value:_data[pos].atXYZ(x,y,z,c,out_value);

Project: CImg
File: CImg.h

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

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

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

Project: CImg
File: CImg.h

    //! Convert 3d object into a CImg3d representation \overloading.
    CImg<T>& object3dtoCImg3d(const bool full_check=true) {
      return get_object3dtoCImg3d(full_check).move_to(*this);

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& distance(const T& value, const CImg<t>& metric_mask) {
      if (is_empty()) return *this;
      bool is_value = false;
      cimg_for(*this,ptr,T) *ptr = *ptr==value?is_value=true,0:(T)999999999;
      if (!is_value) return fill(cimg::type<T>::max());
      const ulongT wh = (ulongT)_width*_height;
      cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2))
      cimg_forC(*this,c) {
        CImg<T> img = get_shared_channel(c);
        cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width*_height*_depth>=1024))
        cimg_forXYZ(metric_mask,dx,dy,dz) {
          const t weight = metric_mask(dx,dy,dz);
          if (weight) {
            for (int z = dz, nz = 0; z<depth(); ++z,++nz) { // Forward scan.
              for (int y = dy , ny = 0; y<height(); ++y,++ny) {
                for (int x = dx, nx = 0; x<width(); ++x,++nx) {
                  const T dd = img(nx,ny,nz,0,wh) + weight;
                  if (dd<img(x,y,z,0,wh)) img(x,y,z,0,wh) = dd;
                }
              }
            }
            for (int z = depth() - 1 - dz, nz = depth() - 1; z>=0; --z,--nz) { // Backward scan.
              for (int y = height() - 1 - dy, ny = height() - 1; y>=0; --y,--ny) {
                for (int x = width() - 1 - dx, nx = width() - 1; x>=0; --x,--nx) {
                  const T dd = img(nx,ny,nz,0,wh) + weight;
                  if (dd<img(x,y,z,0,wh)) img(x,y,z,0,wh) = dd;
                }
              }
            }
          }
        }
      }
      return *this;

Project: CImg
File: CImg.h

      // Tell for each character of an expression if it is inside a string or not.
      CImg<boolT> is_inside_string(CImg<charT>& expr) const {
        bool is_escaped = false, next_is_escaped = false;
        unsigned int mode = 0, next_mode = 0; // { 0=normal | 1=char-string | 2=vector-string
        CImg<boolT> res = CImg<charT>::string(expr);
        bool *pd = res._data;
        for (const char *ps = expr._data; *ps; ++ps) {
          if (!next_is_escaped && *ps=='\\') next_is_escaped = true;
          if (!is_escaped && *ps=='\'') { // Non-escaped character
            if (!mode && ps>expr._data && *(ps - 1)=='[') next_mode = mode = 2; // Start vector-string
            else if (mode==2 && *(ps + 1)==']') next_mode = !mode; // End vector-string
            else if (mode<2) next_mode = mode?(mode = 0):1; // Start/end char-string
          }
          *(pd++) = mode>=1 || is_escaped;
          mode = next_mode;
          is_escaped = next_is_escaped;
          next_is_escaped = false;
        }
        return res;

Project: CImg
File: CImg.h


    inline double rand(const double val_min, const double val_max) {
      const double val = cimg::_rand()/16777215.;
      return val_min + (val_max - val_min)*val;

Project: CImg
File: CImg.h

    **/
    const CImg<T>& save_yuv(std::FILE *const file,
                            const unsigned int chroma_subsampling=444,
                            const bool is_rgb=true) const {
      get_split('z').save_yuv(file,chroma_subsampling,is_rgb);
      return *this;

Project: CImg
File: CImg.h


    CImg<T>& _load_pandore(std::FILE *const file, const char *const filename) {
#define __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,ndim,stype) \
        cimg::fread(dims,nbdim,nfile); \
        if (endian) cimg::invert_endianness(dims,nbdim); \
        assign(nwidth,nheight,ndepth,ndim); \
        const size_t siz = size(); \
        stype *buffer = new stype[siz]; \
        cimg::fread(buffer,siz,nfile); \
        if (endian) cimg::invert_endianness(buffer,siz); \
        T *ptrd = _data; \
        cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); \
        buffer-=siz; \
        delete[] buffer

#define _cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1,stype2,stype3,ltype) { \
        if (sizeof(stype1)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1); } \
        else if (sizeof(stype2)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype2); } \
        else if (sizeof(stype3)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype3); } \
        else throw CImgIOException(_cimg_instance \
                                   "load_pandore(): Unknown pixel datatype in file '%s'.", \
                                   cimg_instance, \
                                   filename?filename:"(FILE*)"); }
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "load_pandore(): Specified filename is (null).",
                                    cimg_instance);

      std::FILE *const nfile = file?file:cimg::fopen(filename,"rb");
      CImg<charT> header(32);
      cimg::fread(header._data,12,nfile);
      if (cimg::strncasecmp("PANDORE",header,7)) {
        if (!file) cimg::fclose(nfile);
        throw CImgIOException(_cimg_instance
                              "load_pandore(): PANDORE header not found in file '%s'.",
                              cimg_instance,
                              filename?filename:"(FILE*)");
      }
      unsigned int imageid, dims[8] = { 0 };
      int ptbuf[4] = { 0 };
      cimg::fread(&imageid,1,nfile);
      const bool endian = imageid>255;
      if (endian) cimg::invert_endianness(imageid);
      cimg::fread(header._data,20,nfile);

      switch (imageid) {
      case 2 : _cimg_load_pandore_case(2,dims[1],1,1,1,unsigned char,unsigned char,unsigned char,1); break;
      case 3 : _cimg_load_pandore_case(2,dims[1],1,1,1,long,int,short,4); break;
      case 4 : _cimg_load_pandore_case(2,dims[1],1,1,1,double,float,float,4); break;
      case 5 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,unsigned char,unsigned char,unsigned char,1); break;
      case 6 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,long,int,short,4); break;
      case 7 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,double,float,float,4); break;
      case 8 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,unsigned char,unsigned char,unsigned char,1); break;
      case 9 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,long,int,short,4); break;
      case 10 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,double,float,float,4); break;
      case 11 : { // Region 1d
        cimg::fread(dims,3,nfile);
        if (endian) cimg::invert_endianness(dims,3);
        assign(dims[1],1,1,1);
        const unsigned siz = size();
        if (dims[2]<256) {
          unsigned char *buffer = new unsigned char[siz];
          cimg::fread(buffer,siz,nfile);
          T *ptrd = _data;
          cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++);
          buffer-=siz;
          delete[] buffer;
        } else {
          if (dims[2]<65536) {
            unsigned short *buffer = new unsigned short[siz];
            cimg::fread(buffer,siz,nfile);
            if (endian) cimg::invert_endianness(buffer,siz);
            T *ptrd = _data;
            cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++);
            buffer-=siz;
            delete[] buffer;
          } else {
            unsigned int *buffer = new unsigned int[siz];
            cimg::fread(buffer,siz,nfile);
            if (endian) cimg::invert_endianness(buffer,siz);
            T *ptrd = _data;
            cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++);
            buffer-=siz;
            delete[] buffer;
          }
        }
      }
        break;
      case 12 : { // Region 2d
        cimg::fread(dims,4,nfile);
        if (endian) cimg::invert_endianness(dims,4);
        assign(dims[2],dims[1],1,1);
        const size_t siz = size();
        if (dims[3]<256) {
          unsigned char *buffer = new unsigned char[siz];
          cimg::fread(buffer,siz,nfile);
          T *ptrd = _data;
          cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++);
          buffer-=siz;
          delete[] buffer;
        } else {
          if (dims[3]<65536) {
            unsigned short *buffer = new unsigned short[siz];
            cimg::fread(buffer,siz,nfile);
            if (endian) cimg::invert_endianness(buffer,siz);
            T *ptrd = _data;
            cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++);
            buffer-=siz;
            delete[] buffer;
          } else {
            unsigned int *buffer = new unsigned int[siz];
            cimg::fread(buffer,siz,nfile);
            if (endian) cimg::invert_endianness(buffer,siz);
            T *ptrd = _data;
            cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++);
            buffer-=siz;
            delete[] buffer;
          }
        }
      }
        break;
      case 13 : { // Region 3d
        cimg::fread(dims,5,nfile);
        if (endian) cimg::invert_endianness(dims,5);
        assign(dims[3],dims[2],dims[1],1);
        const size_t siz = size();
        if (dims[4]<256) {
          unsigned char *buffer = new unsigned char[siz];
          cimg::fread(buffer,siz,nfile);
          T *ptrd = _data;
          cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++);
          buffer-=siz;
          delete[] buffer;
        } else {
          if (dims[4]<65536) {
            unsigned short *buffer = new unsigned short[siz];
            cimg::fread(buffer,siz,nfile);
            if (endian) cimg::invert_endianness(buffer,siz);
            T *ptrd = _data;
            cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++);
            buffer-=siz;
            delete[] buffer;
          } else {
            unsigned int *buffer = new unsigned int[siz];
            cimg::fread(buffer,siz,nfile);
            if (endian) cimg::invert_endianness(buffer,siz);
            T *ptrd = _data;
            cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++);
            buffer-=siz;
            delete[] buffer;
          }
        }
      }
        break;
      case 16 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,unsigned char,unsigned char,unsigned char,1); break;
      case 17 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,long,int,short,4); break;
      case 18 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,double,float,float,4); break;
      case 19 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,unsigned char,unsigned char,unsigned char,1); break;
      case 20 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,long,int,short,4); break;
      case 21 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,double,float,float,4); break;
      case 22 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],unsigned char,unsigned char,unsigned char,1); break;
      case 23 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],long,int,short,4); break;
      case 24 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],unsigned long,unsigned int,unsigned short,4); break;
      case 25 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],double,float,float,4); break;
      case 26 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],unsigned char,unsigned char,unsigned char,1); break;
      case 27 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],long,int,short,4); break;
      case 28 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],unsigned long,unsigned int,unsigned short,4); break;
      case 29 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],double,float,float,4); break;
      case 30 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],unsigned char,unsigned char,unsigned char,1);
        break;
      case 31 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],long,int,short,4); break;
      case 32 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],unsigned long,unsigned int,unsigned short,4);
        break;
      case 33 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],double,float,float,4); break;
      case 34 : { // Points 1d
        cimg::fread(ptbuf,1,nfile);
        if (endian) cimg::invert_endianness(ptbuf,1);
        assign(1); (*this)(0) = (T)ptbuf[0];
      } break;
      case 35 : { // Points 2d
        cimg::fread(ptbuf,2,nfile);
        if (endian) cimg::invert_endianness(ptbuf,2);
        assign(2); (*this)(0) = (T)ptbuf[1]; (*this)(1) = (T)ptbuf[0];
      } break;
      case 36 : { // Points 3d
        cimg::fread(ptbuf,3,nfile);
        if (endian) cimg::invert_endianness(ptbuf,3);
        assign(3); (*this)(0) = (T)ptbuf[2]; (*this)(1) = (T)ptbuf[1]; (*this)(2) = (T)ptbuf[0];
      } break;
      default :
        if (!file) cimg::fclose(nfile);
        throw CImgIOException(_cimg_instance
                              "load_pandore(): Unable to load data with ID_type %u in file '%s'.",
                              cimg_instance,
                              imageid,filename?filename:"(FILE*)");
      }
      if (!file) cimg::fclose(nfile);
      return *this;

Project: CImg
File: CImg.h

    template<typename tp, typename tt, typename tc>
    CImg<T>& draw_spline(const CImg<tp>& points, const CImg<tt>& tangents,
                         const tc *const color, const float opacity=1,
                         const bool is_closed_set=false, const float precision=4,
                         const unsigned int pattern=~0U, const bool init_hatch=true) {
      if (is_empty() || !points || !tangents || points._width<2 || tangents._width<2) return *this;
      bool ninit_hatch = init_hatch;
      switch (points._height) {
      case 0 : case 1 :
        throw CImgArgumentException(_cimg_instance
                                    "draw_spline(): Invalid specified point set (%u,%u,%u,%u,%p).",
                                    cimg_instance,
                                    points._width,points._height,points._depth,points._spectrum,points._data);

      case 2 : {
        const int x0 = (int)points(0,0), y0 = (int)points(0,1);
        const float u0 = (float)tangents(0,0), v0 = (float)tangents(0,1);
        int ox = x0, oy = y0;
        float ou = u0, ov = v0;
        for (unsigned int i = 1; i<points._width; ++i) {
          const int x = (int)points(i,0), y = (int)points(i,1);
          const float u = (float)tangents(i,0), v = (float)tangents(i,1);
          draw_spline(ox,oy,ou,ov,x,y,u,v,color,precision,opacity,pattern,ninit_hatch);
          ninit_hatch = false;
          ox = x; oy = y; ou = u; ov = v;
        }
        if (is_closed_set) draw_spline(ox,oy,ou,ov,x0,y0,u0,v0,color,precision,opacity,pattern,false);
      } break;
      default : {
        const int x0 = (int)points(0,0), y0 = (int)points(0,1), z0 = (int)points(0,2);
        const float u0 = (float)tangents(0,0), v0 = (float)tangents(0,1), w0 = (float)tangents(0,2);
        int ox = x0, oy = y0, oz = z0;
        float ou = u0, ov = v0, ow = w0;
        for (unsigned int i = 1; i<points._width; ++i) {
          const int x = (int)points(i,0), y = (int)points(i,1), z = (int)points(i,2);
          const float u = (float)tangents(i,0), v = (float)tangents(i,1), w = (float)tangents(i,2);
          draw_spline(ox,oy,oz,ou,ov,ow,x,y,z,u,v,w,color,opacity,pattern,ninit_hatch);
          ninit_hatch = false;
          ox = x; oy = y; oz = z; ou = u; ov = v; ow = w;
        }
        if (is_closed_set) draw_spline(ox,oy,oz,ou,ov,ow,x0,y0,z0,u0,v0,w0,color,precision,opacity,pattern,false);
      }
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    CImg<T>& cumulate(const char axis=0) {
      switch (cimg::lowercase(axis)) {
      case 'x' :
        cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=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 collapse(3) cimg_openmp_if(_height>=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 collapse(3) cimg_openmp_if(_depth>=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 collapse(3) cimg_openmp_if(_spectrum>=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

    //! Compute the cosine of each pixel value \newinstance.
    CImg<Tfloat> get_cos() const {
      return CImg<Tfloat>(*this,false).cos();

Project: CImg
File: CImg.h

  template<typename T>
  inline CImg<_cimg_Tfloat> log10(const CImg<T>& instance) {
    return instance.get_log10();

Project: CImg
File: CImg.h

      static half nan() { const half val_nan = (half)-std::sqrt(-1.0); return val_nan; }

Project: CImg
File: CImg.h

  template<typename T>
  inline CImg<_cimg_Tfloat> tanh(const CImg<T>& instance) {
    return instance.get_tanh();

Project: CImg
File: CImg.h


      static double mp_g(_cimg_math_parser& mp) {
        cimg::unused(mp);
        return cimg::grand();

Project: CImg
File: CImg.h

  template<typename T>
  inline CImg<_cimg_Tfloat> cos(const CImg<T>& instance) {
    return instance.get_cos();

Project: CImg
File: CImg.h

    template<typename tc, typename tl>
    CImg<T>& draw_triangle(const int x0, const int y0,
                           const int x1, const int y1,
                           const int x2, const int y2,
                           const tc *const color,
                           const CImg<tl>& light,
                           const int lx0, const int ly0,
                           const int lx1, const int ly1,
                           const int lx2, const int ly2,
                           const float opacity=1) {
      if (is_empty()) return *this;
      if (!color)
        throw CImgArgumentException(_cimg_instance
                                    "draw_triangle(): Specified color is (null).",
                                    cimg_instance);
      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(light)) return draw_triangle(x0,y0,x1,y1,x2,y2,color,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
      static const T maxval = (T)std::min(cimg::type<T>::max(),(T)cimg::type<tc>::max());
      const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f);
      int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
        nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2;
      const ulongT
        whd = (ulongT)_width*_height*_depth,
        lwh = (ulongT)light._width*light._height,
        offx = _spectrum*whd - 1;
      if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nlx0,nlx1,nly0,nly1);
      if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nlx0,nlx2,nly0,nly2);
      if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nlx1,nlx2,nly1,nly2);
      if (ny0>=height() || ny2<0) return *this;
      _cimg_for_triangle3(*this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y,
                          nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) {
        int
          xleft = xleft0, xright = xright0,
          lxleft = lxleft0, lxright = lxright0,
          lyleft = lyleft0, lyright = lyright0;
        if (xright<xleft) cimg::swap(xleft,xright,lxleft,lxright,lyleft,lyright);
        const int
          dx = xright - xleft,
          dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright,
          dly = lyright>lyleft?lyright - lyleft:lyleft - lyright,
          rlx = dx?(lxright - lxleft)/dx:0,
          rly = dx?(lyright - lyleft)/dx:0,
          slx = lxright>lxleft?1:-1,
          sly = lyright>lyleft?1:-1,
          ndlx = dlx - (dx?dx*(dlx/dx):0),
          ndly = dly - (dx?dx*(dly/dx):0);
        int errlx = dx>>1, errly = errlx;
        if (xleft<0 && dx) {
          lxleft-=xleft*(lxright - lxleft)/dx;
          lyleft-=xleft*(lyright - lyleft)/dx;
        }
        if (xleft<0) xleft = 0;
        if (xright>=width() - 1) xright = width() - 1;
        T* ptrd = data(xleft,y,0,0);
        if (opacity>=1) for (int x = xleft; x<=xright; ++x) {
          const tc *col = color;
          const tl *lig = &light._atXY(lxleft,lyleft);
          cimg_forC(*this,c) {
            const tl l = *lig;
            *ptrd = (T)(l<1?l**(col++):((2 - l)**(col++) + (l - 1)*maxval));
            ptrd+=whd; lig+=lwh;
          }
          ptrd-=offx;
          lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
          lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
        } else  for (int x = xleft; x<=xright; ++x) {
          const tc *col = color;
          const tl *lig = &light._atXY(lxleft,lyleft);
          cimg_forC(*this,c) {
            const tl l = *lig;
            const T val = (T)(l<1?l**(col++):((2 - l)**(col++) + (l - 1)*maxval));
            *ptrd = (T)(nopacity*val + *ptrd*copacity);
            ptrd+=whd; lig+=lwh;
          }
          ptrd-=offx;
          lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
          lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
        }
      }
      return *this;

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

    **/
    CImg<T>& autocrop(const T *const color=0, const char *const axes="zyx") {
      if (is_empty()) return *this;
      if (!color) { // Guess color.
        const CImg<T> col1 = get_vector_at(0,0,0);
        const unsigned int w = _width, h = _height, d = _depth, s = _spectrum;
        autocrop(col1,axes);
        if (_width==w && _height==h && _depth==d && _spectrum==s) {
          const CImg<T> col2 = get_vector_at(w - 1,h - 1,d - 1);
          autocrop(col2,axes);
        }
        return *this;
      }
      for (const char *s = axes; *s; ++s) {
        const char axis = cimg::lowercase(*s);
        switch (axis) {
        case 'x' : {
	  int x0 = width(), x1 = -1;
	  cimg_forC(*this,c) {
	    const CImg<intT> coords = get_shared_channel(c)._autocrop(color[c],'x');
	    const int nx0 = coords[0], nx1 = coords[1];
	    if (nx0>=0 && nx1>=0) { x0 = std::min(x0,nx0); x1 = std::max(x1,nx1); }
	  }
          if (x0==width() && x1==-1) return assign(); else crop(x0,x1);
	} break;
        case 'y' : {
	  int y0 = height(), y1 = -1;
	  cimg_forC(*this,c) {
	    const CImg<intT> coords = get_shared_channel(c)._autocrop(color[c],'y');
	    const int ny0 = coords[0], ny1 = coords[1];
	    if (ny0>=0 && ny1>=0) { y0 = std::min(y0,ny0); y1 = std::max(y1,ny1); }
	  }
          if (y0==height() && y1==-1) return assign(); else crop(0,y0,_width - 1,y1);
	} break;
        default : {
	  int z0 = depth(), z1 = -1;
	  cimg_forC(*this,c) {
	    const CImg<intT> coords = get_shared_channel(c)._autocrop(color[c],'z');
	    const int nz0 = coords[0], nz1 = coords[1];
	    if (nz0>=0 && nz1>=0) { z0 = std::min(z0,nz0); z1 = std::max(z1,nz1); }
	  }
	  if (z0==depth() && z1==-1) return assign(); else crop(0,0,z0,_width - 1,_height - 1,z1);
	}
        }
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& operator>>=(const t value) {
      if (is_empty()) return *this;
      cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=65536))
      cimg_rof(*this,ptrd,T) *ptrd = (T)(((longT)*ptrd) >> (int)value);
      return *this;

Project: CImg
File: CImg.h

    **/
    CImgDisplay& wait(const unsigned int milliseconds) {
      cimg::_wait(milliseconds,_timer);
      return *this;

Project: CImg
File: CImg.h

    //! Compute the hyperbolic cosine of each pixel value \newinstance.
    CImg<Tfloat> get_cosh() const {
      return CImg<Tfloat>(*this,false).cosh();

Project: CImg
File: CImg.h

    template<typename tc>
    CImg<T>& draw_point(const int x0, const int y0, const int z0,
                        const tc *const color, const float opacity=1) {
      if (is_empty()) return *this;
      if (!color)
        throw CImgArgumentException(_cimg_instance
                                    "draw_point(): Specified color is (null).",
                                    cimg_instance);
      if (x0>=0 && y0>=0 && z0>=0 && x0<width() && y0<height() && z0<depth()) {
        const ulongT whd = (ulongT)_width*_height*_depth;
        const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f);
        T *ptrd = data(x0,y0,z0,0);
        const tc *col = color;
        if (opacity>=1) cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=whd; }
        else cimg_forC(*this,c) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whd; }
      }
      return *this;

Project: CImg
File: CImg.h

    //! Compute the arccosine of each pixel value \newinstance.
    CImg<Tfloat> get_acos() const {
      return CImg<Tfloat>(*this,false).acos();

Project: CImg
File: CImg.h

  template<typename T>
  inline CImg<_cimg_Tfloat> sign(const CImg<T>& instance) {
    return instance.get_sign();

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

    //! Compute a n-d Fast Fourier Transform.
    /**
      \param invert Tells if the direct (\c false) or inverse transform (\c true) is computed.
    **/
    CImgList<T>& FFT(const bool invert=false) {
      if (is_empty()) return *this;
      if (_width==1) insert(1);
      if (_width>2)
        cimg::warn(_cimglist_instance
                   "FFT(): Instance has more than 2 images",
                   cimglist_instance);

Project: CImg
File: CImg.h

    **/
    CImg<T>& log() {
      if (is_empty()) return *this;
      cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=262144))
      cimg_rof(*this,ptrd,T) *ptrd = (T)std::log((double)*ptrd);
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<t> get_map(const CImg<t>& colormap, const unsigned int boundary_conditions=0) const {
      if (_spectrum!=1 && colormap._spectrum!=1)
        throw CImgArgumentException(_cimg_instance
                                    "map(): Instance and specified colormap (%u,%u,%u,%u,%p) "
                                    "have incompatible dimensions.",
                                    cimg_instance,
                                    colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data);

      const ulongT
        whd = (ulongT)_width*_height*_depth,
        cwhd = (ulongT)colormap._width*colormap._height*colormap._depth,
        cwhd2 = 2*cwhd;
      CImg<t> res(_width,_height,_depth,colormap._spectrum==1?_spectrum:colormap._spectrum);
      switch (colormap._spectrum) {

      case 1 : { // Optimized for scalars
        const T *ptrs = _data;
        switch (boundary_conditions) {
        case 3 : // Mirror
          cimg_for(res,ptrd,t) {
            const ulongT ind = ((ulongT)*(ptrs++))%cwhd2;
            *ptrd = colormap[ind<cwhd?ind:cwhd2 - ind - 1];
          }
          break;
        case 2 : // Periodic
          cimg_for(res,ptrd,t) {
            const ulongT ind = (ulongT)*(ptrs++);
            *ptrd = colormap[ind%cwhd];
          } break;
        case 1 : // Neumann
          cimg_for(res,ptrd,t) {
            const longT ind = (longT)*(ptrs++);
            *ptrd = colormap[cimg::cut(ind,(longT)0,(longT)cwhd - 1)];
          } break;
        default : // Dirichlet
          cimg_for(res,ptrd,t) {
            const ulongT ind = (ulongT)*(ptrs++);
            *ptrd = ind<cwhd?colormap[ind]:(t)0;
          }
        }
      } break;

      case 2 : { // Optimized for 2d vectors.
        const t *const ptrp0 = colormap._data, *ptrp1 = ptrp0 + cwhd;
        t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd;
        switch (boundary_conditions) {
        case 3 : // Mirror
          for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
            const ulongT
              _ind = ((ulongT)*(ptrs++))%cwhd2,
              ind = _ind<cwhd?_ind:cwhd2 - _ind - 1;
            *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind];
          }
          break;
        case 2 : // Periodic
          for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
            const ulongT ind = ((ulongT)*(ptrs++))%cwhd;
            *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind];
          }
          break;
        case 1 : // Neumann
          for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
            const longT ind = cimg::cut((longT)*(ptrs++),(longT)0,(longT)cwhd - 1);
            *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind];
          }
          break;
        default : // Dirichlet
          for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
            const ulongT ind = (ulongT)*(ptrs++);
            const bool is_in = ind<cwhd;
            *(ptrd0++) = is_in?ptrp0[ind]:(t)0; *(ptrd1++) = is_in?ptrp1[ind]:(t)0;
          }
        }
      } break;

      case 3 : { // Optimized for 3d vectors (colors).
        const t *const ptrp0 = colormap._data, *ptrp1 = ptrp0 + cwhd, *ptrp2 = ptrp1 + cwhd;
        t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd, *ptrd2 = ptrd1 + whd;
        switch (boundary_conditions) {
        case 3 : // Mirror
          for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
            const ulongT
              _ind = ((ulongT)*(ptrs++))%cwhd2,
              ind = _ind<cwhd?_ind:cwhd2 - _ind - 1;
            *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind]; *(ptrd2++) = ptrp2[ind];
          } break;
        case 2 : // Periodic
          for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
            const ulongT ind = ((ulongT)*(ptrs++))%cwhd;
            *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind]; *(ptrd2++) = ptrp2[ind];
          } break;
        case 1 : // Neumann
          for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
            const longT ind = cimg::cut((longT)*(ptrs++),(longT)0,(longT)cwhd - 1);
            *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind]; *(ptrd2++) = ptrp2[ind];
          } break;
        default : // Dirichlet
          for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
            const ulongT ind = (ulongT)*(ptrs++);
            const bool is_in = ind<cwhd;
            *(ptrd0++) = is_in?ptrp0[ind]:(t)0; *(ptrd1++) = is_in?ptrp1[ind]:(t)0; *(ptrd2++) = is_in?ptrp2[ind]:(t)0;
          }
        }
      } break;

      default : { // Generic version.
        t *ptrd = res._data;
        switch (boundary_conditions) {
        case 3 : // Mirror
          for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
            const ulongT
              _ind = ((ulongT)*(ptrs++))%cwhd,
              ind = _ind<cwhd?_ind:cwhd2 - _ind - 1;
            const t *ptrp = colormap._data + ind;
            t *_ptrd = ptrd++; cimg_forC(res,c) { *_ptrd = *ptrp; _ptrd+=whd; ptrp+=cwhd; }
          } break;
        case 2 : // Periodic
          for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
            const ulongT ind = ((ulongT)*(ptrs++))%cwhd;
            const t *ptrp = colormap._data + ind;
            t *_ptrd = ptrd++; cimg_forC(res,c) { *_ptrd = *ptrp; _ptrd+=whd; ptrp+=cwhd; }
          } break;
        case 1 : // Neumann
          for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
            const longT ind = cimg::cut((longT)*(ptrs++),(longT)0,(longT)cwhd - 1);
            const t *ptrp = colormap._data + ind;
            t *_ptrd = ptrd++; cimg_forC(res,c) { *_ptrd = *ptrp; _ptrd+=whd; ptrp+=cwhd; }
          } break;
        default : // Dirichlet
          for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
            const ulongT ind = (ulongT)*(ptrs++);
            const bool is_in = ind<cwhd;
            if (is_in) {
              const t *ptrp = colormap._data + ind;
              t *_ptrd = ptrd++; cimg_forC(res,c) { *_ptrd = *ptrp; _ptrd+=whd; ptrp+=cwhd; }
            } else {
              t *_ptrd = ptrd++; cimg_forC(res,c) { *_ptrd = (t)0; _ptrd+=whd; }
            }
          }
        }
      }
      }
      return res;

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h


      static double mp_srand(_cimg_math_parser& mp) {
        return cimg::srand((unsigned int)_mp_arg(2));

Project: CImg
File: CImg.h

    template<typename tf>
    static CImg<floatT> cylinder3d(CImgList<tf>& primitives,
                                   const float radius=50, const float size_z=100, const unsigned int subdivisions=24) {
      primitives.assign();
      if (!subdivisions) return CImg<floatT>();
      CImgList<floatT> vertices(2,1,3,1,1,
                                0.,0.,0.,
                                0.,0.,size_z);
      for (float delta = 360.0f/subdivisions, angle = 0; angle<360; angle+=delta) {
	const float a = (float)(angle*cimg::PI/180);
        CImg<floatT>::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),0.0f).move_to(vertices);
        CImg<floatT>::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),size_z).move_to(vertices);
      }
      const unsigned int nbr = (vertices._width - 2)/2;
      for (unsigned int p = 0; p<nbr; ++p) {
	const unsigned int curr = 2 + 2*p, next = 2 + (2*((p + 1)%nbr));
        CImg<tf>::vector(0,next,curr).move_to(primitives);
        CImg<tf>::vector(1,curr + 1,next + 1).move_to(primitives);
        CImg<tf>::vector(curr,next,next + 1,curr + 1).move_to(primitives);
      }
      return vertices>'x';

Project: CImg
File: CImg.h

    //! Compute image laplacian \newinstance.
    CImg<Tfloat> get_laplacian() const {
      if (is_empty()) return CImg<Tfloat>();
      CImg<Tfloat> res(_width,_height,_depth,_spectrum);
      if (_depth>1) { // 3d
        cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2))
        cimg_forC(*this,c) {
          Tfloat *ptrd = res.data(0,0,0,c);
          CImg_3x3x3(I,Tfloat);
          cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) *(ptrd++) = Incc + Ipcc + Icnc + Icpc + Iccn + Iccp - 6*Iccc;
        }
      } else if (_height>1) { // 2d
        cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2))
        cimg_forC(*this,c) {
          Tfloat *ptrd = res.data(0,0,0,c);
          CImg_3x3(I,Tfloat);
          cimg_for3x3(*this,x,y,0,c,I,Tfloat) *(ptrd++) = Inc + Ipc + Icn + Icp - 4*Icc;
        }
      } else { // 1d
        cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=1048576 && _height*_depth*_spectrum>=2))
        cimg_forC(*this,c) {
          Tfloat *ptrd = res.data(0,0,0,c);
          CImg_3x3(I,Tfloat);
          cimg_for3x3(*this,x,y,0,c,I,Tfloat) *(ptrd++) = Inc + Ipc - 2*Icc;
        }
      }
      return res;

Project: CImg
File: CImg.h

    //! Convert pixel values from RGB to CMY color spaces.
    CImg<T>& RGBtoCMY() {
      if (_spectrum!=3)
        throw CImgInstanceException(_cimg_instance
                                    "RGBtoCMY(): 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 ulongT whd = (ulongT)_width*_height*_depth;
      cimg_pragma_openmp(parallel for cimg_openmp_if(whd>=2048))
      for (ulongT N = 0; N<whd; ++N) {
        const Tfloat
          R = (Tfloat)p1[N],
          G = (Tfloat)p2[N],
          B = (Tfloat)p3[N],
          C = 255 - R,
          M = 255 - G,
          Y = 255 - B;
        p1[N] = (T)cimg::cut(C,0,255),
        p2[N] = (T)cimg::cut(M,0,255),
        p3[N] = (T)cimg::cut(Y,0,255);
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    CImg<T>& threshold(const T& value, const bool soft_threshold=false, const bool strict_threshold=false) {
      if (is_empty()) return *this;
      if (strict_threshold) {
        if (soft_threshold)
          cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768))
          cimg_rof(*this,ptrd,T) {
            const T v = *ptrd;
            *ptrd = v>value?(T)(v-value):v<-(float)value?(T)(v + value):(T)0;
          }
        else
          cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=65536))
          cimg_rof(*this,ptrd,T) *ptrd = *ptrd>value?(T)1:(T)0;
      } else {
        if (soft_threshold)
          cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768))
          cimg_rof(*this,ptrd,T) {
            const T v = *ptrd;
            *ptrd = v>=value?(T)(v-value):v<=-(float)value?(T)(v + value):(T)0;
          }
        else
          cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=65536))
          cimg_rof(*this,ptrd,T) *ptrd = *ptrd>=value?(T)1:(T)0;
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    CImg<T> rotate(const float u, const float v, const float w, const float angle,
                   const float cx, const float cy, const float cz,
                   const unsigned int interpolation=1, const unsigned int boundary_conditions=0) {
      const float nangle = cimg::mod(angle,360.0f);
      if (nangle==0.0f) return *this;
      return get_rotate(u,v,w,nangle,cx,cy,cz,interpolation,boundary_conditions).move_to(*this);

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

      // Return type of a memory element as a string.
      CImg<charT> s_type(const unsigned int arg) const {
        CImg<charT> res;
        if (_cimg_mp_is_vector(arg)) { // Vector
          CImg<charT>::string("vectorXXXXXXXXXXXXXXXX").move_to(res);
          std::sprintf(res._data + 6,"%u",_cimg_mp_size(arg));
        } else CImg<charT>::string("scalar").move_to(res);
        return res;

Project: CImg
File: CImg.h

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

      T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
      const ulongT whd = (ulongT)_width*_height*_depth;
      cimg_pragma_openmp(parallel for cimg_openmp_if(whd>=2048))
      for (ulongT N = 0; N<whd; ++N) {
        const Tfloat
          C = (Tfloat)p1[N],
          M = (Tfloat)p2[N],
          Y = (Tfloat)p3[N],
          R = 255 - C,
          G = 255 - M,
          B = 255 - Y;
        p1[N] = (T)cimg::cut(R,0,255),
        p2[N] = (T)cimg::cut(G,0,255),
        p3[N] = (T)cimg::cut(B,0,255);
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename tp, typename tf, typename tc, typename to>
    CImg<T>& draw_object3d(LibBoard::Board& board,
                           const float x0, const float y0, const float z0,
                           const CImg<tp>& vertices, const CImgList<tf>& primitives,
                           const CImgList<tc>& colors,
                           const unsigned int render_type=4,
                           const bool is_double_sided=false, const float focale=700,
                           const float lightx=0, const float lighty=0, const float lightz=-5e8,
                           const float specular_lightness=0.2f, const float specular_shininess=0.1f) {
      return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg<floatT>::const_empty(),
                           render_type,is_double_sided,focale,lightx,lighty,lightz,
                           specular_lightness,specular_shininess,CImg<floatT>::empty());

Project: CImg
File: CImg.h

    template<typename tc>
    CImg<T>& _draw_triangle(const int x0, const int y0,
                            const int x1, const int y1,
                            const int x2, const int y2,
                            const tc *const color, const float opacity,
                            const float brightness) {
      cimg_init_scanline(color,opacity);
      const float nbrightness = cimg::cut(brightness,0,2);
      int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2;
      if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1);
      if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2);
      if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2);
      if (ny0<height() && ny2>=0) {
        if ((nx1 - nx0)*(ny2 - ny0) - (nx2 - nx0)*(ny1 - ny0)<0)
          _cimg_for_triangle1(*this,xl,xr,y,nx0,ny0,nx1,ny1,nx2,ny2)
            cimg_draw_scanline(xl,xr,y,color,opacity,nbrightness);
        else
          _cimg_for_triangle1(*this,xl,xr,y,nx0,ny0,nx1,ny1,nx2,ny2)
            cimg_draw_scanline(xr,xl,y,color,opacity,nbrightness);
      }
      return *this;

Project: CImg
File: CImg.h

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

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

Project: CImg
File: CImg.h

    **/
    CImg<T>& normalize() {
      const ulongT whd = (ulongT)_width*_height*_depth;
      cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=512 && _height*_depth>=16))
      cimg_forYZ(*this,y,z) {
        T *ptrd = data(0,y,z,0);
        cimg_forX(*this,x) {
          const T *ptrs = ptrd;
          float n = 0;
          cimg_forC(*this,c) { n+=cimg::sqr((float)*ptrs); ptrs+=whd; }
          n = (float)std::sqrt(n);
          T *_ptrd = ptrd++;
          if (n>0) cimg_forC(*this,c) { *_ptrd = (T)(*_ptrd/n); _ptrd+=whd; }
          else cimg_forC(*this,c) { *_ptrd = (T)0; _ptrd+=whd; }
        }
      }
      return *this;

Project: CImg
File: CImg.h

     **/
    CImg<T>& operator++() {
      if (is_empty()) return *this;
      cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=524288))
      cimg_rof(*this,ptrd,T) ++*ptrd;
      return *this;

Project: CImg
File: CImg.h


      _cimg_math_parser():
        code(_code),p_code_end(0),p_break((CImg<ulongT>*)0 - 2),
        imgin(CImg<T>::const_empty()),listin(CImgList<T>::const_empty()),
        imgout(CImg<T>::empty()),listout(CImgList<T>::empty()),
        img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),debug_indent(0),
        result_dim(0),break_type(0),constcache_size(0),is_parallelizable(true),is_fill(false),need_input_copy(false),
        calling_function(0) {
        mem.assign(1 + _cimg_mp_slot_c,1,1,1,0); // Allow to skip 'is_empty?' test in operator()()
        result = mem._data;

Project: CImg
File: CImg.h


      static double mp_dowhile(_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


    CImg<T>& _load_analyze(std::FILE *const file, const char *const filename, float *const voxel_size=0) {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "load_analyze(): Specified filename is (null).",
                                    cimg_instance);

      std::FILE *nfile_header = 0, *nfile = 0;
      if (!file) {
        CImg<charT> body(1024);
        const char *const ext = cimg::split_filename(filename,body);
        if (!cimg::strcasecmp(ext,"hdr")) { // File is an Analyze header file.
          nfile_header = cimg::fopen(filename,"rb");
          cimg_sprintf(body._data + std::strlen(body),".img");
          nfile = cimg::fopen(body,"rb");
        } else if (!cimg::strcasecmp(ext,"img")) { // File is an Analyze data file.
          nfile = cimg::fopen(filename,"rb");
          cimg_sprintf(body._data + std::strlen(body),".hdr");
          nfile_header = cimg::fopen(body,"rb");
        } else nfile_header = nfile = cimg::fopen(filename,"rb"); // File is a Niftii file.
      } else nfile_header = nfile = file; // File is a Niftii file.
      if (!nfile || !nfile_header)
        throw CImgIOException(_cimg_instance
                              "load_analyze(): Invalid Analyze7.5 or NIFTI header in file '%s'.",
                              cimg_instance,
                              filename?filename:"(FILE*)");

      // Read header.
      bool endian = false;
      unsigned int header_size;
      cimg::fread(&header_size,1,nfile_header);
      if (!header_size)
        throw CImgIOException(_cimg_instance
                              "load_analyze(): Invalid zero-size header in file '%s'.",
                              cimg_instance,
                              filename?filename:"(FILE*)");
      if (header_size>=4096) { endian = true; cimg::invert_endianness(header_size); }

      unsigned char *const header = new unsigned char[header_size];
      cimg::fread(header + 4,header_size - 4,nfile_header);
      if (!file && nfile_header!=nfile) cimg::fclose(nfile_header);
      if (endian) {
        cimg::invert_endianness((short*)(header + 40),5);
        cimg::invert_endianness((short*)(header + 70),1);
        cimg::invert_endianness((short*)(header + 72),1);
        cimg::invert_endianness((float*)(header + 76),4);
        cimg::invert_endianness((float*)(header + 108),1);
        cimg::invert_endianness((float*)(header + 112),1);
      }

      if (nfile_header==nfile) {
        const unsigned int vox_offset = (unsigned int)*(float*)(header + 108);
        std::fseek(nfile,vox_offset,SEEK_SET);
      }

      unsigned short *dim = (unsigned short*)(header + 40), dimx = 1, dimy = 1, dimz = 1, dimv = 1;
      if (!dim[0])
        cimg::warn(_cimg_instance
                   "load_analyze(): File '%s' defines an image with zero dimensions.",
                   cimg_instance,
                   filename?filename:"(FILE*)");

      if (dim[0]>4)
        cimg::warn(_cimg_instance
                   "load_analyze(): File '%s' defines an image with %u dimensions, reading only the 4 first.",
                   cimg_instance,
                   filename?filename:"(FILE*)",dim[0]);

      if (dim[0]>=1) dimx = dim[1];
      if (dim[0]>=2) dimy = dim[2];
      if (dim[0]>=3) dimz = dim[3];
      if (dim[0]>=4) dimv = dim[4];
      float scalefactor = *(float*)(header + 112); if (scalefactor==0) scalefactor = 1;
      const unsigned short datatype = *(unsigned short*)(header + 70);
      if (voxel_size) {
        const float *vsize = (float*)(header + 76);
        voxel_size[0] = vsize[1]; voxel_size[1] = vsize[2]; voxel_size[2] = vsize[3];
      }
      delete[] header;

      // Read pixel data.
      assign(dimx,dimy,dimz,dimv);
      const size_t pdim = (size_t)dimx*dimy*dimz*dimv;
      switch (datatype) {
      case 2 : {
        unsigned char *const buffer = new unsigned char[pdim];
        cimg::fread(buffer,pdim,nfile);
        cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor);
        delete[] buffer;
      } break;
      case 4 : {
        short *const buffer = new short[pdim];
        cimg::fread(buffer,pdim,nfile);
        if (endian) cimg::invert_endianness(buffer,pdim);
        cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor);
        delete[] buffer;
      } break;
      case 8 : {
        int *const buffer = new int[pdim];
        cimg::fread(buffer,pdim,nfile);
        if (endian) cimg::invert_endianness(buffer,pdim);
        cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor);
        delete[] buffer;
      } break;
      case 16 : {
        float *const buffer = new float[pdim];
        cimg::fread(buffer,pdim,nfile);
        if (endian) cimg::invert_endianness(buffer,pdim);
        cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor);
        delete[] buffer;
      } break;
      case 64 : {
        double *const buffer = new double[pdim];
        cimg::fread(buffer,pdim,nfile);
        if (endian) cimg::invert_endianness(buffer,pdim);
        cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor);
        delete[] buffer;
      } break;
      default :
        if (!file) cimg::fclose(nfile);
        throw CImgIOException(_cimg_instance
                              "load_analyze(): Unable to load datatype %d in file '%s'",
                              cimg_instance,
                              datatype,filename?filename:"(FILE*)");
      }
      if (!file) cimg::fclose(nfile);
      return *this;

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 {
      if (is_empty())
        throw CImgInstanceException(_cimglist_instance
                                    "max_min(): Empty instance.",
                                    cimglist_instance);
      const T *ptr_max = _data->_data;
      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

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

      T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
      const ulongT whd = (ulongT)_width*_height*_depth;
      cimg_pragma_openmp(parallel for cimg_openmp_if(whd>=256))
      for (ulongT N = 0; N<whd; ++N) {
        const Tfloat
          H = cimg::mod((Tfloat)p1[N],(Tfloat)360),
          S = (Tfloat)p2[N],
          L = (Tfloat)p3[N],
          q = 2*L<1?L*(1 + S):L + S - L*S,
          p = 2*L - q,
          h = H/360,
          tr = h + (Tfloat)1/3,
          tg = h,
          tb = h - (Tfloat)1/3,
          ntr = tr<0?tr + 1:tr>1?tr - 1:(Tfloat)tr,
          ntg = tg<0?tg + 1:tg>1?tg - 1:(Tfloat)tg,
          ntb = tb<0?tb + 1:tb>1?tb - 1:(Tfloat)tb,
          R = 6*ntr<1?p + (q - p)*6*ntr:2*ntr<1?q:3*ntr<2?p + (q - p)*6*(2.0f/3 - ntr):p,
          G = 6*ntg<1?p + (q - p)*6*ntg:2*ntg<1?q:3*ntg<2?p + (q - p)*6*(2.0f/3 - ntg):p,
          B = 6*ntb<1?p + (q - p)*6*ntb:2*ntb<1?q:3*ntb<2?p + (q - p)*6*(2.0f/3 - ntb):p;
        p1[N] = (T)cimg::cut(255*R,0,255);
        p2[N] = (T)cimg::cut(255*G,0,255);
        p3[N] = (T)cimg::cut(255*B,0,255);
      }
      return *this;

Project: CImg
File: CImg.h


    inline unsigned int srand() {
      unsigned int t = (unsigned int)cimg::time();
#if cimg_OS==1
      t+=(unsigned int)getpid();
#elif cimg_OS==2
      t+=(unsigned int)_getpid();
#endif
      return cimg::_rand(t,true);

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

    template<typename tf, typename tc>
    const CImg<T>& _save_off(const CImgList<tf>& primitives, const CImgList<tc>& colors,
                             std::FILE *const file, const char *const filename) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_off(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty())
        throw CImgInstanceException(_cimg_instance
                                    "save_off(): Empty instance, for file '%s'.",
                                    cimg_instance,
                                    filename?filename:"(FILE*)");

      CImgList<T> opacities;
      CImg<charT> error_message(1024);
      if (!is_object3d(primitives,colors,opacities,true,error_message))
        throw CImgInstanceException(_cimg_instance
                                    "save_off(): Invalid specified 3d object, for file '%s' (%s).",
                                    cimg_instance,
                                    filename?filename:"(FILE*)",error_message.data());

      const CImg<tc> default_color(1,3,1,1,200);
      std::FILE *const nfile = file?file:cimg::fopen(filename,"w");
      unsigned int supported_primitives = 0;
      cimglist_for(primitives,l) if (primitives[l].size()!=5) ++supported_primitives;
      std::fprintf(nfile,"OFF\n%u %u %u\n",_width,supported_primitives,3*primitives._width);
      cimg_forX(*this,i) std::fprintf(nfile,"%f %f %f\n",
                                      (float)((*this)(i,0)),(float)((*this)(i,1)),(float)((*this)(i,2)));
      cimglist_for(primitives,l) {
        const CImg<tc>& color = l<colors.width()?colors[l]:default_color;
        const unsigned int psiz = primitives[l].size(), csiz = color.size();
        const float r = color[0]/255.0f, g = (csiz>1?color[1]:r)/255.0f, b = (csiz>2?color[2]:g)/255.0f;
        switch (psiz) {
        case 1 : std::fprintf(nfile,"1 %u %f %f %f\n",
                              (unsigned int)primitives(l,0),r,g,b); break;
        case 2 : std::fprintf(nfile,"2 %u %u %f %f %f\n",
                              (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),r,g,b); break;
        case 3 : std::fprintf(nfile,"3 %u %u %u %f %f %f\n",
                              (unsigned int)primitives(l,0),(unsigned int)primitives(l,2),
                              (unsigned int)primitives(l,1),r,g,b); break;
        case 4 : std::fprintf(nfile,"4 %u %u %u %u %f %f %f\n",
                              (unsigned int)primitives(l,0),(unsigned int)primitives(l,3),
                              (unsigned int)primitives(l,2),(unsigned int)primitives(l,1),r,g,b); break;
        case 5 : std::fprintf(nfile,"2 %u %u %f %f %f\n",
                              (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),r,g,b); break;
        case 6 : {
          const unsigned int xt = (unsigned int)primitives(l,2), yt = (unsigned int)primitives(l,3);
          const float
            rt = color.atXY(xt,yt,0)/255.0f,
            gt = (csiz>1?color.atXY(xt,yt,1):r)/255.0f,
            bt = (csiz>2?color.atXY(xt,yt,2):g)/255.0f;
          std::fprintf(nfile,"2 %u %u %f %f %f\n",
                       (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),rt,gt,bt);
        } break;
        case 9 : {
          const unsigned int xt = (unsigned int)primitives(l,3), yt = (unsigned int)primitives(l,4);
          const float
            rt = color.atXY(xt,yt,0)/255.0f,
            gt = (csiz>1?color.atXY(xt,yt,1):r)/255.0f,
            bt = (csiz>2?color.atXY(xt,yt,2):g)/255.0f;
          std::fprintf(nfile,"3 %u %u %u %f %f %f\n",
                       (unsigned int)primitives(l,0),(unsigned int)primitives(l,2),
                       (unsigned int)primitives(l,1),rt,gt,bt);
        } break;
        case 12 : {
          const unsigned int xt = (unsigned int)primitives(l,4), yt = (unsigned int)primitives(l,5);
          const float
            rt = color.atXY(xt,yt,0)/255.0f,
            gt = (csiz>1?color.atXY(xt,yt,1):r)/255.0f,
            bt = (csiz>2?color.atXY(xt,yt,2):g)/255.0f;
          std::fprintf(nfile,"4 %u %u %u %u %f %f %f\n",
                       (unsigned int)primitives(l,0),(unsigned int)primitives(l,3),
                       (unsigned int)primitives(l,2),(unsigned int)primitives(l,1),rt,gt,bt);
        } break;
        }
      }
      if (!file) cimg::fclose(nfile);
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& operator*=(const t value) {
      if (is_empty()) return *this;
      cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=262144))
      cimg_rof(*this,ptrd,T) *ptrd = (T)(*ptrd * value);
      return *this;

Project: CImg
File: CImg.h


    CImg<intT> _select(CImgDisplay &disp, const char *const title,
                       const unsigned int feature_type, unsigned int *const XYZ,
                       const int origX, const int origY, const int origZ,
                       const bool exit_on_anykey,
                       const bool reset_view3d,
                       const bool force_display_z_coord) const {
      if (is_empty()) return CImg<intT>(1,feature_type==0?3:6,1,1,-1);
      if (!disp) {
        disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1);
        if (!title) disp.set_title("CImg<%s> (%ux%ux%ux%u)",pixel_type(),_width,_height,_depth,_spectrum);
      } else if (title) disp.set_title("%s",title);

      CImg<T> thumb;
      if (width()>disp.screen_width() || height()>disp.screen_height())
        get_resize(cimg_fitscreen(width(),height(),depth()),depth(),-100).move_to(thumb);

      const unsigned int old_normalization = disp.normalization();
      bool old_is_resized = disp.is_resized();
      disp._normalization = 0;
      disp.show().set_key(0).set_wheel().show_mouse();

      static const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 };

      int area = 0, starting_area = 0, clicked_area = 0, phase = 0,
        X0 = (int)((XYZ?XYZ[0]:(_width - 1)/2)%_width),
        Y0 = (int)((XYZ?XYZ[1]:(_height - 1)/2)%_height),
        Z0 = (int)((XYZ?XYZ[2]:(_depth - 1)/2)%_depth),
        X1 =-1, Y1 = -1, Z1 = -1,
        X3d = -1, Y3d = -1,
        oX3d = X3d, oY3d = -1,
        omx = -1, omy = -1;
      float X = -1, Y = -1, Z = -1;
      unsigned int old_button = 0, key = 0;

      bool shape_selected = false, text_down = false, visible_cursor = true;
      static CImg<floatT> pose3d;
      static bool is_view3d = false, is_axes = true;
      if (reset_view3d) { pose3d.assign(); is_view3d = false; }
      CImg<floatT> points3d, opacities3d, sel_opacities3d;
      CImgList<uintT> primitives3d, sel_primitives3d;
      CImgList<ucharT> colors3d, sel_colors3d;
      CImg<ucharT> visu, visu0, view3d;
      CImg<charT> text(1024); *text = 0;

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

        // Handle mouse motion and selection
        int
          mx = disp.mouse_x(),
          my = disp.mouse_y();

        const float
          mX = mx<0?-1.0f:(float)mx*(width() + (depth()>1?depth():0))/disp.width(),
          mY = my<0?-1.0f:(float)my*(height() + (depth()>1?depth():0))/disp.height();

        area = 0;
        if (mX>=0 && mY>=0 && mX<width() && mY<height())  { area = 1; X = mX; Y = mY; Z = (float)(phase?Z1:Z0); }
        if (mX>=0 && mX<width() && mY>=height()) { area = 2; X = mX; Z = mY - _height; Y = (float)(phase?Y1:Y0); }
        if (mY>=0 && mX>=width() && mY<height()) { area = 3; Y = mY; Z = mX - _width; X = (float)(phase?X1:X0); }
        if (mX>=width() && mY>=height()) area = 4;
        if (disp.button()) { if (!clicked_area) clicked_area = area; } else clicked_area = 0;

        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::keyPAGEUP :
          if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { disp.set_wheel(1); key = 0; } break;
        case cimg::keyPAGEDOWN :
          if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { disp.set_wheel(-1); key = 0; } break;
        case cimg::keyA : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            is_axes = !is_axes; disp.set_key(key,false); key = 0; visu0.assign();
          } 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(_width,_height,_depth),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::keyV : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
            is_view3d = !is_view3d; 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=std_fopen(filename,"r"))!=0) cimg::fclose(file);
            } while (file);
            if (visu0) {
              (+visu0).draw_text(0,0," Saving snapshot... ",foreground_color,background_color,0.7f,13).display(disp);
              visu0.save(filename);
              (+visu0).draw_text(0,0," Snapshot '%s' saved. ",foreground_color,background_color,0.7f,13,filename._data).
                display(disp);
            }
            disp.set_key(key,false); 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=std_fopen(filename,"r"))!=0) cimg::fclose(file);
            } while (file);
            (+visu0).draw_text(0,0," Saving instance... ",foreground_color,background_color,0.7f,13).display(disp);
            save(filename);
            (+visu0).draw_text(0,0," Instance '%s' saved. ",foreground_color,background_color,0.7f,13,filename._data).
              display(disp);
            disp.set_key(key,false); key = 0;
          } break;
        }

        switch (area) {

        case 0 : // When mouse is out of image range.
          mx = my = -1; X = Y = Z = -1;
          break;

        case 1 : case 2 : case 3 : // When mouse is over the XY,XZ or YZ projections.
          if (disp.button()&1 && phase<2 && clicked_area==area) { // When selection has been started (1st step).
            if (_depth>1 && (X1!=(int)X || Y1!=(int)Y || Z1!=(int)Z)) visu0.assign();
            X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z;
          }
          if (!(disp.button()&1) && phase>=2 && clicked_area!=area) { // When selection is at 2nd step (for volumes).
            switch (starting_area) {
            case 1 : if (Z1!=(int)Z) visu0.assign(); Z1 = (int)Z; break;
            case 2 : if (Y1!=(int)Y) visu0.assign(); Y1 = (int)Y; break;
            case 3 : if (X1!=(int)X) visu0.assign(); X1 = (int)X; break;
            }
          }
          if (disp.button()&2 && clicked_area==area) { // When moving through the image/volume.
            if (phase) {
              if (_depth>1 && (X1!=(int)X || Y1!=(int)Y || Z1!=(int)Z)) visu0.assign();
              X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z;
            } else {
              if (_depth>1 && (X0!=(int)X || Y0!=(int)Y || Z0!=(int)Z)) visu0.assign();
              X0 = (int)X; Y0 = (int)Y; Z0 = (int)Z;
            }
          }
          if (disp.button()&4) {
            X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = area = clicked_area = starting_area = 0;
            visu0.assign();
          }
          if (disp.wheel()) { // When moving through the slices of the volume (with mouse wheel).
            if (_depth>1 && !disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT() &&
                !disp.is_keySHIFTLEFT() && !disp.is_keySHIFTRIGHT()) {
              switch (area) {
              case 1 :
                if (phase) Z = (float)(Z1+=disp.wheel()); else Z = (float)(Z0+=disp.wheel());
                visu0.assign(); break;
              case 2 :
                if (phase) Y = (float)(Y1+=disp.wheel()); else Y = (float)(Y0+=disp.wheel());
                visu0.assign(); break;
              case 3 :
                if (phase) X = (float)(X1+=disp.wheel()); else X = (float)(X0+=disp.wheel());
                visu0.assign(); break;
              }
              disp.set_wheel();
            } else key = ~0U;
          }
          if ((disp.button()&1)!=old_button) { // When left button has just been pressed or released.
            switch (phase) {
            case 0 :
              if (area==clicked_area) {
                X0 = X1 = (int)X; Y0 = Y1 = (int)Y; Z0 = Z1 = (int)Z; starting_area = area; ++phase;
              } break;
            case 1 :
              if (area==starting_area) {
                X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; ++phase;
              } else if (!(disp.button()&1)) { X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = 0; visu0.assign(); }
              break;
            case 2 : ++phase; break;
            }
            old_button = disp.button()&1;
          }
          break;

        case 4 : // When mouse is over the 3d view.
          if (is_view3d && points3d) {
            X3d = mx - width()*disp.width()/(width() + (depth()>1?depth():0));
            Y3d = my - height()*disp.height()/(height() + (depth()>1?depth():0));
            if (oX3d<0) { oX3d = X3d; oY3d = Y3d; }
            // Left + right buttons: reset.
            if ((disp.button()&3)==3) { pose3d.assign(); view3d.assign(); oX3d = oY3d = X3d = Y3d = -1; }
            else if (disp.button()&1 && pose3d && (oX3d!=X3d || oY3d!=Y3d)) { // Left button: rotate.
              const float
                R = 0.45f*std::min(view3d._width,view3d._height),
                R2 = R*R,
                u0 = (float)(oX3d - view3d.width()/2),
                v0 = (float)(oY3d - view3d.height()/2),
                u1 = (float)(X3d - view3d.width()/2),
                v1 = (float)(Y3d - view3d.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.0f,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.0f,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;
              pose3d.draw_image(CImg<floatT>::rotation_matrix(u,v,w,-alpha)*pose3d.get_crop(0,0,2,2));
              view3d.assign();
            } else if (disp.button()&2 && pose3d && oY3d!=Y3d) {  // Right button: zoom.
              pose3d(3,2)-=(oY3d - Y3d)*1.5f; view3d.assign();
            }
            if (disp.wheel()) { // Wheel: zoom
              pose3d(3,2)-=disp.wheel()*15; view3d.assign(); disp.set_wheel();
            }
            if (disp.button()&4 && pose3d && (oX3d!=X3d || oY3d!=Y3d)) { // Middle button: shift.
              pose3d(3,0)-=oX3d - X3d; pose3d(3,1)-=oY3d - Y3d; view3d.assign();
            }
            oX3d = X3d; oY3d = Y3d;
          }
          mx = my = -1; X = Y = Z = -1;
          break;
        }

        if (phase) {
          if (!feature_type) shape_selected = phase?true:false;
          else {
            if (_depth>1) shape_selected = (phase==3)?true:false;
            else shape_selected = (phase==2)?true:false;
          }
        }

        if (X0<0) X0 = 0;
        if (X0>=width()) X0 = width() - 1;
        if (Y0<0) Y0 = 0;
        if (Y0>=height()) Y0 = height() - 1;
        if (Z0<0) Z0 = 0;
        if (Z0>=depth()) Z0 = depth() - 1;
        if (X1<1) X1 = 0;
        if (X1>=width()) X1 = width() - 1;
        if (Y1<0) Y1 = 0;
        if (Y1>=height()) Y1 = height() - 1;
        if (Z1<0) Z1 = 0;
        if (Z1>=depth()) Z1 = depth() - 1;

        // Draw visualization image on the display
        if (mx!=omx || my!=omy || !visu0 || (_depth>1 && !view3d)) {

          if (!visu0) { // Create image of projected planes.
            if (thumb) thumb.__get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0);
            else __get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0);
            visu0.resize(disp);
            view3d.assign();
            points3d.assign();
          }

          if (is_view3d && _depth>1 && !view3d) { // Create 3d view for volumetric images.
            const unsigned int
              _x3d = (unsigned int)cimg::round((float)_width*visu0._width/(_width + _depth),1,1),
              _y3d = (unsigned int)cimg::round((float)_height*visu0._height/(_height + _depth),1,1),
              x3d = _x3d>=visu0._width?visu0._width - 1:_x3d,
              y3d = _y3d>=visu0._height?visu0._height - 1:_y3d;
            CImg<ucharT>(1,2,1,1,64,128).resize(visu0._width - x3d,visu0._height - y3d,1,visu0._spectrum,3).
              move_to(view3d);
            if (!points3d) {
              get_projections3d(primitives3d,colors3d,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0,true).move_to(points3d);
              points3d.append(CImg<floatT>(8,3,1,1,
                                           0,_width - 1,_width - 1,0,0,_width - 1,_width - 1,0,
                                           0,0,_height - 1,_height - 1,0,0,_height - 1,_height - 1,
                                           0,0,0,0,_depth - 1,_depth - 1,_depth - 1,_depth - 1),'x');
              CImg<uintT>::vector(12,13).move_to(primitives3d); CImg<uintT>::vector(13,14).move_to(primitives3d);
              CImg<uintT>::vector(14,15).move_to(primitives3d); CImg<uintT>::vector(15,12).move_to(primitives3d);
              CImg<uintT>::vector(16,17).move_to(primitives3d); CImg<uintT>::vector(17,18).move_to(primitives3d);
              CImg<uintT>::vector(18,19).move_to(primitives3d); CImg<uintT>::vector(19,16).move_to(primitives3d);
              CImg<uintT>::vector(12,16).move_to(primitives3d); CImg<uintT>::vector(13,17).move_to(primitives3d);
              CImg<uintT>::vector(14,18).move_to(primitives3d); CImg<uintT>::vector(15,19).move_to(primitives3d);
              colors3d.insert(12,CImg<ucharT>::vector(255,255,255));
              opacities3d.assign(primitives3d.width(),1,1,1,0.5f);
              if (!phase) {
                opacities3d[0] = opacities3d[1] = opacities3d[2] = 0.8f;
                sel_primitives3d.assign();
                sel_colors3d.assign();
                sel_opacities3d.assign();
              } else {
                if (feature_type==2) {
                  points3d.append(CImg<floatT>(8,3,1,1,
                                               X0,X1,X1,X0,X0,X1,X1,X0,
                                               Y0,Y0,Y1,Y1,Y0,Y0,Y1,Y1,
                                               Z0,Z0,Z0,Z0,Z1,Z1,Z1,Z1),'x');
                  sel_primitives3d.assign();
                  CImg<uintT>::vector(20,21).move_to(sel_primitives3d);
                  CImg<uintT>::vector(21,22).move_to(sel_primitives3d);
                  CImg<uintT>::vector(22,23).move_to(sel_primitives3d);
                  CImg<uintT>::vector(23,20).move_to(sel_primitives3d);
                  CImg<uintT>::vector(24,25).move_to(sel_primitives3d);
                  CImg<uintT>::vector(25,26).move_to(sel_primitives3d);
                  CImg<uintT>::vector(26,27).move_to(sel_primitives3d);
                  CImg<uintT>::vector(27,24).move_to(sel_primitives3d);
                  CImg<uintT>::vector(20,24).move_to(sel_primitives3d);
                  CImg<uintT>::vector(21,25).move_to(sel_primitives3d);
                  CImg<uintT>::vector(22,26).move_to(sel_primitives3d);
                  CImg<uintT>::vector(23,27).move_to(sel_primitives3d);
                } else {
                  points3d.append(CImg<floatT>(2,3,1,1,
                                               X0,X1,
                                               Y0,Y1,
                                               Z0,Z1),'x');
                  sel_primitives3d.assign(CImg<uintT>::vector(20,21));
                }
                sel_colors3d.assign(sel_primitives3d._width,CImg<ucharT>::vector(255,255,255));
                sel_opacities3d.assign(sel_primitives3d._width,1,1,1,0.8f);
              }
              points3d.shift_object3d(-0.5f*(_width - 1),-0.5f*(_height - 1),-0.5f*(_depth - 1)).resize_object3d();
              points3d*=0.75f*std::min(view3d._width,view3d._height);
            }

            if (!pose3d) CImg<floatT>(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0).move_to(pose3d);
            CImg<floatT> zbuffer3d(view3d._width,view3d._height,1,1,0);
            const CImg<floatT> rotated_points3d = pose3d.get_crop(0,0,2,2)*points3d;
            if (sel_primitives3d)
              view3d.draw_object3d(pose3d(3,0) + 0.5f*view3d._width,
                                   pose3d(3,1) + 0.5f*view3d._height,
                                   pose3d(3,2),
                                   rotated_points3d,sel_primitives3d,sel_colors3d,sel_opacities3d,
                                   2,true,500,0,0,0,0,0,zbuffer3d);
            view3d.draw_object3d(pose3d(3,0) + 0.5f*view3d._width,
                                 pose3d(3,1) + 0.5f*view3d._height,
                                 pose3d(3,2),
                                 rotated_points3d,primitives3d,colors3d,opacities3d,
                                 2,true,500,0,0,0,0,0,zbuffer3d);
            visu0.draw_image(x3d,y3d,view3d);
          }
          visu = visu0;

          if (X<0 || Y<0 || Z<0) { if (!visible_cursor) { disp.show_mouse(); visible_cursor = true; }}
          else {
            if (is_axes) { if (visible_cursor) { disp.hide_mouse(); visible_cursor = false; }}
            else { if (!visible_cursor) { disp.show_mouse(); visible_cursor = true; }}
            const int d = (depth()>1)?depth():0;
            int
              _vX = (int)X, _vY = (int)Y, _vZ = (int)Z,
              w = disp.width(), W = width() + d,
              h = disp.height(), H = height() + d,
              _xp = (int)(_vX*(float)w/W), xp = _xp + ((int)(_xp*(float)W/w)!=_vX),
              _yp = (int)(_vY*(float)h/H), yp = _yp + ((int)(_yp*(float)H/h)!=_vY),
              _xn = (int)((_vX + 1.0f)*w/W - 1), xn = _xn + ((int)((_xn + 1.0f)*W/w)!=_vX + 1),
              _yn = (int)((_vY + 1.0f)*h/H - 1), yn = _yn + ((int)((_yn + 1.0f)*H/h)!=_vY + 1),
              _zxp = (int)((_vZ + width())*(float)w/W), zxp = _zxp + ((int)(_zxp*(float)W/w)!=_vZ + width()),
              _zyp = (int)((_vZ + height())*(float)h/H), zyp = _zyp + ((int)(_zyp*(float)H/h)!=_vZ + height()),
              _zxn = (int)((_vZ + width() + 1.0f)*w/W - 1),
                       zxn = _zxn + ((int)((_zxn + 1.0f)*W/w)!=_vZ + width() + 1),
              _zyn = (int)((_vZ + height() + 1.0f)*h/H - 1),
                       zyn = _zyn + ((int)((_zyn + 1.0f)*H/h)!=_vZ + height() + 1),
              _xM = (int)(width()*(float)w/W - 1), xM = _xM + ((int)((_xM + 1.0f)*W/w)!=width()),
              _yM = (int)(height()*(float)h/H - 1), yM = _yM + ((int)((_yM + 1.0f)*H/h)!=height()),
              xc = (xp + xn)/2,
              yc = (yp + yn)/2,
              zxc = (zxp + zxn)/2,
              zyc = (zyp + zyn)/2,
              xf = (int)(X*w/W),
              yf = (int)(Y*h/H),
              zxf = (int)((Z + width())*w/W),
              zyf = (int)((Z + height())*h/H);

            if (is_axes) { // Draw axes.
              visu.draw_line(0,yf,visu.width() - 1,yf,foreground_color,0.7f,0xFF00FF00).
                draw_line(0,yf,visu.width() - 1,yf,background_color,0.7f,0x00FF00FF).
                draw_line(xf,0,xf,visu.height() - 1,foreground_color,0.7f,0xFF00FF00).
                draw_line(xf,0,xf,visu.height() - 1,background_color,0.7f,0x00FF00FF);
              if (_depth>1)
                visu.draw_line(zxf,0,zxf,yM,foreground_color,0.7f,0xFF00FF00).
                  draw_line(zxf,0,zxf,yM,background_color,0.7f,0x00FF00FF).
                  draw_line(0,zyf,xM,zyf,foreground_color,0.7f,0xFF00FF00).
                  draw_line(0,zyf,xM,zyf,background_color,0.7f,0x00FF00FF);
            }

            // Draw box cursor.
            if (xn - xp>=4 && yn - yp>=4) visu.draw_rectangle(xp,yp,xn,yn,foreground_color,0.2f).
                                        draw_rectangle(xp,yp,xn,yn,foreground_color,1,0xAAAAAAAA).
                                        draw_rectangle(xp,yp,xn,yn,background_color,1,0x55555555);
            if (_depth>1) {
              if (yn - yp>=4 && zxn - zxp>=4) visu.draw_rectangle(zxp,yp,zxn,yn,background_color,0.2f).
                                            draw_rectangle(zxp,yp,zxn,yn,foreground_color,1,0xAAAAAAAA).
                                            draw_rectangle(zxp,yp,zxn,yn,background_color,1,0x55555555);
              if (xn - xp>=4 && zyn - zyp>=4) visu.draw_rectangle(xp,zyp,xn,zyn,background_color,0.2f).
                                            draw_rectangle(xp,zyp,xn,zyn,foreground_color,1,0xAAAAAAAA).
                                            draw_rectangle(xp,zyp,xn,zyn,background_color,1,0x55555555);
            }

            // Draw selection.
            if (phase) {
              const int
                _xp0 = (int)(X0*(float)w/W), xp0 = _xp0 + ((int)(_xp0*(float)W/w)!=X0),
                _yp0 = (int)(Y0*(float)h/H), yp0 = _yp0 + ((int)(_yp0*(float)H/h)!=Y0),
                _xn0 = (int)((X0 + 1.0f)*w/W - 1), xn0 = _xn0 + ((int)((_xn0 + 1.0f)*W/w)!=X0 + 1),
                _yn0 = (int)((Y0 + 1.0f)*h/H - 1), yn0 = _yn0 + ((int)((_yn0 + 1.0f)*H/h)!=Y0 + 1),
                _zxp0 = (int)((Z0 + width())*(float)w/W), zxp0 = _zxp0 + ((int)(_zxp0*(float)W/w)!=Z0 + width()),
                _zyp0 = (int)((Z0 + height())*(float)h/H), zyp0 = _zyp0 + ((int)(_zyp0*(float)H/h)!=Z0 + height()),
                _zxn0 = (int)((Z0 + width() + 1.0f)*w/W - 1),
                zxn0 = _zxn0 + ((int)((_zxn0 + 1.0f)*W/w)!=Z0 + width() + 1),
                _zyn0 = (int)((Z0 + height() + 1.0f)*h/H - 1),
                zyn0 = _zyn0 + ((int)((_zyn0 + 1.0f)*H/h)!=Z0 + height() + 1),
                xc0 = (xp0 + xn0)/2,
                yc0 = (yp0 + yn0)/2,
                zxc0 = (zxp0 + zxn0)/2,
                zyc0 = (zyp0 + zyn0)/2;

              switch (feature_type) {
              case 1 : {
                visu.draw_arrow(xc0,yc0,xc,yc,background_color,0.9f,30,5,0x55555555).
                  draw_arrow(xc0,yc0,xc,yc,foreground_color,0.9f,30,5,0xAAAAAAAA);
                if (d) {
                  visu.draw_arrow(zxc0,yc0,zxc,yc,background_color,0.9f,30,5,0x55555555).
                    draw_arrow(zxc0,yc0,zxc,yc,foreground_color,0.9f,30,5,0xAAAAAAAA).
                    draw_arrow(xc0,zyc0,xc,zyc,background_color,0.9f,30,5,0x55555555).
                    draw_arrow(xc0,zyc0,xc,zyc,foreground_color,0.9f,30,5,0xAAAAAAAA);
                }
              } break;
              case 2 : {
                visu.draw_rectangle(X0<X1?xp0:xp,Y0<Y1?yp0:yp,X0<X1?xn:xn0,Y0<Y1?yn:yn0,background_color,0.2f).
                  draw_rectangle(X0<X1?xp0:xp,Y0<Y1?yp0:yp,X0<X1?xn:xn0,Y0<Y1?yn:yn0,background_color,0.9f,0x55555555).
                  draw_rectangle(X0<X1?xp0:xp,Y0<Y1?yp0:yp,X0<X1?xn:xn0,Y0<Y1?yn:yn0,foreground_color,0.9f,0xAAAAAAAA).
                  draw_arrow(xc0,yc0,xc,yc,background_color,0.5f,30,5,0x55555555).
                  draw_arrow(xc0,yc0,xc,yc,foreground_color,0.5f,30,5,0xAAAAAAAA);
                if (d) {
                  visu.draw_rectangle(Z0<Z1?zxp0:zxp,Y0<Y1?yp0:yp,Z0<Z1?zxn:zxn0,Y0<Y1?yn:yn0,background_color,0.2f).
                    draw_rectangle(Z0<Z1?zxp0:zxp,Y0<Y1?yp0:yp,Z0<Z1?zxn:zxn0,Y0<Y1?yn:yn0,
                                   background_color,0.9f,0x55555555).
                    draw_rectangle(Z0<Z1?zxp0:zxp,Y0<Y1?yp0:yp,Z0<Z1?zxn:zxn0,Y0<Y1?yn:yn0,
                                   foreground_color,0.9f,0xAAAAAAAA).
                    draw_arrow(zxc0,yc0,zxc,yc,background_color,0.5f,30,5,0x55555555).
                    draw_arrow(zxc0,yc0,zxc,yc,foreground_color,0.5f,30,5,0xAAAAAAAA).
                    draw_rectangle(X0<X1?xp0:xp,Z0<Z1?zyp0:zyp,X0<X1?xn:xn0,Z0<Z1?zyn:zyn0,
                                   background_color,0.2f).
                    draw_rectangle(X0<X1?xp0:xp,Z0<Z1?zyp0:zyp,X0<X1?xn:xn0,Z0<Z1?zyn:zyn0,
                                   background_color,0.9f,0x55555555).
                    draw_rectangle(X0<X1?xp0:xp,Z0<Z1?zyp0:zyp,X0<X1?xn:xn0,Z0<Z1?zyn:zyn0,
                                   foreground_color,0.9f,0xAAAAAAAA).
                    draw_arrow(xp0,zyp0,xn,zyn,background_color,0.5f,30,5,0x55555555).
                    draw_arrow(xp0,zyp0,xn,zyn,foreground_color,0.5f,30,5,0xAAAAAAAA);
                }
              } break;
              case 3 : {
                visu.draw_ellipse(xc0,yc0,
                                  (float)cimg::abs(xc - xc0),
                                  (float)cimg::abs(yc - yc0),0,background_color,0.2f).
                  draw_ellipse(xc0,yc0,
                               (float)cimg::abs(xc - xc0),
                               (float)cimg::abs(yc - yc0),0,foreground_color,0.9f,~0U).
                  draw_point(xc0,yc0,foreground_color,0.9f);
                if (d) {
                  visu.draw_ellipse(zxc0,yc0,(float)cimg::abs(zxc - zxc0),(float)cimg::abs(yc - yc0),0,
                                    background_color,0.2f).
                    draw_ellipse(zxc0,yc0,(float)cimg::abs(zxc - zxc0),(float)cimg::abs(yc - yc0),0,
                                 foreground_color,0.9f,~0U).
                    draw_point(zxc0,yc0,foreground_color,0.9f).
                    draw_ellipse(xc0,zyc0,(float)cimg::abs(xc - xc0),(float)cimg::abs(zyc - zyc0),0,
                                 background_color,0.2f).
                    draw_ellipse(xc0,zyc0,(float)cimg::abs(xc - xc0),(float)cimg::abs(zyc - zyc0),0,
                                 foreground_color,0.9f,~0U).
                    draw_point(xc0,zyc0,foreground_color,0.9f);
                }
              } break;
              }
            }

            // Draw text info.
            if (my>=0 && my<13) text_down = true; else if (my>=visu.height() - 13) text_down = false;
            if (!feature_type || !phase) {
              if (X>=0 && Y>=0 && Z>=0 && X<width() && Y<height() && Z<depth()) {
                if (_depth>1 || force_display_z_coord)
                  cimg_snprintf(text,text._width," Point (%d,%d,%d) = [ ",origX + (int)X,origY + (int)Y,origZ + (int)Z);
                else cimg_snprintf(text,text._width," Point (%d,%d) = [ ",origX + (int)X,origY + (int)Y);
                CImg<T> values = get_vector_at(X,Y,Z);
                const bool is_large_spectrum = values._height>16;
                if (is_large_spectrum)
                  values.draw_image(0,8,values.get_rows(values._height - 8,values._height - 1)).resize(1,16,1,1,0);
                char *ctext = text._data + std::strlen(text), *const ltext = text._data + 512;
                for (unsigned int c = 0; c<values._height && ctext<ltext; ++c) {
                  cimg_snprintf(ctext,24,cimg::type<T>::format_s(),
                                cimg::type<T>::format(values[c]));
                  ctext += std::strlen(ctext);
                  if (c==7 && is_large_spectrum) {
                    cimg_snprintf(ctext,24," (...)");
                    ctext += std::strlen(ctext);
                  }
                  *(ctext++) = ' '; *ctext = 0;
                }
                std::strcpy(text._data + std::strlen(text),"] ");
              }
            } else switch (feature_type) {
              case 1 : {
                const double dX = (double)(X0 - X1), dY = (double)(Y0 - Y1), dZ = (double)(Z0 - Z1),
                  length = cimg::hypot(dX,dY,dZ);
                if (_depth>1 || force_display_z_coord)
                  cimg_snprintf(text,text._width," Vect (%d,%d,%d)-(%d,%d,%d), Length = %g ",
                                origX + X0,origY + Y0,origZ + Z0,origX + X1,origY + Y1,origZ + Z1,length);
                else cimg_snprintf(text,text._width," Vect (%d,%d)-(%d,%d), Length = %g ",
                                   origX + X0,origY + Y0,origX + X1,origY + Y1,length);
              } break;
              case 2 : {
                const double dX = (double)(X0 - X1), dY = (double)(Y0 - Y1), dZ = (double)(Z0 - Z1),
                  length = cimg::hypot(dX,dY,dZ);
                if (_depth>1 || force_display_z_coord)
                  cimg_snprintf(text,text._width," Box (%d,%d,%d)-(%d,%d,%d), Size = (%d,%d,%d), Length = %g ",
                                origX + (X0<X1?X0:X1),origY + (Y0<Y1?Y0:Y1),origZ + (Z0<Z1?Z0:Z1),
                                origX + (X0<X1?X1:X0),origY + (Y0<Y1?Y1:Y0),origZ + (Z0<Z1?Z1:Z0),
                                1 + cimg::abs(X0 - X1),1 + cimg::abs(Y0 - Y1),1 + cimg::abs(Z0 - Z1),length);
                else cimg_snprintf(text,text._width," Box (%d,%d)-(%d,%d), Size = (%d,%d), Length = %g ",
                                   origX + (X0<X1?X0:X1),origY + (Y0<Y1?Y0:Y1),
                                   origX + (X0<X1?X1:X0),origY + (Y0<Y1?Y1:Y0),
                                   1 + cimg::abs(X0 - X1),1 + cimg::abs(Y0 - Y1),length);
              } break;
              default :
                if (_depth>1 || force_display_z_coord)
                  cimg_snprintf(text,text._width," Ellipse (%d,%d,%d)-(%d,%d,%d), Radii = (%d,%d,%d) ",
                                origX + X0,origY + Y0,origZ + Z0,origX + X1,origY + Y1,origZ + Z1,
                                1 + cimg::abs(X0 - X1),1 + cimg::abs(Y0 - Y1),1 + cimg::abs(Z0 - Z1));
                else cimg_snprintf(text,text._width," Ellipse (%d,%d)-(%d,%d), Radii = (%d,%d) ",
                                   origX + X0,origY + Y0,origX + X1,origY + Y1,
                                   1 + cimg::abs(X0 - X1),1 + cimg::abs(Y0 - Y1));
              }
            if (phase || (mx>=0 && my>=0))
              visu.draw_text(0,text_down?visu.height() - 13:0,text,foreground_color,background_color,0.7f,13);
          }

          disp.display(visu).wait();
        } else if (!shape_selected) disp.wait();
        if (disp.is_resized()) { disp.resize(false)._is_resized = false; old_is_resized = true; visu0.assign(); }
        omx = mx; omy = my;
        if (!exit_on_anykey && key && key!=cimg::keyESC &&
            (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) {
          key = 0;
        }
      }

      // Return result.
      CImg<intT> res(1,feature_type==0?3:6,1,1,-1);
      if (XYZ) { XYZ[0] = (unsigned int)X0; XYZ[1] = (unsigned int)Y0; XYZ[2] = (unsigned int)Z0; }
      if (shape_selected) {
        if (feature_type==2) {
          if (X0>X1) cimg::swap(X0,X1);
          if (Y0>Y1) cimg::swap(Y0,Y1);
          if (Z0>Z1) cimg::swap(Z0,Z1);
        }
	if (X1<0 || Y1<0 || Z1<0) X0 = Y0 = Z0 = X1 = Y1 = Z1 = -1;
	switch (feature_type) {
	case 1 : case 2 : res[0] = X0; res[1] = Y0; res[2] = Z0; res[3] = X1; res[4] = Y1; res[5] = Z1; break;
        case 3 :
          res[3] = cimg::abs(X1 - X0); res[4] = cimg::abs(Y1 - Y0); res[5] = cimg::abs(Z1 - Z0);
          res[0] = X0; res[1] = Y0; res[2] = Z0;
          break;
	default : res[0] = X0; res[1] = Y0; res[2] = Z0;
	}
      }
      if (!exit_on_anykey || !(disp.button()&4)) disp.set_button();
      if (!visible_cursor) disp.show_mouse();
      disp._normalization = old_normalization;
      disp._is_resized = old_is_resized;
      if (key!=~0U) disp.set_key(key);
      return res;

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

    template<typename t>
    void _eik_priority_queue_insert(CImg<charT>& state, unsigned int& siz, const t value,
                                    const unsigned int x, const unsigned int y, const unsigned int z) {
      if (state(x,y,z)>0) return;
      state(x,y,z) = 0;
      if (++siz>=_width) { if (!is_empty()) resize(_width*2,4,1,1,0); else assign(64,4); }
      (*this)(siz - 1,0) = (T)value; (*this)(siz - 1,1) = (T)x; (*this)(siz - 1,2) = (T)y; (*this)(siz - 1,3) = (T)z;
      for (unsigned int pos = siz - 1, par = 0; pos && value>(*this)(par=(pos + 1)/2 - 1,0); pos = par) {
        cimg::swap((*this)(pos,0),(*this)(par,0)); cimg::swap((*this)(pos,1),(*this)(par,1));
        cimg::swap((*this)(pos,2),(*this)(par,2)); cimg::swap((*this)(pos,3),(*this)(par,3));
      }

Project: CImg
File: CImg.h


      static double mp_fsize(_cimg_math_parser& mp) {
        const CImg<charT> filename(mp.opcode._data + 3,mp.opcode[2] - 3);
        return (double)cimg::fsize(filename);

Project: CImg
File: CImg.h

    //! Compute correspondence map between two images, using the patch-match algorithm \overloading.
    CImg<intT> get_patchmatch(const CImg<T>& patch_image,
                              const unsigned int patch_width,
                              const unsigned int patch_height,
                              const unsigned int patch_depth=1,
                              const unsigned int nb_iterations=5,
                              const unsigned int nb_randoms=5) const {
      return _patchmatch(patch_image,patch_width,patch_height,patch_depth,
                         nb_iterations,nb_randoms,
                         CImg<T>::const_empty(),
                         false,CImg<T>::empty());

Project: CImg
File: CImg.h

     **/
    CImg<T>& blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.6f,
                              const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, const float da=30,
                              const float gauss_prec=2, const unsigned int interpolation_type=0,
                              const bool is_fast_approx=true) {
      return blur_anisotropic(get_diffusion_tensors(sharpness,anisotropy,alpha,sigma,interpolation_type!=3),
                              amplitude,dl,da,gauss_prec,interpolation_type,is_fast_approx);

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 tc>
    CImg<T>& draw_triangle(const int x0, const int y0,
                           const int x1, const int y1,
                           const int x2, const int y2,
                           const tc *const color,
                           const float brightness0,
                           const float brightness1,
                           const float brightness2,
                           const float opacity=1) {
      if (is_empty()) return *this;
      if (!color)
        throw CImgArgumentException(_cimg_instance
                                    "draw_triangle(): Specified color is (null).",
                                    cimg_instance);
      static const T maxval = (T)std::min(cimg::type<T>::max(),(T)cimg::type<tc>::max());
      const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f);
      const longT whd = (longT)width()*height()*depth(), offx = spectrum()*whd - 1;
      int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
        nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f),
        nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f),
        nc2 = (int)((brightness2<0.0f?0.0f:(brightness2>2.0f?2.0f:brightness2))*256.0f);
      if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nc0,nc1);
      if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nc0,nc2);
      if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nc1,nc2);
      if (ny0>=height() || ny2<0) return *this;
      _cimg_for_triangle2(*this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) {
        int xleft = xleft0, xright = xright0, cleft = cleft0, cright = cright0;
        if (xright<xleft) cimg::swap(xleft,xright,cleft,cright);
        const int
          dx = xright - xleft,
          dc = cright>cleft?cright - cleft:cleft - cright,
          rc = dx?(cright - cleft)/dx:0,
          sc = cright>cleft?1:-1,
          ndc = dc - (dx?dx*(dc/dx):0);
        int errc = dx>>1;
        if (xleft<0 && dx) cleft-=xleft*(cright - cleft)/dx;
        if (xleft<0) xleft = 0;
        if (xright>=width() - 1) xright = width() - 1;
        T* ptrd = data(xleft,y);
        if (opacity>=1) for (int x = xleft; x<=xright; ++x) {
          const tc *col = color;
          cimg_forC(*this,c) {
            *ptrd = (T)(cleft<256?cleft**(col++)/256:((512 - cleft)**(col++)+(cleft - 256)*maxval)/256);
            ptrd+=whd;
          }
          ptrd-=offx;
          cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0);
        } else for (int x = xleft; x<=xright; ++x) {
          const tc *col = color;
          cimg_forC(*this,c) {
            const T val = (T)(cleft<256?cleft**(col++)/256:((512 - cleft)**(col++)+(cleft - 256)*maxval)/256);
            *ptrd = (T)(nopacity*val + *ptrd*copacity);
            ptrd+=whd;
          }
          ptrd-=offx;
          cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0);
        }
      }
      return *this;

Project: CImg
File: CImg.h

     \param user_path Specified path, or \c 0 to get the path currently used.
     \param reinit_path Force path to be recalculated (may take some time).
     \return Path containing the \c gm binary.
  **/
  inline const char* graphicsmagick_path(const char *const user_path, const bool reinit_path) {
    static CImg<char> s_path;
    cimg::mutex(7);
    if (reinit_path) s_path.assign();
    if (user_path) {
      if (!s_path) s_path.assign(1024);
      std::strncpy(s_path,user_path,1023);
    } else if (!s_path) {
      s_path.assign(1024);
      bool path_found = false;
      std::FILE *file = 0;
#if cimg_OS==2
      const char *const pf_path = programfiles_path();
      if (!path_found) {
        std::strcpy(s_path,".\\gm.exe");
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 32; k>=10 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%.2d-\\gm.exe",pf_path,k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 9; k>=0 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d-Q\\gm.exe",pf_path,k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 32; k>=0 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d\\gm.exe",pf_path,k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 32; k>=10 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",pf_path,k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 9; k>=0 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",pf_path,k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 32; k>=0 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",pf_path,k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 32; k>=10 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%.2d-\\gm.exe",k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 9; k>=0 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d-Q\\gm.exe",k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 32; k>=0 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d\\gm.exe",k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 32; k>=10 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 9; k>=0 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 32; k>=0 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 32; k>=10 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%.2d-\\gm.exe",k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 9; k>=0 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d-Q\\gm.exe",k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 32; k>=0 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d\\gm.exe",k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 32; k>=10 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 9; k>=0 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      for (int k = 32; k>=0 && !path_found; --k) {
        cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k);
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      if (!path_found) std::strcpy(s_path,"gm.exe");
#else
      if (!path_found) {
        std::strcpy(s_path,"./gm");
        if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; }
      }
      if (!path_found) std::strcpy(s_path,"gm");
#endif
      winformat_string(s_path);

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);
      tuint *ptrd = res._data;
      if (dithering>0) { // Dithered versions.
        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 collapse(2) cimg_openmp_if(_width>=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 collapse(2) cimg_openmp_if(_width>=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 collapse(2) cimg_openmp_if(_width>=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 collapse(2) cimg_openmp_if(_width>=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

     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

    template<typename t>
    static int _isosurface3d_indice(const unsigned int edge, const CImg<t>& indices1, const CImg<t>& indices2,
                                    const unsigned int x, const unsigned int y,
                                    const unsigned int nx, const unsigned int ny) {
      switch (edge) {
      case 0 : return indices1(x,y,0);
      case 1 : return indices1(nx,y,1);
      case 2 : return indices1(x,ny,0);
      case 3 : return indices1(x,y,1);
      case 4 : return indices2(x,y,0);
      case 5 : return indices2(nx,y,1);
      case 6 : return indices2(x,ny,0);
      case 7 : return indices2(x,y,1);
      case 8 : return indices1(x,y,2);
      case 9 : return indices1(nx,y,2);
      case 10 : return indices1(nx,ny,2);
      case 11 : return indices1(x,ny,2);
      }
      return 0;

Project: CImg
File: CImg.h

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

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

Project: CImg
File: CImg.h

    **/
    CImg<T>& asin() {
      if (is_empty()) return *this;
      cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=8192))
      cimg_rof(*this,ptrd,T) *ptrd = (T)std::asin((double)*ptrd);
      return *this;

Project: CImg
File: CImg.h

      \param last_frame Index of the last frame to read.
      \param step_frame Step value for frame reading.
      \note If step_frame==0, the current video stream is forced to be released (without any frames read).
    **/
    CImgList<T>& load_video(const char *const filename,
                            const unsigned int first_frame=0, const unsigned int last_frame=~0U,
                            const unsigned int step_frame=1) {
#ifndef cimg_use_opencv
      if (first_frame || last_frame!=~0U || step_frame>1)
        throw CImgArgumentException(_cimglist_instance
                                    "load_video() : File '%s', arguments 'first_frame', 'last_frame' "
                                    "and 'step_frame' can be only set when using OpenCV "
                                    "(-Dcimg_use_opencv must be enabled).",
                                    cimglist_instance,filename);
      return load_ffmpeg_external(filename);
#else
      static CvCapture *captures[32] = { 0 };
      static CImgList<charT> filenames(32);
      static CImg<uintT> positions(32,1,1,1,0);
      static int last_used_index = -1;

      // Detect if a video capture already exists for the specified filename.
      cimg::mutex(9);
      int index = -1;
      if (filename) {
        if (last_used_index>=0 && !std::strcmp(filename,filenames[last_used_index])) {
          index = last_used_index;
        } else cimglist_for(filenames,l) if (filenames[l] && !std::strcmp(filename,filenames[l])) {
            index = l; break;
          }
      } else index = last_used_index;
      cimg::mutex(9,0);

      // Release stream if needed.
      if (!step_frame || (index>=0 && positions[index]>first_frame)) {
        if (index>=0) {
          cimg::mutex(9);
          cvReleaseCapture(&captures[index]);
          captures[index] = 0; filenames[index].assign(); positions[index] = 0;
          if (last_used_index==index) last_used_index = -1;
          index = -1;
          cimg::mutex(9,0);
        } else
          if (filename)
            cimg::warn(_cimglist_instance
                       "load_video() : File '%s', no opened video stream associated with filename found.",
                       cimglist_instance,filename);
          else
            cimg::warn(_cimglist_instance
                       "load_video() : No opened video stream found.",
                       cimglist_instance,filename);
        if (!step_frame) return *this;
      }

      // Find empty slot for capturing video stream.
      if (index<0) {
        if (!filename)
          throw CImgArgumentException(_cimglist_instance
                                      "load_video(): No already open video reader found. You must specify a "
                                      "non-(null) filename argument for the first call.",
                                      cimglist_instance);
        else { cimg::mutex(9); cimglist_for(filenames,l) if (!filenames[l]) { index = l; break; } cimg::mutex(9,0); }
        if (index<0)
          throw CImgIOException(_cimglist_instance
                                "load_video(): File '%s', no video reader slots available. "
                                "You have to release some of your previously opened videos.",
                                cimglist_instance,filename);
        cimg::mutex(9);
        captures[index] = cvCaptureFromFile(filename);
        CImg<charT>::string(filename).move_to(filenames[index]);
        positions[index] = 0;
        cimg::mutex(9,0);
        if (!captures[index]) {
          filenames[index].assign();
          std::fclose(cimg::fopen(filename,"rb"));  // Check file availability.
          throw CImgIOException(_cimglist_instance
                                "load_video(): File '%s', unable to detect format of video file.",
                                cimglist_instance,filename);
        }
      }

      cimg::mutex(9);
      const unsigned int nb_frames = (unsigned int)std::max(0.,cvGetCaptureProperty(captures[index],
                                                                                     CV_CAP_PROP_FRAME_COUNT));
      cimg::mutex(9,0);
      assign();

      // Skip frames if necessary.
      bool go_on = true;
      unsigned int &pos = positions[index];
      while (pos<first_frame) {
        cimg::mutex(9);
        if (!cvGrabFrame(captures[index])) { cimg::mutex(9,0); go_on = false; break; }
        cimg::mutex(9,0);
        ++pos;
      }

      // Read and convert frames.
      const IplImage *src = 0;
      if (go_on) {
        const unsigned int _last_frame = std::min(nb_frames?nb_frames - 1:~0U,last_frame);
        while (pos<=_last_frame) {
          cimg::mutex(9);
          src = cvQueryFrame(captures[index]);
          if (src) {
            CImg<T> frame(src->width,src->height,1,3);
            const int step = (int)(src->widthStep - 3*src->width);
            const unsigned char* ptrs = (unsigned char*)src->imageData;
            T *ptr_r = frame.data(0,0,0,0), *ptr_g = frame.data(0,0,0,1), *ptr_b = frame.data(0,0,0,2);
            if (step>0) cimg_forY(frame,y) {
                cimg_forX(frame,x) { *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++); }
                ptrs+=step;
              } else for (ulongT siz = (ulongT)src->width*src->height; siz; --siz) {
                *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++);
              }
            frame.move_to(*this);
            ++pos;

            bool skip_failed = false;
            for (unsigned int i = 1; i<step_frame && pos<=_last_frame; ++i, ++pos)
              if (!cvGrabFrame(captures[index])) { skip_failed = true; break; }
            if (skip_failed) src = 0;
          }
          cimg::mutex(9,0);
          if (!src) break;
        }
      }

      if (!src || (nb_frames && pos>=nb_frames)) { // Close video stream when necessary.
        cimg::mutex(9);
        cvReleaseCapture(&captures[index]);
        captures[index] = 0;
        filenames[index].assign();
        positions[index] = 0;
        index = -1;
        cimg::mutex(9,0);
      }

      cimg::mutex(9);
      last_used_index = index;
      cimg::mutex(9,0);

      if (is_empty())
        throw CImgIOException(_cimglist_instance
                              "load_video(): File '%s', unable to locate frame %u.",

Project: CImg
File: CImg.h

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

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

Project: CImg
File: CImg.h

    template<typename t>
    const CImg<T>& symmetric_eigen(CImg<t>& val, CImg<t>& vec) const {
      if (is_empty()) { val.assign(); vec.assign(); }
      else {
#ifdef cimg_use_lapack
        char JOB = 'V', UPLO = 'U';
        int N = _width, LWORK = 4*N, INFO;
        Tfloat
          *const lapA = new Tfloat[N*N],
          *const lapW = new Tfloat[N],
          *const WORK = new Tfloat[LWORK];
        cimg_forXY(*this,k,l) lapA[k*N + l] = (Tfloat)((*this)(k,l));
        cimg::syev(JOB,UPLO,N,lapA,lapW,WORK,LWORK,INFO);
        if (INFO)
          cimg::warn(_cimg_instance
                     "symmetric_eigen(): LAPACK library function dsyev_() returned error code %d.",
                     cimg_instance,
                     INFO);

        val.assign(1,N);
	vec.assign(N,N);
        if (!INFO) {
          cimg_forY(val,i) val(i) = (T)lapW[N - 1 -i];
          cimg_forXY(vec,k,l) vec(k,l) = (T)(lapA[(N - 1 - k)*N + l]);
        } else { val.fill(0); vec.fill(0); }
        delete[] lapA; delete[] lapW; delete[] WORK;
#else
        if (_width!=_height || _depth>1 || _spectrum>1)
          throw CImgInstanceException(_cimg_instance
                                      "eigen(): Instance is not a square matrix.",
                                      cimg_instance);

	val.assign(1,_width);
	if (vec._data) vec.assign(_width,_width);
        if (_width<3) {
          eigen(val,vec);
          if (_width==2) { vec[1] = -vec[2]; vec[3] = vec[0]; } // Force orthogonality for 2x2 matrices.
          return *this;
        }
        CImg<t> V(_width,_width);
        Tfloat M = 0, m = (Tfloat)min_max(M), maxabs = cimg::max((Tfloat)1,cimg::abs(m),cimg::abs(M));
        (CImg<Tfloat>(*this,false)/=maxabs).SVD(vec,val,V,false);
        if (maxabs!=1) val*=maxabs;

	bool is_ambiguous = false;
	float eig = 0;
	cimg_forY(val,p) {       // check for ambiguous cases.
	  if (val[p]>eig) eig = (float)val[p];
          t scal = 0;
          cimg_forY(vec,y) scal+=vec(p,y)*V(p,y);
          if (cimg::abs(scal)<0.9f) is_ambiguous = true;
          if (scal<0) val[p] = -val[p];
        }
	if (is_ambiguous) {
	  ++(eig*=2);
	  SVD(vec,val,V,false,40,eig);
	  val-=eig;
	}
        CImg<intT> permutations;  // sort eigenvalues in decreasing order
        CImg<t> tmp(_width);
        val.sort(permutations,false);
        cimg_forY(vec,k) {
          cimg_forY(permutations,y) tmp(y) = vec(permutations(y),k);
          std::memcpy(vec.data(0,k),tmp._data,sizeof(t)*_width);
        }
#endif
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    CImg<T>& load_gzip_external(const char *const filename) {
      if (!filename)
        throw CImgIOException(_cimg_instance
                              "load_gzip_external(): Specified filename is (null).",
                              cimg_instance);
      std::fclose(cimg::fopen(filename,"rb"));            // Check if file exists.
      CImg<charT> command(1024), filename_tmp(256), body(256);
      const char
        *const ext = cimg::split_filename(filename,body),
        *const ext2 = cimg::split_filename(body,0);

      std::FILE *file = 0;
      do {
        if (!cimg::strcasecmp(ext,"gz")) {
          if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s",
                                   cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2);
          else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s",
                             cimg::temporary_path(),cimg_file_separator,cimg::filenamerand());
        } else {
          if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s",
                                  cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext);
          else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s",
                             cimg::temporary_path(),cimg_file_separator,cimg::filenamerand());
        }
        if ((file=std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file);
      } while (file);
      cimg_snprintf(command,command._width,"%s -c \"%s\" > \"%s\"",
                    cimg::gunzip_path(),
                    CImg<charT>::string(filename)._system_strescape().data(),
                    CImg<charT>::string(filename_tmp)._system_strescape().data());
      cimg::system(command);
      if (!(file = std_fopen(filename_tmp,"rb"))) {
        cimg::fclose(cimg::fopen(filename,"r"));
        throw CImgIOException(_cimg_instance
                              "load_gzip_external(): Failed to load file '%s' with external command 'gunzip'.",
                              cimg_instance,
                              filename);

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

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& patchmatch(const CImg<T>& patch_image,
                        const unsigned int patch_width,
                        const unsigned int patch_height,
                        const unsigned int patch_depth,
                        const unsigned int nb_iterations,
                        const unsigned int nb_randoms,
                        const CImg<t> &guide) {
      return get_patchmatch(patch_image,patch_width,patch_height,patch_depth,
                            nb_iterations,nb_randoms,guide).move_to(*this);

Project: CImg
File: CImg.h


    //! Return a reference to the minimum pixel value of the instance list.
    /**
    **/
    T& min() {
      if (is_empty())
        throw CImgInstanceException(_cimglist_instance
                                    "min(): Empty instance.",
                                    cimglist_instance);
      T *ptr_min = _data->_data;
      T min_value = *ptr_min;
      cimglist_for(*this,l) {
        const CImg<T>& img = _data[l];

Project: CImg
File: CImg.h

    template<typename tc, typename tl>
    CImg<T>& draw_triangle(const int x0, const int y0, const float z0,
                           const int x1, const int y1, const float z1,
                           const int x2, const int y2, const float z2,
                           const CImg<tc>& texture,
                           const int tx0, const int ty0,
                           const int tx1, const int ty1,
                           const int tx2, const int ty2,
                           const CImg<tl>& light,
                           const int lx0, const int ly0,
                           const int lx1, const int ly1,
                           const int lx2, const int ly2,
                           const float opacity=1) {
      if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this;
      if (texture._depth>1 || texture._spectrum<_spectrum)
        throw CImgArgumentException(_cimg_instance
                                    "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
                                    cimg_instance,
                                    texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
      if (light._depth>1 || light._spectrum<_spectrum)
        throw CImgArgumentException(_cimg_instance
                                    "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).",
                                    cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data);
      if (is_overlapped(texture))
        return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,
                             light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
      if (is_overlapped(light))
        return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,texture,tx0,ty0,tx1,ty1,tx2,ty2,
                             +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
      static const T maxval = (T)std::min(cimg::type<T>::max(),(T)cimg::type<tc>::max());
      const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f);
      const ulongT
        whd = (ulongT)_width*_height*_depth,
        twh = (ulongT)texture._width*texture._height,
        lwh = (ulongT)light._width*light._height,
        offx = _spectrum*whd - 1;
      int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
        nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2;
      float
        ntx0 = tx0/z0, nty0 = ty0/z0,
        ntx1 = tx1/z1, nty1 = ty1/z1,
        ntx2 = tx2/z2, nty2 = ty2/z2,
        nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2;
      if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nlx0,nlx1,nly0,nly1,nz0,nz1);
      if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nlx0,nlx2,nly0,nly2,nz0,nz2);
      if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nlx1,nlx2,nly1,nly2,nz1,nz2);
      if (ny0>=height() || ny2<0) return *this;
      float
        ptxl = (ntx1 - ntx0)/(ny1 - ny0),
        ptxr = (ntx2 - ntx0)/(ny2 - ny0),
        ptxn = (ntx2 - ntx1)/(ny2 - ny1),
        ptyl = (nty1 - nty0)/(ny1 - ny0),
        ptyr = (nty2 - nty0)/(ny2 - ny0),
        ptyn = (nty2 - nty1)/(ny2 - ny1),
        pzl = (nz1 - nz0)/(ny1 - ny0),
        pzr = (nz2 - nz0)/(ny2 - ny0),
        pzn = (nz2 - nz1)/(ny2 - ny1),
        zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)),
        txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)),
        tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)),
        zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))),
        txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))):
          (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))),
        tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))):
          (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1)));
      const bool is_bump = texture._spectrum>=_spectrum + 2;
      const ulongT obx = twh*_spectrum, oby = twh*(_spectrum + 1);

      _cimg_for_triangle3(*this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y,
                          nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) {
        if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; }
        int
          xleft = xleft0, xright = xright0,
          lxleft = lxleft0, lxright = lxright0,
          lyleft = lyleft0, lyright = lyright0;
        float
          zleft = zl, zright = zr,
          txleft = txl, txright = txr,
          tyleft = tyl, tyright = tyr;
        if (xright<xleft)
          cimg::swap(xleft,xright,zleft,zright,txleft,txright,tyleft,tyright,lxleft,lxright,lyleft,lyright);
        const int
          dx = xright - xleft,
          dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright,
          dly = lyright>lyleft?lyright - lyleft:lyleft - lyright,
          rlx = dx?(lxright - lxleft)/dx:0,
          rly = dx?(lyright - lyleft)/dx:0,
          slx = lxright>lxleft?1:-1,
          sly = lyright>lyleft?1:-1,
          ndlx = dlx - (dx?dx*(dlx/dx):0),
          ndly = dly - (dx?dx*(dly/dx):0);
        const float
          pentez = (zright - zleft)/dx,
          pentetx = (txright - txleft)/dx,
          pentety = (tyright - tyleft)/dx;
        int errlx = dx>>1, errly = errlx;
        if (xleft<0 && dx) {
          zleft-=xleft*(zright - zleft)/dx;
          lxleft-=xleft*(lxright - lxleft)/dx;
          lyleft-=xleft*(lyright - lyleft)/dx;
          txleft-=xleft*(txright - txleft)/dx;
          tyleft-=xleft*(tyright - tyleft)/dx;
        }
        if (xleft<0) xleft = 0;
        if (xright>=width() - 1) xright = width() - 1;
        T* ptrd = data(xleft,y,0,0);
        if (opacity>=1) for (int x = xleft; x<=xright; ++x) {
          const float invz = 1/zleft;
          const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz));
          const int bx = is_bump?128 - (int)col[obx]:0, by = is_bump?128 - (int)col[oby]:0;
          const tl *lig = &light._atXY(lxleft + bx,lyleft + by);
          cimg_forC(*this,c) {
            const tl l = *lig;
            *ptrd = (T)(l<1?l**col:(2 - l)**col + (l - 1)*maxval);
            ptrd+=whd; col+=twh; lig+=lwh;
          }
          ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
          lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
          lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
        } else for (int x = xleft; x<=xright; ++x) {
          const float invz = 1/zleft;
          const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz));
          const int bx = is_bump?128 - (int)col[obx]:0, by = is_bump?128 - (int)col[oby]:0;
          const tl *lig = &light._atXY(lxleft + bx,lyleft + by);
          cimg_forC(*this,c) {
            const tl l = *lig;
            const T val = (T)(l<1?l**col:(2 - l)**col + (l - 1)*maxval);
            *ptrd = (T)(nopacity*val + *ptrd*copacity);
            ptrd+=whd; col+=twh; lig+=lwh;
          }
          ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety;
          lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
          lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
        }
        zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl;
      }
      return *this;

Project: CImg
File: CImg.h

    /**
       \param[out] min_val Value of the minimum value found.
    **/
    template<typename t>
    T& max_min(t& min_val) {
      if (is_empty())
        throw CImgInstanceException(_cimglist_instance
                                    "max_min(): Empty instance.",
                                    cimglist_instance);
      T *ptr_max = _data->_data;
      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

    //! Load image from an ascii file \overloading.
    CImg<T>& load_ascii(std::FILE *const file) {
      return _load_ascii(file,0);

Project: CImg
File: CImg.h

    template<typename t, typename tc>
    CImg<T>& draw_line(const CImg<t>& points,
                       const tc *const color, const float opacity=1,
                       const unsigned int pattern=~0U, const bool init_hatch=true) {
      if (is_empty() || !points || points._width<2) return *this;
      bool ninit_hatch = init_hatch;
      switch (points._height) {
      case 0 : case 1 :
        throw CImgArgumentException(_cimg_instance
                                    "draw_line(): Invalid specified point set (%u,%u,%u,%u,%p).",
                                    cimg_instance,
                                    points._width,points._height,points._depth,points._spectrum,points._data);

      case 2 : {
        const int x0 = (int)points(0,0), y0 = (int)points(0,1);
        int ox = x0, oy = y0;
        for (unsigned int i = 1; i<points._width; ++i) {
          const int x = (int)points(i,0), y = (int)points(i,1);
          draw_line(ox,oy,x,y,color,opacity,pattern,ninit_hatch);
          ninit_hatch = false;
          ox = x; oy = y;
        }
      } break;
      default : {
        const int x0 = (int)points(0,0), y0 = (int)points(0,1), z0 = (int)points(0,2);
        int ox = x0, oy = y0, oz = z0;
        for (unsigned int i = 1; i<points._width; ++i) {
          const int x = (int)points(i,0), y = (int)points(i,1), z = (int)points(i,2);
          draw_line(ox,oy,oz,x,y,z,color,opacity,pattern,ninit_hatch);
          ninit_hatch = false;
          ox = x; oy = y; oz = z;
        }
      }
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    CImg<T>& log2() {
      if (is_empty()) return *this;
      cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=4096))
      cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::log2((double)*ptrd);
      return *this;

Project: CImg
File: CImg.h

    **/
    CImgList<Tfloat> get_gradient(const char *const axes=0, const int scheme=3) const {
      CImgList<Tfloat> grad(2,_width,_height,_depth,_spectrum);
      bool is_3d = false;
      if (axes) {
        for (unsigned int a = 0; axes[a]; ++a) {
          const char axis = cimg::lowercase(axes[a]);
          switch (axis) {
          case 'x' : case 'y' : break;
          case 'z' : is_3d = true; break;
          default :
            throw CImgArgumentException(_cimg_instance
                                        "get_gradient(): Invalid specified axis '%c'.",
                                        cimg_instance,
                                        axis);
          }
        }
      } else is_3d = (_depth>1);
      if (is_3d) {
        CImg<Tfloat>(_width,_height,_depth,_spectrum).move_to(grad);
        switch (scheme) { // 3d.
        case -1 : { // Backward finite differences.
          cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2))
          cimg_forC(*this,c) {
            const ulongT off = (ulongT)c*_width*_height*_depth;
            Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off, *ptrd2 = grad[2]._data + off;
            CImg_3x3x3(I,Tfloat);
            cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) {
              *(ptrd0++) = Iccc - Ipcc;
              *(ptrd1++) = Iccc - Icpc;
              *(ptrd2++) = Iccc - Iccp;
            }
          }
        } break;
        case 1 : { // Forward finite differences.
          cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2))
          cimg_forC(*this,c) {
            const ulongT off = (ulongT)c*_width*_height*_depth;
            Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off, *ptrd2 = grad[2]._data + off;
            CImg_2x2x2(I,Tfloat);
            cimg_for2x2x2(*this,x,y,z,c,I,Tfloat) {
              *(ptrd0++) = Incc - Iccc;
              *(ptrd1++) = Icnc - Iccc;
              *(ptrd2++) = Iccn - Iccc;
            }
          }
        } break;
        case 4 : { // Deriche filter with low standard variation.
          grad[0] = get_deriche(0,1,'x');
          grad[1] = get_deriche(0,1,'y');
          grad[2] = get_deriche(0,1,'z');
        } break;
        case 5 : { // Van Vliet filter with low standard variation.
          grad[0] = get_vanvliet(0,1,'x');
          grad[1] = get_vanvliet(0,1,'y');
          grad[2] = get_vanvliet(0,1,'z');
        } break;
        default : { // Central finite differences.
          cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2))
          cimg_forC(*this,c) {
            const ulongT off = (ulongT)c*_width*_height*_depth;
            Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off, *ptrd2 = grad[2]._data + off;
            CImg_3x3x3(I,Tfloat);
            cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) {
              *(ptrd0++) = (Incc - Ipcc)/2;
              *(ptrd1++) = (Icnc - Icpc)/2;
              *(ptrd2++) = (Iccn - Iccp)/2;
            }
          }
        }
        }
      } else switch (scheme) { // 2d.
      case -1 : { // Backward finite differences.
        cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2))
        cimg_forZC(*this,z,c) {
          const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height;
          Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
          CImg_3x3(I,Tfloat);
          cimg_for3x3(*this,x,y,z,c,I,Tfloat) {
            *(ptrd0++) = Icc - Ipc;
            *(ptrd1++) = Icc - Icp;
          }
        }
      } break;
      case 1 : { // Forward finite differences.
        cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2))
        cimg_forZC(*this,z,c) {
          const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height;
          Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
          CImg_2x2(I,Tfloat);
          cimg_for2x2(*this,x,y,z,c,I,Tfloat) {
            *(ptrd0++) = Inc - Icc;
            *(ptrd1++) = Icn - Icc;
          }
        }
      } break;
      case 2 : { // Sobel scheme.
        cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2))
        cimg_forZC(*this,z,c) {
          const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height;
          Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
          CImg_3x3(I,Tfloat);
          cimg_for3x3(*this,x,y,z,c,I,Tfloat) {
            *(ptrd0++) = -Ipp - 2*Ipc - Ipn + Inp + 2*Inc + Inn;
            *(ptrd1++) = -Ipp - 2*Icp - Inp + Ipn + 2*Icn + Inn;
          }
        }
      } break;
      case 3 : { // Rotation invariant kernel.
        cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2))
        cimg_forZC(*this,z,c) {
          const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height;
          Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
          CImg_3x3(I,Tfloat);
          const Tfloat a = (Tfloat)(0.25f*(2 - std::sqrt(2.0f))), b = (Tfloat)(0.5f*(std::sqrt(2.0f) - 1));
          cimg_for3x3(*this,x,y,z,c,I,Tfloat) {
            *(ptrd0++) = -a*Ipp - b*Ipc - a*Ipn + a*Inp + b*Inc + a*Inn;
            *(ptrd1++) = -a*Ipp - b*Icp - a*Inp + a*Ipn + b*Icn + a*Inn;
          }
        }
      } break;
      case 4 : { // Van Vliet filter with low standard variation
        grad[0] = get_deriche(0,1,'x');
        grad[1] = get_deriche(0,1,'y');
      } break;
      case 5 : { // Deriche filter with low standard variation
        grad[0] = get_vanvliet(0,1,'x');
        grad[1] = get_vanvliet(0,1,'y');
      } break;
      default : { // Central finite differences
        cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2))
        cimg_forZC(*this,z,c) {
          const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height;
          Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
          CImg_3x3(I,Tfloat);
          cimg_for3x3(*this,x,y,z,c,I,Tfloat) {
            *(ptrd0++) = (Inc - Ipc)/2;
            *(ptrd1++) = (Icn - Icp)/2;
          }
        }
      }
      }
      if (!axes) return grad;
      CImgList<Tfloat> res;
      for (unsigned int l = 0; axes[l]; ++l) {
        const char axis = cimg::lowercase(axes[l]);
        switch (axis) {
        case 'x' : res.insert(grad[0]); break;
        case 'y' : res.insert(grad[1]); break;
        case 'z' : res.insert(grad[2]); break;
        }
      }
      grad.assign();
      return res;

Project: CImg
File: CImg.h

    **/
    float frames_per_second() {
      if (!_fps_timer) _fps_timer = cimg::time();
      const float delta = (cimg::time() - _fps_timer)/1000.0f;
      ++_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

    template<typename tc, typename tl>
    CImg<T>& draw_triangle(const int x0, const int y0,
                           const int x1, const int y1,
                           const int x2, const int y2,
                           const CImg<tc>& texture,
                           const int tx0, const int ty0,
                           const int tx1, const int ty1,
                           const int tx2, const int ty2,
                           const CImg<tl>& light,
                           const int lx0, const int ly0,
                           const int lx1, const int ly1,
                           const int lx2, const int ly2,
                           const float opacity=1) {
      if (is_empty()) return *this;
      if (texture._depth>1 || texture._spectrum<_spectrum)
        throw CImgArgumentException(_cimg_instance
                                    "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).",
                                    cimg_instance,
                                    texture._width,texture._height,texture._depth,texture._spectrum,texture._data);
      if (light._depth>1 || light._spectrum<_spectrum)
        throw CImgArgumentException(_cimg_instance
                                    "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).",
                                    cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data);
      if (is_overlapped(texture))
        return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
      if (is_overlapped(light))
        return draw_triangle(x0,y0,x1,y1,x2,y2,texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
      static const T maxval = (T)std::min(cimg::type<T>::max(),(T)cimg::type<tc>::max());
      const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f);
      const ulongT
        whd = (ulongT)_width*_height*_depth,
        twh = (ulongT)texture._width*texture._height,
        lwh = (ulongT)light._width*light._height,
        offx = _spectrum*whd - 1;
      int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
        ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2,
        nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2;
      if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nlx0,nlx1,nly0,nly1);
      if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nlx0,nlx2,nly0,nly2);
      if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nlx1,nlx2,nly1,nly2);
      if (ny0>=height() || ny2<0) return *this;
      const bool is_bump = texture._spectrum>=_spectrum + 2;
      const ulongT obx = twh*_spectrum, oby = twh*(_spectrum + 1);

      _cimg_for_triangle5(*this,xleft0,lxleft0,lyleft0,txleft0,tyleft0,xright0,lxright0,lyright0,txright0,tyright0,y,
                          nx0,ny0,nlx0,nly0,ntx0,nty0,nx1,ny1,nlx1,nly1,ntx1,nty1,nx2,ny2,nlx2,nly2,ntx2,nty2) {
        int
          xleft = xleft0, xright = xright0,
          lxleft = lxleft0, lxright = lxright0,
          lyleft = lyleft0, lyright = lyright0,
          txleft = txleft0, txright = txright0,
          tyleft = tyleft0, tyright = tyright0;
        if (xright<xleft) cimg::swap(xleft,xright,lxleft,lxright,lyleft,lyright,txleft,txright,tyleft,tyright);
        const int
          dx = xright - xleft,
          dlx = lxright>lxleft?lxright - lxleft:lxleft - lxright,
          dly = lyright>lyleft?lyright - lyleft:lyleft - lyright,
          dtx = txright>txleft?txright - txleft:txleft - txright,
          dty = tyright>tyleft?tyright - tyleft:tyleft - tyright,
          rlx = dx?(lxright - lxleft)/dx:0,
          rly = dx?(lyright - lyleft)/dx:0,
          rtx = dx?(txright - txleft)/dx:0,
          rty = dx?(tyright - tyleft)/dx:0,
          slx = lxright>lxleft?1:-1,
          sly = lyright>lyleft?1:-1,
          stx = txright>txleft?1:-1,
          sty = tyright>tyleft?1:-1,
          ndlx = dlx - (dx?dx*(dlx/dx):0),
          ndly = dly - (dx?dx*(dly/dx):0),
          ndtx = dtx - (dx?dx*(dtx/dx):0),
          ndty = dty - (dx?dx*(dty/dx):0);
        int errlx = dx>>1, errly = errlx, errtx = errlx, errty = errlx;
        if (xleft<0 && dx) {
          lxleft-=xleft*(lxright - lxleft)/dx;
          lyleft-=xleft*(lyright - lyleft)/dx;
          txleft-=xleft*(txright - txleft)/dx;
          tyleft-=xleft*(tyright - tyleft)/dx;
        }
        if (xleft<0) xleft = 0;
        if (xright>=width() - 1) xright = width() - 1;
        T* ptrd = data(xleft,y,0,0);
        if (opacity>=1) for (int x = xleft; x<=xright; ++x) {
          const tc *col = &texture._atXY(txleft,tyleft);
          const int bx = is_bump?128 - (int)col[obx]:0, by = is_bump?128 - (int)col[oby]:0;
          const tl *lig = &light._atXY(lxleft + bx,lyleft + by);
          cimg_forC(*this,c) {
            const tl l = *lig;
            *ptrd = (T)(l<1?l**col:(2 - l)**col + (l - 1)*maxval);
            ptrd+=whd; col+=twh; lig+=lwh;
          }
          ptrd-=offx;
          lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
          lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
          txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0);
          tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0);
        } else for (int x = xleft; x<=xright; ++x) {
          const tc *col = &texture._atXY(txleft,tyleft);
          const int bx = is_bump?128 - (int)col[obx]:0, by = is_bump?128 - (int)col[oby]:0;
          const tl *lig = &light._atXY(lxleft + bx,lyleft + by);
          cimg_forC(*this,c) {
            const tl l = *lig;
            const T val = (T)(l<1?l**col:(2 - l)**col + (l - 1)*maxval);
            *ptrd = (T)(nopacity*val + *ptrd*copacity);
            ptrd+=whd; col+=twh; lig+=lwh;
          }
          ptrd-=offx;
          lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0);
          lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0);
          txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0);
          tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0);
        }
      }
      return *this;

Project: CImg
File: CImg.h

    **/
    CImg<T>& load_camera(const unsigned int camera_index=0, const unsigned int skip_frames=0,
                         const bool release_camera=true, const unsigned int capture_width=0,
                         const unsigned int capture_height=0) {
#ifdef cimg_use_opencv
      if (camera_index>99)
        throw CImgArgumentException(_cimg_instance
                                    "load_camera(): Invalid request for camera #%u "
                                    "(no more than 100 cameras can be managed simultaneously).",
                                    cimg_instance,
                                    camera_index);
      static CvCapture *capture[100] = { 0 };
      static unsigned int capture_w[100], capture_h[100];
      if (release_camera) {
        cimg::mutex(9);
        if (capture[camera_index]) cvReleaseCapture(&(capture[camera_index]));
        capture[camera_index] = 0;
        capture_w[camera_index] = capture_h[camera_index] = 0;
        cimg::mutex(9,0);
        return *this;
      }
      if (!capture[camera_index]) {
        cimg::mutex(9);
        capture[camera_index] = cvCreateCameraCapture(camera_index);
        capture_w[camera_index] = 0;
        capture_h[camera_index] = 0;
        cimg::mutex(9,0);
        if (!capture[camera_index]) {
          throw CImgIOException(_cimg_instance
                                "load_camera(): Failed to initialize camera #%u.",
                                cimg_instance,
                                camera_index);
        }
      }
      cimg::mutex(9);
      if (capture_width!=capture_w[camera_index]) {
        cvSetCaptureProperty(capture[camera_index],CV_CAP_PROP_FRAME_WIDTH,capture_width);
        capture_w[camera_index] = capture_width;
      }
      if (capture_height!=capture_h[camera_index]) {
        cvSetCaptureProperty(capture[camera_index],CV_CAP_PROP_FRAME_HEIGHT,capture_height);
        capture_h[camera_index] = capture_height;
      }
      const IplImage *img = 0;
      for (unsigned int i = 0; i<skip_frames; ++i) img = cvQueryFrame(capture[camera_index]);
      img = cvQueryFrame(capture[camera_index]);
      if (img) {
        const int step = (int)(img->widthStep - 3*img->width);
        assign(img->width,img->height,1,3);
        const unsigned char* ptrs = (unsigned char*)img->imageData;
        T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2);
        if (step>0) cimg_forY(*this,y) {
            cimg_forX(*this,x) { *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++); }
            ptrs+=step;
          } else for (ulongT siz = (ulongT)img->width*img->height; siz; --siz) {
            *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++);
          }
      }
      cimg::mutex(9,0);
      return *this;
#else
      cimg::unused(camera_index,skip_frames,release_camera,capture_width,capture_height);
      throw CImgIOException(_cimg_instance
                            "load_camera(): This function requires the OpenCV library to run "
                            "(macro 'cimg_use_opencv' must be defined).",
                            cimg_instance);
#endif

Project: CImg
File: CImg.h

    template<typename tf>
    CImg<floatT> get_isoline3d(CImgList<tf>& primitives, const float isovalue,
                               const int size_x=-100, const int size_y=-100) const {
      if (_spectrum>1)
        throw CImgInstanceException(_cimg_instance
                                    "get_isoline3d(): Instance is not a scalar image.",
                                    cimg_instance);
      if (_depth>1)
        throw CImgInstanceException(_cimg_instance
                                    "get_isoline3d(): Instance is not a 2d image.",
                                    cimg_instance);
      primitives.assign();
      if (is_empty()) return *this;
      CImg<floatT> vertices;
      if ((size_x==-100 && size_y==-100) || (size_x==width() && size_y==height())) {
        const _functor2d_int func(*this);
        vertices = isoline3d(primitives,func,isovalue,0,0,width() - 1.0f,height() - 1.0f,width(),height());
      } else {
        const _functor2d_float func(*this);
        vertices = isoline3d(primitives,func,isovalue,0,0,width() - 1.0f,height() - 1.0f,size_x,size_y);
      }
      return vertices;

Project: CImg
File: CImg.h

    **/
    CImg<T>& load(const char *const filename) {
      if (!filename)
        throw CImgArgumentException(_cimg_instance
                                    "load(): Specified filename is (null).",
                                    cimg_instance);

      if (!cimg::strncasecmp(filename,"http://",7) || !cimg::strncasecmp(filename,"https://",8)) {
        CImg<charT> filename_local(256);
        load(cimg::load_network(filename,filename_local));
        std::remove(filename_local);
        return *this;
      }

      const char *const ext = cimg::split_filename(filename);
      const unsigned int omode = cimg::exception_mode();
      cimg::exception_mode(0);
      bool is_loaded = true;
      try {
#ifdef cimg_load_plugin
        cimg_load_plugin(filename);
#endif
#ifdef cimg_load_plugin1
        cimg_load_plugin1(filename);
#endif
#ifdef cimg_load_plugin2
        cimg_load_plugin2(filename);
#endif
#ifdef cimg_load_plugin3
        cimg_load_plugin3(filename);
#endif
#ifdef cimg_load_plugin4
        cimg_load_plugin4(filename);
#endif
#ifdef cimg_load_plugin5
        cimg_load_plugin5(filename);
#endif
#ifdef cimg_load_plugin6
        cimg_load_plugin6(filename);
#endif
#ifdef cimg_load_plugin7
        cimg_load_plugin7(filename);
#endif
#ifdef cimg_load_plugin8
        cimg_load_plugin8(filename);
#endif
        // Ascii formats
        if (!cimg::strcasecmp(ext,"asc")) load_ascii(filename);
        else if (!cimg::strcasecmp(ext,"dlm") ||
                 !cimg::strcasecmp(ext,"txt")) load_dlm(filename);

        // 2d binary formats
        else if (!cimg::strcasecmp(ext,"bmp")) load_bmp(filename);
        else if (!cimg::strcasecmp(ext,"jpg") ||
                 !cimg::strcasecmp(ext,"jpeg") ||
                 !cimg::strcasecmp(ext,"jpe") ||
                 !cimg::strcasecmp(ext,"jfif") ||
                 !cimg::strcasecmp(ext,"jif")) load_jpeg(filename);
        else if (!cimg::strcasecmp(ext,"png")) load_png(filename);
        else if (!cimg::strcasecmp(ext,"ppm") ||
                 !cimg::strcasecmp(ext,"pgm") ||
                 !cimg::strcasecmp(ext,"pnm") ||
                 !cimg::strcasecmp(ext,"pbm") ||
                 !cimg::strcasecmp(ext,"pnk")) load_pnm(filename);
        else if (!cimg::strcasecmp(ext,"pfm")) load_pfm(filename);
        else if (!cimg::strcasecmp(ext,"tif") ||
                 !cimg::strcasecmp(ext,"tiff")) load_tiff(filename);
        else if (!cimg::strcasecmp(ext,"exr")) load_exr(filename);
        else if (!cimg::strcasecmp(ext,"cr2") ||
                 !cimg::strcasecmp(ext,"crw") ||
                 !cimg::strcasecmp(ext,"dcr") ||
                 !cimg::strcasecmp(ext,"mrw") ||
                 !cimg::strcasecmp(ext,"nef") ||
                 !cimg::strcasecmp(ext,"orf") ||
                 !cimg::strcasecmp(ext,"pix") ||
                 !cimg::strcasecmp(ext,"ptx") ||
                 !cimg::strcasecmp(ext,"raf") ||
                 !cimg::strcasecmp(ext,"srf")) load_dcraw_external(filename);
        else if (!cimg::strcasecmp(ext,"gif")) load_gif_external(filename);

        // 3d binary formats
        else if (!cimg::strcasecmp(ext,"dcm") ||
                 !cimg::strcasecmp(ext,"dicom")) load_medcon_external(filename);
        else if (!cimg::strcasecmp(ext,"hdr") ||
                 !cimg::strcasecmp(ext,"nii")) load_analyze(filename);
        else if (!cimg::strcasecmp(ext,"par") ||
                 !cimg::strcasecmp(ext,"rec")) load_parrec(filename);
        else if (!cimg::strcasecmp(ext,"mnc")) load_minc2(filename);
        else if (!cimg::strcasecmp(ext,"inr")) load_inr(filename);
        else if (!cimg::strcasecmp(ext,"pan")) load_pandore(filename);
        else if (!cimg::strcasecmp(ext,"cimg") ||
                 !cimg::strcasecmp(ext,"cimgz") ||
                 !*ext)  return load_cimg(filename);

        // Archive files
        else if (!cimg::strcasecmp(ext,"gz")) load_gzip_external(filename);

        // Image sequences
        else if (!cimg::strcasecmp(ext,"avi") ||
                 !cimg::strcasecmp(ext,"mov") ||
                 !cimg::strcasecmp(ext,"asf") ||
                 !cimg::strcasecmp(ext,"divx") ||
                 !cimg::strcasecmp(ext,"flv") ||
                 !cimg::strcasecmp(ext,"mpg") ||
                 !cimg::strcasecmp(ext,"m1v") ||
                 !cimg::strcasecmp(ext,"m2v") ||
                 !cimg::strcasecmp(ext,"m4v") ||
                 !cimg::strcasecmp(ext,"mjp") ||
                 !cimg::strcasecmp(ext,"mp4") ||
                 !cimg::strcasecmp(ext,"mkv") ||
                 !cimg::strcasecmp(ext,"mpe") ||
                 !cimg::strcasecmp(ext,"movie") ||
                 !cimg::strcasecmp(ext,"ogm") ||
                 !cimg::strcasecmp(ext,"ogg") ||
                 !cimg::strcasecmp(ext,"ogv") ||
                 !cimg::strcasecmp(ext,"qt") ||
                 !cimg::strcasecmp(ext,"rm") ||
                 !cimg::strcasecmp(ext,"vob") ||
                 !cimg::strcasecmp(ext,"wmv") ||
                 !cimg::strcasecmp(ext,"xvid") ||
                 !cimg::strcasecmp(ext,"mpeg")) load_video(filename);
        else is_loaded = false;
      } catch (CImgIOException&) { is_loaded = false; }

      // If nothing loaded, try to guess file format from magic number in file.
      if (!is_loaded) {
        std::FILE *file = std_fopen(filename,"rb");
        if (!file) {
          cimg::exception_mode(omode);
          throw CImgIOException(_cimg_instance
                                "load(): Failed to open file '%s'.",
                                cimg_instance,
                                filename);
        }

        const char *const f_type = cimg::ftype(file,filename);
        std::fclose(file);
        is_loaded = true;
        try {
          if (!cimg::strcasecmp(f_type,"pnm")) load_pnm(filename);
          else if (!cimg::strcasecmp(f_type,"pfm")) load_pfm(filename);
          else if (!cimg::strcasecmp(f_type,"bmp")) load_bmp(filename);
          else if (!cimg::strcasecmp(f_type,"inr")) load_inr(filename);
          else if (!cimg::strcasecmp(f_type,"jpg")) load_jpeg(filename);
          else if (!cimg::strcasecmp(f_type,"pan")) load_pandore(filename);
          else if (!cimg::strcasecmp(f_type,"png")) load_png(filename);
          else if (!cimg::strcasecmp(f_type,"tif")) load_tiff(filename);
          else if (!cimg::strcasecmp(f_type,"gif")) load_gif_external(filename);
          else if (!cimg::strcasecmp(f_type,"dcm")) load_medcon_external(filename);
          else is_loaded = false;
        } catch (CImgIOException&) { is_loaded = false; }
      }

      // If nothing loaded, try to load file with other means.
      if (!is_loaded) {
        try {
          load_other(filename);
        } catch (CImgIOException&) {
          cimg::exception_mode(omode);
          throw CImgIOException(_cimg_instance
                                "load(): Failed to recognize format of file '%s'.",
                                cimg_instance,
                                filename);
        }
      }
      cimg::exception_mode(omode);
      return *this;

Project: CImg
File: CImg.h

    //! Compute the sine of each pixel value \newinstance.
    CImg<Tfloat> get_sin() const {
      return CImg<Tfloat>(*this,false).sin();

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.0f);
      if (boundary_conditions!=1 && cimg::mod(nangle,90.0f)==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.0),
          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 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,k,l,1,1,true) = U;
        CImg<doubleT>(ptrd + k*l,1,k,1,1,true) = S;
        CImg<doubleT>(ptrd + k*l + k,k,k,1,1,true) = V;
        return cimg::type<double>::nan();

Project: CImg
File: CImg.h

    //! Rotate volumetric image with arbitrary angle and axis \newinstance.
    CImg<T> get_rotate(const float u, const float v, const float w, const float angle,
                       const unsigned int interpolation, const unsigned int boundary_conditions) const {
      if (is_empty()) return *this;
      CImg<T> res;
      const float
        w1 = _width - 1, h1 = _height - 1, d1 = _depth -1,
        w2 = 0.5f*w1, h2 = 0.5f*h1, d2 = 0.5f*d1;
      CImg<floatT> R = CImg<floatT>::rotation_matrix(u,v,w,angle);
      const CImg<Tfloat>
        X = R*CImg<Tfloat>(8,3,1,1,
                           0.0f,w1,w1,0.0f,0.0f,w1,w1,0.0f,
                           0.0f,0.0f,h1,h1,0.0f,0.0f,h1,h1,
                           0.0f,0.0f,0.0f,0.0f,d1,d1,d1,d1);
      float
        xm, xM = X.get_shared_row(0).max_min(xm),
        ym, yM = X.get_shared_row(1).max_min(ym),
        zm, zM = X.get_shared_row(2).max_min(zm);
      const int
        dx = (int)cimg::round(xM - xm),
        dy = (int)cimg::round(yM - ym),
        dz = (int)cimg::round(zM - zm);
      R.transpose();
      res.assign(1 + dx,1 + dy,1 + dz,_spectrum);
      const float rw2 = 0.5f*dx, rh2 = 0.5f*dy, rd2 = 0.5f*dz;
      _rotate(res,R,interpolation,boundary_conditions,w2,h2,d2,rw2,rh2,rd2);
      return res;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<doubleT> _eval(CImg<T> *const output, const char *const expression, const CImg<t>& xyzc,
                        const CImgList<T> *const list_inputs=0, CImgList<T> *const list_outputs=0) const {
      CImg<doubleT> res(1,xyzc.size()/4);
      if (!expression || !*expression) return res.fill(0);
      _cimg_math_parser mp(expression,"eval",*this,output,list_inputs,list_outputs,false);
#ifdef cimg_use_openmp
      cimg_pragma_openmp(parallel if (res._height>=512))
      {
        _cimg_math_parser
          _mp = omp_get_thread_num()?mp:_cimg_math_parser(),
          &lmp = omp_get_thread_num()?_mp:mp;
        cimg_pragma_openmp(for)
          for (unsigned int i = 0; i<res._height; ++i) {
            const unsigned int i4 = 4*i;
            const double
              x = (double)xyzc[i4], y = (double)xyzc[i4 + 1],
              z = (double)xyzc[i4 + 2], c = (double)xyzc[i4 + 3];
            res[i] = lmp(x,y,z,c);
          }
        }
#else
      const t *ps = xyzc._data;
      cimg_for(res,pd,double) {
        const double x = (double)*(ps++), y = (double)*(ps++), z = (double)*(ps++), c = (double)*(ps++);
        *pd = mp(x,y,z,c);
      }
#endif
      mp.end();
      return res;

Project: CImg
File: CImg.h

    **/
    CImg<T>& draw_rectangle(const int x0, const int y0, const int z0, const int c0,
                            const int x1, const int y1, const int z1, const int c1,
                            const T val, const float opacity=1) {
      if (is_empty()) return *this;
      const int
        nx0 = x0<x1?x0:x1, nx1 = x0^x1^nx0,
        ny0 = y0<y1?y0:y1, ny1 = y0^y1^ny0,
        nz0 = z0<z1?z0:z1, nz1 = z0^z1^nz0,
        nc0 = c0<c1?c0:c1, nc1 = c0^c1^nc0;
      const int
        lX = (1 + nx1 - nx0) + (nx1>=width()?width() - 1 - nx1:0) + (nx0<0?nx0:0),
        lY = (1 + ny1 - ny0) + (ny1>=height()?height() - 1 - ny1:0) + (ny0<0?ny0:0),
        lZ = (1 + nz1 - nz0) + (nz1>=depth()?depth() - 1 - nz1:0) + (nz0<0?nz0:0),
        lC = (1 + nc1 - nc0) + (nc1>=spectrum()?spectrum() - 1 - nc1:0) + (nc0<0?nc0:0);
      const ulongT
        offX = (ulongT)_width - lX,
        offY = (ulongT)_width*(_height - lY),
        offZ = (ulongT)_width*_height*(_depth - lZ);
      const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f);
      T *ptrd = data(nx0<0?0:nx0,ny0<0?0:ny0,nz0<0?0:nz0,nc0<0?0:nc0);
      if (lX>0 && lY>0 && lZ>0 && lC>0)
        for (int v = 0; v<lC; ++v) {
          for (int z = 0; z<lZ; ++z) {
            for (int y = 0; y<lY; ++y) {
              if (opacity>=1) {
                if (sizeof(T)!=1) { for (int x = 0; x<lX; ++x) *(ptrd++) = val; ptrd+=offX; }
                else { std::memset(ptrd,(int)val,lX); ptrd+=_width; }
              } else { for (int x = 0; x<lX; ++x) { *ptrd = (T)(nopacity*val + *ptrd*copacity); ++ptrd; } ptrd+=offX; }
            }
            ptrd+=offY;
          }
          ptrd+=offZ;
        }
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImgList<T> get_split(const CImg<t>& values, const char axis=0, const bool keep_values=true) const {
      CImgList<T> res;
      if (is_empty()) return res;
      const ulongT vsiz = values.size();
      const char _axis = cimg::lowercase(axis);
      if (!vsiz) return CImgList<T>(*this);
      if (vsiz==1) { // Split according to a single value.
        const T value = (T)*values;
        switch (_axis) {
        case 'x' : {
          unsigned int i0 = 0, i = 0;
          do {
            while (i<_width && (*this)(i)==value) ++i;
            if (i>i0) { if (keep_values) get_columns(i0,i - 1).move_to(res); i0 = i; }
            while (i<_width && (*this)(i)!=value) ++i;
            if (i>i0) { get_columns(i0,i - 1).move_to(res); i0 = i; }
          } while (i<_width);
        } break;
        case 'y' : {
          unsigned int i0 = 0, i = 0;
          do {
            while (i<_height && (*this)(0,i)==value) ++i;
            if (i>i0) { if (keep_values) get_rows(i0,i - 1).move_to(res); i0 = i; }
            while (i<_height && (*this)(0,i)!=value) ++i;
            if (i>i0) { get_rows(i0,i - 1).move_to(res); i0 = i; }
          } while (i<_height);
        } break;
        case 'z' : {
          unsigned int i0 = 0, i = 0;
          do {
            while (i<_depth && (*this)(0,0,i)==value) ++i;
            if (i>i0) { if (keep_values) get_slices(i0,i - 1).move_to(res); i0 = i; }
            while (i<_depth && (*this)(0,0,i)!=value) ++i;
            if (i>i0) { get_slices(i0,i - 1).move_to(res); i0 = i; }
          } while (i<_depth);
        } break;
        case 'c' : {
          unsigned int i0 = 0, i = 0;
          do {
            while (i<_spectrum && (*this)(0,0,0,i)==value) ++i;
            if (i>i0) { if (keep_values) get_channels(i0,i - 1).move_to(res); i0 = i; }
            while (i<_spectrum && (*this)(0,0,0,i)!=value) ++i;
            if (i>i0) { get_channels(i0,i - 1).move_to(res); i0 = i; }
          } while (i<_spectrum);
        } break;
        default : {
          const ulongT siz = size();
          ulongT i0 = 0, i = 0;
          do {
            while (i<siz && (*this)[i]==value) ++i;
            if (i>i0) { if (keep_values) CImg<T>(_data + i0,1,(unsigned int)(i - i0)).move_to(res); i0 = i; }
            while (i<siz && (*this)[i]!=value) ++i;
            if (i>i0) { CImg<T>(_data + i0,1,(unsigned int)(i - i0)).move_to(res); i0 = i; }
          } while (i<siz);
        }
        }
      } else { // Split according to multiple values.
        ulongT j = 0;
        switch (_axis) {
        case 'x' : {
          unsigned int i0 = 0, i1 = 0, i = 0;
          do {
            if ((*this)(i)==*values) {
              i1 = i; j = 0;
              while (i<_width && (*this)(i)==values[j]) { ++i; if (++j>=vsiz) j = 0; }
              i-=j;
              if (i>i1) {
                if (i1>i0) get_columns(i0,i1 - 1).move_to(res);
                if (keep_values) get_columns(i1,i - 1).move_to(res);
                i0 = i;
              } else ++i;
            } else ++i;
          } while (i<_width);
          if (i0<_width) get_columns(i0,width() - 1).move_to(res);
        } break;
        case 'y' : {
          unsigned int i0 = 0, i1 = 0, i = 0;
          do {
            if ((*this)(0,i)==*values) {
              i1 = i; j = 0;
              while (i<_height && (*this)(0,i)==values[j]) { ++i; if (++j>=vsiz) j = 0; }
              i-=j;
              if (i>i1) {
                if (i1>i0) get_rows(i0,i1 - 1).move_to(res);
                if (keep_values) get_rows(i1,i - 1).move_to(res);
                i0 = i;
              } else ++i;
            } else ++i;
          } while (i<_height);
          if (i0<_height) get_rows(i0,height() - 1).move_to(res);
        } break;
        case 'z' : {
          unsigned int i0 = 0, i1 = 0, i = 0;
          do {
            if ((*this)(0,0,i)==*values) {
              i1 = i; j = 0;
              while (i<_depth && (*this)(0,0,i)==values[j]) { ++i; if (++j>=vsiz) j = 0; }
              i-=j;
              if (i>i1) {
                if (i1>i0) get_slices(i0,i1 - 1).move_to(res);
                if (keep_values) get_slices(i1,i - 1).move_to(res);
                i0 = i;
              } else ++i;
            } else ++i;
          } while (i<_depth);
          if (i0<_depth) get_slices(i0,depth() - 1).move_to(res);
        } break;
        case 'c' : {
          unsigned int i0 = 0, i1 = 0, i = 0;
          do {
            if ((*this)(0,0,0,i)==*values) {
              i1 = i; j = 0;
              while (i<_spectrum && (*this)(0,0,0,i)==values[j]) { ++i; if (++j>=vsiz) j = 0; }
              i-=j;
              if (i>i1) {
                if (i1>i0) get_channels(i0,i1 - 1).move_to(res);
                if (keep_values) get_channels(i1,i - 1).move_to(res);
                i0 = i;
              } else ++i;
            } else ++i;
          } while (i<_spectrum);
          if (i0<_spectrum) get_channels(i0,spectrum() - 1).move_to(res);
        } break;
        default : {
          ulongT i0 = 0, i1 = 0, i = 0;
          const ulongT siz = size();
          do {
            if ((*this)[i]==*values) {
              i1 = i; j = 0;
              while (i<siz && (*this)[i]==values[j]) { ++i; if (++j>=vsiz) j = 0; }
              i-=j;
              if (i>i1) {
                if (i1>i0) CImg<T>(_data + i0,1,(unsigned int)(i1 - i0)).move_to(res);
                if (keep_values) CImg<T>(_data + i1,1,(unsigned int)(i - i1)).move_to(res);
                i0 = i;
              } else ++i;
            } else ++i;
          } while (i<siz);
          if (i0<siz) CImg<T>(_data + i0,1,(unsigned int)(siz - i0)).move_to(res);
        } break;
        }
      }
      return res;

Project: CImg
File: CImg.h

    **/
    CImg<T>& operator--() {
      if (is_empty()) return *this;
      cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=524288))
      cimg_rof(*this,ptrd,T) *ptrd = *ptrd - (T)1;
      return *this;

Project: CImg
File: CImg.h

    //! Compute the sign of each pixel value \newinstance.
    CImg<Tfloat> get_sign() const {
      return CImg<Tfloat>(*this,false).sign();

Project: CImg
File: CImg.h

    **/
    T cubic_cut_atXYZ(const float fx, const float fy, const float fz, const int c, const T& out_value) const {
      return cimg::type<T>::cut(cubic_atXYZ(fx,fy,fz,c,out_value));

Project: CImg
File: CImg.h

      }
      static double nan() {
#ifdef NAN
        return (double)NAN;
#else
        const double val_nan = -std::sqrt(-1.0); return val_nan;
#endif

Project: CImg
File: CImg.h

    **/
    CImg<T>& sinc() {
      if (is_empty()) return *this;
      cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=2048))
      cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::sinc((double)*ptrd);
      return *this;

Project: CImg
File: CImg.h

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

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

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

Project: CImg
File: CImg.h

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

Project: CImg
File: CImg.h

                              cimglist_instance,filename);
      return *this;
    }

    CImgList<T>& _load_gif_external(const char *const filename, const bool use_graphicsmagick=false) {
      CImg<charT> command(1024), filename_tmp(256), filename_tmp2(256);
      std::FILE *file = 0;
      do {
        cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s",
                      cimg::temporary_path(),cimg_file_separator,cimg::filenamerand());
        if (use_graphicsmagick) cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png.0",filename_tmp._data);
        else cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s-0.png",filename_tmp._data);
        if ((file=std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file);
      } while (file);
      if (use_graphicsmagick) cimg_snprintf(command,command._width,"%s convert \"%s\" \"%s.png\"",
                                            cimg::graphicsmagick_path(),
                                            CImg<charT>::string(filename)._system_strescape().data(),
                                            CImg<charT>::string(filename_tmp)._system_strescape().data());
      else cimg_snprintf(command,command._width,"%s \"%s\" \"%s.png\"",
                         cimg::imagemagick_path(),
                         CImg<charT>::string(filename)._system_strescape().data(),
                         CImg<charT>::string(filename_tmp)._system_strescape().data());
      cimg::system(command,0);
      const unsigned int omode = cimg::exception_mode();
      cimg::exception_mode(0);
      assign();

      // Try to read a single frame gif.
      cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png",filename_tmp._data);
      CImg<T> img;
      try { img.load_png(filename_tmp2); }
      catch (CImgException&) { }
      if (img) { img.move_to(*this); std::remove(filename_tmp2); }
      else { // Try to read animated gif.
        unsigned int i = 0;
        for (bool stop_flag = false; !stop_flag; ++i) {
          if (use_graphicsmagick) cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png.%u",filename_tmp._data,i);
          else cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s-%u.png",filename_tmp._data,i);
          CImg<T> img;
          try { img.load_png(filename_tmp2); }
          catch (CImgException&) { stop_flag = true; }
          if (img) { img.move_to(*this); std::remove(filename_tmp2); }
        }

Project: CImg
File: CImg.h


    CImg<T>& _priority_queue_remove(unsigned int& siz) {
      (*this)(0,0) = (*this)(--siz,0);
      (*this)(0,1) = (*this)(siz,1);
      (*this)(0,2) = (*this)(siz,2);
      (*this)(0,3) = (*this)(siz,3);
      const float value = (*this)(0,0);
      for (unsigned int pos = 0, left = 0, right = 0;
           ((right=2*(pos + 1),(left=right - 1))<siz && value<(*this)(left,0)) ||
             (right<siz && value<(*this)(right,0));) {
        if (right<siz) {
          if ((*this)(left,0)>(*this)(right,0)) {
            cimg::swap((*this)(pos,0),(*this)(left,0));
            cimg::swap((*this)(pos,1),(*this)(left,1));
            cimg::swap((*this)(pos,2),(*this)(left,2));
            cimg::swap((*this)(pos,3),(*this)(left,3));
            pos = left;
          } else {
            cimg::swap((*this)(pos,0),(*this)(right,0));
            cimg::swap((*this)(pos,1),(*this)(right,1));
            cimg::swap((*this)(pos,2),(*this)(right,2));
            cimg::swap((*this)(pos,3),(*this)(right,3));
            pos = right;
          }
        } else {
          cimg::swap((*this)(pos,0),(*this)(left,0));
          cimg::swap((*this)(pos,1),(*this)(left,1));
          cimg::swap((*this)(pos,2),(*this)(left,2));
          cimg::swap((*this)(pos,3),(*this)(left,3));
          pos = left;
        }
      }
      return *this;

Project: CImg
File: CImg.h

    template<typename t>
    CImg<T>& operator/=(const t value) {
      if (is_empty()) return *this;
      cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768))
      cimg_rof(*this,ptrd,T) *ptrd = (T)(*ptrd / value);
      return *this;