Solving issue 2023: "Pseudo memory leak with Detail window + memory handling optimization"

The Detail window buffers are now freed up when the it is closed. The CIECAM buffers are allocated only if necessary now, and if the single block allocation fails, it will try to allocate it in several blocks.
This commit is contained in:
Hombre
2013-11-06 00:19:06 +01:00
parent 91c45758c4
commit b7e0b0ebab
10 changed files with 599 additions and 504 deletions

View File

@@ -155,7 +155,7 @@ namespace rtengine {
//srand((unsigned)time(0));//test with random data
const float gain = pow (2.0f, expcomp);
const float gain = pow (2.0f, float(expcomp));
float incr=1.f;
float noisevar_Ldetail = SQR((SQR(100.f-dnparams.Ldetail) + 50.f*(100.f-dnparams.Ldetail)) * TS * 0.5f * incr);

View File

@@ -11,8 +11,15 @@ CieImage::CieImage (int w, int h) : fromImage(false), W(w), H(h) {
// ch_p = new float*[H];
h_p = new float*[H];
data = new float [W*H*6];
float * index = data;
// Initialize the pointers to zero
for (unsigned int c=0; c<6; ++c)
data[c] = NULL;
// Trying to allocate all in one block
data[0] = new (std::nothrow) float [W*H*6];
if (data[0]) {
float * index = data[0];
for (int i=0; i<H; i++)
J_p[i] = index + i*W;
index+=W*H;
@@ -34,6 +41,34 @@ CieImage::CieImage (int w, int h) : fromImage(false), W(w), H(h) {
for (int i=0; i<H; i++)
h_p[i] = index + i*W;
}
else {
// Allocating each plane separately
for (unsigned int c=0; c<6; ++c)
data[c] = new float [W*H];
unsigned int c = 0;
for (int i=0; i<H; i++)
J_p[i] = data[c] + i*W;
++c;
for (int i=0; i<H; i++)
Q_p[i] = data[c] + i*W;
++c;
for (int i=0; i<H; i++)
M_p[i] = data[c] + i*W;
++c;
for (int i=0; i<H; i++)
C_p[i] = data[c] + i*W;
++c;
for (int i=0; i<H; i++)
sh_p[i] = data[c] + i*W;
++c;
// for (int i=0; i<H; i++)
// ch_p[i] = data[c] + i*W;
// ++c;
for (int i=0; i<H; i++)
h_p[i] = data[c] + i*W;
}
}
CieImage::~CieImage () {
@@ -46,13 +81,19 @@ CieImage::~CieImage () {
// delete [] ch_p;
delete [] h_p;
delete [] data;
for (unsigned int c=0; c<6; ++c)
if (data[c]) delete [] data[c];
}
}
void CieImage::CopyFrom(CieImage *Img){
if (!data [1])
// Only one allocated block
memcpy(data, Img->data, W*H*6*sizeof(float));
else
// Separate allocation
for (unsigned int c=0; c<6; ++c)
memcpy(data[c], Img->data[c], W*H*sizeof(float));
}
}

View File

@@ -29,7 +29,7 @@ private:
public:
int W, H;
float * data;
float * data[6];
float** J_p;
float** Q_p;
float** M_p;

View File

@@ -30,9 +30,15 @@ namespace rtengine {
extern const Settings* settings;
Crop::Crop (ImProcCoordinator* parent)
: resizeCrop(NULL), transCrop(NULL), updating(false),
skip(10),cropw(-1), croph(-1), trafw(-1), trafh(-1),
borderRequested(32), cropAllocated(false),
: origCrop(NULL), transCrop(NULL), laboCrop(NULL), labnCrop(NULL),
cropImg(NULL), cieCrop(NULL), cbuf_real(NULL), cshmap(NULL),
cbuffer(NULL), updating(false), newUpdatePending(false),
skip(10),
cropx(0), cropy(0), cropw(-1), croph(-1),
trafx(0), trafy(0), trafw(-1), trafh(-1),
rqcropx(0), rqcropy(0), rqcropw(-1), rqcroph(-1),
borderRequested(32), upperBorder(0), leftBorder(0),
cropAllocated(false),
cropImageListener(NULL), parent(parent)
{
parent->crops.push_back (this);
@@ -40,15 +46,19 @@ Crop::Crop (ImProcCoordinator* parent)
Crop::~Crop () {
cropMutex.lock ();
parent->mProcessing.lock ();
MyMutex::MyLock cropLock(cropMutex);
MyMutex::MyLock processingLock(parent->mProcessing);
std::vector<Crop*>::iterator i = std::find (parent->crops.begin(), parent->crops.end(), this);
if (i!=parent->crops.end ())
parent->crops.erase (i);
freeAll ();
parent->mProcessing.unlock ();
cropMutex.unlock ();
}
void Crop::destroy () {
MyMutex::MyLock lock(cropMutex);
MyMutex::MyLock processingLock(parent->mProcessing); ///////// RETESTER MAINTENANT QUE CE VERROU EST AJOUTE!!!
freeAll();
}
void Crop::setListener (DetailedCropListener* il) {
@@ -80,10 +90,10 @@ void Crop::update (int todo) {
if (needsinitupdate || (todo & M_HIGHQUAL))
todo = ALL;
// set improcfuncions' scale now that skip has been updated
// Tells to the ImProcFunctions' tool what is the preview scale, which may lead to some simplifications
parent->ipf.setScale (skip);
baseCrop = origCrop;
Imagefloat* baseCrop = origCrop;
bool needstransform = parent->ipf.needsTransform();
@@ -107,26 +117,28 @@ void Crop::update (int todo) {
//parent->imgsrc->convertColorSpace(origCrop, params.icm);
if (todo & M_LINDENOISE) {
if (skip==1 && params.dirpyrDenoise.enabled) {
if (skip==1 && params.dirpyrDenoise.enabled)
parent->ipf.RGB_denoise(origCrop, origCrop, parent->imgsrc->isRAW(), /*Roffset,*/ params.dirpyrDenoise, params.defringe, parent->imgsrc->getDirPyrDenoiseExpComp());
}
}
parent->imgsrc->convertColorSpace(origCrop, params.icm, params.raw);
}
// transform
if ((!needstransform && transCrop) || (transCrop && (transCrop->width!=cropw || transCrop->height!=croph))) {
delete transCrop;
transCrop = NULL;
}
if (needstransform && !transCrop)
if (needstransform) {
if (!transCrop)
transCrop = new Imagefloat (cropw, croph);
if ((todo & M_TRANSFORM) && needstransform)
parent->ipf.transform (baseCrop, transCrop, cropx/skip, cropy/skip, trafx/skip, trafy/skip, SKIPS(parent->fw,skip), SKIPS(parent->fh,skip),
parent->imgsrc->getMetaData()->getFocalLen(), parent->imgsrc->getMetaData()->getFocalLen35mm(),
parent->imgsrc->getMetaData()->getFocusDist(), parent->imgsrc->getRotateDegree(), false);
if (transCrop)
baseCrop = transCrop;
}
else {
if (transCrop) delete transCrop;
transCrop = NULL;
}
// blurmap for shadow & highlights
if ((todo & M_BLURMAP) && params.sh.enabled) {
@@ -205,31 +217,39 @@ void Crop::update (int todo) {
if(params.colorappearance.enabled){
float fnum = parent->imgsrc->getMetaData()->getFNumber (); // F number
float fiso = parent->imgsrc->getMetaData()->getISOSpeed () ; // ISO
float fspeed = parent->imgsrc->getMetaData()->getShutterSpeed () ;//speed
float fcomp = parent->imgsrc->getMetaData()->getExpComp ();//compensation + -
float adap2,adap;
double ada, ada2;
if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) {adap=adap=2000.f;ada=ada2=2000.;}//if no exif data or wrong
float fspeed = parent->imgsrc->getMetaData()->getShutterSpeed () ; // Speed
double fcomp = parent->imgsrc->getMetaData()->getExpComp (); // Compensation +/-
double adap; // Scene's luminosity adaptation factor
if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong
adap=2000.;
}
else {
float E_V = fcomp + log2 ((fnum*fnum) / fspeed / (fiso/100.f));
float expo2= params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV
E_V += expo2;
float expo1;//exposure raw white point
expo1=log2(params.raw.expos);//log2 ==>linear to EV
E_V += expo1;
adap2 = adap= powf(2.f, E_V-3.f);//cd / m2
ada=ada2=(double) adap;
double E_V = fcomp + log2 (double((fnum*fnum) / fspeed / (fiso/100.f)));
E_V += params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV
E_V += log2(params.raw.expos);// exposure raw white point ; log2 ==> linear to EV
adap= pow(2., E_V-3.);// cd / m2
// end calculation adaptation scene luminosity
}
int begh = 0, endh = labnCrop->H;
bool execsharp=false;
float d;
double dd;
if(skip==1) execsharp=true;
if(settings->ciecamfloat) {parent->ipf.ciecam_02float (cieCrop, adap, begh, endh, 1, 2,labnCrop, &params,parent->customColCurve1,parent->customColCurve2,parent->customColCurve3, dummy, dummy, 5, 1,(float**)cbuffer, execsharp, d);
if (!cieCrop)
cieCrop = new CieImage (cropw, croph);
if(settings->ciecamfloat) {
float d; // not used after this block
parent->ipf.ciecam_02float (cieCrop, float(adap), begh, endh, 1, 2, labnCrop, &params, parent->customColCurve1, parent->customColCurve2, parent->customColCurve3, dummy, dummy, 5, 1,(float**)cbuffer, execsharp, d);
}
else {parent->ipf.ciecam_02 (cieCrop,ada, begh, endh, 1, 2, labnCrop, &params,parent->customColCurve1,parent->customColCurve2,parent->customColCurve3, dummy, dummy, 5, 1,(float**)cbuffer, execsharp, dd);}
else {
double dd; // not used after this block
parent->ipf.ciecam_02 (cieCrop,adap, begh, endh, 1, 2, labnCrop, &params, parent->customColCurve1, parent->customColCurve2, parent->customColCurve3, dummy, dummy, 5, 1,(float**)cbuffer, execsharp, dd);
}
}
else {
// CIECAM is disbaled, we free up its image buffer to save some space
if (cieCrop) delete cieCrop; cieCrop=NULL;
}
}
// switch back to rgb
@@ -300,26 +320,23 @@ void Crop::freeAll () {
if (settings->verbose) printf ("freeallcrop starts %d\n", (int)cropAllocated);
if (cropAllocated) {
delete origCrop;
if (transCrop)
delete transCrop;
transCrop = NULL;
if (resizeCrop)
delete resizeCrop;
resizeCrop = NULL;
delete laboCrop;
delete cieCrop;
delete labnCrop;
delete cropImg;
delete cshmap;
// for (int i=0; i<croph; i++)
// delete [] cbuffer[i];
delete [] cbuf_real;
delete [] cbuffer;
if (origCrop ) { delete origCrop; origCrop=NULL; }
if (transCrop) { delete transCrop; transCrop=NULL; }
if (laboCrop ) { delete laboCrop; laboCrop=NULL; }
if (labnCrop ) { delete labnCrop; labnCrop=NULL; }
if (cropImg ) { delete cropImg; cropImg=NULL; }
if (cieCrop ) { delete cieCrop; cieCrop=NULL; }
if (cbuf_real) { delete [] cbuf_real; cbuf_real=NULL; }
if (cbuffer ) { delete [] cbuffer; cbuffer=NULL; }
if (cshmap ) { delete cshmap; cshmap=NULL; }
}
cropAllocated = false;
}
/** @brief Handles crop's image buffer reallocation and trigger sizeChanged of SizeListener[s]
* If the scale changes, this method will free all buffers and reallocate ones of the new size.
* It will then tell to the SizeListener that size has changed (sizeChanged)
*/
bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool internal) {
if (settings->verbose) printf ("setcropsizes before lock\n");
@@ -392,20 +409,16 @@ if (settings->verbose) printf ("setcropsizes before lock\n");
trafh = orH;
origCrop = new Imagefloat (trafw, trafh);
//transCrop will be allocated later, if necessary
laboCrop = new LabImage (cropw, croph);
labnCrop = new LabImage (cropw, croph);
cropImg = new Image8 (cropw, croph);
cieCrop = new CieImage (cropw, croph);
cshmap = new SHMap (cropw, croph, true);
//cieCrop is only used in Crop::update, it will be allocated on first use and deleted if not used anymore
cbuffer = new float*[croph];
cbuf_real= new float[(croph+2)*cropw];
for (int i=0; i<croph; i++)
cbuffer[i] = cbuf_real+cropw*i+cropw;
resizeCrop = NULL;
transCrop = NULL;
cshmap = new SHMap (cropw, croph, true);
cropAllocated = true;
@@ -425,20 +438,31 @@ if (settings->verbose) printf ("setcropsizes before lock\n");
return changed;
}
// Try a simple, threadless update flag first
/** @brief Look out if a new thread has to be started to process the update
*
* @return If true, a new updating thread has to be created. If false, the current updating thread will be used
*/
bool Crop::tryUpdate() {
bool needsFullUpdate = true;
bool needsNewThread = true;
// If there are more update request, the following WHILE will collect it
if (updating) {
needsNext = true;
needsFullUpdate = false;
} else updating = true;
// tells to the updater thread that a new update is pending
newUpdatePending = true;
// no need for a new thread, the current one will do the job
needsNewThread = false;
}
else
// the crop is now being updated ...well, when fullUpdate will be called
updating = true;
return needsFullUpdate;
return needsNewThread;
}
// Full update, should be called via thread
/* @brief Handles Crop updating in its own thread
*
* This method will cycle updates ss long as Crop::newUpdatePending will be true. During the processing,
* intermediary update will be automatically flushed by Crop::tryUpdate.
*/
void Crop::fullUpdate () {
parent->updaterThreadStart.lock ();
@@ -453,12 +477,13 @@ void Crop::fullUpdate () {
if (parent->plistener)
parent->plistener->setProgressState (true);
needsNext = true;
while (needsNext) {
needsNext = false;
// If there are more update request, the following WHILE will collect it
newUpdatePending = true;
while (newUpdatePending) {
newUpdatePending = false;
update (ALL);
}
updating = false;
updating = false; // end of crop update
if (parent->plistener)
parent->plistener->setProgressState (false);

View File

@@ -37,20 +37,24 @@ class ImProcCoordinator;
class Crop : public DetailedCrop {
protected:
Imagefloat* origCrop, *baseCrop;
Imagefloat* *resizeCrop, *transCrop;
LabImage *laboCrop, *labnCrop;
Image8 *cropImg; // permanently allocated in RAM and only renewed on size changes
CieImage *cieCrop;
// --- permanently allocated in RAM and only renewed on size changes
Imagefloat* origCrop; // "one chunk" allocation
Imagefloat* transCrop; // "one chunk" allocation, allocated if necessary
LabImage* laboCrop; // "one chunk" allocation
LabImage* labnCrop; // "one chunk" allocation
Image8* cropImg; // "one chunk" allocation
CieImage* cieCrop; // allocating 6 images, each in "one chunk" allocation
float * cbuf_real; // "one chunk" allocation
SHMap* cshmap; // per line allocation
// -----------------------------------------------------------------
float** cbuffer;
float * cbuf_real;
SHMap* cshmap;
bool updating, needsNext;
bool updating; /// Flag telling if an updater thread is currently processing
bool newUpdatePending; /// Flag telling the updater thread that a new update is pending
int skip;
int cropx, cropy, cropw, croph; // size of the detail crop image ('skip' taken into account), with border
int trafx, trafy, trafw, trafh; // the size and position to get from the imagesource that is transformed to the requested crop area
int rqcropx, rqcropy, rqcropw, rqcroph; // size of the requested detail crop image (the image might be smaller) (without border)
int cropx, cropy, cropw, croph; /// size of the detail crop image ('skip' taken into account), with border
int trafx, trafy, trafw, trafh; /// the size and position to get from the imagesource that is transformed to the requested crop area
int rqcropx, rqcropy, rqcropw, rqcroph; /// size of the requested detail crop image (the image might be smaller) (without border)
int borderRequested, upperBorder, leftBorder;
bool cropAllocated;
@@ -70,11 +74,15 @@ class Crop : public DetailedCrop {
void update (int todo);
void setWindow (int cx, int cy, int cw, int ch, int skip) { setCropSizes (cx, cy, cw, ch, skip, false); }
bool tryUpdate (); // First try, only make fullUpdate if this returns false
/** @brief Synchronously look out if a full update is necessary
* First try, only make fullUpdate if this returns false
*/
bool tryUpdate ();
/** @brief Asynchronously reprocess the detailed crop */
void fullUpdate (); // called via thread
void setListener (DetailedCropListener* il);
void destroy () {}
void destroy ();
int get_skip () { return skip;}
};
}

View File

@@ -29,8 +29,9 @@ namespace rtengine {
extern const Settings* settings;
ImProcCoordinator::ImProcCoordinator ()
: workimg(NULL), lastAwbEqual(0.), ipf(&params, true), scale(10), highDetailPreprocessComputed(false),
highDetailRawComputed(false), allocated(false),
: orig_prev(NULL), oprevi(NULL), oprevl(NULL), nprevl(NULL), previmg(NULL), workimg(NULL),
ncie(NULL), imgsrc(NULL), shmap(NULL), lastAwbEqual(0.), ipf(&params, true), scale(10),
highDetailPreprocessComputed(false), highDetailRawComputed(false), allocated(false),
hltonecurve(65536,0),
shtonecurve(65536,2),//clip above
@@ -106,11 +107,12 @@ DetailedCrop* ImProcCoordinator::createCrop () {
// cropCall: calling crop, used to prevent self-updates
void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
mProcessing.lock ();
MyMutex::MyLock processingLock(mProcessing);
int numofphases = 14;
int readyphase = 0;
// Tells to the ImProcFunctions' tools what is the preview scale, which may lead to some simplifications
ipf.setScale (scale);
// Check if any detail crops need high detail. If not, take a fast path short cut
@@ -177,7 +179,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
if (todo & (M_INIT|M_LINDENOISE)) {
MyMutex::MyLock lock(minit); // Also used in crop window
MyMutex::MyLock initLock(minit); // Also used in crop window
imgsrc->HLRecovery_Global( params.hlrecovery ); // this handles Color HLRecovery
@@ -215,7 +217,10 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
imgsrc->getFullSize (fw, fh, tr);
PreviewProps pp (0, 0, fw, fh, scale);
// Will (re)allocate the preview's buffers
setScale (scale);
imgsrc->getImage (currWB, tr, orig_prev, pp, params.hlrecovery, params.icm, params.raw);
//ColorTemp::CAT02 (orig_prev, &params) ;
@@ -223,10 +228,9 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
if (todo & M_LINDENOISE) {
//printf("denoising!\n");
if (scale==1 && params.dirpyrDenoise.enabled) {
if (scale==1 && params.dirpyrDenoise.enabled)
ipf.RGB_denoise(orig_prev, orig_prev, imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp());
}
}
imgsrc->convertColorSpace(orig_prev, params.icm, params.raw);
ipf.firstAnalysis (orig_prev, &params, vhist16, imgsrc->getGamma());
@@ -254,7 +258,6 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
double shradius = params.sh.radius;
if (!params.sh.hq) shradius *= radius / 1800.0;
shmap->update (oprevi, shradius, ipf.lumimul, params.sh.hq, scale);
}
readyphase++;
@@ -316,13 +319,11 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
if ((todo & M_LUMACURVE) || todo==CROP) {
CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, lhist16, lhist16Cropped,
lumacurve, histLCurve, scale==1 ? 1 : 16, utili);
}
if (todo & M_LUMACURVE) {
CurveFactory::complexsgnCurve (autili, butili,ccutili,cclutili, params.labCurve.chromaticity, params.labCurve.rstprotection,
params.labCurve.acurve, params.labCurve.bcurve,params.labCurve.cccurve,params.labCurve.lccurve, chroma_acurve, chroma_bcurve, satcurve,lhskcurve,
lhist16Clad,lhist16CroppedClad, histCCurve, scale==1 ? 1 : 16);
}
if (todo & (M_LUMINANCE+M_COLOR) ) {
nprevl->CopyFrom(oprevl);
@@ -330,7 +331,6 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
progress ("Applying Color Boost...",100*readyphase/numofphases);
int poscc;
ipf.chromiLuminanceCurve (pW,nprevl, nprevl, chroma_acurve, chroma_bcurve, satcurve,lhskcurve, lumacurve, utili, autili, butili, ccutili,cclutili, histCCurve);
ipf.vibrance(nprevl);
if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) ipf.EPDToneMap(nprevl,5,1);
@@ -379,8 +379,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
ipf.dirpyrequalizer (nprevl);
readyphase++;
}
}
//L histo and Chroma histo for ciecam
// histogram well be for Lab (Lch) values, because very difficult to do with J,Q, M, s, C
int x1, y1, x2, y2, pos, posc;
@@ -406,25 +406,22 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
customColCurve1,
customColCurve2,
customColCurve3,
scale==1 ? 1 : 1);
int Iterates=0;
scale==1 ? 1 : 1
);
if(params.colorappearance.enabled){
float fnum = imgsrc->getMetaData()->getFNumber (); // F number
float fiso = imgsrc->getMetaData()->getISOSpeed () ; // ISO
float fspeed = imgsrc->getMetaData()->getShutterSpeed () ;//speed
float fcomp = imgsrc->getMetaData()->getExpComp ();//compensation + -
float adap2,adap;
double ada, ada2;
if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) {adap=adap=2000.f;ada=2000.;}//if no exif data or wrong
float fspeed = imgsrc->getMetaData()->getShutterSpeed () ; // Speed
double fcomp = imgsrc->getMetaData()->getExpComp (); // Compensation +/-
double adap;
if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong
adap=2000.;
}
else {
float E_V = fcomp + log2 ((fnum*fnum) / fspeed / (fiso/100.f));
float expo2= params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV
E_V += expo2;
float expo1;//exposure raw white point
expo1=log2(params.raw.expos);//log2 ==>linear to EV
E_V += expo1;
adap2 = adap= powf(2.f, E_V-3.f);//cd / m2
ada=ada2=(double) adap;
double E_V = fcomp + log2 (double((fnum*fnum) / fspeed / (fiso/100.f)));
E_V += params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV
E_V += log2(params.raw.expos);// exposure raw white point ; log2 ==> linear to EV
adap= powf(2.f, E_V-3.f);// cd / m2
// end calculation adaptation scene luminosity
}
int begh=0;
@@ -436,20 +433,31 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
buffer[i] = new float[pW];
bool execsharp=false;
if(scale==1) execsharp=true;
if(settings->ciecamfloat){ipf.ciecam_02float (ncie, adap, begh, endh, pW, 2, nprevl, &params, customColCurve1,customColCurve2,customColCurve3, histLCAM, histCCAM, 5, 1, (float**)buffer, execsharp, d);
if(params.colorappearance.autodegree && acListener && params.colorappearance.enabled) acListener->autoCamChanged(100.*(double)d);
if(params.colorappearance.autoadapscen && acListener && params.colorappearance.enabled) acListener->adapCamChanged(adap2);//real value of adapt scene luminosity
}
else {ipf.ciecam_02 (ncie, ada, begh, endh, pW, 2, nprevl, &params, customColCurve1,customColCurve2,customColCurve3, histLCAM, histCCAM, 5, 1, (float**)buffer, execsharp, dd);
if(params.colorappearance.autodegree && acListener && params.colorappearance.enabled) acListener->autoCamChanged(100.*dd);
if(params.colorappearance.autoadapscen && acListener && params.colorappearance.enabled) acListener->adapCamChanged(ada);
if(!ncie)
ncie = new CieImage (pW, pH);
if(settings->ciecamfloat){
ipf.ciecam_02float (ncie, float(adap), begh, endh, pW, 2, nprevl, &params, customColCurve1,customColCurve2,customColCurve3, histLCAM, histCCAM, 5, 1, (float**)buffer, execsharp, d);
if(params.colorappearance.autodegree && acListener && params.colorappearance.enabled) acListener->autoCamChanged(100.*(double)d);
if(params.colorappearance.autoadapscen && acListener && params.colorappearance.enabled) acListener->adapCamChanged(adap);//real value of adapt scene luminosity
}
else {
ipf.ciecam_02 (ncie, adap, begh, endh, pW, 2, nprevl, &params, customColCurve1,customColCurve2,customColCurve3, histLCAM, histCCAM, 5, 1, (float**)buffer, execsharp, dd);
if(params.colorappearance.autodegree && acListener && params.colorappearance.enabled) acListener->autoCamChanged(100.*dd);
if(params.colorappearance.autoadapscen && acListener && params.colorappearance.enabled) acListener->adapCamChanged(adap);
}
for (int i=0; i<pH; i++)
delete [] buffer[i];
delete [] buffer;
readyphase++;
}
else {
// CIECAM is disbaled, we free up its image buffer to save some space
if (ncie)
delete ncie; ncie=NULL;
}
}
// process crop, if needed
for (size_t i=0; i<crops.size(); i++)
@@ -458,7 +466,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
progress ("Conversion to RGB...",100*readyphase/numofphases);
if (todo!=CROP) {
previmg->getMutex().lock();
MyMutex::MyLock prevImgLock(previmg->getMutex());
try
{
ipf.lab2monitorRgb (nprevl, previmg);
@@ -468,11 +476,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
catch(char * str)
{
progress ("Error converting file...",0);
previmg->getMutex().unlock();
mProcessing.unlock ();
return;
}
previmg->getMutex().unlock();
}
if (!resultValid) {
resultValid = true;
@@ -489,8 +494,6 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
updateLRGBHistograms ();
hListener->histogramChanged (histRed, histGreen, histBlue, histLuma, histToneCurve, histLCurve,histCCurve, histLCAM, histCCAM, histRedRaw, histGreenRaw, histBlueRaw, histChroma);
}
mProcessing.unlock ();
}
@@ -500,11 +503,12 @@ void ImProcCoordinator::freeAll () {
if (allocated) {
if (orig_prev!=oprevi)
delete oprevi;
delete orig_prev;
delete oprevl;
delete nprevl;
delete ncie;
delete oprevi; oprevi = NULL;
delete orig_prev; orig_prev = NULL;
delete oprevl; oprevl = NULL;
delete nprevl; nprevl = NULL;
if (ncie)
delete ncie; ncie = NULL;
if (imageListener) {
imageListener->delImage (previmg);
@@ -519,6 +523,12 @@ void ImProcCoordinator::freeAll () {
allocated = false;
}
/** @brief Handles image buffer (re)allocation and trigger sizeChanged of SizeListener[s]
* If the scale change, this method will free all buffers and reallocate ones of the new size.
* It will then tell to the SizeListener that size has changed (sizeChanged)
*
* @param prevscale New Preview's scale.
*/
void ImProcCoordinator::setScale (int prevscale) {
if (settings->verbose) printf ("setscale before lock\n");
@@ -549,7 +559,7 @@ if (settings->verbose) printf ("setscale before lock\n");
oprevi = orig_prev;
oprevl = new LabImage (pW, pH);
nprevl = new LabImage (pW, pH);
ncie = new CieImage (pW, pH);
//ncie is only used in ImProcCoordinator::updatePreviewImage, it will be allocated on first use and deleted if not used anymore
previmg = new Image8 (pW, pH);
workimg = new Image8 (pW, pH);
shmap = new SHMap (pW, pH, true);
@@ -598,7 +608,6 @@ void ImProcCoordinator::updateLRGBHistograms () {
for (int j=x1; j<x2; j++) {
histChroma[(int)(sqrt(nprevl->a[i][j]*nprevl->a[i][j] + nprevl->b[i][j]*nprevl->b[i][j]))/188]++;//188 = 48000/256
histLuma[(int)(nprevl->L[i][j]/128)]++;
}
/*for (int i=0; i<256; i++) {
@@ -657,7 +666,10 @@ void ImProcCoordinator::getCamWB (double& temp, double& green) {
void ImProcCoordinator::getSpotWB (int x, int y, int rect, double& temp, double& tgreen) {
mProcessing.lock ();
ColorTemp ret;
{
MyMutex::MyLock lock(mProcessing);
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++)
@@ -670,12 +682,12 @@ void ImProcCoordinator::getSpotWB (int x, int y, int rect, double& temp, double&
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, params.wb.equal);
ret = imgsrc->getSpotWB (red, green, blue, tr, params.wb.equal);
currWB = ColorTemp (params.wb.temperature, params.wb.green,params.wb.equal, params.wb.method);
//double rr,gg,bb;
//currWB.getMultipliers(rr,gg,bb);
mProcessing.unlock ();
} // end of mutex lockong
if (ret.getTemp() > 0) {
temp = ret.getTemp ();
@@ -688,7 +700,7 @@ void ImProcCoordinator::getSpotWB (int x, int y, int rect, double& temp, double&
void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int &h) {
mProcessing.lock ();
MyMutex::MyLock lock(mProcessing);
LCPMapper *pLCPMap=NULL;
if (params.lensProf.lcpFile.length() && imgsrc->getMetaData()->getFocalLen()>0) {
@@ -712,14 +724,12 @@ void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int &
}
x = (fullw - w) / 2;
y = (fullh - h) / 2;
mProcessing.unlock ();
}
void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname) {
mProcessing.lock ();
MyMutex::MyLock lock(mProcessing);
int fW, fH;
imgsrc->getFullSize (fW, fH, 0);
@@ -758,7 +768,6 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname) {
im16->saveTIFF (fname,16,true);
delete im16;
//im->saveJPEG (fname, 85);
mProcessing.unlock ();
}
void ImProcCoordinator::stopProcessing () {

View File

@@ -35,8 +35,17 @@ using namespace procparams;
class Crop;
// Manages the image processing, espc. of the preview windows
// There is one ImProcCoordinator per edit panel
/** @brief Manages the image processing, espc. of the preview windows
*
* There is one ImProcCoordinator per edit panel.
*
* The ImProcCoordinator handle an sized down image representation of the full image, that is used when paning
* and in the Navigator object.
*
* Each ImProcCoordinator handles an rtengine::Crop list, which process images too with their own pipeline,
* but using this class' LUT and other precomputed parameters. The main preview area is displaying a non framed Crop object,
* while detail windows are framed Crop objects.
*/
class ImProcCoordinator : public StagedImageProcessor {
friend class Crop;
@@ -124,7 +133,7 @@ class ImProcCoordinator : public StagedImageProcessor {
bool resultValid;
MyMutex minit;
MyMutex minit; // to gain mutually exclusive access to ... to what exactly?
void progress (Glib::ustring str, int pr);
void reallocAll ();

View File

@@ -252,10 +252,11 @@ namespace rtengine {
class AutoCamListener {
public :
virtual ~AutoCamListener() {}
virtual void autoCamChanged (double ccam) {}
virtual void adapCamChanged (double cadap) {}
};
/** This class represents a detailed part of the image (looking through a kind of window).
* It can be created and destroyed with the appropriate members of StagedImageProcessor.
* Several crops can be assigned to the same image. */

View File

@@ -42,8 +42,10 @@ CropHandler::~CropHandler () {
ipc->delSizeListener (this);
setEnabled (false);
if (crop)
if (crop) {
crop->destroy ();
crop = NULL;
}
cimg.lock ();
if (chi->pending)
chi->destroyed = true;