Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > by-pkgid > f727cbde223ed2ba3ee196e8a83ff9fc > files > 1

CImg-1.2.2.1-2mdv2008.0.src.rpm

--- CImg-1.2.2.1/examples/greycstoration4gimp.cpp.252	2007-07-11 10:29:24.000000000 +0200
+++ CImg-1.2.2.1/examples/greycstoration4gimp.cpp	2007-07-25 19:18:29.000000000 +0200
@@ -10,13 +10,13 @@
 
     "Fast Anisotropic Smoothing of Multi-Valued Images
     using Curvature-Preserving PDE's"
-    (D. Tschumperle)
+    (D. Tschumperlé)
     International Journal of Computer Vision, May 2006.
     (see also http://www.greyc.ensicaen.fr/~dtschump/greycstoration)
 
     "Vector-Valued Image Regularization with PDE's : A Common Framework
     for Different Applications"
-    (D. Tschumperle, R. Deriche).
+    (D. Tschumperlé, R. Deriche).
     IEEE Transactions on Pattern Analysis and Machine Intelligence,
     Vol 27, No 4, pp 506-517, April 2005.
 
@@ -74,12 +74,15 @@
 
 /* Include the CImg Library, with the GREYCstoration plugin included */
 #define cimg_plugin "plugins/greycstoration.h"
+#if defined(sun)         || defined(__sun)      || defined(linux)       || defined(__linux) \
+ || defined(__linux__)   || defined(__CYGWIN__) || defined(BSD)         || defined(__FreeBSD__) \
+ || defined(__OPENBSD__) || defined(__MACOSX__) || defined(__APPLE__)   || defined(sgi) \
+ || defined(__sgi)
+#include <pthread.h>
+#endif
 #define cimg_display_type 0
 #include "CImg.h"
 using namespace cimg_library;
-#if cimg_OS!=2
-#include <pthread.h>
-#endif
 
 /* Uncomment the line below if you want to use preview with zoom (GIMP >= 2.3.4) */
 /*#define ZOOMPREVIEW*/
--- CImg-1.2.2.1/examples/greycstoration4integration.cpp.252	2007-07-11 10:29:24.000000000 +0200
+++ CImg-1.2.2.1/examples/greycstoration4integration.cpp	2007-07-25 19:18:29.000000000 +0200
@@ -4,7 +4,7 @@
 
     Description : Example of used of the GREYCstoration_4integration plug-in.
 
-                  (see http://www.greyc.ensicaen.fr/~dtschump/greycstoration/)
+		  (see http://www.greyc.ensicaen.fr/~dtschump/greycstoration/)
 
    THIS VERSION IS FOR DEVELOPERS ONLY. IT SHOWS AN EXAMPLE OF HOW THE
    INTEGRATION OF THE GREYCSTORATION ALGORITHM CAN BE DONE IN
@@ -47,20 +47,16 @@
 
 // Include the CImg Library, with the GREYCstoration plugin included
 #define cimg_plugin "plugins/greycstoration.h"
-#include "../CImg.h"
-using namespace cimg_library;
 #if cimg_OS!=2
 #include <pthread.h>
 #endif
+#include "../CImg.h"
+using namespace cimg_library;
 
-// The lines below is necessary when using a non-standard compiler as visualcpp6.
+// The undef below is necessary when using a non-standard compiler.
 #ifdef cimg_use_visualcpp6
 #define std
 #endif
-#ifdef min
-#undef min
-#undef max
-#endif
 
 // Main procedure
 //----------------
@@ -94,7 +90,7 @@ int main(int argc,char **argv) {
 
     // This function will start a thread running one iteration of the GREYCstoration filter.
     // It returns immediately, so you can do what you want after (update a progress bar for instance).
-    img.greycstoration_run(amplitude,sharpness,anisotropy,alpha,sigma,1.0f,dl,da,gauss_prec,interp,fast_approx,tile,btile);
+    img.greycstoration_run(amplitude,sharpness,anisotropy,alpha,sigma,dl,da,gauss_prec,interp,fast_approx,tile,btile);
 
     // Here, we print the overall progress percentage.
     do {
--- CImg-1.2.2.1/examples/greycstoration.cpp.252	2007-07-11 10:29:24.000000000 +0200
+++ CImg-1.2.2.1/examples/greycstoration.cpp	2007-07-25 19:33:33.000000000 +0200
@@ -9,13 +9,13 @@
 
     "Fast Anisotropic Smoothing of Multi-Valued Images
     using Curvature-Preserving PDE's"
-    (D. Tschumperle)
+    (D. Tschumperlé)
     International Journal of Computer Vision, May 2006.
     (see also http://www.greyc.ensicaen.fr/~dtschump/greycstoration)
 
     "Vector-Valued Image Regularization with PDE's : A Common Framework
     for Different Applications"
-    (D. Tschumperle, R. Deriche).
+    (D. Tschumperlé, R. Deriche).
     IEEE Transactions on Pattern Analysis and Machine Intelligence,
     Vol 27, No 4, pp 506-517, April 2005.
 
@@ -50,24 +50,20 @@
   ------------------------------------------------------------------------------*/
 
 #define greycstoration_version 2.52
-#ifndef cimg_debug
-#define cimg_debug 1
+#if defined(sun)         || defined(__sun)      || defined(linux)       || defined(__linux) \
+ || defined(__linux__)   || defined(__CYGWIN__) || defined(BSD)         || defined(__FreeBSD__) \
+ || defined(__OPENBSD__) || defined(__MACOSX__) || defined(__APPLE__)   || defined(sgi) \
+ || defined(__sgi)
+#include <pthread.h>
 #endif
+#define cimg_debug 1
 #define cimg_plugin "plugins/greycstoration.h"
 #include "../CImg.h"
 using namespace cimg_library;
-#if cimg_OS!=2
-#include <pthread.h>
-#endif
-
-// The lines below are necessary when using a non-standard compiler as visualcpp6.
+// The undef below is necessary when using a non-standard compiler.
 #ifdef cimg_use_visualcpp6
 #define std
 #endif
-#ifdef min
-#undef min
-#undef max
-#endif
 
 //-----------
 // get_geom() : read geometry from a string (for instance '320x256' or '200%x200%').
@@ -154,8 +150,8 @@ template<typename T> void greycstoration
       (restore && resize) ||
       (inpaint && resize)) {
     cimg::dialog(cimg::basename(argv[0]),
-                 "You must specify (only) one of the '-restore', '-inpaint', or '-resize' options.\n"
-                 "(try option '-h', '-h -restore','-h -inpaint' or '-h -resize' to get options relative to specific actions\n");
+		 "You must specify (only) one of the '-restore', '-inpaint', or '-resize' options.\n"
+		 "(try option '-h', '-h -restore','-h -inpaint' or '-h -resize' to get options relative to specific actions\n");
     std::exit(0);
   }
 
@@ -163,7 +159,7 @@ template<typename T> void greycstoration
   //----------------
   CImg<T> img0, img, imgr;
   CImg<unsigned char> mask;
-  CImgDisplay disp;
+  CImgDisplay *disp = 0;
 
   // Specific parameters for image denoising
   //----------------------------------------
@@ -182,7 +178,7 @@ template<typename T> void greycstoration
     img.load(restore);
     const CImgStats stats(img,false);
     std::fprintf(stderr,"\r- Input image : '%s' (size %ux%u, value range [%g,%g])\n",
-                 cimg::basename(restore),img.width,img.height,stats.min,stats.max);
+		 cimg::basename(restore),img.width,img.height,stats.min,stats.max);
     if (ng>0 || nu>0 || ns>0) {
       img0 = img;
       if (ng>0) img.noise(ng,0);
@@ -190,7 +186,7 @@ template<typename T> void greycstoration
       if (ns>0) img.noise(ns,2);
       const CImgStats stats(img,false);
       std::fprintf(stderr,"\r- Noisy image : value range [%g,%g], PSNR Noisy / Original : %g\n",
-                   stats.min,stats.max,img.PSNR(img0));
+		   stats.min,stats.max,img.PSNR(img0));
     }
   }
 
@@ -211,7 +207,7 @@ template<typename T> void greycstoration
     img.load(inpaint);
     const CImgStats stats(img,false);
     std::fprintf(stderr,"\r- Input image : '%s' (size %ux%u, value range [%g,%g])\n",
-                 cimg::basename(inpaint),img.width,img.height,stats.min,stats.max);
+		 cimg::basename(inpaint),img.width,img.height,stats.min,stats.max);
     if (!file_m) {
       cimg::dialog(cimg::basename(argv[0]),"You need to specify a valid inpainting mask filename after the '-m' flag.");
       std::exit(0);
@@ -240,18 +236,18 @@ template<typename T> void greycstoration
       CImg_3x3(M,uchar);
       CImg_3x3(I,T);
       while (CImgStats(ntmask,false).max>0) {
-        cimg_for3x3(tmask,x,y,0,0,M) if (Mcc && (!Mpc || !Mnc || !Mcp || !Mcn)) {
-          const float
+	cimg_for3x3(tmask,x,y,0,0,M) if (Mcc && (!Mpc || !Mnc || !Mcp || !Mcn)) {
+	  const float
             ccp = Mcp?0.0f:1.0f, cpc = Mpc?0.0f:1.0f,
-            cnc = Mnc?0.0f:1.0f, ccn = Mcn?0.0f:1.0f,
+	    cnc = Mnc?0.0f:1.0f, ccn = Mcn?0.0f:1.0f,
             csum = ccp + cpc + cnc + ccn;
-          cimg_forV(img,k) {
-            cimg_get3x3(img,x,y,0,k,I);
-            img(x,y,k) = (T)((ccp*Icp + cpc*Ipc + cnc*Inc + ccn*Icn)/csum);
-          }
-          ntmask(x,y) = 0;
-        }
-        tmask = ntmask;
+	  cimg_forV(img,k) {
+	    cimg_get3x3(img,x,y,0,k,I);
+	    img(x,y,k) = (T)((ccp*Icp + cpc*Ipc + cnc*Inc + ccn*Icn)/csum);
+	  }
+	  ntmask(x,y) = 0;
+	}
+	tmask = ntmask;
       }
     } break;
     }
