G'MIC relation to the CImg library - GreycLab/gmic-community GitHub Wiki
#Reasons to look at CImg
- Documentation of Core Functions
- Optimising Code
- Extending functionality
##Documentation of Core Functions For documentation of CImg template library which is distributed as a single header file in C++ read the source files which contain this Doxygen Formatted Reference - The Link is Broken documentation.
##Optimising Code Sequences of G'MIC commands are interpreted and may call other commands but eventually will result in low-level calls to CImg functions that implement basic built-in algorithms. The main reason to look at the CImg library is because it is more granular, for example the CImg C++ function "FFT" is polymorphic:
:::c++
static void FFT(CImg<T>& real, CImg<T>& imag, const char axis, const bool is_invert=false)
static void FFT(CImg<T>& real, CImg<T>& imag, const bool is_invert=false)
CImgList<T>& FFT(const bool invert=false)
So it can operate in a single dimension whereas G'MIC's -fft / -ifft and the derivatives will act on a 2d or 3d image if supplied.
##Extending functionality Example Canny Edge Detection : http://en.wikipedia.org/wiki/Canny_edge_detector
The algorithm requires hysteresis, this is more efficient if implemented within the scan at a per-pixel level than calculated for the whole image with multiple passes as would be necessary in G'MIC.
:::perl
$ ./gmic priyanka-chopra.jpg -norm -gradient -b 1.5 -complex2polar -f[1] "int(4*i/pi+0.5)%4" --neq[1] 0 -f[1] "(i==0)+(i==1)-(i==3)" -a[1,2] c --warp[0] [1],1 -*[1] -1 --warp[0] [1],1 -rm[1] -max[1,2] -+[1] 0.4 -le[0,1]
This command line computes the oriented local maxima according to neighbouring pixels with a simple threshold and without hysteresis .. the true Canny algorithm applies a similar test per pixel but up-rates any pixel to the edge if any of it's neighbours are edges, this assists extending continuous lines while suppressing noise.
TO DO: CImg& img CImgList grad(2,_width,_height,1,1); // hardcode 2d grayscale Tfloat dx,dy,ptrd0 = grad[0]._data, ptrd1 = grad[1]._data; 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,0,0,I,Tfloat) { dx = -aIpp - bIpc - aIpn + aInp + bInc + aInn; dy = -aIpp - bIcp - aInp + aIpn + bIcn + aInn (ptrd0++) = sqrt(dxdx+dydy); *(ptrd1++) = int(atan2(dz,dy)/pi); }