621 lines
18 KiB
C++
621 lines
18 KiB
C++
/*
|
|
* This file is part of RawTherapee.
|
|
*
|
|
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
|
*
|
|
* RawTherapee is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* RawTherapee is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#include <improccoordinator.h>
|
|
#include <curves.h>
|
|
#include <mytime.h>
|
|
#include <refreshmap.h>
|
|
#include <simpleprocess.h>
|
|
#define CLIPTO(a,b,c) ((a)>b?((a)<c?(a):c):b)
|
|
#define CLIP(a) ((a)<65535 ? (a) : (65535));
|
|
|
|
namespace rtengine {
|
|
|
|
extern Settings* settings;
|
|
|
|
ImProcCoordinator::ImProcCoordinator ()
|
|
: awbComputed(false), ipf(¶ms, true), scale(10), allocated(false),
|
|
pW(-1), pH(-1), plistener(NULL), imageListener(NULL),fineDetailsProcessed(false),
|
|
aeListener(NULL), hListener(NULL), resultValid(false),
|
|
changeSinceLast(0), updaterRunning(false), destroying(false) {
|
|
}
|
|
|
|
void ImProcCoordinator::assign (ImageSource* imgsrc) {
|
|
this->imgsrc = imgsrc;
|
|
}
|
|
|
|
ImProcCoordinator::~ImProcCoordinator () {
|
|
|
|
destroying = true;
|
|
updaterThreadStart.lock ();
|
|
if (updaterRunning && thread)
|
|
thread->join ();
|
|
mProcessing.lock();
|
|
mProcessing.unlock();
|
|
freeAll ();
|
|
|
|
std::vector<Crop*> toDel = crops;
|
|
for (int i=0; i<toDel.size(); i++)
|
|
delete toDel[i];
|
|
|
|
imgsrc->decreaseRef ();
|
|
updaterThreadStart.unlock ();
|
|
}
|
|
|
|
DetailedCrop* ImProcCoordinator::createCrop () {
|
|
|
|
return new Crop (this);
|
|
}
|
|
|
|
void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
|
|
|
|
mProcessing.lock ();
|
|
|
|
int numofphases = 10;
|
|
int readyphase = 0;
|
|
|
|
if (!params.resize.enabled)
|
|
params.resize.scale = 1.0;
|
|
else if (params.resize.dataspec==1)
|
|
params.resize.scale = (double)params.resize.width / (params.coarse.rotate==90 || params.coarse.rotate==270 ? fh : fw);
|
|
else if (params.resize.dataspec==2)
|
|
params.resize.scale = (double)params.resize.height / (params.coarse.rotate==90 || params.coarse.rotate==270 ? fw : fh);
|
|
|
|
ipf.setScale (scale);
|
|
|
|
bool highDetailNeeded=false;
|
|
for (int i=0; i<crops.size(); i++)
|
|
if (crops[i]->get_skip() == 1 ){
|
|
highDetailNeeded=true;
|
|
break;
|
|
}
|
|
RAWParams rp = params.raw;
|
|
if( !highDetailNeeded ){
|
|
rp.dmethod = RAWParams::methodstring[RAWParams::fast];
|
|
rp.ca_autocorrect = false;
|
|
rp.hotdeadpix_filt = false;
|
|
rp.ccSteps = 0;
|
|
}
|
|
progress ("Applying white balance, color correction & sRBG conversion...",100*readyphase/numofphases);
|
|
if ( todo & M_PREPROC)
|
|
imgsrc->preprocess( rp );
|
|
if( todo & M_RAW){
|
|
if( !highDetailNeeded ){
|
|
fineDetailsProcessed = false;
|
|
}else
|
|
fineDetailsProcessed = true;
|
|
imgsrc->demosaic( rp );
|
|
}
|
|
if (todo & M_INIT) {
|
|
minit.lock ();
|
|
if (settings->verbose) printf ("Applying white balance, color correction & sRBG conversion...\n");
|
|
currWB = ColorTemp (params.wb.temperature, params.wb.green);
|
|
if (params.wb.method=="Camera")
|
|
currWB = imgsrc->getWB ();
|
|
else if (params.wb.method=="Auto") {
|
|
if (!awbComputed) {
|
|
autoWB = imgsrc->getAutoWB ();
|
|
awbComputed = true;
|
|
}
|
|
currWB = autoWB;
|
|
}
|
|
params.wb.temperature = currWB.getTemp ();
|
|
params.wb.green = currWB.getGreen ();
|
|
|
|
int tr = TR_NONE;
|
|
if (params.coarse.rotate==90) tr |= TR_R90;
|
|
if (params.coarse.rotate==180) tr |= TR_R180;
|
|
if (params.coarse.rotate==270) tr |= TR_R270;
|
|
if (params.coarse.hflip) tr |= TR_HFLIP;
|
|
if (params.coarse.vflip) tr |= TR_VFLIP;
|
|
|
|
imgsrc->getFullSize (fw, fh, tr);
|
|
PreviewProps pp (0, 0, fw, fh, scale);
|
|
setScale (scale, true);
|
|
imgsrc->getImage (currWB, tr, orig_prev, pp, params.hlrecovery, params.icm, params.raw);
|
|
ipf.firstAnalysis (orig_prev, ¶ms, vhist16, imgsrc->getGamma());
|
|
minit.unlock ();
|
|
}
|
|
readyphase++;
|
|
|
|
progress ("Rotate / Distortion...",100*readyphase/numofphases);
|
|
bool needstransform = ipf.needsTransform();
|
|
if (!needstransform && orig_prev!=oprevi) {
|
|
delete oprevi;
|
|
oprevi = orig_prev;
|
|
}
|
|
if (needstransform && orig_prev==oprevi)
|
|
oprevi = new Image16 (pW, pH);
|
|
if ((todo & M_TRANSFORM) && needstransform)
|
|
ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH);
|
|
|
|
readyphase++;
|
|
|
|
progress ("Preparing shadow/highlight map...",100*readyphase/numofphases);
|
|
if ((todo & M_BLURMAP) && params.sh.enabled) {
|
|
double radius = sqrt (double(pW*pW+pH*pH)) / 2.0;
|
|
double shradius = radius / 1800.0 * params.sh.radius;
|
|
shmap->update (oprevi, (unsigned short**)buffer, shradius, ipf.lumimul, params.sh.hq);
|
|
}
|
|
readyphase++;
|
|
|
|
if (todo & M_AUTOEXP) {
|
|
if (params.toneCurve.autoexp) {
|
|
unsigned int aehist[65536]; int aehistcompr;
|
|
imgsrc->getAEHistogram (aehist, aehistcompr);
|
|
ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, params.toneCurve.expcomp, params.toneCurve.black);
|
|
if (aeListener)
|
|
aeListener->autoExpChanged (params.toneCurve.expcomp, params.toneCurve.black);
|
|
}
|
|
}
|
|
|
|
progress ("Exposure curve & CIELAB conversion...",100*readyphase/numofphases);
|
|
if (todo & M_RGBCURVE) {
|
|
CurveFactory::complexCurve (params.toneCurve.expcomp, params.toneCurve.black/65535.0, params.toneCurve.hlcompr, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, imgsrc->getDefGain(), imgsrc->getGamma(), true, params.toneCurve.curve, vhist16, hltonecurve, shtonecurve, tonecurve, bcrgbhist, scale==1 ? 1 : 1);
|
|
ipf.rgbProc (oprevi, oprevl, hltonecurve, shtonecurve, tonecurve, shmap, params.toneCurve.saturation);
|
|
|
|
// recompute luminance histogram
|
|
memset (lhist16, 0, 65536*sizeof(int));
|
|
for (int i=0; i<pH; i++)
|
|
for (int j=0; j<pW; j++)
|
|
lhist16[oprevl->L[i][j]]++;
|
|
}
|
|
readyphase++;
|
|
|
|
if (todo & M_LUMACURVE) {
|
|
CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, params.labCurve.brightness, params.labCurve.contrast, 0.0, 0.0, false, params.labCurve.lcurve, lhist16, dummy1, dummy2, lumacurve, bcLhist, scale==1 ? 1 : 16);
|
|
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, chroma_acurve, scale==1 ? 1 : 16);
|
|
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, chroma_bcurve, scale==1 ? 1 : 16);
|
|
}
|
|
|
|
|
|
if (todo & (M_LUMINANCE+M_COLOR) ) {
|
|
progress ("Applying Luminance Curve...",100*readyphase/numofphases);
|
|
ipf.luminanceCurve (oprevl, nprevl, lumacurve, 0, pH);
|
|
|
|
readyphase++;
|
|
progress ("Applying Color Boost...",100*readyphase/numofphases);
|
|
ipf.chrominanceCurve (oprevl, nprevl, 0, chroma_acurve, 0, pH);
|
|
ipf.chrominanceCurve (oprevl, nprevl, 1, chroma_bcurve, 0, pH);
|
|
ipf.colorCurve (nprevl, nprevl);
|
|
|
|
readyphase++;
|
|
if (scale==1) {
|
|
progress ("Denoising luminance impulse...",100*readyphase/numofphases);
|
|
ipf.impulsedenoise (nprevl);
|
|
}
|
|
if (scale==1) {
|
|
progress ("Defringing...",100*readyphase/numofphases);
|
|
ipf.defringe (nprevl);
|
|
}
|
|
if (scale==1) {
|
|
progress ("Denoising luminance...",100*readyphase/numofphases);
|
|
ipf.lumadenoise (nprevl, buffer);
|
|
}
|
|
readyphase++;
|
|
if (scale==1) {
|
|
progress ("Denoising color...",100*readyphase/numofphases);
|
|
ipf.colordenoise (nprevl, buffer);
|
|
}
|
|
if (scale==1) {
|
|
progress ("Denoising luma/chroma...",100*readyphase/numofphases);
|
|
ipf.dirpyrdenoise (nprevl);
|
|
}
|
|
if (scale==1) {
|
|
progress ("Sharpening...",100*readyphase/numofphases);
|
|
ipf.sharpening (nprevl, (unsigned short**)buffer);
|
|
}
|
|
readyphase++;
|
|
if (scale==1) {
|
|
progress ("Pyramid equalizer...",100*readyphase/numofphases);
|
|
ipf.dirpyrequalizer (nprevl);
|
|
}
|
|
if (scale==1) {
|
|
progress ("Wavelet...",100*readyphase/numofphases);
|
|
ipf.waveletEqualizer (nprevl, true, true);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// process crop, if needed
|
|
for (int i=0; i<crops.size(); i++)
|
|
if (crops[i]->hasListener () && cropCall != crops[i] )
|
|
crops[i]->update (todo, true);
|
|
|
|
progress ("Conversion to RGB...",100*readyphase/numofphases);
|
|
if (todo!=CROP) {
|
|
previmg->getMutex().lock();
|
|
try
|
|
{
|
|
ipf.lab2rgb (nprevl, previmg);
|
|
}
|
|
catch(char * str)
|
|
{
|
|
progress ("Error converting file...",0);
|
|
mProcessing.unlock ();
|
|
return;
|
|
}
|
|
previmg->getMutex().unlock();
|
|
}
|
|
if (!resultValid) {
|
|
resultValid = true;
|
|
if (imageListener)
|
|
imageListener->setImage (previmg, scale*params.resize.scale, params.crop);
|
|
}
|
|
if (imageListener)
|
|
imageListener->imageReady (params.crop);
|
|
|
|
readyphase++;
|
|
|
|
if (hListener) {
|
|
int hx1 = 0, hx2 = pW, hy1 = 0, hy2 = pH;
|
|
if (params.crop.enabled) {
|
|
hx1 = MIN(pW-1,MAX(0,params.crop.x / scale));
|
|
hy1 = MIN(pH-1,MAX(0,params.crop.y / scale));
|
|
hx2 = MIN(pW,MAX(0,(params.crop.x+params.crop.w) / scale));
|
|
hy2 = MIN(pH,MAX(0,(params.crop.y+params.crop.h) / scale));
|
|
}
|
|
updateHistograms (hx1, hy1, hx2, hy2);
|
|
hListener->histogramChanged (rhist, ghist, bhist, Lhist, bcrgbhist, bcLhist);
|
|
}
|
|
|
|
progress ("Ready",100*readyphase/numofphases);
|
|
mProcessing.unlock ();
|
|
}
|
|
|
|
|
|
void ImProcCoordinator::freeAll () {
|
|
|
|
if (settings->verbose) printf ("freeall starts %d\n", (int)allocated);
|
|
|
|
if (allocated) {
|
|
if (orig_prev!=oprevi)
|
|
delete oprevi;
|
|
delete orig_prev;
|
|
delete oprevl;
|
|
delete nprevl;
|
|
if (imageListener) {
|
|
imageListener->delImage (previmg);
|
|
}
|
|
else
|
|
delete previmg;
|
|
delete shmap;
|
|
for (int i=0; i<pH; i++)
|
|
delete [] buffer[i];
|
|
delete [] buffer;
|
|
}
|
|
allocated = false;
|
|
}
|
|
|
|
void ImProcCoordinator::setScale (int prevscale, bool internal) {
|
|
|
|
if (settings->verbose) printf ("setscale before lock\n");
|
|
|
|
if (!internal)
|
|
mProcessing.lock ();
|
|
|
|
tr = TR_NONE;
|
|
if (params.coarse.rotate==90) tr |= TR_R90;
|
|
if (params.coarse.rotate==180) tr |= TR_R180;
|
|
if (params.coarse.rotate==270) tr |= TR_R270;
|
|
if (params.coarse.hflip) tr |= TR_HFLIP;
|
|
if (params.coarse.vflip) tr |= TR_VFLIP;
|
|
|
|
int nW, nH;
|
|
imgsrc->getFullSize (fw, fh, tr);
|
|
|
|
PreviewProps pp (0, 0, fw, fh, prevscale);
|
|
imgsrc->getSize (tr, pp, nW, nH);
|
|
|
|
if (settings->verbose) printf ("setscale starts (%d, %d)\n", nW, nH);
|
|
|
|
if (nW!=pW || nH!=pH) {
|
|
|
|
freeAll ();
|
|
|
|
pW = nW;
|
|
pH = nH;
|
|
|
|
orig_prev = new Image16 (pW, pH);
|
|
oprevi = orig_prev;
|
|
oprevl = new LabImage (pW, pH);
|
|
nprevl = new LabImage (pW, pH);
|
|
previmg = new Image8 (pW, pH);
|
|
shmap = new SHMap (pW, pH, true);
|
|
|
|
buffer = new int*[pH];
|
|
for (int i=0; i<pH; i++)
|
|
buffer[i] = new int[pW];
|
|
allocated = true;
|
|
}
|
|
|
|
scale = prevscale;
|
|
resultValid = false;
|
|
if (!params.resize.enabled) {
|
|
fullw = fw;
|
|
fullh = fh;
|
|
}
|
|
else if (params.resize.dataspec==0) {
|
|
fullw = fw*params.resize.scale;
|
|
fullh = fh*params.resize.scale;
|
|
}
|
|
else if (params.resize.dataspec==1) {
|
|
fullw = params.resize.width;
|
|
fullh = (double)fh*params.resize.width/(params.coarse.rotate==90 || params.coarse.rotate==270 ? fh : fw);
|
|
}
|
|
else if (params.resize.dataspec==2) {
|
|
fullw = (double)fw*params.resize.height/(params.coarse.rotate==90 || params.coarse.rotate==270 ? fw : fh);
|
|
fullh = params.resize.height;
|
|
}
|
|
if (settings->verbose) printf ("setscale ends\n");
|
|
if (sizeListeners.size()>0)
|
|
for (int i=0; i<sizeListeners.size(); i++)
|
|
sizeListeners[i]->sizeChanged (fullw, fullh, fw, fh);
|
|
if (settings->verbose) printf ("setscale ends2\n");
|
|
|
|
if (!internal)
|
|
mProcessing.unlock ();
|
|
}
|
|
|
|
|
|
void ImProcCoordinator::updateHistograms (int x1, int y1, int x2, int y2) {
|
|
|
|
memset (rhist, 0, 256*sizeof(int));
|
|
memset (ghist, 0, 256*sizeof(int));
|
|
memset (bhist, 0, 256*sizeof(int));
|
|
|
|
for (int i=y1; i<y2; i++) {
|
|
int ofs = (i*pW + x1)*3;
|
|
for (int j=x1; j<x2; j++) {
|
|
rhist[previmg->data[ofs++]]++;
|
|
ghist[previmg->data[ofs++]]++;
|
|
bhist[previmg->data[ofs++]]++;
|
|
}
|
|
}
|
|
|
|
memset (Lhist, 0, 256*sizeof(int));
|
|
for (int i=y1; i<y2; i++)
|
|
for (int j=x1; j<x2; j++) {
|
|
Lhist[nprevl->L[i][j]/256]++;
|
|
}
|
|
|
|
/*for (int i=0; i<256; i++) {
|
|
Lhist[i] = (int)(256*sqrt(Lhist[i]));
|
|
rhist[i] = (int)(256*sqrt(rhist[i]));
|
|
ghist[i] = (int)(256*sqrt(ghist[i]));
|
|
bhist[i] = (int)(256*sqrt(bhist[i]));
|
|
bcrgbhist[i] = (int)(256*sqrt(bcrgbhist[i]));
|
|
bcLhist[i] = (int)(256*sqrt(bcLhist[i]));
|
|
}*/
|
|
}
|
|
|
|
void ImProcCoordinator::progress (Glib::ustring str, int pr) {
|
|
|
|
/* if (plistener) {
|
|
plistener->setProgressStr (str);
|
|
plistener->setProgress ((double)pr / 100.0);
|
|
}*/
|
|
}
|
|
|
|
void ImProcCoordinator::getAutoWB (double& temp, double& green) {
|
|
|
|
if (imgsrc) {
|
|
if (!awbComputed) {
|
|
minit.lock ();
|
|
autoWB = imgsrc->getAutoWB ();
|
|
minit.unlock ();
|
|
awbComputed = true;
|
|
}
|
|
temp = autoWB.getTemp ();
|
|
green = autoWB.getGreen ();
|
|
}
|
|
}
|
|
|
|
void ImProcCoordinator::getCamWB (double& temp, double& green) {
|
|
|
|
if (imgsrc) {
|
|
temp = imgsrc->getWB().getTemp ();
|
|
green = imgsrc->getWB().getGreen ();
|
|
}
|
|
}
|
|
|
|
void ImProcCoordinator::getSpotWB (int x, int y, int rect, double& temp, double& tgreen) {
|
|
|
|
mProcessing.lock ();
|
|
std::vector<Coord2D> points, red, green, blue;
|
|
for (int i=y-rect; i<=y+rect; i++)
|
|
for (int j=x-rect; j<=x+rect; j++)
|
|
points.push_back (Coord2D (j, i));
|
|
|
|
ipf.transCoord (fw, fh, points, red, green, blue);
|
|
int tr = TR_NONE;
|
|
if (params.coarse.rotate==90) tr |= TR_R90;
|
|
if (params.coarse.rotate==180) tr |= TR_R180;
|
|
if (params.coarse.rotate==270) tr |= TR_R270;
|
|
if (params.coarse.hflip) tr |= TR_HFLIP;
|
|
if (params.coarse.vflip) tr |= TR_VFLIP;
|
|
|
|
ColorTemp ret = imgsrc->getSpotWB (red, green, blue, tr);
|
|
currWB = ColorTemp (params.wb.temperature, params.wb.green);
|
|
mProcessing.unlock ();
|
|
if (ret.getTemp() > 0) {
|
|
temp = ret.getTemp ();
|
|
tgreen = ret.getGreen ();
|
|
} else {
|
|
temp = currWB.getTemp ();
|
|
tgreen = currWB.getGreen ();
|
|
}
|
|
}
|
|
|
|
void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int &h) {
|
|
|
|
mProcessing.lock ();
|
|
|
|
double fillscale = ipf.getTransformAutoFill (fullw, fullh);
|
|
if (ratio>0) {
|
|
w = fullw * fillscale;
|
|
h = w / ratio;
|
|
if (h > fullh * fillscale) {
|
|
h = fullh * fillscale;
|
|
w = h * ratio;
|
|
}
|
|
}
|
|
else {
|
|
w = fullw * fillscale;
|
|
h = fullh * fillscale;
|
|
}
|
|
x = (fullw - w) / 2;
|
|
y = (fullh - h) / 2;
|
|
|
|
mProcessing.unlock ();
|
|
}
|
|
|
|
void ImProcCoordinator::fullUpdatePreviewImage () {
|
|
|
|
if (destroying)
|
|
return;
|
|
|
|
updaterThreadStart.lock ();
|
|
if (updaterRunning && thread) {
|
|
changeSinceLast = 0;
|
|
thread->join ();
|
|
}
|
|
|
|
if (plistener)
|
|
plistener->setProgressState (1);
|
|
|
|
updatePreviewImage (ALL);
|
|
|
|
if (plistener)
|
|
plistener->setProgressState (0);
|
|
|
|
updaterThreadStart.unlock ();
|
|
}
|
|
|
|
void ImProcCoordinator::fullUpdateDetailedCrops () {
|
|
|
|
if (destroying)
|
|
return;
|
|
|
|
updaterThreadStart.lock ();
|
|
if (updaterRunning && thread) {
|
|
changeSinceLast = 0;
|
|
thread->join ();
|
|
}
|
|
|
|
if (plistener)
|
|
plistener->setProgressState (1);
|
|
|
|
for (int i=0; i<crops.size(); i++)
|
|
crops[i]->update (ALL, true);
|
|
|
|
if (plistener)
|
|
plistener->setProgressState (0);
|
|
|
|
updaterThreadStart.unlock ();
|
|
}
|
|
|
|
|
|
void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname) {
|
|
|
|
mProcessing.lock ();
|
|
|
|
int fW, fH;
|
|
imgsrc->getFullSize (fW, fH, 0);
|
|
PreviewProps pp (0, 0, fW, fH, 1);
|
|
ProcParams ppar = params;
|
|
ppar.hlrecovery.enabled = false;
|
|
ppar.icm.input = "(none)";
|
|
Image16* im = new Image16 (fW, fH);
|
|
imgsrc->preprocess( ppar.raw );
|
|
imgsrc->demosaic(ppar.raw );
|
|
imgsrc->getImage (imgsrc->getWB(), 0, im, pp, ppar.hlrecovery, ppar.icm, ppar.raw);
|
|
im->saveJPEG (fname, 85);
|
|
mProcessing.unlock ();
|
|
}
|
|
|
|
void ImProcCoordinator::stopProcessing () {
|
|
|
|
updaterThreadStart.lock ();
|
|
if (updaterRunning && thread) {
|
|
changeSinceLast = 0;
|
|
thread->join ();
|
|
}
|
|
updaterThreadStart.unlock ();
|
|
}
|
|
|
|
void ImProcCoordinator::startProcessing () {
|
|
|
|
#undef THREAD_PRIORITY_NORMAL
|
|
|
|
if (!destroying) {
|
|
updaterThreadStart.lock ();
|
|
if (!updaterRunning) {
|
|
thread = NULL;
|
|
updaterRunning = true;
|
|
updaterThreadStart.unlock ();
|
|
|
|
batchThread->yield(); //the running batch should wait other threads to avoid conflict
|
|
|
|
thread = Glib::Thread::create(sigc::mem_fun(*this, &ImProcCoordinator::process), 0, true, true, Glib::THREAD_PRIORITY_NORMAL);
|
|
|
|
}
|
|
else
|
|
updaterThreadStart.unlock ();
|
|
}
|
|
}
|
|
|
|
void ImProcCoordinator::process () {
|
|
|
|
if (plistener)
|
|
plistener->setProgressState (1);
|
|
|
|
paramsUpdateMutex.lock ();
|
|
while (changeSinceLast) {
|
|
params = nextParams;
|
|
int ch = changeSinceLast;
|
|
changeSinceLast = 0;
|
|
paramsUpdateMutex.unlock ();
|
|
if (ch&32767)
|
|
updatePreviewImage (ch);
|
|
paramsUpdateMutex.lock ();
|
|
}
|
|
paramsUpdateMutex.unlock ();
|
|
updaterRunning = false;
|
|
|
|
if (plistener)
|
|
plistener->setProgressState (0);
|
|
}
|
|
|
|
ProcParams* ImProcCoordinator::getParamsForUpdate (ProcEvent change) {
|
|
|
|
paramsUpdateMutex.lock ();
|
|
changeSinceLast |= refreshmap[(int)change];
|
|
return &nextParams;
|
|
}
|
|
|
|
void ImProcCoordinator::paramsUpdateReady () {
|
|
|
|
paramsUpdateMutex.unlock ();
|
|
startProcessing ();
|
|
}
|
|
|
|
|
|
}
|