@@ -279,7 +275,7 @@ template<typename T> void greycstoration
     img.load(resize);
     const CImgStats stats(img,false);
     std::fprintf(stderr,"\r- Input image : '%s' (size %ux%u, value range [%g,%g])\n",
-                 cimg::basename(resize),img.width,img.height,stats.min,stats.max);
+		 cimg::basename(resize),img.width,img.height,stats.min,stats.max);
     int w,h;
     if (geom0) {
       int w0,h0;
@@ -287,7 +283,7 @@ template<typename T> void greycstoration
       w0 = w0>0?w0:-w0*img.dimx()/100;
       h0 = h0>0?h0:-h0*img.dimy()/100;
       std::fprintf(stderr,"- Reducing geometry to %dx%d using %s interpolation.\n",w0,h0,
-                   init==1?"bloc":(init==3?"linear":"bicubic"));
+		   init==1?"bloc":(init==3?"linear":"bicubic"));
       img0.assign(img);
       w = img.dimx();
       h = img.dimy();
@@ -301,7 +297,7 @@ template<typename T> void greycstoration
     mask.assign(img.dimx(),img.dimy(),1,1,255);
     if (!anchor) mask.resize(w,h,1,1,1); else mask = !mask.resize(w,h,1,1,4);
     img.resize(w,h,1,-100,init);
