capture sharpening: do not trigger demosaic when changing adjusters

This commit is contained in:
Ingo Weyrich 2019-08-28 18:03:31 +02:00
parent ada08b3b71
commit ba8c3d15bf
6 changed files with 128 additions and 30 deletions

View File

@ -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 &params) {};
virtual bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams& currentParams, std::array<float, 3>& 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<float, 4> &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<float, 4> &conversionBuffer, LUTu &lhist16RETI) {};

View File

@ -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 {

View File

@ -45,6 +45,7 @@
#include <omp.h>
#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<float>(W, H);
greenCache = new array2D<float>(W, H);
blueCache = new array2D<float>(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<float>& redVals = redCache ? *redCache : red;
array2D<float>& greenVals = greenCache ? *greenCache : green;
array2D<float>& blueVals = blueCache ? *blueCache : blue;
if (showMask) {
StopWatch Stop1("Show mask");
array2D<float>& 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<float>& 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<float> 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 ()

View File

@ -88,6 +88,12 @@ protected:
array2D<float> red;
// the interpolated blue plane:
array2D<float> blue;
// the interpolated green plane:
array2D<float>* greenCache;
// the interpolated red plane:
array2D<float>* redCache;
// the interpolated blue plane:
array2D<float>* 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 &params) override;
bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams &currentParams, std::array<float, 3>& 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<float, 4> &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<float, 4> &conversionBuffer, LUTu &lhist16RETI) override;

View File

@ -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);
}

View File

@ -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();