From 3e510cd94e70da320da18e04e8b318d4f837f5aa Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 18 Aug 2016 21:41:16 +0200 Subject: [PATCH] Fix some ciecam02 issues, fixes ##3380, fixes #3396, fixes #3397 --- rtengine/improccoordinator.cc | 11 +- rtengine/improcfun.cc | 237 +++++++++++++++++----------------- rtengine/rtthumbnail.cc | 40 +++--- rtengine/simpleprocess.cc | 2 +- 4 files changed, 153 insertions(+), 137 deletions(-) diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index f585acacf..a0dd47960 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -35,7 +35,7 @@ ImProcCoordinator::ImProcCoordinator () : orig_prev(NULL), oprevi(NULL), oprevl(NULL), nprevl(NULL), previmg(NULL), workimg(NULL), ncie(NULL), imgsrc(NULL), shmap(NULL), lastAwbEqual(0.), ipf(¶ms, true), monitorIntent(RI_RELATIVE), scale(10), highDetailPreprocessComputed(false), highDetailRawComputed(false), allocated(false), - bwAutoR(-9000.f), bwAutoG(-9000.f), bwAutoB(-9000.f), CAMMean(0.), + bwAutoR(-9000.f), bwAutoG(-9000.f), bwAutoB(-9000.f), CAMMean(NAN), hltonecurve(65536), shtonecurve(65536), @@ -743,6 +743,10 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } // Issue 2785, only float version of ciecam02 for navigator and pan background + CAMMean = NAN; + CAMBrightCurveJ.dirty = true; + CAMBrightCurveQ.dirty = true; + ipf.ciecam_02float (ncie, float(adap), begh, endh, pW, 2, nprevl, ¶ms, customColCurve1, customColCurve2, customColCurve3, histLCAM, histCCAM, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, execsharp, d, scale, 1); if(params.colorappearance.autodegree && acListener && params.colorappearance.enabled) { @@ -783,11 +787,6 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) crops[i]->update (todo); // may call ourselves } - // Flagging some LUT as dirty now, whether they have been freed up or not - CAMBrightCurveJ.dirty = true; - CAMBrightCurveQ.dirty = true; - - progress ("Conversion to RGB...", 100 * readyphase / numofphases); if ((todo != CROP && todo != MINUPDATE) || (todo & M_MONITOR)) { diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 5730befbb..67103d521 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -1667,86 +1667,12 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int const ColorAppearanceParams::eCTCModeId curveMode3 = params->colorappearance.curveMode3; const bool hasColCurve3 = bool(customColCurve3); - if(settings->viewinggreySc == 0) { //auto - if (mean < 15.f) { - yb = 3.0f; - } else if(mean < 30.f) { - yb = 5.0f; - } else if(mean < 40.f) { - yb = 10.0f; - } else if(mean < 45.f) { - yb = 15.0f; - } else if(mean < 50.f) { - yb = 18.0f; - } else if(mean < 55.f) { - yb = 23.0f; - } else if(mean < 60.f) { - yb = 30.0f; - } else if(mean < 70.f) { - yb = 40.0f; - } else if(mean < 80.f) { - yb = 60.0f; - } else if(mean < 90.f) { - yb = 80.0f; - } else { - yb = 90.0f; - } - } else if(settings->viewinggreySc == 1) { - yb = 18.0f; //fixed - } + bool needJ = (alg == 0 || alg == 1 || alg == 3); + bool needQ = (alg == 2 || alg == 3); + LUTu hist16J; + LUTu hist16Q; - - const bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated - - const int gamu = (params->colorappearance.gamut == true) ? 1 : 0; - xw = 100.0f * Xw; - yw = 100.0f * Yw; - zw = 100.0f * Zw; - float xw1, yw1, zw1, xw2, yw2, zw2; - - // settings of WB: scene and viewing - if(params->colorappearance.wbmodel == "RawT") { - xw1 = 96.46f; //use RT WB; CAT 02 is used for output device (see prefreneces) - yw1 = 100.0f; - zw1 = 82.445f; - xw2 = xwd; - yw2 = ywd; - zw2 = zwd; - } else if(params->colorappearance.wbmodel == "RawTCAT02") { - xw1 = xw; // Settings RT WB are used for CAT02 => mix , CAT02 is use for output device (screen: D50 D65, projector: lamp, LED) see preferences - yw1 = yw; - zw1 = zw; - xw2 = xwd; - yw2 = ywd; - zw2 = zwd; - } - - float cz, wh, pfl; - Ciecam02::initcam1float(gamu, yb, pilot, f, la, xw, yw, zw, n, d, nbb, ncb, cz, aw, wh, pfl, fl, c); - const float pow1 = pow_F( 1.64f - pow_F( 0.29f, n ), 0.73f ); - float nj, dj, nbbj, ncbj, czj, awj, flj; - Ciecam02::initcam2float(gamu, yb2, f2, la2, xw2, yw2, zw2, nj, dj, nbbj, ncbj, czj, awj, flj); - const float reccmcz = 1.f / (c2 * czj); - const float pow1n = pow_F( 1.64f - pow_F( 0.29f, nj ), 0.73f ); - - const float epsil = 0.0001f; - const float w_h = wh + epsil; - const float coefQ = 32767.f / wh; - const float a_w = aw; - const float c_ = c; - const float f_l = fl; - const float coe = pow_F(fl, 0.25f); - const float QproFactor = ( 0.4f / c ) * ( aw + 4.0f ) ; - const bool LabPassOne = !((params->colorappearance.tonecie && (epdEnabled)) || (params->sharpening.enabled && settings->autocielab && execsharp) - || (params->dirpyrequalizer.enabled && settings->autocielab) || (params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab) - || (params->impulseDenoise.enabled && settings->autocielab) || (params->colorappearance.badpixsl > 0 && settings->autocielab)); - - - if(CAMBrightCurveJ.dirty || CAMBrightCurveQ.dirty) { - bool needJ = (alg == 0 || alg == 1 || alg == 3); - bool needQ = (alg == 2 || alg == 3); - LUTu hist16J; - LUTu hist16Q; + if((needJ && CAMBrightCurveJ.dirty) || (needQ && CAMBrightCurveQ.dirty) || (std::isnan(mean) && settings->viewinggreySc != 0)) { if (needJ) { hist16J (32768); @@ -1841,31 +1767,112 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int } } + + if(std::isnan(mean)) { + mean = (sum / ((height) * width)) / 327.68f; //for Yb for all image...if one day "pipette" we can adapt Yb for each zone + } } - //mean=(sum/((endh-begh)*width))/327.68f;//for Yb for all image...if one day "pipette" we can adapt Yb for each zone - mean = (sum / ((height) * width)) / 327.68f; //for Yb for all image...if one day "pipette" we can adapt Yb for each zone //evaluate lightness, contrast - if (needJ) { - if (!CAMBrightCurveJ) { - CAMBrightCurveJ(32768, LUT_CLIP_ABOVE); - CAMBrightCurveJ.dirty = false; - } + } - Ciecam02::curveJfloat (params->colorappearance.jlight, params->colorappearance.contrast, hist16J, CAMBrightCurveJ);//lightness and contrast J - CAMBrightCurveJ /= 327.68f; + if(settings->viewinggreySc == 0) { //auto + if (mean < 15.f) { + yb = 3.0f; + } else if(mean < 30.f) { + yb = 5.0f; + } else if(mean < 40.f) { + yb = 10.0f; + } else if(mean < 45.f) { + yb = 15.0f; + } else if(mean < 50.f) { + yb = 18.0f; + } else if(mean < 55.f) { + yb = 23.0f; + } else if(mean < 60.f) { + yb = 30.0f; + } else if(mean < 70.f) { + yb = 40.0f; + } else if(mean < 80.f) { + yb = 60.0f; + } else if(mean < 90.f) { + yb = 80.0f; + } else { + yb = 90.0f; + } + } else if(settings->viewinggreySc == 1) { + yb = 18.0f; //fixed + } + + const bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated + + const int gamu = (params->colorappearance.gamut == true) ? 1 : 0; + xw = 100.0f * Xw; + yw = 100.0f * Yw; + zw = 100.0f * Zw; + float xw1, yw1, zw1, xw2, yw2, zw2; + + // settings of WB: scene and viewing + if(params->colorappearance.wbmodel == "RawT") { + xw1 = 96.46f; //use RT WB; CAT 02 is used for output device (see prefreneces) + yw1 = 100.0f; + zw1 = 82.445f; + xw2 = xwd; + yw2 = ywd; + zw2 = zwd; + } else if(params->colorappearance.wbmodel == "RawTCAT02") { + xw1 = xw; // Settings RT WB are used for CAT02 => mix , CAT02 is use for output device (screen: D50 D65, projector: lamp, LED) see preferences + yw1 = yw; + zw1 = zw; + xw2 = xwd; + yw2 = ywd; + zw2 = zwd; + } + + float cz, wh, pfl; + Ciecam02::initcam1float(gamu, yb, pilot, f, la, xw, yw, zw, n, d, nbb, ncb, cz, aw, wh, pfl, fl, c); + const float pow1 = pow_F( 1.64f - pow_F( 0.29f, n ), 0.73f ); + float nj, dj, nbbj, ncbj, czj, awj, flj; + Ciecam02::initcam2float(gamu, yb2, f2, la2, xw2, yw2, zw2, nj, dj, nbbj, ncbj, czj, awj, flj); + const float reccmcz = 1.f / (c2 * czj); + const float pow1n = pow_F( 1.64f - pow_F( 0.29f, nj ), 0.73f ); + + const float epsil = 0.0001f; + const float w_h = wh + epsil; + const float coefQ = 32767.f / wh; + const float a_w = aw; + const float c_ = c; + const float f_l = fl; + const float coe = pow_F(fl, 0.25f); + const float QproFactor = ( 0.4f / c ) * ( aw + 4.0f ) ; + const bool LabPassOne = !((params->colorappearance.tonecie && (epdEnabled)) || (params->sharpening.enabled && settings->autocielab && execsharp) + || (params->dirpyrequalizer.enabled && settings->autocielab) || (params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab) + || (params->impulseDenoise.enabled && settings->autocielab) || (params->colorappearance.badpixsl > 0 && settings->autocielab)); + + + if (needJ) { + if (!CAMBrightCurveJ) { + CAMBrightCurveJ(32768, LUT_CLIP_ABOVE); } - if (needQ) { - if (!CAMBrightCurveQ) { - CAMBrightCurveQ(32768, LUT_CLIP_ABOVE); - CAMBrightCurveQ.dirty = false; - } + if(CAMBrightCurveJ.dirty) { + Ciecam02::curveJfloat (params->colorappearance.jlight, params->colorappearance.contrast, hist16J, CAMBrightCurveJ);//lightness and contrast J + CAMBrightCurveJ /= 327.68f; + CAMBrightCurveJ.dirty = false; + } + } + if (needQ) { + if (!CAMBrightCurveQ) { + CAMBrightCurveQ(32768, LUT_CLIP_ABOVE); + } + + if(CAMBrightCurveQ.dirty) { Ciecam02::curveJfloat (params->colorappearance.qbright, params->colorappearance.qcontrast, hist16Q, CAMBrightCurveQ);//brightness and contrast Q CAMBrightCurveQ /= coefQ; + CAMBrightCurveQ.dirty = false; } } @@ -2238,17 +2245,17 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int int sk = 1; float ko = 1.f / coef; Color::skinredfloat(Jpro, hpro, Cc, Ccold, dred, protect_red, sk, rstprotection, ko, Cpro); -/* - if(Jpro < 1.f && Cpro > 12.f) { - Cpro = 12.f; //reduce artifacts by "pseudo gamut control CIECAM" - } else if(Jpro < 2.f && Cpro > 15.f) { - Cpro = 15.f; - } else if(Jpro < 4.f && Cpro > 30.f) { - Cpro = 30.f; - } else if(Jpro < 7.f && Cpro > 50.f) { - Cpro = 50.f; - } -*/ + /* + if(Jpro < 1.f && Cpro > 12.f) { + Cpro = 12.f; //reduce artifacts by "pseudo gamut control CIECAM" + } else if(Jpro < 2.f && Cpro > 15.f) { + Cpro = 15.f; + } else if(Jpro < 4.f && Cpro > 30.f) { + Cpro = 30.f; + } else if(Jpro < 7.f && Cpro > 50.f) { + Cpro = 50.f; + } + */ } else if (curveMode3 == ColorAppearanceParams::TC_MODE_SATUR) { // float parsat = 0.8f; //0.6 float coef = 327.68f / parsat; @@ -2280,17 +2287,17 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int int sk = 0; float ko = 1.f / coef; Color::skinredfloat(Jpro, hpro, Mm, Mold, dred, protect_red, sk, rstprotection, ko, Mpro); -/* - if(Jpro < 1.f && Mpro > 12.f * coe) { - Mpro = 12.f * coe; //reduce artifacts by "pseudo gamut control CIECAM" - } else if(Jpro < 2.f && Mpro > 15.f * coe) { - Mpro = 15.f * coe; - } else if(Jpro < 4.f && Mpro > 30.f * coe) { - Mpro = 30.f * coe; - } else if(Jpro < 7.f && Mpro > 50.f * coe) { - Mpro = 50.f * coe; - } -*/ + /* + if(Jpro < 1.f && Mpro > 12.f * coe) { + Mpro = 12.f * coe; //reduce artifacts by "pseudo gamut control CIECAM" + } else if(Jpro < 2.f && Mpro > 15.f * coe) { + Mpro = 15.f * coe; + } else if(Jpro < 4.f && Mpro > 30.f * coe) { + Mpro = 30.f * coe; + } else if(Jpro < 7.f && Mpro > 50.f * coe) { + Mpro = 50.f * coe; + } + */ Cpro = Mpro / coe; } } diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index e8c1cd096..7c6aa5b5b 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -421,23 +421,23 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati c = ri->XTRANSFC(row, col); switch (c) { - case 0: - tmpImg->r(y, x) = image[ofs][0]; - tmpImg->g(y, x) = sum[1] / 5.f; - tmpImg->b(y, x) = sum[2] / 3.f; - break; + case 0: + tmpImg->r(y, x) = image[ofs][0]; + tmpImg->g(y, x) = sum[1] / 5.f; + tmpImg->b(y, x) = sum[2] / 3.f; + break; - case 1: - tmpImg->r(y, x) = sum[0] / 2.f; - tmpImg->g(y, x) = image[ofs][1]; - tmpImg->b(y, x) = sum[2] / 2.f; - break; + case 1: + tmpImg->r(y, x) = sum[0] / 2.f; + tmpImg->g(y, x) = image[ofs][1]; + tmpImg->b(y, x) = sum[2] / 2.f; + break; - case 2: - tmpImg->r(y, x) = sum[0] / 3.f; - tmpImg->g(y, x) = sum[1] / 5.f; - tmpImg->b(y, x) = image[ofs][2]; - break; + case 2: + tmpImg->r(y, x) = sum[0] / 3.f; + tmpImg->g(y, x) = sum[1] / 5.f; + tmpImg->b(y, x) = image[ofs][2]; + break; } } } @@ -799,6 +799,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei double focalLen, double focalLen35mm, float focusDist, float shutter, float fnumber, float iso, std::string expcomp_, double& myscale) { BENCHFUN + // check if the WB's equalizer value has changed if (wbEqual < (params.wb.equal - 5e-4) || wbEqual > (params.wb.equal + 5e-4)) { wbEqual = params.wb.equal; @@ -878,6 +879,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei #ifdef _OPENMP #pragma omp simd #endif + for (int j = 0; j < rwidth; j++) { float red = baseImg->r(i, j) * rmi; baseImg->r(i, j) = CLIP(red); @@ -947,6 +949,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei int black = params.toneCurve.black; int hlcompr = params.toneCurve.hlcompr; int hlcomprthresh = params.toneCurve.hlcomprthresh; + if (params.toneCurve.autoexp && aeHistogram) { ipf.getAutoExp (aeHistogram, aeHistCompression, logDefGain, params.toneCurve.clip, expcomp, bright, contr, black, hlcompr, hlcomprthresh); } @@ -986,6 +989,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, 16); bool opautili = false; + if(params.colorToning.enabled) { TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); double wp[3][3] = { @@ -1042,6 +1046,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei LabImage* labView = new LabImage (fw, fh); DCPProfile *dcpProf = nullptr; DCPProfile::ApplyState as; + if (isRaw) { cmsHPROFILE dummy; RawImageSource::findInputProfile(params.icm.input, nullptr, camName, &dcpProf, dummy); @@ -1050,6 +1055,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei dcpProf->setStep2ApplyState(params.icm.working, params.icm.toneCurve, params.icm.applyLookTable, params.icm.applyBaselineExposureOffset, as); } } + ipf.rgbProc (baseImg, labView, nullptr, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf, as); // freeing up some memory @@ -1067,6 +1073,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei // luminance histogram update if(params.labCurve.contrast != 0) { hist16.clear(); + for (int i = 0; i < fh; i++) for (int j = 0; j < fw; j++) { hist16[(int)((labView->L[i][j]))]++; @@ -1142,6 +1149,9 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei sk = 16; int rtt = 0; CieImage* cieView = new CieImage (fw, fh); + CAMMean = NAN; + CAMBrightCurveJ.dirty = true; + CAMBrightCurveQ.dirty = true; ipf.ciecam_02float (cieView, adap, begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 6, execsharp, d, sk, rtt); delete cieView; } diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 25bf45742..63a207beb 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1050,7 +1050,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p LUTf CAMBrightCurveJ; LUTf CAMBrightCurveQ; - float CAMMean; + float CAMMean = NAN; if (params.sharpening.enabled) { float d;