1.1 diff -r 5edfbd3e7a46 -r 1204ebf9340d PTdecode/CImg-1.3.0/plugins/greycstoration.h 1.2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 +++ b/PTdecode/CImg-1.3.0/plugins/greycstoration.h Mon Aug 03 14:09:20 2009 +0100 1.4 @@ -0,0 +1,481 @@ 1.5 +/* 1.6 + # 1.7 + # File : greycstoration.h 1.8 + # ( C++ header file - CImg plug-in ) 1.9 + # 1.10 + # Description : GREYCstoration plug-in allowing easy integration in 1.11 + # third parties softwares. 1.12 + # ( http://www.greyc.ensicaen.fr/~dtschump/greycstoration/ ) 1.13 + # This file is a part of the CImg Library project. 1.14 + # ( http://cimg.sourceforge.net ) 1.15 + # 1.16 + # THIS PLUG-IN IS INTENDED FOR DEVELOPERS ONLY. IT EASES THE INTEGRATION ALGORITHM IN 1.17 + # THIRD PARTIES SOFTWARES. IF YOU ARE A USER OF GREYCSTORATION, PLEASE LOOK 1.18 + # AT THE FILE 'greycstoration.cpp' WHICH IS THE SOURCE OF THE COMPLETE 1.19 + # COMMAND LINE GREYCSTORATION TOOL. 1.20 + # 1.21 + # Copyright : David Tschumperle 1.22 + # ( http://www.greyc.ensicaen.fr/~dtschump/ ) 1.23 + # 1.24 + # License : CeCILL v2.0 1.25 + # ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html ) 1.26 + # 1.27 + # This software is governed by the CeCILL license under French law and 1.28 + # abiding by the rules of distribution of free software. You can use, 1.29 + # modify and/ or redistribute the software under the terms of the CeCILL 1.30 + # license as circulated by CEA, CNRS and INRIA at the following URL 1.31 + # "http://www.cecill.info". 1.32 + # 1.33 + # As a counterpart to the access to the source code and rights to copy, 1.34 + # modify and redistribute granted by the license, users are provided only 1.35 + # with a limited warranty and the software's author, the holder of the 1.36 + # economic rights, and the successive licensors have only limited 1.37 + # liability. 1.38 + # 1.39 + # In this respect, the user's attention is drawn to the risks associated 1.40 + # with loading, using, modifying and/or developing or reproducing the 1.41 + # software by the user in light of its specific status of free software, 1.42 + # that may mean that it is complicated to manipulate, and that also 1.43 + # therefore means that it is reserved for developers and experienced 1.44 + # professionals having in-depth computer knowledge. Users are therefore 1.45 + # encouraged to load and test the software's suitability as regards their 1.46 + # requirements in conditions enabling the security of their systems and/or 1.47 + # data to be ensured and, more generally, to use and operate it in the 1.48 + # same conditions as regards security. 1.49 + # 1.50 + # The fact that you are presently reading this means that you have had 1.51 + # knowledge of the CeCILL license and that you accept its terms. 1.52 + # 1.53 +*/ 1.54 + 1.55 +#ifndef cimg_plugin_greycstoration 1.56 +#define cimg_plugin_greycstoration 1.57 + 1.58 +//------------------------------------------------------------------------------ 1.59 +// GREYCstoration parameter structure, storing important informations about 1.60 +// algorithm parameters and computing threads. 1.61 +// ** This structure has not to be manipulated by the API user, so please just 1.62 +// ignore it if you want to ** 1.63 +//------------------------------------------------------------------------------- 1.64 +struct _greycstoration_params { 1.65 + 1.66 + // Tell if the patch-based algorithm is selected 1.67 + bool patch_based; 1.68 + 1.69 + // Parameters specific to the non-patch regularization algorithm 1.70 + float amplitude; 1.71 + float sharpness; 1.72 + float anisotropy; 1.73 + float alpha; 1.74 + float sigma; 1.75 + float gfact; 1.76 + float dl; 1.77 + float da; 1.78 + float gauss_prec; 1.79 + unsigned int interpolation; 1.80 + 1.81 + // Parameters specific to the patch-based regularization algorithm 1.82 + unsigned int patch_size; 1.83 + float sigma_s; 1.84 + float sigma_p; 1.85 + unsigned int lookup_size; 1.86 + 1.87 + // Non-specific parameters of the algorithms. 1.88 + CImg<T> *source; 1.89 + const CImg<unsigned char> *mask; 1.90 + CImg<T> *temporary; 1.91 + unsigned long *counter; 1.92 + unsigned int tile; 1.93 + unsigned int tile_border; 1.94 + unsigned int thread; 1.95 + unsigned int nb_threads; 1.96 + bool fast_approx; 1.97 + bool is_running; 1.98 + bool *stop_request; 1.99 +#if cimg_OS==1 && defined(_PTHREAD_H) 1.100 + pthread_mutex_t 1.101 + *mutex; 1.102 +#elif cimg_OS==2 1.103 + HANDLE mutex; 1.104 +#else 1.105 + void *mutex; 1.106 +#endif 1.107 + 1.108 + // Default constructor 1.109 + _greycstoration_params():patch_based(false),amplitude(0),sharpness(0),anisotropy(0),alpha(0),sigma(0),gfact(1), 1.110 + dl(0),da(0),gauss_prec(0),interpolation(0),patch_size(0), 1.111 + sigma_s(0),sigma_p(0),lookup_size(0),source(0),mask(0),temporary(0),counter(0),tile(0), 1.112 + tile_border(0),thread(0),nb_threads(0),fast_approx(false),is_running(false), stop_request(0), mutex(0) {} 1.113 +}; 1.114 + 1.115 +_greycstoration_params greycstoration_params[16]; 1.116 + 1.117 +//---------------------------------------------------------- 1.118 +// Public functions of the GREYCstoration API. 1.119 +// Use the functions below for integrating GREYCstoration 1.120 +// in your own C++ code. 1.121 +//---------------------------------------------------------- 1.122 + 1.123 +//! Test if GREYCstoration threads are still running. 1.124 +bool greycstoration_is_running() const { 1.125 + return greycstoration_params->is_running; 1.126 +} 1.127 + 1.128 +//! Force the GREYCstoration threads to stop. 1.129 +CImg& greycstoration_stop() { 1.130 + if (greycstoration_is_running()) { 1.131 + *(greycstoration_params->stop_request) = true; 1.132 + while (greycstoration_params->is_running) cimg::wait(50); 1.133 + } 1.134 + return *this; 1.135 +} 1.136 + 1.137 +//! Return the GREYCstoration progress bar indice (between 0 and 100). 1.138 +float greycstoration_progress() const { 1.139 + if (!greycstoration_is_running()) return 0.0f; 1.140 + const unsigned long counter = greycstoration_params->counter?*(greycstoration_params->counter):0; 1.141 + const float 1.142 + da = greycstoration_params->da, 1.143 + factor = greycstoration_params->patch_based?1:(1+360/da); 1.144 + float maxcounter = 0; 1.145 + if (greycstoration_params->tile==0) maxcounter = width*height*depth*factor; 1.146 + else { 1.147 + const unsigned int 1.148 + t = greycstoration_params->tile, 1.149 + b = greycstoration_params->tile_border, 1.150 + n = (1+(width-1)/t)*(1+(height-1)/t)*(1+(depth-1)/t); 1.151 + maxcounter = (width*height*depth + n*4*b*(b + t))*factor; 1.152 + } 1.153 + return cimg::min(counter*99.9f/maxcounter,99.9f); 1.154 +} 1.155 + 1.156 +//! Run the non-patch version of the GREYCstoration algorithm on the instance image, using a mask. 1.157 +CImg& greycstoration_run(const CImg<unsigned char>& mask, 1.158 + const float amplitude=60, const float sharpness=0.7f, const float anisotropy=0.3f, 1.159 + const float alpha=0.6f, const float sigma=1.1f, const float gfact=1.0f, 1.160 + const float dl=0.8f, const float da=30.0f, 1.161 + const float gauss_prec=2.0f, const unsigned int interpolation=0, const bool fast_approx=true, 1.162 + const unsigned int tile=0, const unsigned int tile_border=0, const unsigned int nb_threads=1) { 1.163 + 1.164 + if (greycstoration_is_running()) 1.165 + throw CImgInstanceException("CImg<T>::greycstoration_run() : A GREYCstoration thread is already running on" 1.166 + " the instance image (%u,%u,%u,%u,%p).",width,height,depth,dim,data); 1.167 + 1.168 + else { 1.169 + if (!mask.is_empty() && !mask.is_sameXY(*this)) 1.170 + throw CImgArgumentException("CImg<%s>::greycstoration_run() : Given mask (%u,%u,%u,%u,%p) and instance image " 1.171 + "(%u,%u,%u,%u,%p) have different dimensions.", 1.172 + pixel_type(),mask.width,mask.height,mask.depth,mask.dim,mask.data,width,height,depth,dim,data); 1.173 + if (nb_threads>16) cimg::warn("CImg<%s>::greycstoration_run() : Multi-threading mode limited to 16 threads max."); 1.174 + const unsigned int 1.175 + ntile = (tile && (tile<width || tile<height || (depth>1 && tile<depth)))?tile:0, 1.176 +#if cimg_OS==1 && !defined(_PTHREAD_H) 1.177 + nthreads = 0; 1.178 +#else 1.179 + nthreads = ntile?cimg::min(nb_threads,16U):cimg::min(nb_threads,1U); 1.180 +#endif 1.181 + 1.182 + CImg<T> *const temporary = ntile?new CImg<T>(*this):0; 1.183 + unsigned long *const counter = new unsigned long; 1.184 + *counter = 0; 1.185 + bool *const stop_request = new bool; 1.186 + *stop_request = false; 1.187 + 1.188 + for (unsigned int k=0; k<(nthreads?nthreads:1); k++) { 1.189 + greycstoration_params[k].patch_based = false; 1.190 + greycstoration_params[k].amplitude = amplitude; 1.191 + greycstoration_params[k].sharpness = sharpness; 1.192 + greycstoration_params[k].anisotropy = anisotropy; 1.193 + greycstoration_params[k].alpha = alpha; 1.194 + greycstoration_params[k].sigma = sigma; 1.195 + greycstoration_params[k].gfact = gfact; 1.196 + greycstoration_params[k].dl = dl; 1.197 + greycstoration_params[k].da = da; 1.198 + greycstoration_params[k].gauss_prec = gauss_prec; 1.199 + greycstoration_params[k].interpolation = interpolation; 1.200 + greycstoration_params[k].fast_approx = fast_approx; 1.201 + greycstoration_params[k].source = this; 1.202 + greycstoration_params[k].mask = &mask; 1.203 + greycstoration_params[k].temporary = temporary; 1.204 + greycstoration_params[k].counter = counter; 1.205 + greycstoration_params[k].tile = ntile; 1.206 + greycstoration_params[k].tile_border = tile_border; 1.207 + greycstoration_params[k].thread = k; 1.208 + greycstoration_params[k].nb_threads = nthreads; 1.209 + greycstoration_params[k].is_running = true; 1.210 + greycstoration_params[k].stop_request = stop_request; 1.211 + if (k) greycstoration_params[k].mutex = greycstoration_params[0].mutex; 1.212 + else greycstoration_mutex_create(greycstoration_params[0]); 1.213 + } 1.214 + if (nthreads) { // Threaded version 1.215 +#if cimg_OS==1 1.216 +#ifdef _PTHREAD_H 1.217 + pthread_attr_t attr; 1.218 + pthread_attr_init(&attr); 1.219 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 1.220 + for (unsigned int k=0; k<greycstoration_params->nb_threads; k++) { 1.221 + pthread_t thread; 1.222 + const int err = pthread_create(&thread, &attr, greycstoration_thread, (void*)(greycstoration_params+k)); 1.223 + if (err) throw CImgException("CImg<%s>::greycstoration_run() : pthread_create returned error %d", 1.224 + pixel_type(), err); 1.225 + } 1.226 +#endif 1.227 +#elif cimg_OS==2 1.228 + for (unsigned int k=0; k<greycstoration_params->nb_threads; k++) { 1.229 + unsigned long ThreadID = 0; 1.230 + CreateThread(0,0,greycstoration_thread,(void*)(greycstoration_params+k),0,&ThreadID); 1.231 + } 1.232 +#else 1.233 + throw CImgInstanceException("CImg<T>::greycstoration_run() : Threads are not supported, please define cimg_OS first."); 1.234 +#endif 1.235 + } else greycstoration_thread((void*)greycstoration_params); // Non-threaded version 1.236 + } 1.237 + return *this; 1.238 +} 1.239 + 1.240 +//! Run the non-patch version of the GREYCstoration algorithm on the instance image. 1.241 +CImg& greycstoration_run(const float amplitude=50, const float sharpness=0.7f, const float anisotropy=0.3f, 1.242 + const float alpha=0.6f, const float sigma=1.1f, const float gfact=1.0f, 1.243 + const float dl=0.8f, const float da=30.0f, 1.244 + const float gauss_prec=2.0f, const unsigned int interpolation=0, const bool fast_approx=true, 1.245 + const unsigned int tile=0, const unsigned int tile_border=0, const unsigned int nb_threads=1) { 1.246 + static const CImg<unsigned char> empty_mask; 1.247 + return greycstoration_run(empty_mask,amplitude,sharpness,anisotropy,alpha,sigma,gfact,dl,da,gauss_prec, 1.248 + interpolation,fast_approx,tile,tile_border,nb_threads); 1.249 +} 1.250 + 1.251 +//! Run the patch-based version of the GREYCstoration algorithm on the instance image. 1.252 +CImg& greycstoration_patch_run(const unsigned int patch_size=5, const float sigma_p=10, const float sigma_s=100, 1.253 + const unsigned int lookup_size=20, const bool fast_approx=true, 1.254 + const unsigned int tile=0, const unsigned int tile_border=0, const unsigned int nb_threads=1) { 1.255 + 1.256 + static const CImg<unsigned char> empty_mask; 1.257 + if (greycstoration_is_running()) 1.258 + throw CImgInstanceException("CImg<T>::greycstoration_run() : A GREYCstoration thread is already running on" 1.259 + " the instance image (%u,%u,%u,%u,%p).",width,height,depth,dim,data); 1.260 + 1.261 + else { 1.262 + if (nb_threads>16) cimg::warn("CImg<%s>::greycstoration_run() : Multi-threading mode limited to 16 threads max."); 1.263 + const unsigned int 1.264 + ntile = (tile && (tile<width || tile<height || (depth>1 && tile<depth)))?tile:0, 1.265 +#if cimg_OS==1 && !defined(_PTHREAD_H) 1.266 + nthreads = 0; 1.267 +#else 1.268 + nthreads = ntile?cimg::min(nb_threads,16U):cimg::min(nb_threads,1U); 1.269 +#endif 1.270 + 1.271 + CImg<T> *const temporary = ntile?new CImg<T>(*this):0; 1.272 + unsigned long *const counter = new unsigned long; 1.273 + *counter = 0; 1.274 + bool *const stop_request = new bool; 1.275 + *stop_request = false; 1.276 + 1.277 + for (unsigned int k=0; k<(nthreads?nthreads:1); k++) { 1.278 + greycstoration_params[k].patch_based = true; 1.279 + greycstoration_params[k].patch_size = patch_size; 1.280 + greycstoration_params[k].sigma_s = sigma_s; 1.281 + greycstoration_params[k].sigma_p = sigma_p; 1.282 + greycstoration_params[k].lookup_size = lookup_size; 1.283 + greycstoration_params[k].source = this; 1.284 + greycstoration_params[k].mask = &empty_mask; 1.285 + greycstoration_params[k].temporary = temporary; 1.286 + greycstoration_params[k].counter = counter; 1.287 + greycstoration_params[k].tile = ntile; 1.288 + greycstoration_params[k].tile_border = tile_border; 1.289 + greycstoration_params[k].thread = k; 1.290 + greycstoration_params[k].nb_threads = nthreads; 1.291 + greycstoration_params[k].fast_approx = fast_approx; 1.292 + greycstoration_params[k].is_running = true; 1.293 + greycstoration_params[k].stop_request = stop_request; 1.294 + if (k) greycstoration_params[k].mutex = greycstoration_params[0].mutex; 1.295 + else greycstoration_mutex_create(greycstoration_params[0]); 1.296 + } 1.297 + if (nthreads) { // Threaded version 1.298 +#if cimg_OS==1 1.299 +#ifdef _PTHREAD_H 1.300 + pthread_attr_t attr; 1.301 + pthread_attr_init(&attr); 1.302 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 1.303 + for (unsigned int k=0; k<greycstoration_params->nb_threads; k++) { 1.304 + pthread_t thread; 1.305 + const int err = pthread_create(&thread, &attr, greycstoration_thread, (void*)(greycstoration_params+k)); 1.306 + if (err) throw CImgException("CImg<%s>::greycstoration_run() : pthread_create returned error %d", 1.307 + pixel_type(), err); 1.308 + } 1.309 +#endif 1.310 +#elif cimg_OS==2 1.311 + for (unsigned int k=0; k<greycstoration_params->nb_threads; k++) { 1.312 + unsigned long ThreadID = 0; 1.313 + CreateThread(0,0,greycstoration_thread,(void*)(greycstoration_params+k),0,&ThreadID); 1.314 + } 1.315 +#else 1.316 + throw CImgInstanceException("CImg<T>::greycstoration_run() : Threads support have not been enabled in this version of GREYCstoration."); 1.317 +#endif 1.318 + } else greycstoration_thread((void*)greycstoration_params); // Non-threaded version 1.319 + } 1.320 + return *this; 1.321 +} 1.322 + 1.323 +//------------------------------------------------------------------------------ 1.324 +// GREYCstoration private functions. 1.325 +// Should not be used directly by the API user. 1.326 +//------------------------------------------------------------------------------- 1.327 + 1.328 +static void greycstoration_mutex_create(_greycstoration_params &p) { 1.329 + if (p.nb_threads>1) { 1.330 +#if cimg_OS==1 && defined(_PTHREAD_H) 1.331 + p.mutex = new pthread_mutex_t; 1.332 + pthread_mutex_init(p.mutex,0); 1.333 +#elif cimg_OS==2 1.334 + p.mutex = CreateMutex(0,FALSE,0); 1.335 +#endif 1.336 + } 1.337 +} 1.338 + 1.339 +static void greycstoration_mutex_lock(_greycstoration_params &p) { 1.340 + if (p.nb_threads>1) { 1.341 +#if cimg_OS==1 && defined(_PTHREAD_H) 1.342 + if (p.mutex) pthread_mutex_lock(p.mutex); 1.343 +#elif cimg_OS==2 1.344 + WaitForSingleObject(p.mutex,INFINITE); 1.345 +#endif 1.346 + } 1.347 +} 1.348 + 1.349 +static void greycstoration_mutex_unlock(_greycstoration_params &p) { 1.350 + if (p.nb_threads>1) { 1.351 +#if cimg_OS==1 && defined(_PTHREAD_H) 1.352 + if (p.mutex) pthread_mutex_unlock(p.mutex); 1.353 +#elif cimg_OS==2 1.354 + ReleaseMutex(p.mutex); 1.355 +#endif 1.356 + } 1.357 +} 1.358 + 1.359 +static void greycstoration_mutex_destroy(_greycstoration_params &p) { 1.360 + if (p.nb_threads>1) { 1.361 +#if cimg_OS==1 && defined(_PTHREAD_H) 1.362 + if (p.mutex) pthread_mutex_destroy(p.mutex); 1.363 +#elif cimg_OS==2 1.364 + CloseHandle(p.mutex); 1.365 +#endif 1.366 + p.mutex = 0; 1.367 + } 1.368 +} 1.369 + 1.370 +#if cimg_OS==1 1.371 +static void* greycstoration_thread(void *arg) { 1.372 +#elif cimg_OS==2 1.373 + static DWORD WINAPI greycstoration_thread(void *arg) { 1.374 +#endif 1.375 + _greycstoration_params &p = *(_greycstoration_params*)arg; 1.376 + greycstoration_mutex_lock(p); 1.377 + const CImg<unsigned char> &mask = *(p.mask); 1.378 + CImg<T> &source = *(p.source); 1.379 + 1.380 + if (!p.tile) { 1.381 + 1.382 + // Non-tiled version 1.383 + //------------------ 1.384 + if (p.patch_based) source.blur_patch(p.patch_size,p.sigma_p,p.sigma_s,p.lookup_size,p.fast_approx); 1.385 + else source.blur_anisotropic(mask,p.amplitude,p.sharpness,p.anisotropy,p.alpha,p.sigma,p.dl,p.da,p.gauss_prec, 1.386 + p.interpolation,p.fast_approx,p.gfact); 1.387 + 1.388 + } else { 1.389 + 1.390 + // Tiled version 1.391 + //--------------- 1.392 + CImg<T> &temporary = *(p.temporary); 1.393 + const bool threed = (source.depth>1); 1.394 + const unsigned int b = p.tile_border; 1.395 + unsigned int ctile = 0; 1.396 + if (threed) { 1.397 + for (unsigned int z=0; z<source.depth && !*(p.stop_request); z+=p.tile) 1.398 + for (unsigned int y=0; y<source.height && !*(p.stop_request); y+=p.tile) 1.399 + for (unsigned int x=0; x<source.width && !*(p.stop_request); x+=p.tile) 1.400 + if (!p.nb_threads || ((ctile++)%p.nb_threads)==p.thread) { 1.401 + const unsigned int 1.402 + x1 = x+p.tile-1, 1.403 + y1 = y+p.tile-1, 1.404 + z1 = z+p.tile-1, 1.405 + xe = x1<source.width?x1:source.width-1, 1.406 + ye = y1<source.height?y1:source.height-1, 1.407 + ze = z1<source.depth?z1:source.depth-1; 1.408 + CImg<T> img = source.get_crop(x-b,y-b,z-b,xe+b,ye+b,ze+b,true); 1.409 + CImg<unsigned char> mask_tile = mask.is_empty()?mask:mask.get_crop(x-b,y-b,z-b,xe+b,ye+b,ze+b,true); 1.410 + img.greycstoration_params[0] = p; 1.411 + greycstoration_mutex_unlock(p); 1.412 + if (p.patch_based) img.blur_patch(p.patch_size,p.sigma_p,p.sigma_s,p.lookup_size,p.fast_approx); 1.413 + else img.blur_anisotropic(mask_tile,p.amplitude,p.sharpness,p.anisotropy, 1.414 + p.alpha,p.sigma,p.dl,p.da,p.gauss_prec,p.interpolation,p.fast_approx,p.gfact); 1.415 + greycstoration_mutex_lock(p); 1.416 + temporary.draw_image(x,y,z,img.crop(b,b,b,img.width-b,img.height-b,img.depth-b)); 1.417 + } 1.418 + } else { 1.419 + for (unsigned int y=0; y<source.height && !*(p.stop_request); y+=p.tile) 1.420 + for (unsigned int x=0; x<source.width && !*(p.stop_request); x+=p.tile) 1.421 + if (!p.nb_threads || ((ctile++)%p.nb_threads)==p.thread) { 1.422 + const unsigned int 1.423 + x1 = x+p.tile-1, 1.424 + y1 = y+p.tile-1, 1.425 + xe = x1<source.width?x1:source.width-1, 1.426 + ye = y1<source.height?y1:source.height-1; 1.427 + CImg<T> img = source.get_crop(x-b,y-b,xe+b,ye+b,true); 1.428 + CImg<unsigned char> mask_tile = mask.is_empty()?mask:mask.get_crop(x-b,y-b,xe+b,ye+b,true); 1.429 + img.greycstoration_params[0] = p; 1.430 + greycstoration_mutex_unlock(p); 1.431 + if (p.patch_based) img.blur_patch(p.patch_size,p.sigma_p,p.sigma_s,p.lookup_size,p.fast_approx); 1.432 + else img.blur_anisotropic(mask_tile,p.amplitude,p.sharpness,p.anisotropy, 1.433 + p.alpha,p.sigma,p.dl,p.da,p.gauss_prec,p.interpolation,p.fast_approx,p.gfact); 1.434 + temporary.draw_image(x,y,img.crop(b,b,img.width-b,img.height-b)); 1.435 + greycstoration_mutex_lock(p); 1.436 + } 1.437 + } 1.438 + } 1.439 + greycstoration_mutex_unlock(p); 1.440 + 1.441 + if (!p.thread) { 1.442 + if (p.nb_threads>1) { 1.443 + bool stopflag = true; 1.444 + do { 1.445 + stopflag = true; 1.446 + for (unsigned int k=1; k<p.nb_threads; k++) if (source.greycstoration_params[k].is_running) stopflag = false; 1.447 + if (!stopflag) cimg::wait(50); 1.448 + } while (!stopflag); 1.449 + } 1.450 + if (p.counter) delete p.counter; 1.451 + if (p.temporary) { source = *(p.temporary); delete p.temporary; } 1.452 + if (p.stop_request) delete p.stop_request; 1.453 + p.mask = 0; 1.454 + p.amplitude = p.sharpness = p.anisotropy = p.alpha = p.sigma = p.gfact = p.dl = p.da = p.gauss_prec = p.sigma_s = p.sigma_p = 0; 1.455 + p.patch_size = p.interpolation = p.lookup_size = 0; 1.456 + p.fast_approx = false; 1.457 + p.source = 0; 1.458 + p.temporary = 0; 1.459 + p.counter = 0; 1.460 + p.tile = p.tile_border = p.thread = p.nb_threads = 0; 1.461 + p.stop_request = false; 1.462 + greycstoration_mutex_destroy(p); 1.463 + } 1.464 + p.is_running = false; 1.465 + 1.466 + if (p.nb_threads) { 1.467 +#if cimg_OS==1 && defined(_PTHREAD_H) 1.468 + pthread_exit(arg); 1.469 + return arg; 1.470 +#elif cimg_OS==2 1.471 + ExitThread(0); 1.472 +#endif 1.473 + } 1.474 + return 0; 1.475 + } 1.476 + 1.477 + 1.478 +#define cimg_plugin_greycstoration_count \ 1.479 + if (!*(greycstoration_params->stop_request)) ++(*greycstoration_params->counter); else return *this; 1.480 +#define cimg_plugin_greycstoration_lock \ 1.481 + greycstoration_mutex_lock(greycstoration_params[0]); 1.482 +#define cimg_plugin_greycstoration_unlock \ 1.483 + greycstoration_mutex_unlock(greycstoration_params[0]); 1.484 + 1.485 +#endif