-    if (img0) std::fprintf(stderr,"\r- PSNR Original / Thumbnail : %g\n",img.PSNR(img0));
+    if (!img0.is_empty()) std::fprintf(stderr,"\r- PSNR Original / Thumbnail : %g\n",img.PSNR(img0));
   }
 
   // Load reference image if any mentioned
@@ -311,8 +307,8 @@ template<typename T> void greycstoration
     imgr.load(refer);
     const CImgStats stats(imgr,false);
     std::fprintf(stderr,"\r- Reference image : '%s' (size %ux%u, value range [%g,%g])",
-                 cimg::basename(refer),imgr.width,imgr.height,stats.min,stats.max);
-    if (img0) {
+		 cimg::basename(refer),imgr.width,imgr.height,stats.min,stats.max);
+    if (!img0.is_empty()) {
       imgr.resize(img0);
       std::fprintf(stderr,", PSNR Reference / Original : %g dB\n",imgr.PSNR(img0));
     } else {
@@ -330,8 +326,8 @@ template<typename T> void greycstoration
     int nwidth=dest.dimx(), nheight=dest.dimy();
     if (nwidth>sx) { nheight = nheight*sx/nwidth; nwidth = sx; }
     if (nheight>sy) { nwidth = nwidth*sy/nheight; nheight = sy; }
-    disp.assign(img.get_resize(nwidth,nheight),"GREYCstoration");
-    dest.display(disp);
+    disp = new CImgDisplay(img.get_resize(nwidth,nheight),"GREYCstoration");
+    dest.display(*disp);
   }
   const float gfact = (sizeof(T)==2)?1.0f/256:1.0f;
 
