PTdecode/CImg-1.3.0/plugins/greycstoration.h

Thu, 24 Sep 2009 17:18:28 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Thu, 24 Sep 2009 17:18:28 +0100
changeset 19
b7fe751ea60d
parent 5
1204ebf9340d
permissions
-rwxr-xr-x

Added support for separator ticks between labels

philpem@5 1 /*
philpem@5 2 #
philpem@5 3 # File : greycstoration.h
philpem@5 4 # ( C++ header file - CImg plug-in )
philpem@5 5 #
philpem@5 6 # Description : GREYCstoration plug-in allowing easy integration in
philpem@5 7 # third parties softwares.
philpem@5 8 # ( http://www.greyc.ensicaen.fr/~dtschump/greycstoration/ )
philpem@5 9 # This file is a part of the CImg Library project.
philpem@5 10 # ( http://cimg.sourceforge.net )
philpem@5 11 #
philpem@5 12 # THIS PLUG-IN IS INTENDED FOR DEVELOPERS ONLY. IT EASES THE INTEGRATION ALGORITHM IN
philpem@5 13 # THIRD PARTIES SOFTWARES. IF YOU ARE A USER OF GREYCSTORATION, PLEASE LOOK
philpem@5 14 # AT THE FILE 'greycstoration.cpp' WHICH IS THE SOURCE OF THE COMPLETE
philpem@5 15 # COMMAND LINE GREYCSTORATION TOOL.
philpem@5 16 #
philpem@5 17 # Copyright : David Tschumperle
philpem@5 18 # ( http://www.greyc.ensicaen.fr/~dtschump/ )
philpem@5 19 #
philpem@5 20 # License : CeCILL v2.0
philpem@5 21 # ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
philpem@5 22 #
philpem@5 23 # This software is governed by the CeCILL license under French law and
philpem@5 24 # abiding by the rules of distribution of free software. You can use,
philpem@5 25 # modify and/ or redistribute the software under the terms of the CeCILL
philpem@5 26 # license as circulated by CEA, CNRS and INRIA at the following URL
philpem@5 27 # "http://www.cecill.info".
philpem@5 28 #
philpem@5 29 # As a counterpart to the access to the source code and rights to copy,
philpem@5 30 # modify and redistribute granted by the license, users are provided only
philpem@5 31 # with a limited warranty and the software's author, the holder of the
philpem@5 32 # economic rights, and the successive licensors have only limited
philpem@5 33 # liability.
philpem@5 34 #
philpem@5 35 # In this respect, the user's attention is drawn to the risks associated
philpem@5 36 # with loading, using, modifying and/or developing or reproducing the
philpem@5 37 # software by the user in light of its specific status of free software,
philpem@5 38 # that may mean that it is complicated to manipulate, and that also
philpem@5 39 # therefore means that it is reserved for developers and experienced
philpem@5 40 # professionals having in-depth computer knowledge. Users are therefore
philpem@5 41 # encouraged to load and test the software's suitability as regards their
philpem@5 42 # requirements in conditions enabling the security of their systems and/or
philpem@5 43 # data to be ensured and, more generally, to use and operate it in the
philpem@5 44 # same conditions as regards security.
philpem@5 45 #
philpem@5 46 # The fact that you are presently reading this means that you have had
philpem@5 47 # knowledge of the CeCILL license and that you accept its terms.
philpem@5 48 #
philpem@5 49 */
philpem@5 50
philpem@5 51 #ifndef cimg_plugin_greycstoration
philpem@5 52 #define cimg_plugin_greycstoration
philpem@5 53
philpem@5 54 //------------------------------------------------------------------------------
philpem@5 55 // GREYCstoration parameter structure, storing important informations about
philpem@5 56 // algorithm parameters and computing threads.
philpem@5 57 // ** This structure has not to be manipulated by the API user, so please just
philpem@5 58 // ignore it if you want to **
philpem@5 59 //-------------------------------------------------------------------------------
philpem@5 60 struct _greycstoration_params {
philpem@5 61
philpem@5 62 // Tell if the patch-based algorithm is selected
philpem@5 63 bool patch_based;
philpem@5 64
philpem@5 65 // Parameters specific to the non-patch regularization algorithm
philpem@5 66 float amplitude;
philpem@5 67 float sharpness;
philpem@5 68 float anisotropy;
philpem@5 69 float alpha;
philpem@5 70 float sigma;
philpem@5 71 float gfact;
philpem@5 72 float dl;
philpem@5 73 float da;
philpem@5 74 float gauss_prec;
philpem@5 75 unsigned int interpolation;
philpem@5 76
philpem@5 77 // Parameters specific to the patch-based regularization algorithm
philpem@5 78 unsigned int patch_size;
philpem@5 79 float sigma_s;
philpem@5 80 float sigma_p;
philpem@5 81 unsigned int lookup_size;
philpem@5 82
philpem@5 83 // Non-specific parameters of the algorithms.
philpem@5 84 CImg<T> *source;
philpem@5 85 const CImg<unsigned char> *mask;
philpem@5 86 CImg<T> *temporary;
philpem@5 87 unsigned long *counter;
philpem@5 88 unsigned int tile;
philpem@5 89 unsigned int tile_border;
philpem@5 90 unsigned int thread;
philpem@5 91 unsigned int nb_threads;
philpem@5 92 bool fast_approx;
philpem@5 93 bool is_running;
philpem@5 94 bool *stop_request;
philpem@5 95 #if cimg_OS==1 && defined(_PTHREAD_H)
philpem@5 96 pthread_mutex_t
philpem@5 97 *mutex;
philpem@5 98 #elif cimg_OS==2
philpem@5 99 HANDLE mutex;
philpem@5 100 #else
philpem@5 101 void *mutex;
philpem@5 102 #endif
philpem@5 103
philpem@5 104 // Default constructor
philpem@5 105 _greycstoration_params():patch_based(false),amplitude(0),sharpness(0),anisotropy(0),alpha(0),sigma(0),gfact(1),
philpem@5 106 dl(0),da(0),gauss_prec(0),interpolation(0),patch_size(0),
philpem@5 107 sigma_s(0),sigma_p(0),lookup_size(0),source(0),mask(0),temporary(0),counter(0),tile(0),
philpem@5 108 tile_border(0),thread(0),nb_threads(0),fast_approx(false),is_running(false), stop_request(0), mutex(0) {}
philpem@5 109 };
philpem@5 110
philpem@5 111 _greycstoration_params greycstoration_params[16];
philpem@5 112
philpem@5 113 //----------------------------------------------------------
philpem@5 114 // Public functions of the GREYCstoration API.
philpem@5 115 // Use the functions below for integrating GREYCstoration
philpem@5 116 // in your own C++ code.
philpem@5 117 //----------------------------------------------------------
philpem@5 118
philpem@5 119 //! Test if GREYCstoration threads are still running.
philpem@5 120 bool greycstoration_is_running() const {
philpem@5 121 return greycstoration_params->is_running;
philpem@5 122 }
philpem@5 123
philpem@5 124 //! Force the GREYCstoration threads to stop.
philpem@5 125 CImg& greycstoration_stop() {
philpem@5 126 if (greycstoration_is_running()) {
philpem@5 127 *(greycstoration_params->stop_request) = true;
philpem@5 128 while (greycstoration_params->is_running) cimg::wait(50);
philpem@5 129 }
philpem@5 130 return *this;
philpem@5 131 }
philpem@5 132
philpem@5 133 //! Return the GREYCstoration progress bar indice (between 0 and 100).
philpem@5 134 float greycstoration_progress() const {
philpem@5 135 if (!greycstoration_is_running()) return 0.0f;
philpem@5 136 const unsigned long counter = greycstoration_params->counter?*(greycstoration_params->counter):0;
philpem@5 137 const float
philpem@5 138 da = greycstoration_params->da,
philpem@5 139 factor = greycstoration_params->patch_based?1:(1+360/da);
philpem@5 140 float maxcounter = 0;
philpem@5 141 if (greycstoration_params->tile==0) maxcounter = width*height*depth*factor;
philpem@5 142 else {
philpem@5 143 const unsigned int
philpem@5 144 t = greycstoration_params->tile,
philpem@5 145 b = greycstoration_params->tile_border,
philpem@5 146 n = (1+(width-1)/t)*(1+(height-1)/t)*(1+(depth-1)/t);
philpem@5 147 maxcounter = (width*height*depth + n*4*b*(b + t))*factor;
philpem@5 148 }
philpem@5 149 return cimg::min(counter*99.9f/maxcounter,99.9f);
philpem@5 150 }
philpem@5 151
philpem@5 152 //! Run the non-patch version of the GREYCstoration algorithm on the instance image, using a mask.
philpem@5 153 CImg& greycstoration_run(const CImg<unsigned char>& mask,
philpem@5 154 const float amplitude=60, const float sharpness=0.7f, const float anisotropy=0.3f,
philpem@5 155 const float alpha=0.6f, const float sigma=1.1f, const float gfact=1.0f,
philpem@5 156 const float dl=0.8f, const float da=30.0f,
philpem@5 157 const float gauss_prec=2.0f, const unsigned int interpolation=0, const bool fast_approx=true,
philpem@5 158 const unsigned int tile=0, const unsigned int tile_border=0, const unsigned int nb_threads=1) {
philpem@5 159
philpem@5 160 if (greycstoration_is_running())
philpem@5 161 throw CImgInstanceException("CImg<T>::greycstoration_run() : A GREYCstoration thread is already running on"
philpem@5 162 " the instance image (%u,%u,%u,%u,%p).",width,height,depth,dim,data);
philpem@5 163
philpem@5 164 else {
philpem@5 165 if (!mask.is_empty() && !mask.is_sameXY(*this))
philpem@5 166 throw CImgArgumentException("CImg<%s>::greycstoration_run() : Given mask (%u,%u,%u,%u,%p) and instance image "
philpem@5 167 "(%u,%u,%u,%u,%p) have different dimensions.",
philpem@5 168 pixel_type(),mask.width,mask.height,mask.depth,mask.dim,mask.data,width,height,depth,dim,data);
philpem@5 169 if (nb_threads>16) cimg::warn("CImg<%s>::greycstoration_run() : Multi-threading mode limited to 16 threads max.");
philpem@5 170 const unsigned int
philpem@5 171 ntile = (tile && (tile<width || tile<height || (depth>1 && tile<depth)))?tile:0,
philpem@5 172 #if cimg_OS==1 && !defined(_PTHREAD_H)
philpem@5 173 nthreads = 0;
philpem@5 174 #else
philpem@5 175 nthreads = ntile?cimg::min(nb_threads,16U):cimg::min(nb_threads,1U);
philpem@5 176 #endif
philpem@5 177
philpem@5 178 CImg<T> *const temporary = ntile?new CImg<T>(*this):0;
philpem@5 179 unsigned long *const counter = new unsigned long;
philpem@5 180 *counter = 0;
philpem@5 181 bool *const stop_request = new bool;
philpem@5 182 *stop_request = false;
philpem@5 183
philpem@5 184 for (unsigned int k=0; k<(nthreads?nthreads:1); k++) {
philpem@5 185 greycstoration_params[k].patch_based = false;
philpem@5 186 greycstoration_params[k].amplitude = amplitude;
philpem@5 187 greycstoration_params[k].sharpness = sharpness;
philpem@5 188 greycstoration_params[k].anisotropy = anisotropy;
philpem@5 189 greycstoration_params[k].alpha = alpha;
philpem@5 190 greycstoration_params[k].sigma = sigma;
philpem@5 191 greycstoration_params[k].gfact = gfact;
philpem@5 192 greycstoration_params[k].dl = dl;
philpem@5 193 greycstoration_params[k].da = da;
philpem@5 194 greycstoration_params[k].gauss_prec = gauss_prec;
philpem@5 195 greycstoration_params[k].interpolation = interpolation;
philpem@5 196 greycstoration_params[k].fast_approx = fast_approx;
philpem@5 197 greycstoration_params[k].source = this;
philpem@5 198 greycstoration_params[k].mask = &mask;
philpem@5 199 greycstoration_params[k].temporary = temporary;
philpem@5 200 greycstoration_params[k].counter = counter;
philpem@5 201 greycstoration_params[k].tile = ntile;
philpem@5 202 greycstoration_params[k].tile_border = tile_border;
philpem@5 203 greycstoration_params[k].thread = k;
philpem@5 204 greycstoration_params[k].nb_threads = nthreads;
philpem@5 205 greycstoration_params[k].is_running = true;
philpem@5 206 greycstoration_params[k].stop_request = stop_request;
philpem@5 207 if (k) greycstoration_params[k].mutex = greycstoration_params[0].mutex;
philpem@5 208 else greycstoration_mutex_create(greycstoration_params[0]);
philpem@5 209 }
philpem@5 210 if (nthreads) { // Threaded version
philpem@5 211 #if cimg_OS==1
philpem@5 212 #ifdef _PTHREAD_H
philpem@5 213 pthread_attr_t attr;
philpem@5 214 pthread_attr_init(&attr);
philpem@5 215 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
philpem@5 216 for (unsigned int k=0; k<greycstoration_params->nb_threads; k++) {
philpem@5 217 pthread_t thread;
philpem@5 218 const int err = pthread_create(&thread, &attr, greycstoration_thread, (void*)(greycstoration_params+k));
philpem@5 219 if (err) throw CImgException("CImg<%s>::greycstoration_run() : pthread_create returned error %d",
philpem@5 220 pixel_type(), err);
philpem@5 221 }
philpem@5 222 #endif
philpem@5 223 #elif cimg_OS==2
philpem@5 224 for (unsigned int k=0; k<greycstoration_params->nb_threads; k++) {
philpem@5 225 unsigned long ThreadID = 0;
philpem@5 226 CreateThread(0,0,greycstoration_thread,(void*)(greycstoration_params+k),0,&ThreadID);
philpem@5 227 }
philpem@5 228 #else
philpem@5 229 throw CImgInstanceException("CImg<T>::greycstoration_run() : Threads are not supported, please define cimg_OS first.");
philpem@5 230 #endif
philpem@5 231 } else greycstoration_thread((void*)greycstoration_params); // Non-threaded version
philpem@5 232 }
philpem@5 233 return *this;
philpem@5 234 }
philpem@5 235
philpem@5 236 //! Run the non-patch version of the GREYCstoration algorithm on the instance image.
philpem@5 237 CImg& greycstoration_run(const float amplitude=50, const float sharpness=0.7f, const float anisotropy=0.3f,
philpem@5 238 const float alpha=0.6f, const float sigma=1.1f, const float gfact=1.0f,
philpem@5 239 const float dl=0.8f, const float da=30.0f,
philpem@5 240 const float gauss_prec=2.0f, const unsigned int interpolation=0, const bool fast_approx=true,
philpem@5 241 const unsigned int tile=0, const unsigned int tile_border=0, const unsigned int nb_threads=1) {
philpem@5 242 static const CImg<unsigned char> empty_mask;
philpem@5 243 return greycstoration_run(empty_mask,amplitude,sharpness,anisotropy,alpha,sigma,gfact,dl,da,gauss_prec,
philpem@5 244 interpolation,fast_approx,tile,tile_border,nb_threads);
philpem@5 245 }
philpem@5 246
philpem@5 247 //! Run the patch-based version of the GREYCstoration algorithm on the instance image.
philpem@5 248 CImg& greycstoration_patch_run(const unsigned int patch_size=5, const float sigma_p=10, const float sigma_s=100,
philpem@5 249 const unsigned int lookup_size=20, const bool fast_approx=true,
philpem@5 250 const unsigned int tile=0, const unsigned int tile_border=0, const unsigned int nb_threads=1) {
philpem@5 251
philpem@5 252 static const CImg<unsigned char> empty_mask;
philpem@5 253 if (greycstoration_is_running())
philpem@5 254 throw CImgInstanceException("CImg<T>::greycstoration_run() : A GREYCstoration thread is already running on"
philpem@5 255 " the instance image (%u,%u,%u,%u,%p).",width,height,depth,dim,data);
philpem@5 256
philpem@5 257 else {
philpem@5 258 if (nb_threads>16) cimg::warn("CImg<%s>::greycstoration_run() : Multi-threading mode limited to 16 threads max.");
philpem@5 259 const unsigned int
philpem@5 260 ntile = (tile && (tile<width || tile<height || (depth>1 && tile<depth)))?tile:0,
philpem@5 261 #if cimg_OS==1 && !defined(_PTHREAD_H)
philpem@5 262 nthreads = 0;
philpem@5 263 #else
philpem@5 264 nthreads = ntile?cimg::min(nb_threads,16U):cimg::min(nb_threads,1U);
philpem@5 265 #endif
philpem@5 266
philpem@5 267 CImg<T> *const temporary = ntile?new CImg<T>(*this):0;
philpem@5 268 unsigned long *const counter = new unsigned long;
philpem@5 269 *counter = 0;
philpem@5 270 bool *const stop_request = new bool;
philpem@5 271 *stop_request = false;
philpem@5 272
philpem@5 273 for (unsigned int k=0; k<(nthreads?nthreads:1); k++) {
philpem@5 274 greycstoration_params[k].patch_based = true;
philpem@5 275 greycstoration_params[k].patch_size = patch_size;
philpem@5 276 greycstoration_params[k].sigma_s = sigma_s;
philpem@5 277 greycstoration_params[k].sigma_p = sigma_p;
philpem@5 278 greycstoration_params[k].lookup_size = lookup_size;
philpem@5 279 greycstoration_params[k].source = this;
philpem@5 280 greycstoration_params[k].mask = &empty_mask;
philpem@5 281 greycstoration_params[k].temporary = temporary;
philpem@5 282 greycstoration_params[k].counter = counter;
philpem@5 283 greycstoration_params[k].tile = ntile;
philpem@5 284 greycstoration_params[k].tile_border = tile_border;
philpem@5 285 greycstoration_params[k].thread = k;
philpem@5 286 greycstoration_params[k].nb_threads = nthreads;
philpem@5 287 greycstoration_params[k].fast_approx = fast_approx;
philpem@5 288 greycstoration_params[k].is_running = true;
philpem@5 289 greycstoration_params[k].stop_request = stop_request;
philpem@5 290 if (k) greycstoration_params[k].mutex = greycstoration_params[0].mutex;
philpem@5 291 else greycstoration_mutex_create(greycstoration_params[0]);
philpem@5 292 }
philpem@5 293 if (nthreads) { // Threaded version
philpem@5 294 #if cimg_OS==1
philpem@5 295 #ifdef _PTHREAD_H
philpem@5 296 pthread_attr_t attr;
philpem@5 297 pthread_attr_init(&attr);
philpem@5 298 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
philpem@5 299 for (unsigned int k=0; k<greycstoration_params->nb_threads; k++) {
philpem@5 300 pthread_t thread;
philpem@5 301 const int err = pthread_create(&thread, &attr, greycstoration_thread, (void*)(greycstoration_params+k));
philpem@5 302 if (err) throw CImgException("CImg<%s>::greycstoration_run() : pthread_create returned error %d",
philpem@5 303 pixel_type(), err);
philpem@5 304 }
philpem@5 305 #endif
philpem@5 306 #elif cimg_OS==2
philpem@5 307 for (unsigned int k=0; k<greycstoration_params->nb_threads; k++) {
philpem@5 308 unsigned long ThreadID = 0;
philpem@5 309 CreateThread(0,0,greycstoration_thread,(void*)(greycstoration_params+k),0,&ThreadID);
philpem@5 310 }
philpem@5 311 #else
philpem@5 312 throw CImgInstanceException("CImg<T>::greycstoration_run() : Threads support have not been enabled in this version of GREYCstoration.");
philpem@5 313 #endif
philpem@5 314 } else greycstoration_thread((void*)greycstoration_params); // Non-threaded version
philpem@5 315 }
philpem@5 316 return *this;
philpem@5 317 }
philpem@5 318
philpem@5 319 //------------------------------------------------------------------------------
philpem@5 320 // GREYCstoration private functions.
philpem@5 321 // Should not be used directly by the API user.
philpem@5 322 //-------------------------------------------------------------------------------
philpem@5 323
philpem@5 324 static void greycstoration_mutex_create(_greycstoration_params &p) {
philpem@5 325 if (p.nb_threads>1) {
philpem@5 326 #if cimg_OS==1 && defined(_PTHREAD_H)
philpem@5 327 p.mutex = new pthread_mutex_t;
philpem@5 328 pthread_mutex_init(p.mutex,0);
philpem@5 329 #elif cimg_OS==2
philpem@5 330 p.mutex = CreateMutex(0,FALSE,0);
philpem@5 331 #endif
philpem@5 332 }
philpem@5 333 }
philpem@5 334
philpem@5 335 static void greycstoration_mutex_lock(_greycstoration_params &p) {
philpem@5 336 if (p.nb_threads>1) {
philpem@5 337 #if cimg_OS==1 && defined(_PTHREAD_H)
philpem@5 338 if (p.mutex) pthread_mutex_lock(p.mutex);
philpem@5 339 #elif cimg_OS==2
philpem@5 340 WaitForSingleObject(p.mutex,INFINITE);
philpem@5 341 #endif
philpem@5 342 }
philpem@5 343 }
philpem@5 344
philpem@5 345 static void greycstoration_mutex_unlock(_greycstoration_params &p) {
philpem@5 346 if (p.nb_threads>1) {
philpem@5 347 #if cimg_OS==1 && defined(_PTHREAD_H)
philpem@5 348 if (p.mutex) pthread_mutex_unlock(p.mutex);
philpem@5 349 #elif cimg_OS==2
philpem@5 350 ReleaseMutex(p.mutex);
philpem@5 351 #endif
philpem@5 352 }
philpem@5 353 }
philpem@5 354
philpem@5 355 static void greycstoration_mutex_destroy(_greycstoration_params &p) {
philpem@5 356 if (p.nb_threads>1) {
philpem@5 357 #if cimg_OS==1 && defined(_PTHREAD_H)
philpem@5 358 if (p.mutex) pthread_mutex_destroy(p.mutex);
philpem@5 359 #elif cimg_OS==2
philpem@5 360 CloseHandle(p.mutex);
philpem@5 361 #endif
philpem@5 362 p.mutex = 0;
philpem@5 363 }
philpem@5 364 }
philpem@5 365
philpem@5 366 #if cimg_OS==1
philpem@5 367 static void* greycstoration_thread(void *arg) {
philpem@5 368 #elif cimg_OS==2
philpem@5 369 static DWORD WINAPI greycstoration_thread(void *arg) {
philpem@5 370 #endif
philpem@5 371 _greycstoration_params &p = *(_greycstoration_params*)arg;
philpem@5 372 greycstoration_mutex_lock(p);
philpem@5 373 const CImg<unsigned char> &mask = *(p.mask);
philpem@5 374 CImg<T> &source = *(p.source);
philpem@5 375
philpem@5 376 if (!p.tile) {
philpem@5 377
philpem@5 378 // Non-tiled version
philpem@5 379 //------------------
philpem@5 380 if (p.patch_based) source.blur_patch(p.patch_size,p.sigma_p,p.sigma_s,p.lookup_size,p.fast_approx);
philpem@5 381 else source.blur_anisotropic(mask,p.amplitude,p.sharpness,p.anisotropy,p.alpha,p.sigma,p.dl,p.da,p.gauss_prec,
philpem@5 382 p.interpolation,p.fast_approx,p.gfact);
philpem@5 383
philpem@5 384 } else {
philpem@5 385
philpem@5 386 // Tiled version
philpem@5 387 //---------------
philpem@5 388 CImg<T> &temporary = *(p.temporary);
philpem@5 389 const bool threed = (source.depth>1);
philpem@5 390 const unsigned int b = p.tile_border;
philpem@5 391 unsigned int ctile = 0;
philpem@5 392 if (threed) {
philpem@5 393 for (unsigned int z=0; z<source.depth && !*(p.stop_request); z+=p.tile)
philpem@5 394 for (unsigned int y=0; y<source.height && !*(p.stop_request); y+=p.tile)
philpem@5 395 for (unsigned int x=0; x<source.width && !*(p.stop_request); x+=p.tile)
philpem@5 396 if (!p.nb_threads || ((ctile++)%p.nb_threads)==p.thread) {
philpem@5 397 const unsigned int
philpem@5 398 x1 = x+p.tile-1,
philpem@5 399 y1 = y+p.tile-1,
philpem@5 400 z1 = z+p.tile-1,
philpem@5 401 xe = x1<source.width?x1:source.width-1,
philpem@5 402 ye = y1<source.height?y1:source.height-1,
philpem@5 403 ze = z1<source.depth?z1:source.depth-1;
philpem@5 404 CImg<T> img = source.get_crop(x-b,y-b,z-b,xe+b,ye+b,ze+b,true);
philpem@5 405 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);
philpem@5 406 img.greycstoration_params[0] = p;
philpem@5 407 greycstoration_mutex_unlock(p);
philpem@5 408 if (p.patch_based) img.blur_patch(p.patch_size,p.sigma_p,p.sigma_s,p.lookup_size,p.fast_approx);
philpem@5 409 else img.blur_anisotropic(mask_tile,p.amplitude,p.sharpness,p.anisotropy,
philpem@5 410 p.alpha,p.sigma,p.dl,p.da,p.gauss_prec,p.interpolation,p.fast_approx,p.gfact);
philpem@5 411 greycstoration_mutex_lock(p);
philpem@5 412 temporary.draw_image(x,y,z,img.crop(b,b,b,img.width-b,img.height-b,img.depth-b));
philpem@5 413 }
philpem@5 414 } else {
philpem@5 415 for (unsigned int y=0; y<source.height && !*(p.stop_request); y+=p.tile)
philpem@5 416 for (unsigned int x=0; x<source.width && !*(p.stop_request); x+=p.tile)
philpem@5 417 if (!p.nb_threads || ((ctile++)%p.nb_threads)==p.thread) {
philpem@5 418 const unsigned int
philpem@5 419 x1 = x+p.tile-1,
philpem@5 420 y1 = y+p.tile-1,
philpem@5 421 xe = x1<source.width?x1:source.width-1,
philpem@5 422 ye = y1<source.height?y1:source.height-1;
philpem@5 423 CImg<T> img = source.get_crop(x-b,y-b,xe+b,ye+b,true);
philpem@5 424 CImg<unsigned char> mask_tile = mask.is_empty()?mask:mask.get_crop(x-b,y-b,xe+b,ye+b,true);
philpem@5 425 img.greycstoration_params[0] = p;
philpem@5 426 greycstoration_mutex_unlock(p);
philpem@5 427 if (p.patch_based) img.blur_patch(p.patch_size,p.sigma_p,p.sigma_s,p.lookup_size,p.fast_approx);
philpem@5 428 else img.blur_anisotropic(mask_tile,p.amplitude,p.sharpness,p.anisotropy,
philpem@5 429 p.alpha,p.sigma,p.dl,p.da,p.gauss_prec,p.interpolation,p.fast_approx,p.gfact);
philpem@5 430 temporary.draw_image(x,y,img.crop(b,b,img.width-b,img.height-b));
philpem@5 431 greycstoration_mutex_lock(p);
philpem@5 432 }
philpem@5 433 }
philpem@5 434 }
philpem@5 435 greycstoration_mutex_unlock(p);
philpem@5 436
philpem@5 437 if (!p.thread) {
philpem@5 438 if (p.nb_threads>1) {
philpem@5 439 bool stopflag = true;
philpem@5 440 do {
philpem@5 441 stopflag = true;
philpem@5 442 for (unsigned int k=1; k<p.nb_threads; k++) if (source.greycstoration_params[k].is_running) stopflag = false;
philpem@5 443 if (!stopflag) cimg::wait(50);
philpem@5 444 } while (!stopflag);
philpem@5 445 }
philpem@5 446 if (p.counter) delete p.counter;
philpem@5 447 if (p.temporary) { source = *(p.temporary); delete p.temporary; }
philpem@5 448 if (p.stop_request) delete p.stop_request;
philpem@5 449 p.mask = 0;
philpem@5 450 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;
philpem@5 451 p.patch_size = p.interpolation = p.lookup_size = 0;
philpem@5 452 p.fast_approx = false;
philpem@5 453 p.source = 0;
philpem@5 454 p.temporary = 0;
philpem@5 455 p.counter = 0;
philpem@5 456 p.tile = p.tile_border = p.thread = p.nb_threads = 0;
philpem@5 457 p.stop_request = false;
philpem@5 458 greycstoration_mutex_destroy(p);
philpem@5 459 }
philpem@5 460 p.is_running = false;
philpem@5 461
philpem@5 462 if (p.nb_threads) {
philpem@5 463 #if cimg_OS==1 && defined(_PTHREAD_H)
philpem@5 464 pthread_exit(arg);
philpem@5 465 return arg;
philpem@5 466 #elif cimg_OS==2
philpem@5 467 ExitThread(0);
philpem@5 468 #endif
philpem@5 469 }
philpem@5 470 return 0;
philpem@5 471 }
philpem@5 472
philpem@5 473
philpem@5 474 #define cimg_plugin_greycstoration_count \
philpem@5 475 if (!*(greycstoration_params->stop_request)) ++(*greycstoration_params->counter); else return *this;
philpem@5 476 #define cimg_plugin_greycstoration_lock \
philpem@5 477 greycstoration_mutex_lock(greycstoration_params[0]);
philpem@5 478 #define cimg_plugin_greycstoration_unlock \
philpem@5 479 greycstoration_mutex_unlock(greycstoration_params[0]);
philpem@5 480
philpem@5 481 #endif