diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index 39f542d0c..fef2d047a 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -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); diff --git a/rtengine/cieimage.cc b/rtengine/cieimage.cc index 2ae1bd9c8..ae66f92b8 100644 --- a/rtengine/cieimage.cc +++ b/rtengine/cieimage.cc @@ -10,49 +10,90 @@ CieImage::CieImage (int w, int h) : fromImage(false), W(w), H(h) { sh_p = new float*[H]; // ch_p = new float*[H]; h_p = new float*[H]; - - data = new float [W*H*6]; - float * index = data; - for (int i=0; idata, W*H*6*sizeof(float)); + 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)); } } diff --git a/rtengine/cieimage.h b/rtengine/cieimage.h index ca6e5785c..0688ad053 100644 --- a/rtengine/cieimage.h +++ b/rtengine/cieimage.h @@ -29,7 +29,7 @@ private: public: int W, H; - float * data; + float * data[6]; float** J_p; float** Q_p; float** M_p; diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index a923d7479..7a4b97cb2 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -30,25 +30,35 @@ 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), - cropImageListener(NULL), parent(parent) + : 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); } Crop::~Crop () { - cropMutex.lock (); - parent->mProcessing.lock (); + MyMutex::MyLock cropLock(cropMutex); + MyMutex::MyLock processingLock(parent->mProcessing); + std::vector::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(); @@ -104,171 +114,181 @@ void Crop::update (int todo) { parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.hlrecovery, params.icm, params.raw ); //ColorTemp::CAT02 (origCrop, ¶ms) ; - //parent->imgsrc->convertColorSpace(origCrop, params.icm); + //parent->imgsrc->convertColorSpace(origCrop, params.icm); if (todo & M_LINDENOISE) { - if (skip==1 && params.dirpyrDenoise.enabled) { - parent->ipf.RGB_denoise(origCrop, origCrop, parent->imgsrc->isRAW(), /*Roffset,*/ params.dirpyrDenoise, params.defringe, parent->imgsrc->getDirPyrDenoiseExpComp()); - } + 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; + 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; } - if (needstransform && !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; // blurmap for shadow & highlights if ((todo & M_BLURMAP) && params.sh.enabled) { double radius = sqrt (double(SKIPS(parent->fw,skip)*SKIPS(parent->fw,skip)+SKIPS(parent->fh,skip)*SKIPS(parent->fh,skip))) / 2.0; - double shradius = params.sh.radius; - if (!params.sh.hq) shradius *= radius / 1800.0; - cshmap->update (baseCrop, shradius, parent->ipf.lumimul, params.sh.hq, skip); + double shradius = params.sh.radius; + if (!params.sh.hq) shradius *= radius / 1800.0; + cshmap->update (baseCrop, shradius, parent->ipf.lumimul, params.sh.hq, skip); cshmap->forceStat (parent->shmap->max_f, parent->shmap->min_f, parent->shmap->avg); } // shadows & highlights & tone curve & convert to cielab - /*int xref,yref; - xref=000;yref=000; - if (colortest && cropw>115 && croph>115) - for(int j=1;j<5;j++){ - xref+=j*30;yref+=j*30; - if (settings->verbose) printf("before rgbProc RGB Xr%i Yr%i Skip=%d R=%f G=%f B=%f gamma=%f \n",xref,yref,skip, - baseCrop->r[(int)(xref/skip)][(int)(yref/skip)]/256, - baseCrop->g[(int)(xref/skip)][(int)(yref/skip)]/256, - baseCrop->b[(int)(xref/skip)][(int)(yref/skip)]/256, - parent->imgsrc->getGamma()); - }*/ - + /*int xref,yref; + xref=000;yref=000; + if (colortest && cropw>115 && croph>115) + for(int j=1;j<5;j++){ + xref+=j*30;yref+=j*30; + if (settings->verbose) printf("before rgbProc RGB Xr%i Yr%i Skip=%d R=%f G=%f B=%f gamma=%f \n",xref,yref,skip, + baseCrop->r[(int)(xref/skip)][(int)(yref/skip)]/256, + baseCrop->g[(int)(xref/skip)][(int)(yref/skip)]/256, + baseCrop->b[(int)(xref/skip)][(int)(yref/skip)]/256, + parent->imgsrc->getGamma()); + }*/ + if (todo & M_RGBCURVE) parent->ipf.rgbProc (baseCrop, laboCrop, parent->hltonecurve, parent->shtonecurve, parent->tonecurve, cshmap, - params.toneCurve.saturation, parent->rCurve, parent->gCurve, parent->bCurve, parent->customToneCurve1, parent->customToneCurve2 ); + params.toneCurve.saturation, parent->rCurve, parent->gCurve, parent->bCurve, parent->customToneCurve1, parent->customToneCurve2 ); - /*xref=000;yref=000; - if (colortest && cropw>115 && croph>115) - for(int j=1;j<5;j++){ - xref+=j*30;yref+=j*30; - if (settings->verbose) { + /*xref=000;yref=000; + if (colortest && cropw>115 && croph>115) + for(int j=1;j<5;j++){ + xref+=j*30;yref+=j*30; + if (settings->verbose) { printf("after rgbProc RGB Xr%i Yr%i Skip=%d R=%f G=%f B=%f \n",xref,yref,skip, - baseCrop->r[(int)(xref/skip)][(int)(yref/skip)]/256, - baseCrop->g[(int)(xref/skip)][(int)(yref/skip)]/256, - baseCrop->b[(int)(xref/skip)][(int)(yref/skip)]/256); - printf("after rgbProc Lab Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip, - laboCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327, - laboCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327, - laboCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327); + baseCrop->r[(int)(xref/skip)][(int)(yref/skip)]/256, + baseCrop->g[(int)(xref/skip)][(int)(yref/skip)]/256, + baseCrop->b[(int)(xref/skip)][(int)(yref/skip)]/256); + printf("after rgbProc Lab Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip, + laboCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327, + laboCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327, + laboCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327); } - }*/ - - // apply luminance operations - if (todo & (M_LUMINANCE+M_COLOR)) { - //I made a little change here. Rather than have luminanceCurve (and others) use in/out lab images, we can do more if we copy right here. - labnCrop->CopyFrom(laboCrop); + }*/ + + // apply luminance operations + if (todo & (M_LUMINANCE+M_COLOR)) { + //I made a little change here. Rather than have luminanceCurve (and others) use in/out lab images, we can do more if we copy right here. + labnCrop->CopyFrom(laboCrop); - // parent->ipf.luminanceCurve (labnCrop, labnCrop, parent->lumacurve); - bool utili=true; - bool autili=true; - bool butili=true; - bool ccutili=true; - bool cclutili=true; + //parent->ipf.luminanceCurve (labnCrop, labnCrop, parent->lumacurve); + bool utili=true; + bool autili=true; + bool butili=true; + bool ccutili=true; + bool cclutili=true; - LUTu dummy; - parent->ipf.chromiLuminanceCurve (1,labnCrop, labnCrop, parent->chroma_acurve, parent->chroma_bcurve, parent->satcurve, parent->lhskcurve, parent->lumacurve, utili, autili, butili, ccutili,cclutili, dummy); - parent->ipf.vibrance (labnCrop); - if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) parent->ipf.EPDToneMap(labnCrop,5,1); - // parent->ipf.EPDToneMap(labnCrop, 5, 1); //Go with much fewer than normal iterates for fast redisplay. - // for all treatments Defringe, Sharpening, Contrast detail , Microcontrast they are activated if "CIECAM" function are disabled - if (skip==1) { - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { - parent->ipf.impulsedenoise (labnCrop);} - if((params.colorappearance.enabled && !settings->autocielab) ||(!params.colorappearance.enabled) ) {parent->ipf.defringe (labnCrop);} - parent->ipf.MLsharpen (labnCrop); - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { - parent->ipf.MLmicrocontrast (labnCrop); - parent->ipf.sharpening (labnCrop, (float**)cbuffer); - parent->ipf.dirpyrequalizer (labnCrop); - } - } - - 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 - 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; - //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, ¶ms,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, ¶ms,parent->customColCurve1,parent->customColCurve2,parent->customColCurve3, dummy, dummy, 5, 1,(float**)cbuffer, execsharp, dd);} - } - } + LUTu dummy; + parent->ipf.chromiLuminanceCurve (1,labnCrop, labnCrop, parent->chroma_acurve, parent->chroma_bcurve, parent->satcurve, parent->lhskcurve, parent->lumacurve, utili, autili, butili, ccutili,cclutili, dummy); + parent->ipf.vibrance (labnCrop); + if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) parent->ipf.EPDToneMap(labnCrop,5,1); + //parent->ipf.EPDToneMap(labnCrop, 5, 1); //Go with much fewer than normal iterates for fast redisplay. + // for all treatments Defringe, Sharpening, Contrast detail , Microcontrast they are activated if "CIECAM" function are disabled + if (skip==1) { + if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { + parent->ipf.impulsedenoise (labnCrop);} + if((params.colorappearance.enabled && !settings->autocielab) ||(!params.colorappearance.enabled) ) {parent->ipf.defringe (labnCrop);} + parent->ipf.MLsharpen (labnCrop); + if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { + parent->ipf.MLmicrocontrast (labnCrop); + parent->ipf.sharpening (labnCrop, (float**)cbuffer); + parent->ipf.dirpyrequalizer (labnCrop); + } + } + + 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 + 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 { + 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; + if(skip==1) execsharp=true; + + 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, ¶ms, parent->customColCurve1, parent->customColCurve2, parent->customColCurve3, dummy, dummy, 5, 1,(float**)cbuffer, execsharp, d); + } + else { + double dd; // not used after this block + parent->ipf.ciecam_02 (cieCrop,adap, begh, endh, 1, 2, labnCrop, ¶ms, 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 parent->ipf.lab2monitorRgb (labnCrop, cropImg); - - //parent->ipf.lab2monitorRgb (laboCrop, cropImg); - - //cropImg = baseCrop->to8(); - /* - // int xref,yref; - xref=000;yref=000; - if (colortest && cropw>115 && croph>115) - for(int j=1;j<5;j++){ - xref+=j*30;yref+=j*30; - int rlin = (CurveFactory::igamma2((float)cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))]/255.0) * 255.0); - int glin = (CurveFactory::igamma2((float)cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+1]/255.0) * 255.0); - int blin = (CurveFactory::igamma2((float)cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+2]/255.0) * 255.0); - printf("after lab2rgb RGB lab2 Xr%i Yr%i Skip=%d R=%d G=%d B=%d \n",xref,yref,skip, - rlin,glin,blin); - //cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))], - //cropImg->data[(3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+1)], - //cropImg->data[(3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+2)]); - //printf("after lab2rgb Lab lab2 Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip, labnCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327,labnCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327,labnCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327); - printf("after lab2rgb Lab Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip, - labnCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327, - labnCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327, - labnCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327)q; - } - */ - /* - if (colortest && cropImg->height>115 && cropImg->width>115) {//for testing - xref=000;yref=000; - printf("dcrop final R= %d G= %d B= %d \n", - cropImg->data[3*xref/(skip)*(cropImg->width+1)], - cropImg->data[3*xref/(skip)*(cropImg->width+1)+1], - cropImg->data[3*xref/(skip)*(cropImg->width+1)+2]); - } - */ + //parent->ipf.lab2monitorRgb (laboCrop, cropImg); + + //cropImg = baseCrop->to8(); + /* + // int xref,yref; + xref=000;yref=000; + if (colortest && cropw>115 && croph>115) + for(int j=1;j<5;j++){ + xref+=j*30;yref+=j*30; + int rlin = (CurveFactory::igamma2((float)cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))]/255.0) * 255.0); + int glin = (CurveFactory::igamma2((float)cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+1]/255.0) * 255.0); + int blin = (CurveFactory::igamma2((float)cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+2]/255.0) * 255.0); + + printf("after lab2rgb RGB lab2 Xr%i Yr%i Skip=%d R=%d G=%d B=%d \n",xref,yref,skip, + rlin,glin,blin); + //cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))], + //cropImg->data[(3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+1)], + //cropImg->data[(3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+2)]); + //printf("after lab2rgb Lab lab2 Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip, labnCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327,labnCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327,labnCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327); + printf("after lab2rgb Lab Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip, + labnCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327, + labnCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327, + labnCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327)q; + } + */ + /* + if (colortest && cropImg->height>115 && cropImg->width>115) {//for testing + xref=000;yref=000; + printf("dcrop final R= %d G= %d B= %d \n", + cropImg->data[3*xref/(skip)*(cropImg->width+1)], + cropImg->data[3*xref/(skip)*(cropImg->width+1)+1], + cropImg->data[3*xref/(skip)*(cropImg->width+1)+2]); + } + */ if (cropImageListener) { // this in output space held in parallel to allow analysis like shadow/highlight Glib::ustring outProfile=params.icm.output; @@ -281,16 +301,16 @@ void Crop::update (int todo) { int finalH = rqcroph; if (cropImg->getHeight()-upperBorder < finalH) finalH = cropImg->getHeight()-upperBorder; - + Image8* final = new Image8 (finalW, finalH); - Image8* finaltrue = new Image8 (finalW, finalH); + Image8* finaltrue = new Image8 (finalW, finalH); for (int i=0; idata + 3*i*finalW, cropImg->data + 3*(i+upperBorder)*cropw + 3*leftBorder, 3*finalW); - memcpy (finaltrue->data + 3*i*finalW, cropImgtrue->data + 3*(i+upperBorder)*cropw + 3*leftBorder, 3*finalW); - } + memcpy (finaltrue->data + 3*i*finalW, cropImgtrue->data + 3*(i+upperBorder)*cropw + 3*leftBorder, 3*finalW); + } cropImageListener->setDetailedCrop (final, finaltrue, params.icm, params.crop, rqcropx, rqcropy, rqcropw, rqcroph, skip); delete final; - delete finaltrue; + delete finaltrue; delete cropImgtrue; } } @@ -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; iverbose) printf ("setcropsizes before lock\n"); @@ -379,8 +396,8 @@ if (settings->verbose) printf ("setcropsizes before lock\n"); leftBorder = SKIPS(rqx1-bx1,skip); upperBorder = SKIPS(rqy1-by1,skip); - if (settings->verbose) - printf ("setsizes starts (%d, %d, %d, %d, %d, %d)\n", orW, orH, trafw, trafh,cw,ch); + if (settings->verbose) + printf ("setsizes starts (%d, %d, %d, %d, %d, %d)\n", orW, orH, trafw, trafh,cw,ch); if (cw!=cropw || ch!=croph || orW!=trafw || orH!=trafh) { @@ -392,26 +409,22 @@ if (settings->verbose) printf ("setcropsizes before lock\n"); trafh = orH; origCrop = new Imagefloat (trafw, trafh); - laboCrop = new LabImage (cropw, croph); - labnCrop = new LabImage (cropw, croph); + //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; iverbose) 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; - - // If there are more update request, the following WHILE will collect it - if (updating) { - needsNext = true; - needsFullUpdate = false; - } else updating = true; - - return needsFullUpdate; + bool needsNewThread = true; + + if (updating) { + // 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 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 (); if (parent->updaterRunning && parent->thread) { - // Do NOT reset changes here, since in a long chain of events it will lead to chroma_scale not being updated, - // causing Color::lab2rgb to return a black image on some opens + // Do NOT reset changes here, since in a long chain of events it will lead to chroma_scale not being updated, + // causing Color::lab2rgb to return a black image on some opens //parent->changeSinceLast = 0; parent->thread->join (); } @@ -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); diff --git a/rtengine/dcrop.h b/rtengine/dcrop.h index b5881546c..52b6f9fe3 100644 --- a/rtengine/dcrop.h +++ b/rtengine/dcrop.h @@ -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; - float** cbuffer; - float * cbuf_real; - SHMap* cshmap; + // --- 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; - 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;} }; } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 0495261e5..f39dedad2 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -29,8 +29,9 @@ namespace rtengine { extern const Settings* settings; ImProcCoordinator::ImProcCoordinator () - : workimg(NULL), lastAwbEqual(0.), ipf(¶ms, 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(¶ms, true), scale(10), + highDetailPreprocessComputed(false), highDetailRawComputed(false), allocated(false), hltonecurve(65536,0), shtonecurve(65536,2),//clip above @@ -46,9 +47,9 @@ ImProcCoordinator::ImProcCoordinator () lhist16(65536), lhist16Cropped(65536), lhist16CAM(65536), lhist16CroppedCAM(65536), lhist16CCAM(65536), lhist16CroppedCCAM(65536), - lhist16CCAMAF(65536), lhist16ClabAF(65536), + lhist16CCAMAF(65536), lhist16ClabAF(65536), histCropped(65536), - lhist16Clad(65536),lhist16CroppedClad(65536), + lhist16Clad(65536),lhist16CroppedClad(65536), histRed(256), histRedRaw(256), histGreen(256), histGreenRaw(256), @@ -57,9 +58,9 @@ ImProcCoordinator::ImProcCoordinator () histToneCurve(256), histLCurve(256), histCCurve(256), - histLCAM(256), - histCCAM(256), - histClad(256), + histLCAM(256), + histCCAM(256), + histClad(256), bcabhist(256), rCurve(), @@ -106,45 +107,46 @@ 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 + // Check if any detail crops need high detail. If not, take a fast path short cut bool highDetailNeeded = (todo & M_HIGHQUAL); if (!highDetailNeeded) { - for (size_t i=0; iget_skip() == 1 ) { // skip=1 -> full resolution - highDetailNeeded=true; - break; - } + for (size_t i=0; iget_skip() == 1 ) { // skip=1 -> full resolution + highDetailNeeded=true; + break; + } } - RAWParams rp = params.raw; - if( !highDetailNeeded ){ + RAWParams rp = params.raw; + if( !highDetailNeeded ){ // if below 100% magnification, take a fast path - rp.dmethod = RAWParams::methodstring[RAWParams::fast]; - rp.ca_autocorrect = false; - rp.hotdeadpix_filt = false; - rp.ccSteps = 0; - //rp.all_enhance = false; - } + rp.dmethod = RAWParams::methodstring[RAWParams::fast]; + rp.ca_autocorrect = false; + rp.hotdeadpix_filt = false; + rp.ccSteps = 0; + //rp.all_enhance = false; + } progress ("Applying white balance, color correction & sRGB conversion...",100*readyphase/numofphases); // raw auto CA is bypassed if no high detail is needed, so we have to compute it when high detail is needed if ( (todo & M_PREPROC) || (!highDetailPreprocessComputed && highDetailNeeded)) { - imgsrc->preprocess( rp, params.lensProf, params.coarse ); + imgsrc->preprocess( rp, params.lensProf, params.coarse ); imgsrc->getRAWHistogram( histRedRaw, histGreenRaw, histBlueRaw ); if (highDetailNeeded) - highDetailPreprocessComputed = true; + highDetailPreprocessComputed = true; else - highDetailPreprocessComputed = false; + highDetailPreprocessComputed = false; } - /* + /* Demosaic is kicked off only when Detail considerations: accurate detail is not displayed yet needed based on preview specifics (driven via highDetailNeeded flag) @@ -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,17 +217,19 @@ 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, ¶ms) ; - //imgsrc->convertColorSpace(orig_prev, params.icm, params.raw); + //imgsrc->convertColorSpace(orig_prev, params.icm, params.raw); if (todo & M_LINDENOISE) { - //printf("denoising!\n"); - if (scale==1 && params.dirpyrDenoise.enabled) { - ipf.RGB_denoise(orig_prev, orig_prev, imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp()); - } + //printf("denoising!\n"); + 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); @@ -243,30 +247,29 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { if (needstransform && orig_prev==oprevi) oprevi = new Imagefloat (pW, pH); if ((todo & M_TRANSFORM) && needstransform) - ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, imgsrc->getMetaData()->getFocalLen(), - imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), false); + ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, imgsrc->getMetaData()->getFocalLen(), + imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), false); 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 = params.sh.radius; - if (!params.sh.hq) shradius *= radius / 1800.0; - shmap->update (oprevi, shradius, ipf.lumimul, params.sh.hq, scale); - + double shradius = params.sh.radius; + if (!params.sh.hq) shradius *= radius / 1800.0; + shmap->update (oprevi, shradius, ipf.lumimul, params.sh.hq, scale); } readyphase++; if (todo & M_AUTOEXP) { if (params.toneCurve.autoexp) { - LUTu aehist; int aehistcompr; - imgsrc->getAutoExpHistogram (aehist, aehistcompr); - ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, params.toneCurve.expcomp, - params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.black, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh); - if (aeListener) - aeListener->autoExpChanged (params.toneCurve.expcomp, params.toneCurve.brightness, params.toneCurve.contrast, - params.toneCurve.black, params.toneCurve.hlcompr,params.toneCurve.hlcomprthresh); + LUTu aehist; int aehistcompr; + imgsrc->getAutoExpHistogram (aehist, aehistcompr); + ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, params.toneCurve.expcomp, + params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.black, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh); + if (aeListener) + aeListener->autoExpChanged (params.toneCurve.expcomp, params.toneCurve.brightness, params.toneCurve.contrast, + params.toneCurve.black, params.toneCurve.hlcompr,params.toneCurve.hlcomprthresh); } } @@ -278,10 +281,10 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { ipf.g = imgsrc->getGamma(); ipf.iGamma = true; CurveFactory::complexCurve (params.toneCurve.expcomp, params.toneCurve.black/65535.0, - params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, - params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, - ipf.g, !ipf.iGamma, params.toneCurve.curveMode, params.toneCurve.curve, params.toneCurve.curveMode2, params.toneCurve.curve2, - vhist16, histCropped, hltonecurve, shtonecurve, tonecurve, histToneCurve, customToneCurve1, customToneCurve2, scale==1 ? 1 : 1); + params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, + params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, + ipf.g, !ipf.iGamma, params.toneCurve.curveMode, params.toneCurve.curve, params.toneCurve.curveMode2, params.toneCurve.curve2, + vhist16, histCropped, hltonecurve, shtonecurve, tonecurve, histToneCurve, customToneCurve1, customToneCurve2, scale==1 ? 1 : 1); CurveFactory::RGBCurve (params.rgbCurves.rcurve, rCurve, scale==1 ? 1 : 1); CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, scale==1 ? 1 : 1); @@ -297,8 +300,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { int x1, y1, x2, y2, pos, poscc; params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); lhist16.clear(); lhist16Cropped.clear(); - lhist16Clad.clear(); lhist16CroppedClad.clear(); - lhist16ClabAF.clear(); + lhist16Clad.clear(); lhist16CroppedClad.clear(); + lhist16ClabAF.clear(); for (int x=0; xL[x][y])); @@ -308,58 +311,55 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { } readyphase++; - utili=false; - autili=false; - butili=false; - ccutili=false; - cclutili=false; + utili=false; + autili=false; + butili=false; + ccutili=false; + cclutili=false; 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); - - 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); - // for all treatments Defringe, Sharpening, Contrast detail , Microcontrast they are activated if "CIECAM" function are disabled - readyphase++; - if (scale==1) { - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ - progress ("Denoising luminance impulse...",100*readyphase/numofphases); - ipf.impulsedenoise (nprevl); - readyphase++; - } - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ - progress ("Defringing...",100*readyphase/numofphases); - ipf.defringe (nprevl); - readyphase++; - } - if (params.sharpenEdge.enabled) { + 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); + + 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); + // for all treatments Defringe, Sharpening, Contrast detail , Microcontrast they are activated if "CIECAM" function are disabled + readyphase++; + if (scale==1) { + if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ + progress ("Denoising luminance impulse...",100*readyphase/numofphases); + ipf.impulsedenoise (nprevl); + readyphase++; + } + if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ + progress ("Defringing...",100*readyphase/numofphases); + ipf.defringe (nprevl); + readyphase++; + } + if (params.sharpenEdge.enabled) { progress ("Edge sharpening...",100*readyphase/numofphases); - ipf.MLsharpen (nprevl); - readyphase++; - } - if (params.sharpenMicro.enabled) { - if(( params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ - progress ("Microcontrast...",100*readyphase/numofphases); - ipf.MLmicrocontrast (nprevl); - readyphase++; - } - } - if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) && params.sharpening.enabled) { + ipf.MLsharpen (nprevl); + readyphase++; + } + if (params.sharpenMicro.enabled) { + if(( params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ + progress ("Microcontrast...",100*readyphase/numofphases); + ipf.MLmicrocontrast (nprevl); + readyphase++; + } + } + if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) && params.sharpening.enabled) { progress ("Sharpening...",100*readyphase/numofphases); float **buffer = new float*[pH]; @@ -373,84 +373,92 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { delete [] buffer; readyphase++; } - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ -// if(params.colorappearance.enabled && !params.colorappearance.sharpcie){ - progress ("Pyramid equalizer...",100*readyphase/numofphases); - ipf.dirpyrequalizer (nprevl); - readyphase++; - } - + if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ + //if(params.colorappearance.enabled && !params.colorappearance.sharpcie){ + progress ("Pyramid equalizer...",100*readyphase/numofphases); + 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 + + //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; - params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); - lhist16CAM.clear(); lhist16CroppedCAM.clear(); - lhist16CCAM.clear(); lhist16CroppedCCAM.clear(); - lhist16CCAMAF.clear(); + params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); + lhist16CAM.clear(); lhist16CroppedCAM.clear(); + lhist16CCAM.clear(); lhist16CroppedCCAM.clear(); + lhist16CCAMAF.clear(); for (int x=0; xL[x][y])); posc=CLIP((int)sqrt(nprevl->a[x][y]*nprevl->a[x][y] + nprevl->b[x][y]*nprevl->b[x][y])); - if(!params.colorappearance.datacie) lhist16CCAM[posc]++; - if(!params.colorappearance.datacie)lhist16CAM[pos]++; + if(!params.colorappearance.datacie) lhist16CCAM[posc]++; + if(!params.colorappearance.datacie)lhist16CAM[pos]++; if (y>=y1 && y=x1 && xgetMetaData()->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 - 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; - //end calculation adaptation scene luminosity - } - int begh=0; - int endh=pH; - float d; - double dd; - float **buffer = new float*[pH]; - for (int i=0; iciecamfloat){ipf.ciecam_02float (ncie, adap, begh, endh, pW, 2, nprevl, ¶ms, 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, ¶ms, 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); - - } - for (int i=0; igetMetaData()->getFNumber (); // F number + float fiso = imgsrc->getMetaData()->getISOSpeed () ; // ISO + 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 { + 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; + int endh=pH; + float d; + double dd; + float **buffer = new float*[pH]; + for (int i=0; iciecamfloat){ + ipf.ciecam_02float (ncie, float(adap), begh, endh, pW, 2, nprevl, ¶ms, 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, ¶ms, 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; ihasListener () && cropCall != crops[i] ) @@ -458,29 +466,26 @@ 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); delete workimg; - workimg = ipf.lab2rgb (nprevl, 0,0,pW,pH, params.icm.working); + workimg = ipf.lab2rgb (nprevl, 0,0,pW,pH, params.icm.working); } catch(char * str) { progress ("Error converting file...",0); - previmg->getMutex().unlock(); - mProcessing.unlock (); return; } - previmg->getMutex().unlock(); - } + } if (!resultValid) { resultValid = true; if (imageListener) imageListener->setImage (previmg, scale, params.crop); } if (imageListener) - // TODO: The WB tool should be advertised too in order to get the AutoWB's temp and green values + // TODO: The WB tool should be advertised too in order to get the AutoWB's temp and green values imageListener->imageReady (params.crop); readyphase++; @@ -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,18 +503,19 @@ 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); } else delete previmg; - + delete workimg; delete shmap; @@ -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"); @@ -529,7 +539,7 @@ if (settings->verbose) printf ("setscale before lock\n"); 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); @@ -541,22 +551,22 @@ if (settings->verbose) printf ("setscale before lock\n"); if (nW!=pW || nH!=pH) { freeAll (); - + pW = nW; pH = nH; - + orig_prev = new Imagefloat (pW, pH); oprevi = orig_prev; - oprevl = new LabImage (pW, pH); - nprevl = new LabImage (pW, pH); - ncie = new CieImage (pW, pH); + oprevl = new LabImage (pW, pH); + nprevl = new LabImage (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); + workimg = new Image8 (pW, pH); shmap = new SHMap (pW, pH, true); allocated = true; } - + scale = prevscale; resultValid = false; fullw = fw; @@ -578,13 +588,13 @@ void ImProcCoordinator::updateLRGBHistograms () { histRed.clear(); histGreen.clear(); histBlue.clear(); - + for (int i=y1; idata[ofs++]; - int g=workimg->data[ofs++]; - int b=workimg->data[ofs++]; + int r=workimg->data[ofs++]; + int g=workimg->data[ofs++]; + int b=workimg->data[ofs++]; histRed[r]++; histGreen[g]++; @@ -592,23 +602,22 @@ void ImProcCoordinator::updateLRGBHistograms () { } } - histLuma.clear(); - histChroma.clear(); + histLuma.clear(); + histChroma.clear(); for (int i=y1; ia[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++) { - 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])); - }*/ + 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++) { + 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) { @@ -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 points, red, green, blue; for (int i=y-rect; i<=y+rect; i++) for (int j=x-rect; j<=x+rect; j++) @@ -670,25 +682,25 @@ 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 (); - tgreen = ret.getGreen (); - } else { - temp = currWB.getTemp (); - tgreen = currWB.getGreen (); - } + 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 (); + MyMutex::MyLock lock(mProcessing); LCPMapper *pLCPMap=NULL; if (params.lensProf.lcpFile.length() && imgsrc->getMetaData()->getFocalLen()>0) { @@ -700,26 +712,24 @@ void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int & double fillscale = ipf.getTransformAutoFill (fullw, fullh, pLCPMap); if (ratio>0) { w = fullw * fillscale; - h = w / ratio; - if (h > fullh * fillscale) { - h = fullh * fillscale; - w = h * ratio; - } + h = w / ratio; + if (h > fullh * fillscale) { + h = fullh * fillscale; + w = h * ratio; + } } else { w = fullw * fillscale; - h = fullh * fillscale; + h = fullh * fillscale; } 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 () { diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 3d2798210..dfc50ece9 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -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; @@ -44,11 +53,11 @@ class ImProcCoordinator : public StagedImageProcessor { protected: Imagefloat *orig_prev; Imagefloat *oprevi; - LabImage *oprevl; - LabImage *nprevl; + LabImage *oprevl; + LabImage *nprevl; Image8 *previmg; Image8 *workimg; - CieImage *ncie; + CieImage *ncie; ImageSource* imgsrc; @@ -82,10 +91,10 @@ class ImProcCoordinator : public StagedImageProcessor { LUTu lhist16,lhist16Cropped; LUTu lhist16CAM,lhist16CroppedCAM; LUTu lhist16CCAM,lhist16CroppedCCAM; - LUTu lhist16CCAMAF; - LUTu lhist16ClabAF; - LUTu histCropped; - LUTu lhist16Clad,lhist16CroppedClad; + LUTu lhist16CCAMAF; + LUTu lhist16ClabAF; + LUTu histCropped; + LUTu lhist16Clad,lhist16CroppedClad; LUTu histRed, histRedRaw; LUTu histGreen, histGreenRaw; LUTu histBlue, histBlueRaw; @@ -94,11 +103,11 @@ class ImProcCoordinator : public StagedImageProcessor { LUTf rCurve; LUTf gCurve; LUTf bCurve; - bool utili; - bool autili; - bool butili; - bool ccutili; - bool cclutili; + bool utili; + bool autili; + bool butili; + bool ccutili; + bool cclutili; ToneCurve customToneCurve1; ToneCurve customToneCurve2; @@ -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 (); @@ -189,7 +198,7 @@ class ImProcCoordinator : public StagedImageProcessor { void setAutoCamListener (AutoCamListener* acl) {acListener = acl; } void saveInputICCReference (const Glib::ustring& fname); - + InitialImage* getInitialImage () { return imgsrc; } }; } diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 85cbafb39..33c478969 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -250,12 +250,13 @@ namespace rtengine { virtual void autoExpChanged (double brightness, int bright, int contrast, int black, int hlcompr, int hlcomprthresh) {} }; - class AutoCamListener { - public : - virtual void autoCamChanged (double ccam) {} - virtual void adapCamChanged (double cadap) {} - - }; + 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. */ diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index 4f612ccd0..4efcaa466 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -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; diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index de95e526a..c6e17f8e7 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -82,15 +82,15 @@ void ImageArea::on_resized (Gtk::Allocation& req) { mainCropWindow->addCropWindowListener (this); mainCropWindow->setCropGUIListener (cropgl); mainCropWindow->setPointerMotionListener (pmlistener); - mainCropWindow->setPointerMotionHListener (pmhlistener); + mainCropWindow->setPointerMotionHListener (pmhlistener); mainCropWindow->setPosition (0, 0); mainCropWindow->setSize (get_width(), get_height(), false); // this execute the refresh itself } else { mainCropWindow->setSize (get_width(), get_height()); } - parent->syncBeforeAfterViews(); - } + parent->syncBeforeAfterViews(); + } } void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) {