@@ -352,9 +348,9 @@ template<typename T> void greycstoration
       const unsigned int progress = (unsigned int)dest.greycstoration_progress();
       std::fprintf(stderr,"\r- Processing : Iteration %u/%u (%u%%)\t\t",1+iter,nb_iter,progress);
       if (disp) {
-        if (disp.is_resized) disp.resize();
-        disp.set_title("Processing : Iteration %u/%u (%u%%)",1+iter,nb_iter,progress);
-        if (disp.is_closed || disp.key==cimg::keyQ || disp.key==cimg::keyESC) {
+        if (disp->is_resized) disp->resize();
+        disp->set_title("Processing : Iteration %u/%u (%u%%)",1+iter,nb_iter,progress);
+        if (disp->is_closed || disp->key==cimg::keyQ || disp->key==cimg::keyESC) {
           dest.greycstoration_stop();
           stop_iteration = true;
           iter = nb_iter-1;
@@ -367,86 +363,87 @@ template<typename T> void greycstoration
 
     // Prepare for next iteration
     //---------------------------
-    if (disp && visu) dest.display(disp);
+    if (disp && visu) dest.display(*disp);
     if (file_o && save && !(iter%save)) dest.save(file_o,iter);
 
     // Display result and allows user interaction if needed.
     //-------------------------------------------------------
     if (iter==nb_iter-1) {
       std::fprintf(stderr,"\r- Processing : Done !                          \n");
-      if (img0) std::fprintf(stderr,"- PSNR Restored / Original : %g dB\n",dest.PSNR(img0));
+      if (!img0.is_empty()) std::fprintf(stderr,"- PSNR Restored / Original : %g dB\n",dest.PSNR(img0));
       if (disp) {
-        static bool first_time = true;
-        if (first_time) {
-          first_time = false;
-          std::fprintf(stderr,
-                       "- GREYCstoration interface :\n"
-                       " > You can now zoom to a particular rectangular region,\n"
+	static bool first_time = true;
+	if (first_time) {
+	  first_time = false;
+	  std::fprintf(stderr,
+		       "- GREYCstoration interface :\n"
+		       " > You can now zoom to a particular rectangular region,\n"
                        "   or press one of the following key on the display window :\n"
-                       "   SPACE : Swap views.\n"
-                       "   S     : Save a snapshot of the current image.\n"
-                       "   I     : Run another iteration.\n"
-                       "   Q     : Quit GREYCstoration.\n");
-        }
-
-        CImgList<T> visu;
-        visu.insert_shared(img0).insert_shared(img).insert_shared(dest).insert_shared(imgr);
-        const char *titles[4] = { "original", "noisy", "restored", "reference"};
-        unsigned int visupos = 2;
-        CImgDisplay dispz;
-        CImg<T> zoom;
-        int s[6], snb=0;
-        bool stop_interact = false;
-        while (!stop_interact) {
-          disp.show().set_title("GREYCstoration (%s)",titles[visupos]);
-          visu(visupos).feature_selection(s,2,disp);
-          if (disp.is_closed) stop_interact = true;
-          switch (disp.key) {
-          case cimg::keySPACE: do { visupos = (visupos+1)%visu.size; } while (!visu(visupos)); break;
-          case cimg::keyBACKSPACE: do { visupos = (visupos-1+visu.size)%visu.size; } while (!visu(visupos)); break;
-          case cimg::keyQ: stop_interact = stop_all = true; break;
-          case cimg::keyI:
-            stop_interact = true;
-            std::fprintf(stderr,"- Perform iteration %u...\n",++nb_iter);
-            dest.display(disp);
-            break;
-          case cimg::keyS:
-            if (!snb) {
+		       "   SPACE : Swap views.\n"
+		       "   S     : Save a snapshot of the current image.\n"
+		       "   I     : Run another iteration.\n"
+		       "   Q     : Quit GREYCstoration.\n");
+	}
+
+	CImgList<T> visu;
+	visu.insert_shared(img0).insert_shared(img).insert_shared(dest).insert_shared(imgr);
+	const char *titles[4] = { "original", "noisy", "restored", "reference"};
+	unsigned int visupos = 2;
+	CImgDisplay *dispz = 0;
+	CImg<T> zoom;
+	int s[6], snb=0;
+	bool stop_interact = false;
+	while (!stop_interact) {
+          disp->show().set_title("GREYCstoration (%s)",titles[visupos]);
+	  visu(visupos).feature_selection(s,2,*disp);
+          if (disp->is_closed) stop_interact = true;
+	  switch (disp->key) {
+	  case cimg::keySPACE: do { visupos = (visupos+1)%visu.size; } while (visu(visupos).is_empty()); break;
+	  case cimg::keyBACKSPACE: do { visupos = (visupos-1+visu.size)%visu.size; } while (visu(visupos).is_empty()); break;
+	  case cimg::keyQ: stop_interact = stop_all = true; break;
+	  case cimg::keyI:
+	    stop_interact = true;
+	    std::fprintf(stderr,"- Perform iteration %u...\n",++nb_iter);
+	    dest.display(*disp);
+	    break;
+	  case cimg::keyS:
+	    if (!snb) {
               if (!append_result) dest.save(file_o?file_o:"GREYCstoration.bmp");
               else CImgList<T>(img,dest).get_append('x').save(file_o?file_o:"GREYCstoration.bmp");
             }
-            if (zoom) zoom.save(file_o?file_o:"GREYCstoration.bmp",snb);
-            std::fprintf(stderr,"- Snapshot %u : '%s' saved\n",snb++,file_o?file_o:"GREYCstoration.bmp");
-            break;
-          }
-          disp.key = 0;
-          if (disp.is_resized) disp.resize().display(visu(visupos));
-          if (dispz && dispz.is_resized) dispz.resize().display(zoom);
-          if (dispz && dispz.is_closed) dispz.assign();
-
-          if (s[0]>=0 && s[1]>=0 && s[3]>=0 && s[4]>=0) {
-            const int x0 = s[0], y0 = s[1], x1 = s[3], y1 = s[4];
-            if (cimg::abs(x0-x1)>4 && cimg::abs(y0-y1)>4) {
-              CImgList<T> tmp(img.get_crop(x0,y0,x1,y1), dest.get_crop(x0,y0,x1,y1));
-              if (img0) tmp.insert(img0.get_crop(x0,y0,x1,y1),0);
-              if (imgr) tmp.insert(imgr.get_crop(x0,y0,x1,y1));
-              zoom = tmp.get_append('x','c');
-              if (!dispz) {
-                const int sx = 5*CImgDisplay::screen_dimx()/6, sy = 5*CImgDisplay::screen_dimy()/6;
-                int nwidth = zoom.dimx(), nheight = zoom.dimy();
-                if (nwidth>nheight) { nheight = nheight*sx/nwidth; nwidth = sx; }
-                else { nwidth = nwidth*sy/nheight; nheight = sy; }
-                dispz.assign(zoom.get_resize(nwidth,nheight));
-                dispz.set_title("GREYCstoration (zoom) : - %s %s %s %s",
-                                img0?"original -":"",
-                                img?"noisy -":"",
-                                dest?"restored -":"",
-                                imgr?"reference -":"");
-              } else dispz.resize(dispz.dimx(),dispz.dimx()*zoom.dimy()/zoom.dimx(),false);
-              dispz.display(zoom).show();
-            }
-          }
-        }
+	    if (!zoom.is_empty()) zoom.save(file_o?file_o:"GREYCstoration.bmp",snb);
+	    std::fprintf(stderr,"- Snapshot %u : '%s' saved\n",snb++,file_o?file_o:"GREYCstoration.bmp");
+	    break;
+	  }
+	  disp->key = 0;
+	  if (disp->is_resized) disp->resize().display(visu(visupos));
+	  if (dispz && dispz->is_resized) dispz->resize().display(zoom);
+	  if (dispz && dispz->is_closed) { delete dispz; dispz = 0; }
+
+	  if (s[0]>=0 && s[1]>=0 && s[3]>=0 && s[4]>=0) {
+	    const int x0 = s[0], y0 = s[1], x1 = s[3], y1 = s[4];
+	    if (cimg::abs(x0-x1)>4 && cimg::abs(y0-y1)>4) {
+	      CImgList<T> tmp(img.get_crop(x0,y0,x1,y1), dest.get_crop(x0,y0,x1,y1));
+	      if (!img0.is_empty()) tmp.insert(img0.get_crop(x0,y0,x1,y1),0);
+	      if (!imgr.is_empty()) tmp.insert(imgr.get_crop(x0,y0,x1,y1));
+	      zoom = tmp.get_append('x','c');
+	      if (!dispz) {
+		const int sx = 5*CImgDisplay::screen_dimx()/6, sy = 5*CImgDisplay::screen_dimy()/6;
+		int nwidth = zoom.dimx(), nheight = zoom.dimy();
+		if (nwidth>nheight) { nheight = nheight*sx/nwidth; nwidth = sx; }
+		else { nwidth = nwidth*sy/nheight; nheight = sy; }
+		dispz = new CImgDisplay(zoom.get_resize(nwidth,nheight));
+		dispz->set_title("GREYCstoration (zoom) : - %s %s %s %s",
+				 img0.is_empty()?"":"original -",
+				 img.is_empty()?"":"noisy -",
+				 dest.is_empty()?"":"restored -",
+				 imgr.is_empty()?"":"reference -");
+	      } else dispz->resize(dispz->dimx(),dispz->dimx()*zoom.dimy()/zoom.dimx(),false);
+	      dispz->display(zoom).show();
+	    }
+	  }
+	}
+	if (dispz) delete dispz;
       }
     }
   }
@@ -464,6 +461,7 @@ template<typename T> void greycstoration
       else CImgList<T>(img,dest).get_append('x').save(file_o);
     }
   }
+  if (disp) delete disp;
   std::fprintf(stderr,"\n- Quit\n\n");
 }
 
