From ba8c3d15bf5e553e3f28c5b323ca1a2793b082f0 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Wed, 28 Aug 2019 18:03:31 +0200 Subject: [PATCH] capture sharpening: do not trigger demosaic when changing adjusters --- rtengine/imagesource.h | 2 +- rtengine/improccoordinator.cc | 27 +++++---- rtengine/rawimagesource.cc | 109 ++++++++++++++++++++++++++++++---- rtengine/rawimagesource.h | 8 ++- rtengine/simpleprocess.cc | 2 +- rtgui/pdsharpening.cc | 10 ++-- 6 files changed, 128 insertions(+), 30 deletions(-) diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 46cbc28a6..1a5469744 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -83,7 +83,7 @@ public: virtual void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, bool prepareDenoise = true) {}; virtual void filmNegativeProcess (const procparams::FilmNegativeParams ¶ms) {}; virtual bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams& currentParams, std::array& newExps) { return false; }; - virtual void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold) {}; + virtual void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold, bool cache = false) {}; virtual void retinex (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &deh, const procparams::ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {}; virtual void retinexPrepareCurves (const procparams::RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) {}; virtual void retinexPrepareBuffers (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI) {}; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 7d485fd19..7496cb2aa 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -332,26 +332,31 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } bool autoContrast = imgsrc->getSensorType() == ST_BAYER ? params->raw.bayersensor.dualDemosaicAutoContrast : params->raw.xtranssensor.dualDemosaicAutoContrast; double contrastThreshold = imgsrc->getSensorType() == ST_BAYER ? params->raw.bayersensor.dualDemosaicContrast : params->raw.xtranssensor.dualDemosaicContrast; - imgsrc->demosaic(rp, autoContrast, contrastThreshold); //enabled demosaic + imgsrc->demosaic(rp, autoContrast, contrastThreshold, params->pdsharpening.enabled); if (imgsrc->getSensorType() == ST_BAYER && bayerAutoContrastListener && autoContrast) { bayerAutoContrastListener->autoContrastChanged(contrastThreshold); } else if (imgsrc->getSensorType() == ST_FUJI_XTRANS && xtransAutoContrastListener && autoContrast) { xtransAutoContrastListener->autoContrastChanged(autoContrast ? contrastThreshold : -1.0); } - - if (params->pdsharpening.enabled) { - double pdSharpencontrastThreshold = params->pdsharpening.contrast; - imgsrc->captureSharpening(params->pdsharpening, sharpMask, pdSharpencontrastThreshold); - if (pdSharpenAutoContrastListener && params->pdsharpening.autoContrast) { - pdSharpenAutoContrastListener->autoContrastChanged(pdSharpencontrastThreshold); - } - } - - // if a demosaic happened we should also call getimage later, so we need to set the M_INIT flag todo |= M_INIT; + } + + if ((todo & M_INIT) && params->pdsharpening.enabled) { + double pdSharpencontrastThreshold = params->pdsharpening.contrast; + imgsrc->captureSharpening(params->pdsharpening, sharpMask, pdSharpencontrastThreshold); + if (pdSharpenAutoContrastListener && params->pdsharpening.autoContrast) { + pdSharpenAutoContrastListener->autoContrastChanged(pdSharpencontrastThreshold); + } + } + + + if ((todo & M_RAW) + || (!highDetailRawComputed && highDetailNeeded) + || (params->toneCurve.hrenabled && params->toneCurve.method != "Color" && imgsrc->isRGBSourceModified()) + || (!params->toneCurve.hrenabled && params->toneCurve.method == "Color" && imgsrc->isRGBSourceModified())) { if (highDetailNeeded) { highDetailRawComputed = true; } else { diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 0602c770b..82863267f 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -45,6 +45,7 @@ #include #endif #include "opthelper.h" +#include "../rtgui/multilangmgr.h" #define clipretinex( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val ) #undef CLIPD #define CLIPD(a) ((a)>0.0f?((a)<1.0f?(a):1.0f):0.0f) @@ -457,6 +458,9 @@ RawImageSource::RawImageSource () , green(0, 0) , red(0, 0) , blue(0, 0) + , greenCache(nullptr) + , redCache(nullptr) + , blueCache(nullptr) , rawDirty(true) , histMatchingParams(new procparams::ColorManagementParams) { @@ -474,6 +478,9 @@ RawImageSource::~RawImageSource () { delete idata; + delete redCache; + delete greenCache; + delete blueCache; for(size_t i = 0; i < numFrames; ++i) { delete riFrames[i]; @@ -1524,7 +1531,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &contrastThreshold) +void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &contrastThreshold, bool cache) { MyTime t1, t2; t1.set(); @@ -1595,7 +1602,49 @@ void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &c rgbSourceModified = false; - + if (cache) { + if (!redCache) { + redCache = new array2D(W, H); + greenCache = new array2D(W, H); + blueCache = new array2D(W, H); + } +#ifdef _OPENMP + #pragma omp parallel sections +#endif + { +#ifdef _OPENMP + #pragma omp section +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + (*redCache)[i][j] = red[i][j]; + } + } +#ifdef _OPENMP + #pragma omp section +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + (*greenCache)[i][j] = green[i][j]; + } + } +#ifdef _OPENMP + #pragma omp section +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + (*blueCache)[i][j] = blue[i][j]; + } + } + } + } else { + delete redCache; + redCache = nullptr; + delete greenCache; + greenCache = nullptr; + delete blueCache; + blueCache = nullptr; + } if( settings->verbose ) { if (getSensorType() == ST_BAYER) { printf("Demosaicing Bayer data: %s - %d usec\n", raw.bayersensor.method.c_str(), t2.etime(t1)); @@ -4954,6 +5003,12 @@ void RawImageSource::getRawValues(int x, int y, int rotate, int &R, int &G, int void RawImageSource::captureSharpening(const procparams::SharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold) { BENCHFUN + + if (plistener) { + plistener->setProgressStr(M("TP_PDSHARPENING_LABEL")); + plistener->setProgress(0.0); + } + const float xyz_rgb[3][3] = { // XYZ from RGB { 0.412453, 0.357580, 0.180423 }, { 0.212671, 0.715160, 0.072169 }, @@ -4962,6 +5017,10 @@ BENCHFUN float contrast = conrastThreshold / 100.f; + array2D& redVals = redCache ? *redCache : red; + array2D& greenVals = greenCache ? *greenCache : green; + array2D& blueVals = blueCache ? *blueCache : blue; + if (showMask) { StopWatch Stop1("Show mask"); array2D& L = blue; // blue will be overridden anyway => we can use its buffer to store L @@ -4970,10 +5029,18 @@ BENCHFUN #endif for (int i = 0; i < H; ++i) { - Color::RGB2L(red[i], green[i], blue[i], L[i], xyz_rgb, W); + Color::RGB2L(redVals[i], greenVals[i], blueVals[i], L[i], xyz_rgb, W); + } + if (plistener) { + plistener->setProgressStr(M("TP_PDSHARPENING_LABEL")); + plistener->setProgress(0.1); } array2D& blend = red; // red will be overridden anyway => we can use its buffer to store the blend mask buildBlendMask(L, blend, W, H, contrast, 1.f, sharpeningParams.autoContrast); + if (plistener) { + plistener->setProgressStr(M("TP_PDSHARPENING_LABEL")); + plistener->setProgress(0.2); + } conrastThreshold = contrast * 100.f; #ifdef _OPENMP #pragma omp parallel for @@ -4983,6 +5050,10 @@ BENCHFUN red[i][j] = green[i][j] = blue[i][j] = blend[i][j] * 16384.f; } } + if (plistener) { + plistener->setProgressStr(M("TP_PDSHARPENING_LABEL")); + plistener->setProgress(1.0); + } return; } @@ -4995,12 +5066,20 @@ BENCHFUN #pragma omp parallel for schedule(dynamic, 16) #endif for (int i = 0; i < H; ++i) { - Color::RGB2L(red[i], green[i], blue[i], L[i], xyz_rgb, W); - Color::RGB2Y(red[i], green[i], blue[i], YOld[i], YNew[i], sharpeningParams.gamma, W); + Color::RGB2L(redVals[i], greenVals[i], blueVals[i], L[i], xyz_rgb, W); + Color::RGB2Y(redVals[i], greenVals[i], blueVals[i], YOld[i], YNew[i], sharpeningParams.gamma, W); + } + if (plistener) { + plistener->setProgressStr(M("TP_PDSHARPENING_LABEL")); + plistener->setProgress(0.1); } // calculate contrast based blend factors to reduce sharpening in regions with low contrast JaggedArray blend(W, H); buildBlendMask(L, blend, W, H, contrast, 1.f, sharpeningParams.autoContrast); + if (plistener) { + plistener->setProgressStr(M("TP_PDSHARPENING_LABEL")); + plistener->setProgress(0.2); + } conrastThreshold = contrast * 100.f; Stop1.stop(); @@ -5008,6 +5087,10 @@ BENCHFUN ProcParams dummy; ImProcFunctions ipf(&dummy); ipf.deconvsharpening(YNew, tmp, blend, W, H, sharpeningParams, 1.0); + if (plistener) { + plistener->setProgressStr(M("TP_PDSHARPENING_LABEL")); + plistener->setProgress(0.9); + } StopWatch Stop2("Y2RGB"); const float gamma = sharpeningParams.gamma; #ifdef _OPENMP @@ -5019,20 +5102,24 @@ BENCHFUN const vfloat gammav = F2V(gamma); for (; j < W - 3; j += 4) { const vfloat factor = pow_F(LVFU(YNew[i][j]) / vmaxf(LVFU(YOld[i][j]), F2V(0.00001f)), gammav); - STVFU(red[i][j], LVFU(red[i][j]) * factor); - STVFU(green[i][j], LVFU(green[i][j]) * factor); - STVFU(blue[i][j], LVFU(blue[i][j]) * factor); + STVFU(red[i][j], LVFU(redVals[i][j]) * factor); + STVFU(green[i][j], LVFU(greenVals[i][j]) * factor); + STVFU(blue[i][j], LVFU(blueVals[i][j]) * factor); } #endif for (; j < W; ++j) { const float factor = pow_F(YNew[i][j] / std::max(YOld[i][j], 0.00001f), gamma); - red[i][j] *= factor; - green[i][j] *= factor; - blue[i][j] *= factor; + red[i][j] = redVals[i][j] * factor; + green[i][j] = greenVals[i][j] * factor; + blue[i][j] = blueVals[i][j] * factor; } } Stop2.stop(); + if (plistener) { + plistener->setProgressStr(M("TP_PDSHARPENING_LABEL")); + plistener->setProgress(1.0); + } } void RawImageSource::cleanup () diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 8cf6b08a9..bbc15c448 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -88,6 +88,12 @@ protected: array2D red; // the interpolated blue plane: array2D blue; + // the interpolated green plane: + array2D* greenCache; + // the interpolated red plane: + array2D* redCache; + // the interpolated blue plane: + array2D* blueCache; bool rawDirty; float psRedBrightness[4]; float psGreenBrightness[4]; @@ -117,7 +123,7 @@ public: void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, bool prepareDenoise = true) override; void filmNegativeProcess (const procparams::FilmNegativeParams ¶ms) override; bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, std::array& newExps) override; - void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold) override; + void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold, bool cache = false) override; void retinex (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &deh, const procparams::ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) override; void retinexPrepareCurves (const procparams::RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) override; void retinexPrepareBuffers (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI) override; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 0524734e0..1751a7cea 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -220,7 +220,7 @@ private: bool autoContrast = imgsrc->getSensorType() == ST_BAYER ? params.raw.bayersensor.dualDemosaicAutoContrast : params.raw.xtranssensor.dualDemosaicAutoContrast; double contrastThreshold = imgsrc->getSensorType() == ST_BAYER ? params.raw.bayersensor.dualDemosaicContrast : params.raw.xtranssensor.dualDemosaicContrast; - imgsrc->demosaic (params.raw, autoContrast, contrastThreshold); + imgsrc->demosaic (params.raw, autoContrast, contrastThreshold, params.pdsharpening.enabled && pl); if (params.pdsharpening.enabled) { imgsrc->captureSharpening(params.pdsharpening, false, params.pdsharpening.contrast); } diff --git a/rtgui/pdsharpening.cc b/rtgui/pdsharpening.cc index 5c14c052f..8e7c0e8b8 100644 --- a/rtgui/pdsharpening.cc +++ b/rtgui/pdsharpening.cc @@ -30,11 +30,11 @@ PdSharpening::PdSharpening() : FoldableToolPanel(this, "pdsharpening", M("TP_PDS { auto m = ProcEventMapper::getInstance(); - EvPdShrContrast = m->newEvent(DEMOSAIC, "HISTORY_MSG_PDSHARPEN_CONTRAST"); - EvPdSharpenGamma = m->newEvent(DEMOSAIC, "HISTORY_MSG_PDSHARPEN_GAMMA"); - EvPdShrDRadius = m->newEvent(DEMOSAIC, "HISTORY_MSG_PDSHARPEN_RADIUS"); - EvPdShrDIterations = m->newEvent(DEMOSAIC, "HISTORY_MSG_PDSHARPEN_ITERATIONS"); - EvPdShrAutoContrast = m->newEvent(DEMOSAIC, "HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST"); + EvPdShrContrast = m->newEvent(ALLNORAW, "HISTORY_MSG_PDSHARPEN_CONTRAST"); + EvPdSharpenGamma = m->newEvent(ALLNORAW, "HISTORY_MSG_PDSHARPEN_GAMMA"); + EvPdShrDRadius = m->newEvent(ALLNORAW, "HISTORY_MSG_PDSHARPEN_RADIUS"); + EvPdShrDIterations = m->newEvent(ALLNORAW, "HISTORY_MSG_PDSHARPEN_ITERATIONS"); + EvPdShrAutoContrast = m->newEvent(ALLNORAW, "HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST"); Gtk::HBox* hb = Gtk::manage(new Gtk::HBox()); hb->show();