81
82
unsigned int lookup_size;
83
84
// Non-specific parameters of the algorithms.
85
const CImg<unsigned char> *mask;
87
unsigned long *counter;
89
86
unsigned int tile_border;
91
unsigned int nb_threads;
95
#if cimg_OS==1 && defined(_PTHREAD_H)
104
89
// Default constructor
105
_greycstoration_params():patch_based(false),amplitude(0),sharpness(0),anisotropy(0),alpha(0),sigma(0),gfact(1),
106
dl(0),da(0),gauss_prec(0),interpolation(0),patch_size(0),
107
sigma_s(0),sigma_p(0),lookup_size(0),source(0),mask(0),temporary(0),counter(0),tile(0),
108
tile_border(0),thread(0),nb_threads(0),fast_approx(false),is_running(false), stop_request(0), mutex(0) {}
111
_greycstoration_params greycstoration_params[16];
113
//----------------------------------------------------------
114
// Public functions of the GREYCstoration API.
115
// Use the functions below for integrating GREYCstoration
116
// in your own C++ code.
117
//----------------------------------------------------------
119
//! Test if GREYCstoration threads are still running.
120
bool greycstoration_is_running() const {
121
return greycstoration_params->is_running;
124
//! Force the GREYCstoration threads to stop.
125
CImg& greycstoration_stop() {
126
if (greycstoration_is_running()) {
127
*(greycstoration_params->stop_request) = true;
128
while (greycstoration_params->is_running) cimg::wait(50);
133
//! Return the GREYCstoration progress bar indice (between 0 and 100).
134
float greycstoration_progress() const {
135
if (!greycstoration_is_running()) return 0.0f;
136
const unsigned long counter = greycstoration_params->counter?*(greycstoration_params->counter):0;
138
da = greycstoration_params->da,
139
factor = greycstoration_params->patch_based?1:(1+360/da);
140
float maxcounter = 0;
141
if (greycstoration_params->tile==0) maxcounter = width*height*depth*factor;
144
t = greycstoration_params->tile,
145
b = greycstoration_params->tile_border,
146
n = (1+(width-1)/t)*(1+(height-1)/t)*(1+(depth-1)/t);
147
maxcounter = (width*height*depth + n*4*b*(b + t))*factor;
149
return cimg::min(counter*99.9f/maxcounter,99.9f);
152
//! Run the non-patch version of the GREYCstoration algorithm on the instance image, using a mask.
153
CImg& greycstoration_run(const CImg<unsigned char>& mask,
154
const float amplitude=60, const float sharpness=0.7f, const float anisotropy=0.3f,
155
const float alpha=0.6f, const float sigma=1.1f, const float gfact=1.0f,
156
const float dl=0.8f, const float da=30.0f,
157
const float gauss_prec=2.0f, const unsigned int interpolation=0, const bool fast_approx=true,
158
const unsigned int tile=0, const unsigned int tile_border=0, const unsigned int nb_threads=1) {
160
if (greycstoration_is_running())
161
throw CImgInstanceException("CImg<T>::greycstoration_run() : A GREYCstoration thread is already running on"
162
" the instance image (%u,%u,%u,%u,%p).",width,height,depth,dim,data);
165
if (!mask.is_empty() && !mask.is_sameXY(*this))
166
throw CImgArgumentException("CImg<%s>::greycstoration_run() : Given mask (%u,%u,%u,%u,%p) and instance image "
167
"(%u,%u,%u,%u,%p) have different dimensions.",
168
pixel_type(),mask.width,mask.height,mask.depth,mask.dim,mask.data,width,height,depth,dim,data);
169
if (nb_threads>16) cimg::warn("CImg<%s>::greycstoration_run() : Multi-threading mode limited to 16 threads max.");
171
ntile = (tile && (tile<width || tile<height || (depth>1 && tile<depth)))?tile:0,
172
#if cimg_OS==1 && !defined(_PTHREAD_H)
175
nthreads = ntile?cimg::min(nb_threads,16U):cimg::min(nb_threads,1U);
178
CImg<T> *const temporary = ntile?new CImg<T>(*this):0;
179
unsigned long *const counter = new unsigned long;
181
bool *const stop_request = new bool;
182
*stop_request = false;
184
for (unsigned int k=0; k<(nthreads?nthreads:1); k++) {
185
greycstoration_params[k].patch_based = false;
186
greycstoration_params[k].amplitude = amplitude;
187
greycstoration_params[k].sharpness = sharpness;
188
greycstoration_params[k].anisotropy = anisotropy;
189
greycstoration_params[k].alpha = alpha;
190
greycstoration_params[k].sigma = sigma;
191
greycstoration_params[k].gfact = gfact;
192
greycstoration_params[k].dl = dl;
193
greycstoration_params[k].da = da;
194
greycstoration_params[k].gauss_prec = gauss_prec;
195
greycstoration_params[k].interpolation = interpolation;
196
greycstoration_params[k].fast_approx = fast_approx;
197
greycstoration_params[k].source = this;
198
greycstoration_params[k].mask = &mask;
199
greycstoration_params[k].temporary = temporary;
200
greycstoration_params[k].counter = counter;
201
greycstoration_params[k].tile = ntile;
202
greycstoration_params[k].tile_border = tile_border;
203
greycstoration_params[k].thread = k;
204
greycstoration_params[k].nb_threads = nthreads;
205
greycstoration_params[k].is_running = true;
206
greycstoration_params[k].stop_request = stop_request;
207
if (k) greycstoration_params[k].mutex = greycstoration_params[0].mutex;
208
else greycstoration_mutex_create(greycstoration_params[0]);
210
if (nthreads) { // Threaded version
214
pthread_attr_init(&attr);
215
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
216
for (unsigned int k=0; k<greycstoration_params->nb_threads; k++) {
218
const int err = pthread_create(&thread, &attr, greycstoration_thread, (void*)(greycstoration_params+k));
219
if (err) throw CImgException("CImg<%s>::greycstoration_run() : pthread_create returned error %d",
224
for (unsigned int k=0; k<greycstoration_params->nb_threads; k++) {
225
unsigned long ThreadID = 0;
226
CreateThread(0,0,greycstoration_thread,(void*)(greycstoration_params+k),0,&ThreadID);
229
throw CImgInstanceException("CImg<T>::greycstoration_run() : Threads are not supported, please define cimg_OS first.");
231
} else greycstoration_thread((void*)greycstoration_params); // Non-threaded version
236
//! Run the non-patch version of the GREYCstoration algorithm on the instance image.
237
CImg& greycstoration_run(const float amplitude=50, const float sharpness=0.7f, const float anisotropy=0.3f,
238
const float alpha=0.6f, const float sigma=1.1f, const float gfact=1.0f,
239
const float dl=0.8f, const float da=30.0f,
240
const float gauss_prec=2.0f, const unsigned int interpolation=0, const bool fast_approx=true,
241
const unsigned int tile=0, const unsigned int tile_border=0, const unsigned int nb_threads=1) {
242
static const CImg<unsigned char> empty_mask;
243
return greycstoration_run(empty_mask,amplitude,sharpness,anisotropy,alpha,sigma,gfact,dl,da,gauss_prec,
244
interpolation,fast_approx,tile,tile_border,nb_threads);
247
//! Run the patch-based version of the GREYCstoration algorithm on the instance image.
248
CImg& greycstoration_patch_run(const unsigned int patch_size=5, const float sigma_p=10, const float sigma_s=100,
249
const unsigned int lookup_size=20, const bool fast_approx=true,
250
const unsigned int tile=0, const unsigned int tile_border=0, const unsigned int nb_threads=1) {
252
static const CImg<unsigned char> empty_mask;
253
if (greycstoration_is_running())
254
throw CImgInstanceException("CImg<T>::greycstoration_run() : A GREYCstoration thread is already running on"
255
" the instance image (%u,%u,%u,%u,%p).",width,height,depth,dim,data);
258
if (nb_threads>16) cimg::warn("CImg<%s>::greycstoration_run() : Multi-threading mode limited to 16 threads max.");
260
ntile = (tile && (tile<width || tile<height || (depth>1 && tile<depth)))?tile:0,
261
#if cimg_OS==1 && !defined(_PTHREAD_H)
264
nthreads = ntile?cimg::min(nb_threads,16U):cimg::min(nb_threads,1U);
267
CImg<T> *const temporary = ntile?new CImg<T>(*this):0;
268
unsigned long *const counter = new unsigned long;
270
bool *const stop_request = new bool;
271
*stop_request = false;
273
for (unsigned int k=0; k<(nthreads?nthreads:1); k++) {
274
greycstoration_params[k].patch_based = true;
275
greycstoration_params[k].patch_size = patch_size;
276
greycstoration_params[k].sigma_s = sigma_s;
277
greycstoration_params[k].sigma_p = sigma_p;
278
greycstoration_params[k].lookup_size = lookup_size;
279
greycstoration_params[k].source = this;
280
greycstoration_params[k].mask = &empty_mask;
281
greycstoration_params[k].temporary = temporary;
282
greycstoration_params[k].counter = counter;
283
greycstoration_params[k].tile = ntile;
284
greycstoration_params[k].tile_border = tile_border;
285
greycstoration_params[k].thread = k;
286
greycstoration_params[k].nb_threads = nthreads;
287
greycstoration_params[k].fast_approx = fast_approx;
288
greycstoration_params[k].is_running = true;
289
greycstoration_params[k].stop_request = stop_request;
290
if (k) greycstoration_params[k].mutex = greycstoration_params[0].mutex;
291
else greycstoration_mutex_create(greycstoration_params[0]);
293
if (nthreads) { // Threaded version
297
pthread_attr_init(&attr);
298
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
299
for (unsigned int k=0; k<greycstoration_params->nb_threads; k++) {
301
const int err = pthread_create(&thread, &attr, greycstoration_thread, (void*)(greycstoration_params+k));
302
if (err) throw CImgException("CImg<%s>::greycstoration_run() : pthread_create returned error %d",
307
for (unsigned int k=0; k<greycstoration_params->nb_threads; k++) {
308
unsigned long ThreadID = 0;
309
CreateThread(0,0,greycstoration_thread,(void*)(greycstoration_params+k),0,&ThreadID);
312
throw CImgInstanceException("CImg<T>::greycstoration_run() : Threads support have not been enabled in this version of GREYCstoration.");
314
} else greycstoration_thread((void*)greycstoration_params); // Non-threaded version
319
//------------------------------------------------------------------------------
320
// GREYCstoration private functions.
321
// Should not be used directly by the API user.
322
//-------------------------------------------------------------------------------
324
static void greycstoration_mutex_create(_greycstoration_params &p) {
325
if (p.nb_threads>1) {
326
#if cimg_OS==1 && defined(_PTHREAD_H)
327
p.mutex = new pthread_mutex_t;
328
pthread_mutex_init(p.mutex,0);
330
p.mutex = CreateMutex(0,FALSE,0);
335
static void greycstoration_mutex_lock(_greycstoration_params &p) {
336
if (p.nb_threads>1) {
337
#if cimg_OS==1 && defined(_PTHREAD_H)
338
if (p.mutex) pthread_mutex_lock(p.mutex);
340
WaitForSingleObject(p.mutex,INFINITE);
345
static void greycstoration_mutex_unlock(_greycstoration_params &p) {
346
if (p.nb_threads>1) {
347
#if cimg_OS==1 && defined(_PTHREAD_H)
348
if (p.mutex) pthread_mutex_unlock(p.mutex);
350
ReleaseMutex(p.mutex);
355
static void greycstoration_mutex_destroy(_greycstoration_params &p) {
356
if (p.nb_threads>1) {
357
#if cimg_OS==1 && defined(_PTHREAD_H)
358
if (p.mutex) pthread_mutex_destroy(p.mutex);
360
CloseHandle(p.mutex);
367
static void* greycstoration_thread(void *arg) {
369
static DWORD WINAPI greycstoration_thread(void *arg) {
371
_greycstoration_params &p = *(_greycstoration_params*)arg;
372
greycstoration_mutex_lock(p);
373
const CImg<unsigned char> &mask = *(p.mask);
374
CImg<T> &source = *(p.source);
380
if (p.patch_based) source.blur_patch(p.patch_size,p.sigma_p,p.sigma_s,p.lookup_size,p.fast_approx);
381
else source.blur_anisotropic(mask,p.amplitude,p.sharpness,p.anisotropy,p.alpha,p.sigma,p.dl,p.da,p.gauss_prec,
382
p.interpolation,p.fast_approx,p.gfact);
388
CImg<T> &temporary = *(p.temporary);
389
const bool threed = (source.depth>1);
390
const unsigned int b = p.tile_border;
391
unsigned int ctile = 0;
393
for (unsigned int z=0; z<source.depth && !*(p.stop_request); z+=p.tile)
394
for (unsigned int y=0; y<source.height && !*(p.stop_request); y+=p.tile)
395
for (unsigned int x=0; x<source.width && !*(p.stop_request); x+=p.tile)
396
if (!p.nb_threads || ((ctile++)%p.nb_threads)==p.thread) {
401
xe = x1<source.width?x1:source.width-1,
402
ye = y1<source.height?y1:source.height-1,
403
ze = z1<source.depth?z1:source.depth-1;
404
CImg<T> img = source.get_crop(x-b,y-b,z-b,xe+b,ye+b,ze+b,true);
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);
406
img.greycstoration_params[0] = p;
407
greycstoration_mutex_unlock(p);
408
if (p.patch_based) img.blur_patch(p.patch_size,p.sigma_p,p.sigma_s,p.lookup_size,p.fast_approx);
409
else img.blur_anisotropic(mask_tile,p.amplitude,p.sharpness,p.anisotropy,
410
p.alpha,p.sigma,p.dl,p.da,p.gauss_prec,p.interpolation,p.fast_approx,p.gfact);
411
greycstoration_mutex_lock(p);
412
temporary.draw_image(x,y,z,img.crop(b,b,b,img.width-b,img.height-b,img.depth-b));
415
for (unsigned int y=0; y<source.height && !*(p.stop_request); y+=p.tile)
416
for (unsigned int x=0; x<source.width && !*(p.stop_request); x+=p.tile)
417
if (!p.nb_threads || ((ctile++)%p.nb_threads)==p.thread) {
421
xe = x1<source.width?x1:source.width-1,
422
ye = y1<source.height?y1:source.height-1;
423
CImg<T> img = source.get_crop(x-b,y-b,xe+b,ye+b,true);
424
CImg<unsigned char> mask_tile = mask.is_empty()?mask:mask.get_crop(x-b,y-b,xe+b,ye+b,true);
425
img.greycstoration_params[0] = p;
426
greycstoration_mutex_unlock(p);
427
if (p.patch_based) img.blur_patch(p.patch_size,p.sigma_p,p.sigma_s,p.lookup_size,p.fast_approx);
428
else img.blur_anisotropic(mask_tile,p.amplitude,p.sharpness,p.anisotropy,
429
p.alpha,p.sigma,p.dl,p.da,p.gauss_prec,p.interpolation,p.fast_approx,p.gfact);
430
temporary.draw_image(x,y,img.crop(b,b,img.width-b,img.height-b));
431
greycstoration_mutex_lock(p);
435
greycstoration_mutex_unlock(p);
438
if (p.nb_threads>1) {
439
bool stopflag = true;
442
for (unsigned int k=1; k<p.nb_threads; k++) if (source.greycstoration_params[k].is_running) stopflag = false;
443
if (!stopflag) cimg::wait(50);
446
if (p.counter) delete p.counter;
447
if (p.temporary) { source = *(p.temporary); delete p.temporary; }
448
if (p.stop_request) delete p.stop_request;
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;
451
p.patch_size = p.interpolation = p.lookup_size = 0;
452
p.fast_approx = false;
456
p.tile = p.tile_border = p.thread = p.nb_threads = 0;
457
(*p.stop_request) = false;
458
greycstoration_mutex_destroy(p);
460
p.is_running = false;
463
#if cimg_OS==1 && defined(_PTHREAD_H)
90
GreycstorationParameters()
108
fast_approx(false) {}
111
class GreycstorationThreadManager;
112
// class just to have a constructor to initialize the variable
113
class GreycstorationThreadManagerContainer
116
GreycstorationThreadManagerContainer() : threadManager(0) {}
117
GreycstorationThreadManager* threadManager;
119
GreycstorationThreadManagerContainer threadManagerContainer;
121
void setThreadManager(GreycstorationThreadManager* threadManager)
123
threadManagerContainer.threadManager = threadManager;
126
void resetThreadManager()
131
class GreycstorationWorkingThread : public Digikam::DynamicThread
134
GreycstorationWorkingThread(GreycstorationThreadManager* manager, int threadNumber)
135
: manager(manager), threadNumber(threadNumber)
141
manager->workerMethod(threadNumber);
144
GreycstorationThreadManager* const manager;
145
const int threadNumber;
148
//template <typename T>
149
class GreycstorationThreadManager
152
GreycstorationThreadManager()
153
: counter(0), stopRequest(false), activeThreads(0),
154
source(0), temporary(0), empty_mask(new CImg<unsigned char>())
158
~GreycstorationThreadManager()
169
//! Run the non-patch version of the GREYCstoration algorithm on the instance image, using a mask.
170
void start(CImg& s, const CImg<unsigned char>* m,
171
const float amplitude=60, const float sharpness=0.7f,
172
const float anisotropy=0.3f, const float alpha=0.6f,
173
const float sigma=1.1f, const float gfact=1.0f,
174
const float dl=0.8f, const float da=30.0f,
175
const float gauss_prec=2.0f, const unsigned int interpolation=0,
176
const bool fast_approx=true, const unsigned int tile=0,
177
const unsigned int tile_border=0,
178
const unsigned int nb_threads=1)
181
GreycstorationParameters params;
182
params.patch_based = false;
184
params.amplitude = amplitude;
185
params.sharpness = sharpness;
186
params.anisotropy = anisotropy;
187
params.alpha = alpha;
188
params.sigma = sigma;
189
params.gfact = gfact;
192
params.gauss_prec = gauss_prec;
193
params.interpolation = interpolation;
194
params.fast_approx = fast_approx;
195
params.tile_border = tile_border;
198
start(&s, params, tile, nb_threads);
201
//! Run the non-patch version of the GREYCstoration algorithm on the instance image.
202
void start(CImg& s, const float amplitude=50, const float sharpness=0.7f, const float anisotropy=0.3f,
203
const float alpha=0.6f, const float sigma=1.1f, const float gfact=1.0f,
204
const float dl=0.8f, const float da=30.0f,
205
const float gauss_prec=2.0f, const unsigned int interpolation=0, const bool fast_approx=true,
206
const unsigned int tile=0, const unsigned int tile_border=0, const unsigned int nb_threads=1)
208
return start(s, empty_mask, amplitude,sharpness,anisotropy,alpha,sigma,gfact,dl,da,gauss_prec,
209
interpolation,fast_approx,tile,tile_border,nb_threads);
212
//! Run the patch-based version of the GREYCstoration algorithm on the instance image.
213
void start(CImg& s, const unsigned int patch_size=5,
214
const float sigma_p=10,
215
const float sigma_s=100,
216
const unsigned int lookup_size=20,
217
const bool fast_approx=true,
218
const unsigned int tile=0,
219
const unsigned int tile_border=0,
220
const unsigned int nb_threads=1)
222
GreycstorationParameters params;
224
params.patch_based = true;
225
params.patch_size = patch_size;
226
params.sigma_s = sigma_s;
227
params.sigma_p = sigma_p;
228
params.lookup_size = lookup_size;
229
params.mask = empty_mask;
230
params.tile_border = tile_border;
231
params.fast_approx = fast_approx;
233
start(&s, params, tile, nb_threads);
236
bool isRunning() const
238
foreach(GreycstorationWorkingThread* thread, threads)
240
if (thread->isRunning())
250
foreach(GreycstorationWorkingThread* thread, threads)
260
(*source) = (*temporary);
264
source->resetThreadManager();
270
foreach(GreycstorationWorkingThread* thread, threads)
277
float progress() const
281
factor = p.patch_based ? 1 : (1+360/da);
282
float maxcounter = 0;
285
maxcounter = source->width*source->height*source->depth*factor;
292
n = (1+(source->width-1)/t)*(1+(source->height-1)/t)*(1+(source->depth-1)/t);
293
maxcounter = (source->width*source->height*source->depth + n*4*b*(b + t))*factor;
295
return cimg::min(counter*99.9f/maxcounter,99.9f);
298
// Waits at most the specified number of milliseconds, then returns current progress
299
float waitABit(unsigned int msecs)
301
QMutexLocker lock(&mutex);
304
condVar.wait(&mutex, msecs);
311
friend class CImg<T>;
314
QWaitCondition condVar;
315
volatile int counter;
316
volatile bool stopRequest;
317
volatile int activeThreads;
319
GreycstorationParameters p;
322
const CImg<unsigned char> *mask;
325
CImg<unsigned char> *empty_mask;
327
QList<GreycstorationWorkingThread*> threads;
329
void start(CImg* s, const GreycstorationParameters& params, unsigned int tile, unsigned int numberOfThreads)
331
/*if (!mask.is_empty() && !mask.is_sameXY(*this))
333
throw CImgArgumentException("CImg<%s>::greycstoration_run() : Given mask (%u,%u,%u,%u,%p) and instance image "
334
"(%u,%u,%u,%u,%p) have different dimensions.",
335
pixel_type(),mask.width,mask.height,mask.depth,mask.dim,mask.data,width,height,depth,dim,data);
338
if (numberOfThreads>16)
340
cimg::warn("CImg<%s>::greycstoration_run() : Multi-threading mode limited to 16 threads max.");
344
s->setThreadManager(this);
347
p.tile = (tile && (tile<source->width || tile<source->height ||
348
(source->depth>1 && tile<source->depth)))?tile:0,
349
numberOfThreads = p.tile ? cimg::min(numberOfThreads,16U) : cimg::min(numberOfThreads,1U);
355
temporary = p.tile ? new CImg<T>(*source) : 0;
359
for (unsigned int k=0; k<numberOfThreads; k++)
361
GreycstorationWorkingThread* thread = new GreycstorationWorkingThread(this, k);
375
friend class GreycstorationWorkingThread;
376
void workerMethod(unsigned int threadIndex)
378
QMutexLocker lock(&mutex);
386
source->blur_patch(p.patch_size,p.sigma_p,p.sigma_s,p.lookup_size,p.fast_approx);
390
source->blur_anisotropic(*mask,p.amplitude,p.sharpness,p.anisotropy,p.alpha,p.sigma,p.dl,p.da,p.gauss_prec,
391
p.interpolation,p.fast_approx,p.gfact);
398
const bool threed = (source->depth>1);
399
const unsigned int b = p.tile_border;
400
unsigned int ctile = 0;
404
for (unsigned int z=0; z<source->depth && !stopRequest; z+=p.tile)
406
for (unsigned int y=0; y<source->height && !stopRequest; y+=p.tile)
408
for (unsigned int x=0; x<source->width && !stopRequest; x+=p.tile)
410
if (threads.isEmpty() || ((ctile++)%threads.size())==(unsigned int)threadIndex)
416
xe = x1<source->width?x1:source->width-1,
417
ye = y1<source->height?y1:source->height-1,
418
ze = z1<source->depth?z1:source->depth-1;
420
CImg<T> img = source->get_crop(x-b,y-b,z-b,xe+b,ye+b,ze+b,true);
421
CImg<unsigned char> mask_tile = mask->is_empty() ? *mask :
422
mask->get_crop(x-b,y-b,z-b,xe+b,ye+b,ze+b,true);
423
//??img.greycstoration_params[0] = p;
428
img.blur_patch(p.patch_size,p.sigma_p,p.sigma_s,p.lookup_size,p.fast_approx);
432
img.blur_anisotropic(mask_tile,p.amplitude,p.sharpness,p.anisotropy,
433
p.alpha,p.sigma,p.dl,p.da,p.gauss_prec,p.interpolation,p.fast_approx,p.gfact);
437
temporary->draw_image(x,y,z,img.crop(b,b,b,img.width-b,img.height-b,img.depth-b));
445
for (unsigned int y=0; y<source->height && !stopRequest; y+=p.tile)
447
for (unsigned int x=0; x<source->width && !stopRequest; x+=p.tile)
449
if (threads.isEmpty() || ((ctile++)%threads.size())==(unsigned int)threadIndex)
454
xe = x1<source->width?x1:source->width-1,
455
ye = y1<source->height?y1:source->height-1;
456
CImg<T> img = source->get_crop(x-b,y-b,xe+b,ye+b,true);
457
CImg<unsigned char> mask_tile = mask->is_empty() ? *mask : mask->get_crop(x-b,y-b,xe+b,ye+b,true);
458
//img.greycstoration_params[0] = p;
463
img.blur_patch(p.patch_size,p.sigma_p,p.sigma_s,p.lookup_size,p.fast_approx);
467
img.blur_anisotropic(mask_tile,p.amplitude,p.sharpness,p.anisotropy,
468
p.alpha,p.sigma,p.dl,p.da,p.gauss_prec,p.interpolation,p.fast_approx,p.gfact);
472
temporary->draw_image(x,y,img.crop(b,b,img.width-b,img.height-b));
474
484
#define cimg_plugin_greycstoration_count \
475
if (!*(greycstoration_params->stop_request)) ++(*greycstoration_params->counter); else return *this;
485
if (threadManagerContainer.threadManager)\
486
{ if (threadManagerContainer.threadManager->stopRequest) \
488
++threadManagerContainer.threadManager->counter; }
476
490
#define cimg_plugin_greycstoration_lock \
477
greycstoration_mutex_lock(greycstoration_params[0]);
491
if (threadManagerContainer.threadManager) threadManagerContainer.threadManager->mutex.lock();
478
492
#define cimg_plugin_greycstoration_unlock \
479
greycstoration_mutex_unlock(greycstoration_params[0]);
493
if (threadManagerContainer.threadManager) threadManagerContainer.threadManager->mutex.unlock();