--- CImg-1.2.2.1/plugins/greycstoration.h.252	2007-07-11 10:29:23.000000000 +0200
+++ CImg-1.2.2.1/plugins/greycstoration.h	2007-07-25 19:18:29.000000000 +0200
@@ -44,7 +44,7 @@
 
 #ifndef cimg_plugin_greycstoration
 // This tells you about the version of the GREYCstoration algorithm implemented
-#define cimg_plugin_greycstoration 2.51
+#define cimg_plugin_greycstoration 2.5.1
 
 //------------------------------------------------------------------------------
 // GREYCstoration structure, storing important informations about algorithm
@@ -125,7 +125,7 @@ static void* greycstoration_thread(void 
         for (unsigned int z=0; z<source.depth && !*(p.stop_request); z+=p.tile)
           for (unsigned int y=0; y<source.height && !*(p.stop_request); y+=p.tile)
             for (unsigned int x=0; x<source.width && !*(p.stop_request); x+=p.tile)
-              if (!p.threads || ((ctile++)%p.threads)==p.thread) {
+              if (((ctile++)%p.threads)==p.thread) {
                 const unsigned int
                   x1 = x+p.tile-1,
                   y1 = y+p.tile-1,
@@ -143,7 +143,7 @@ static void* greycstoration_thread(void 
       } else {
         for (unsigned int y=0; y<source.height && !*(p.stop_request); y+=p.tile)
           for (unsigned int x=0; x<source.width && !*(p.stop_request); x+=p.tile)
-            if (!p.threads || ((ctile++)%p.threads)==p.thread) {
+            if (((ctile++)%p.threads)==p.thread) {
               const unsigned int
                 x1 = x+p.tile-1,
                 y1 = y+p.tile-1,
@@ -183,15 +183,13 @@ static void* greycstoration_thread(void 
     }
     p.is_running = false;
 
-    if (p.threads) {
 #if cimg_OS==1
-      pthread_exit(arg);
-      return arg;
+    pthread_exit(arg);
+    return arg;
 #elif cimg_OS==2
-      ExitThread(0);
-#endif
-    }
+    ExitThread(0);
     return 0;
+#endif
   }
 
   //----------------------------------------------------------
@@ -250,7 +248,7 @@ static void* greycstoration_thread(void 
       cimg::warn(threads>16,"CImg<%s>::greycstoration_run() : Multi-threading mode limited to 16 threads max.");
       const unsigned int
         ntile = (tile && (tile<width || tile<height || (depth>1 && tile<depth)))?tile:0,
-        nthreads = ntile?cimg::min(threads,16U):cimg::min(threads,1U);
+        nthreads = ntile?cimg::max(cimg::min(threads,16U),1U):1;
 
       CImg<T> *const temporary = ntile?new CImg<T>(*this):0;
       unsigned long *const counter = new unsigned long;
@@ -258,7 +256,7 @@ static void* greycstoration_thread(void 
       bool *const stop_request = new bool;
       *stop_request = false;
 
-      for (unsigned int k=0; k<(nthreads?nthreads:1); k++) {
+      for (unsigned int k=0; k<nthreads; k++) {
         greycstoration_params[k].mask = &mask;
         greycstoration_params[k].amplitude = amplitude;
         greycstoration_params[k].sharpness = sharpness;
@@ -281,26 +279,24 @@ static void* greycstoration_thread(void 
         greycstoration_params[k].is_running = true;
         greycstoration_params[k].stop_request = stop_request;
       }
-      if (nthreads) {  // Threaded version
 #if cimg_OS==1
-        pthread_attr_t attr;
-        pthread_attr_init(&attr);
-        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-        for (unsigned int k=0; k<greycstoration_params->threads; k++) {
-          pthread_t thread;
-          const int err = pthread_create(&thread, &attr, greycstoration_thread, (void*)(greycstoration_params+k));
-          if (err) throw CImgException("CImg<%s>::greycstoration_run() : pthread_create returned error %d",
-                                       pixel_type(), err);
-        }
+      pthread_attr_t attr;
+      pthread_attr_init(&attr);
+      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+      for (unsigned int k=0; k<greycstoration_params->threads; k++) {
+        pthread_t thread;
+        const int err = pthread_create(&thread, &attr, greycstoration_thread, (void*)(greycstoration_params+k));
+        if (err) throw CImgException("CImg<%s>::greycstoration_run() : pthread_create returned error %d",
+                                     pixel_type(), err);
+      }
 #elif cimg_OS==2
-        for (unsigned int k=0; k<greycstoration_params->threads; k++) {
-          unsigned long ThreadID = 0;
-          CreateThread(0,0,greycstoration_thread,(void*)(greycstoration_params+k),0,&ThreadID);
-        }
+      for (unsigned int k=0; k<greycstoration_params->threads; k++) {
+        unsigned long ThreadID = 0;
+        CreateThread(0,0,greycstoration_thread,(void*)(greycstoration_params+k),0,&ThreadID);
+      }
 #else
-        throw CImgInstanceException("CImg<T>::greycstoration_run() : Threads are not supported, please define cimg_OS first.");
+      throw CImgInstanceException("CImg<T>::greycstoration_run() : Threads are not supported, please define cimg_OS first.");
 #endif
-      } else greycstoration_thread((void*)greycstoration_params); // Non-threaded version
     }
     return *this;
   }