diff --git a/rtdata/languages/default b/rtdata/languages/default index e8392db6b..9aa743ab0 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -763,6 +763,11 @@ HISTORY_MSG_LOCALCONTRAST_LIGHTNESS;Local Contrast - Lightness HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius HISTORY_MSG_METADATA_MODE;Metadata copy mode HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +HISTORY_MSG_PDSHARPEN_CONTRAST;CAS - Contrast threshold +HISTORY_MSG_PDSHARPEN_ENABLED;Capture Sharpening +HISTORY_MSG_PDSHARPEN_GAMMA;CAS - Gamma +HISTORY_MSG_PDSHARPEN_ITERATIONS;CAS - Iterations +HISTORY_MSG_PDSHARPEN_RADIUS;CAS - Radius HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter @@ -773,6 +778,7 @@ HISTORY_MSG_RAW_BORDER;Raw border HISTORY_MSG_RESIZE_ALLOWUPSCALING;Resize - Allow upscaling HISTORY_MSG_SHARPENING_BLUR;Sharpening - Blur radius HISTORY_MSG_SHARPENING_CONTRAST;Sharpening - Contrast threshold +HISTORY_MSG_SHARPENING_GAMMA;Sharpening - Gamma HISTORY_MSG_SH_COLORSPACE;S/H - Colorspace HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength @@ -1792,6 +1798,7 @@ TP_PCVIGNETTE_ROUNDNESS;Roundness TP_PCVIGNETTE_ROUNDNESS_TOOLTIP;Roundness:\n0 = rectangle,\n50 = fitted ellipse,\n100 = circle. TP_PCVIGNETTE_STRENGTH;Strength TP_PCVIGNETTE_STRENGTH_TOOLTIP;Filter strength in stops (reached in corners). +TP_PDSHARPENING_LABEL;Capture Sharpening TP_PERSPECTIVE_HORIZONTAL;Horizontal TP_PERSPECTIVE_LABEL;Perspective TP_PERSPECTIVE_VERTICAL;Vertical @@ -2020,6 +2027,7 @@ TP_SHARPENING_BLUR;Blur radius TP_SHARPENING_CONTRAST;Contrast threshold TP_SHARPENING_EDRADIUS;Radius TP_SHARPENING_EDTOLERANCE;Edge tolerance +TP_SHARPENING_GAMMA;Gamma TP_SHARPENING_HALOCONTROL;Halo control TP_SHARPENING_HCAMOUNT;Amount TP_SHARPENING_LABEL;Sharpening diff --git a/rtengine/color.h b/rtengine/color.h index 5bf178636..22a648634 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -1804,6 +1804,18 @@ public: return (hr); } + static inline void RGB2YCbCr(float R, float G, float B, float &Y, float &Cb, float &Cr) { + Y = 0.2627f * R + 0.6780f * G + 0.0593f * B; + Cb = -0.2627f * R - 0.6780f * G + (1.f - 0.0593f) * B; + Cr = (1.f - 0.2627f) * R - 0.6780f * G - 0.0593f * B; + + } + + static inline void YCbCr2RGB(float Y, float Cb, float Cr, float &R, float &G, float &B) { + R = std::max(Y + Cr, 0.f); + G = std::max(Y - (0.0593f / 0.6780f) * Cb - (0.2627f / 0.6780f) * Cr, 0.f); + B = std::max(Y + Cb, 0.f); + } }; } diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index bf73b5bb2..6e57bd532 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -46,7 +46,7 @@ struct LensProfParams; struct RAWParams; struct RetinexParams; struct ToneCurveParams; - +struct SharpeningParams; } class ImageMatrices @@ -182,6 +182,7 @@ public: return this; } virtual void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) = 0; + virtual void captureSharpening(const procparams::SharpeningParams &sharpeningParams) = 0; }; } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 6f471eedf..2e2ae9084 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -332,6 +332,9 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) double contrastThreshold = imgsrc->getSensorType() == ST_BAYER ? params->raw.bayersensor.dualDemosaicContrast : params->raw.xtranssensor.dualDemosaicContrast; imgsrc->demosaic(rp, autoContrast, contrastThreshold); //enabled demosaic + if (params->pdsharpening.enabled) { + imgsrc->captureSharpening(params->pdsharpening); + } if (imgsrc->getSensorType() == ST_BAYER && bayerAutoContrastListener && autoContrast) { bayerAutoContrastListener->autoContrastChanged(autoContrast ? contrastThreshold : -1.0); } @@ -1546,7 +1549,8 @@ void ImProcCoordinator::process() || params->retinex != nextParams->retinex || params->wavelet != nextParams->wavelet || params->dirpyrequalizer != nextParams->dirpyrequalizer - || params->dehaze != nextParams->dehaze; + || params->dehaze != nextParams->dehaze + || params->pdsharpening != nextParams->pdsharpening; *params = *nextParams; int change = changeSinceLast; diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 987a460d7..65f0f5a96 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -248,7 +248,7 @@ public: void Lanczos(const LabImage* src, LabImage* dst, float scale); void Lanczos(const Imagefloat* src, Imagefloat* dst, float scale); - void deconvsharpening(float** luminance, float** buffer, int W, int H, const procparams::SharpeningParams &sharpenParam); + void deconvsharpening(float** luminance, float** buffer, int W, int H, const procparams::SharpeningParams &sharpenParam, double Scale); void MLsharpen(LabImage* lab); // Manuel's clarity / sharpening void MLmicrocontrast(float** luminance, int W, int H); //Manuel's microcontrast void MLmicrocontrast(LabImage* lab); //Manuel's microcontrast diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index 9d7358fa9..eeda786a5 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -158,7 +158,7 @@ namespace rtengine extern const Settings* settings; -void ImProcFunctions::deconvsharpening (float** luminance, float** tmp, int W, int H, const SharpeningParams &sharpenParam) +void ImProcFunctions::deconvsharpening (float** luminance, float** tmp, int W, int H, const SharpeningParams &sharpenParam, double Scale) { if (sharpenParam.deconvamount == 0 && sharpenParam.blurradius < 0.25f) { return; @@ -201,7 +201,7 @@ BENCHFUN } const float damping = sharpenParam.deconvdamping / 5.0; const bool needdamp = sharpenParam.deconvdamping > 0; - const double sigma = sharpenParam.deconvradius / scale; + const double sigma = sharpenParam.deconvradius / Scale; const float amount = sharpenParam.deconvamount / 100.f; #ifdef _OPENMP @@ -274,7 +274,7 @@ void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpen JaggedArray b2(W, H); if (sharpenParam.method == "rld") { - deconvsharpening (lab->L, b2, lab->W, lab->H, sharpenParam); + deconvsharpening (lab->L, b2, lab->W, lab->H, sharpenParam, scale); return; } BENCHFUN @@ -905,7 +905,7 @@ void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2, bool showMask) if (params->sharpening.method == "rld") { - deconvsharpening (ncie->sh_p, b2, ncie->W, ncie->H, params->sharpening); + deconvsharpening (ncie->sh_p, b2, ncie->W, ncie->H, params->sharpening, scale); return; } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 66837f89b..4f2cdce2e 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -1080,6 +1080,7 @@ SharpeningParams::SharpeningParams() : enabled(false), contrast(20.0), blurradius(0.2), + gamma(1.0), radius(0.5), amount(200), threshold(20, 80, 2000, 1200, false), @@ -1102,6 +1103,7 @@ bool SharpeningParams::operator ==(const SharpeningParams& other) const enabled == other.enabled && contrast == other.contrast && blurradius == other.blurradius + && gamma == other.gamma && radius == other.radius && amount == other.amount && threshold == other.threshold @@ -2787,6 +2789,13 @@ void ProcParams::setDefaults() prsharpening.deconviter = 100; prsharpening.deconvdamping = 0; + pdsharpening = {}; + pdsharpening.contrast = 0.0; + prsharpening.method = "rld"; + pdsharpening.gamma = 1.0; + pdsharpening.deconvradius = 0.75; + pdsharpening.deconviter = 30; + vibrance = {}; wb = {}; @@ -3296,6 +3305,13 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->resize.height, "Resize", "Height", resize.height, keyFile); saveToKeyfile(!pedited || pedited->resize.allowUpscaling, "Resize", "AllowUpscaling", resize.allowUpscaling, keyFile); +// Post demosaic sharpening + saveToKeyfile(!pedited || pedited->pdsharpening.enabled, "PostDemosaicSharpening", "Enabled", pdsharpening.enabled, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.contrast, "PostDemosaicSharpening", "Contrast", pdsharpening.contrast, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.gamma, "PostDemosaicSharpening", "DeconvGamma", pdsharpening.gamma, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.deconvradius, "PostDemosaicSharpening", "DeconvRadius", pdsharpening.deconvradius, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.deconviter, "PostDemosaicSharpening", "DeconvIterations", pdsharpening.deconviter, keyFile); + // Post resize sharpening saveToKeyfile(!pedited || pedited->prsharpening.enabled, "PostResizeSharpening", "Enabled", prsharpening.enabled, keyFile); saveToKeyfile(!pedited || pedited->prsharpening.contrast, "PostResizeSharpening", "Contrast", prsharpening.contrast, keyFile); @@ -4376,6 +4392,15 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) } } + if (keyFile.has_group("PostDemosaicSharpening")) { + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "Enabled", pedited, pdsharpening.enabled, pedited->pdsharpening.enabled); + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "Contrast", pedited, pdsharpening.contrast, pedited->pdsharpening.contrast); + + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "DeconvGamma", pedited, pdsharpening.gamma, pedited->pdsharpening.gamma); + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "DeconvRadius", pedited, pdsharpening.deconvradius, pedited->pdsharpening.deconvradius); + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "DeconvIterations", pedited, pdsharpening.deconviter, pedited->pdsharpening.deconviter); + } + if (keyFile.has_group("PostResizeSharpening")) { assignFromKeyfile(keyFile, "PostResizeSharpening", "Enabled", pedited, prsharpening.enabled, pedited->prsharpening.enabled); assignFromKeyfile(keyFile, "PostResizeSharpening", "Contrast", pedited, prsharpening.contrast, pedited->prsharpening.contrast); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 369af85fa..f9255f815 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -494,6 +494,7 @@ struct SharpeningParams { bool enabled; double contrast; double blurradius; + double gamma; double radius; int amount; Threshold threshold; @@ -1526,6 +1527,7 @@ public: ColorToningParams colorToning; ///< Color Toning parameters SharpeningParams sharpening; ///< Sharpening parameters SharpeningParams prsharpening; ///< Sharpening parameters for post resize sharpening + SharpeningParams pdsharpening; ///< Sharpening parameters for post demosaic sharpening SharpenEdgeParams sharpenEdge; ///< Sharpen edge parameters SharpenMicroParams sharpenMicro; ///< Sharpen microcontrast parameters VibranceParams vibrance; ///< Vibrance parameters diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 6cb6fff16..5d8dd8448 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -37,6 +37,9 @@ #include "pdaflinesfilter.h" #include "camconst.h" #include "procparams.h" +#include "color.h" +#define BENCHMARK +#include "StopWatch.h" #ifdef _OPENMP #include #endif @@ -4949,6 +4952,36 @@ void RawImageSource::getRawValues(int x, int y, int rotate, int &R, int &G, int } } +void RawImageSource::captureSharpening(const procparams::SharpeningParams &sharpeningParams) { +BENCHFUN + + array2D Y(W,H); + array2D Cb(W,H); + array2D Cr(W,H); + const float gamma = sharpeningParams.gamma; + StopWatch Stop1("rgb2Y"); + #pragma omp parallel for + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W ; ++j) { + Color::RGB2YCbCr(std::max(red[i][j], 0.f), std::max(green[i][j], 0.f), std::max(blue[i][j], 0.f), Y[i][j], Cb[i][j], Cr[i][j]); + Y[i][j] = pow_F(Y[i][j], 1.f / gamma); + } + } + Stop1.stop(); + array2D tmp(W, H); + ProcParams dummy; + ImProcFunctions ipf(&dummy); + ipf.deconvsharpening(Y, tmp, W, H, sharpeningParams, 1.0); + StopWatch Stop2("Y2RGB"); + #pragma omp parallel for + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W ; ++j) { + Y[i][j] = pow_F(Y[i][j], gamma); + Color::YCbCr2RGB(Y[i][j], Cb[i][j], Cr[i][j], red[i][j], green[i][j], blue[i][j]); + } + } + Stop2.stop(); +} void RawImageSource::cleanup () { delete phaseOneIccCurve; diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 7c50991c0..7b86111af 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -305,7 +305,7 @@ protected: void hflip (Imagefloat* im); void vflip (Imagefloat* im); void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override; - + void captureSharpening(const procparams::SharpeningParams &sharpeningParams) override; }; } diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 2d594e0af..a9d32dbac 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -221,6 +221,9 @@ private: double contrastThreshold = imgsrc->getSensorType() == ST_BAYER ? params.raw.bayersensor.dualDemosaicContrast : params.raw.xtranssensor.dualDemosaicContrast; imgsrc->demosaic (params.raw, autoContrast, contrastThreshold); + if (params.pdsharpening.enabled) { + imgsrc->captureSharpening(params.pdsharpening); + } if (pl) { diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index 8f16880dc..a8251ade0 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -102,7 +102,7 @@ public: void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override { R = G = B = 0;} void flushRGB () override; - + void captureSharpening(const procparams::SharpeningParams &sharpeningParams) override {}; }; } #endif diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index bdd166938..bc52b64b0 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -106,6 +106,7 @@ set(NONCLISOURCEFILES partialpastedlg.cc pathutils.cc pcvignette.cc + pdsharpening.cc perspective.cc placesbrowser.cc popupbutton.cc diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index 163bc27ef..6a4ea83d3 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -142,6 +142,7 @@ enum { ADDSET_XTRANS_FALSE_COLOR_SUPPRESSION, ADDSET_SOFTLIGHT_STRENGTH, ADDSET_DEHAZE_STRENGTH, + ADDSET_SHARP_GAMMA, ADDSET_PARAM_NUM // THIS IS USED AS A DELIMITER!! }; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index cb3d4151c..da65cbf8e 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -152,6 +152,7 @@ void ParamsEdited::set(bool v) sharpening.contrast = v; sharpening.radius = v; sharpening.blurradius = v; + sharpening.gamma = v; sharpening.amount = v; sharpening.threshold = v; sharpening.edgesonly = v; @@ -164,6 +165,12 @@ void ParamsEdited::set(bool v) sharpening.deconvradius = v; sharpening.deconviter = v; sharpening.deconvdamping = v; + pdsharpening.enabled = v; + pdsharpening.contrast = v; + pdsharpening.gamma = v; + pdsharpening.deconvamount = v; + pdsharpening.deconvradius = v; + pdsharpening.deconviter = v; prsharpening.enabled = v; prsharpening.contrast = v; prsharpening.radius = v; @@ -729,6 +736,7 @@ void ParamsEdited::initFrom(const std::vector& sharpening.contrast = sharpening.contrast && p.sharpening.contrast == other.sharpening.contrast; sharpening.radius = sharpening.radius && p.sharpening.radius == other.sharpening.radius; sharpening.blurradius = sharpening.blurradius && p.sharpening.blurradius == other.sharpening.blurradius; + sharpening.gamma = sharpening.gamma && p.sharpening.gamma == other.sharpening.gamma; sharpening.amount = sharpening.amount && p.sharpening.amount == other.sharpening.amount; sharpening.threshold = sharpening.threshold && p.sharpening.threshold == other.sharpening.threshold; sharpening.edgesonly = sharpening.edgesonly && p.sharpening.edgesonly == other.sharpening.edgesonly; @@ -741,6 +749,11 @@ void ParamsEdited::initFrom(const std::vector& sharpening.deconvradius = sharpening.deconvradius && p.sharpening.deconvradius == other.sharpening.deconvradius; sharpening.deconviter = sharpening.deconviter && p.sharpening.deconviter == other.sharpening.deconviter; sharpening.deconvdamping = sharpening.deconvdamping && p.sharpening.deconvdamping == other.sharpening.deconvdamping; + pdsharpening.enabled = pdsharpening.enabled && p.pdsharpening.enabled == other.pdsharpening.enabled; + pdsharpening.contrast = pdsharpening.contrast && p.pdsharpening.contrast == other.pdsharpening.contrast; + pdsharpening.gamma = pdsharpening.gamma && p.pdsharpening.gamma == other.pdsharpening.gamma; + pdsharpening.deconvradius = pdsharpening.deconvradius && p.pdsharpening.deconvradius == other.pdsharpening.deconvradius; + pdsharpening.deconviter = pdsharpening.deconviter && p.pdsharpening.deconviter == other.pdsharpening.deconviter; prsharpening.enabled = prsharpening.enabled && p.prsharpening.enabled == other.prsharpening.enabled; prsharpening.contrast = prsharpening.contrast && p.prsharpening.contrast == other.prsharpening.contrast; prsharpening.radius = prsharpening.radius && p.prsharpening.radius == other.prsharpening.radius; @@ -1654,6 +1667,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.sharpening.blurradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.blurradius + mods.sharpening.blurradius : mods.sharpening.blurradius; } + if (sharpening.gamma) { + toEdit.sharpening.gamma = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.gamma + mods.sharpening.gamma : mods.sharpening.gamma; + } + if (sharpening.amount) { toEdit.sharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.amount + mods.sharpening.amount : mods.sharpening.amount; } @@ -1702,6 +1719,30 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.sharpening.deconvdamping = dontforceSet && options.baBehav[ADDSET_SHARP_DAMPING] ? toEdit.sharpening.deconvdamping + mods.sharpening.deconvdamping : mods.sharpening.deconvdamping; } + if (pdsharpening.enabled) { + toEdit.pdsharpening.enabled = mods.pdsharpening.enabled; + } + + if (pdsharpening.contrast) { + toEdit.pdsharpening.contrast = dontforceSet && options.baBehav[ADDSET_SHARP_CONTRAST] ? toEdit.pdsharpening.contrast + mods.pdsharpening.contrast : mods.pdsharpening.contrast; + } + + if (pdsharpening.deconvamount) { + toEdit.pdsharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.pdsharpening.deconvamount + mods.pdsharpening.deconvamount : mods.pdsharpening.deconvamount; + } + + if (pdsharpening.gamma) { + toEdit.pdsharpening.gamma = dontforceSet && options.baBehav[ADDSET_SHARP_GAMMA] ? toEdit.pdsharpening.gamma + mods.pdsharpening.gamma : mods.pdsharpening.gamma; + } + + if (pdsharpening.deconvradius) { + toEdit.pdsharpening.deconvradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.pdsharpening.deconvradius + mods.pdsharpening.deconvradius : mods.pdsharpening.deconvradius; + } + + if (pdsharpening.deconviter) { + toEdit.pdsharpening.deconviter = dontforceSet && options.baBehav[ADDSET_SHARP_ITER] ? toEdit.pdsharpening.deconviter + mods.pdsharpening.deconviter : mods.pdsharpening.deconviter; + } + if (prsharpening.enabled) { toEdit.prsharpening.enabled = mods.prsharpening.enabled; } @@ -3244,3 +3285,8 @@ bool FilmNegativeParamsEdited::isUnchanged() const { return enabled && redRatio && greenExp && blueRatio; } + +bool SharpeningParamsEdited::isUnchanged() const +{ + return enabled && contrast && gamma && deconvradius && deconviter; +} \ No newline at end of file diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 08a41fc7a..5191bce56 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -180,6 +180,7 @@ struct SharpeningParamsEdited { bool enabled; bool contrast; bool blurradius; + bool gamma; bool radius; bool amount; bool threshold; @@ -194,6 +195,7 @@ struct SharpeningParamsEdited { bool deconvradius; bool deconviter; bool deconvdamping; + bool isUnchanged() const; }; struct VibranceParamsEdited { @@ -684,6 +686,7 @@ struct ParamsEdited { ColorToningEdited colorToning; RetinexParamsEdited retinex; SharpeningParamsEdited sharpening; + SharpeningParamsEdited pdsharpening; SharpeningParamsEdited prsharpening; SharpenEdgeParamsEdited sharpenEdge; SharpenMicroParamsEdited sharpenMicro; diff --git a/rtgui/pdsharpening.cc b/rtgui/pdsharpening.cc new file mode 100644 index 000000000..a33da813d --- /dev/null +++ b/rtgui/pdsharpening.cc @@ -0,0 +1,221 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include +#include "eventmapper.h" +#include "pdsharpening.h" + +using namespace rtengine; +using namespace rtengine::procparams; + +PdSharpening::PdSharpening () : FoldableToolPanel(this, "pdsharpening", M("TP_PDSHARPENING_LABEL"), false, true) +{ + + auto m = ProcEventMapper::getInstance(); + EvPdShrEnabled = m->newEvent(DEMOSAIC, "HISTORY_MSG_PDSHARPEN_ENABLED"); + 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"); + + Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); + hb->show (); + contrast = Gtk::manage(new Adjuster (M("TP_SHARPENING_CONTRAST"), 0, 200, 1, 15)); + contrast->setAdjusterListener (this); + pack_start(*contrast); + contrast->show(); + + pack_start (*hb); + + rld = new Gtk::VBox (); + gamma = Gtk::manage (new Adjuster (M("TP_SHARPENING_GAMMA"), 0.5, 3.0, 0.05, 1.0)); + dradius = Gtk::manage (new Adjuster (M("TP_SHARPENING_EDRADIUS"), 0.4, 2.5, 0.01, 0.75)); + diter = Gtk::manage (new Adjuster (M("TP_SHARPENING_RLD_ITERATIONS"), 5, 100, 1, 30)); + rld->pack_start (*gamma); + rld->pack_start (*dradius); + rld->pack_start (*diter); + gamma->show(); + dradius->show (); + diter->show (); + rld->show (); + pack_start(*rld); + + dradius->setAdjusterListener (this); + gamma->setAdjusterListener (this); + diter->setAdjusterListener (this); + + rld->reference(); +} + +PdSharpening::~PdSharpening () +{ + + delete rld; +} + + +void PdSharpening::read (const ProcParams* pp, const ParamsEdited* pedited) +{ + + disableListener (); + + if (pedited) { + contrast->setEditedState (pedited->pdsharpening.contrast ? Edited : UnEdited); + gamma->setEditedState (pedited->pdsharpening.gamma ? Edited : UnEdited); + dradius->setEditedState (pedited->pdsharpening.deconvradius ? Edited : UnEdited); + diter->setEditedState (pedited->pdsharpening.deconviter ? Edited : UnEdited); + + set_inconsistent (multiImage && !pedited->pdsharpening.enabled); + } + + setEnabled(pp->pdsharpening.enabled); + + contrast->setValue (pp->pdsharpening.contrast); + gamma->setValue (pp->pdsharpening.gamma); + dradius->setValue (pp->pdsharpening.deconvradius); + diter->setValue (pp->pdsharpening.deconviter); + + enableListener (); +} + +void PdSharpening::write (ProcParams* pp, ParamsEdited* pedited) +{ + + pp->pdsharpening.contrast = contrast->getValue (); + pp->pdsharpening.enabled = getEnabled (); + pp->pdsharpening.gamma = gamma->getValue (); + pp->pdsharpening.deconvradius = dradius->getValue (); + pp->pdsharpening.deconviter = (int)diter->getValue (); + + if (pedited) { + pedited->pdsharpening.contrast = contrast->getEditedState (); + pedited->pdsharpening.gamma = gamma->getEditedState (); + pedited->pdsharpening.deconvradius = dradius->getEditedState (); + pedited->pdsharpening.deconviter = diter->getEditedState (); + pedited->pdsharpening.enabled = !get_inconsistent(); + } +} + +void PdSharpening::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ + + contrast->setDefault (defParams->pdsharpening.contrast); + gamma->setDefault (defParams->pdsharpening.gamma); + dradius->setDefault (defParams->pdsharpening.deconvradius); + diter->setDefault (defParams->pdsharpening.deconviter); + + if (pedited) { + contrast->setDefaultEditedState (pedited->pdsharpening.contrast ? Edited : UnEdited); + gamma->setDefaultEditedState (pedited->pdsharpening.gamma ? Edited : UnEdited); + dradius->setDefaultEditedState (pedited->pdsharpening.deconvradius ? Edited : UnEdited); + diter->setDefaultEditedState (pedited->pdsharpening.deconviter ? Edited : UnEdited); + } else { + contrast->setDefaultEditedState (Irrelevant); + gamma->setDefaultEditedState (Irrelevant); + dradius->setDefaultEditedState (Irrelevant); + diter->setDefaultEditedState (Irrelevant); + } +} + +void PdSharpening::adjusterChanged (Adjuster* a, double newval) +{ + if (listener && (multiImage || getEnabled()) ) { + + Glib::ustring costr; + + if (a == gamma || a == dradius) { + costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), a->getValue()); + } else { + costr = Glib::ustring::format ((int)a->getValue()); + } + + if (a == contrast) { + listener->panelChanged (EvPdShrContrast, costr); + } else if (a == gamma) { + listener->panelChanged (EvPdSharpenGamma, costr); + } else if (a == dradius) { + listener->panelChanged (EvPdShrDRadius, costr); + } else if (a == diter) { + listener->panelChanged (EvPdShrDIterations, costr); + } + } +} + +void PdSharpening::enabledChanged () +{ + if (listener) { + if (get_inconsistent()) { + listener->panelChanged (EvPdShrEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged (EvPdShrEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvPdShrEnabled, M("GENERAL_DISABLED")); + } + } +} + +void PdSharpening::adjusterChanged(ThresholdAdjuster* a, double newBottom, double newTop) +{ +} + +void PdSharpening::adjusterChanged(ThresholdAdjuster* a, double newBottomLeft, double newTopLeft, double newBottomRight, double newTopRight) +{ +} + +void PdSharpening::adjusterChanged(ThresholdAdjuster* a, int newBottom, int newTop) +{ +} + +void PdSharpening::adjusterChanged(ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) +{ +} + +void PdSharpening::adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) +{ +} + +void PdSharpening::setBatchMode (bool batchMode) +{ + + ToolPanel::setBatchMode (batchMode); + +// pack_start (*rld); + + contrast->showEditedCB (); + gamma->showEditedCB (); + dradius->showEditedCB (); + diter->showEditedCB (); +} + +void PdSharpening::setAdjusterBehavior (bool contrastadd, bool gammaadd, bool radiusadd, bool amountadd, bool dampingadd, bool iteradd, bool edgetoladd, bool haloctrladd) +{ + + contrast->setAddMode(contrastadd); + gamma->setAddMode(gammaadd); + dradius->setAddMode(radiusadd); + diter->setAddMode(iteradd); +} + +void PdSharpening::trimValues (rtengine::procparams::ProcParams* pp) +{ + + contrast->trimValue(pp->pdsharpening.contrast); + gamma->trimValue(pp->pdsharpening.gamma); + dradius->trimValue(pp->pdsharpening.deconvradius); + diter->trimValue(pp->pdsharpening.deconviter); +} diff --git a/rtgui/pdsharpening.h b/rtgui/pdsharpening.h new file mode 100644 index 000000000..998322fe4 --- /dev/null +++ b/rtgui/pdsharpening.h @@ -0,0 +1,62 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2019 Ingo Weyrich (heckflosse67@gmx.de) + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#pragma once + +#include +#include "adjuster.h" +#include "thresholdadjuster.h" +#include "toolpanel.h" + +class PdSharpening : public ToolParamBlock, public ThresholdAdjusterListener, public AdjusterListener, public FoldableToolPanel +{ + +protected: + Adjuster* contrast; + Adjuster* gamma; + Adjuster* dradius; + Adjuster* diter; + Gtk::VBox* rld; + + rtengine::ProcEvent EvPdShrEnabled; + rtengine::ProcEvent EvPdShrContrast; + rtengine::ProcEvent EvPdShrDRadius; + rtengine::ProcEvent EvPdSharpenGamma; + rtengine::ProcEvent EvPdShrDIterations; +public: + + PdSharpening (); + ~PdSharpening () override; + + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; + void setBatchMode (bool batchMode) override; + + void adjusterChanged (Adjuster* a, double newval) override; + void enabledChanged () override; + + void adjusterChanged(ThresholdAdjuster* a, double newBottom, double newTop) override; + void adjusterChanged(ThresholdAdjuster* a, double newBottomLeft, double newTopLeft, double newBottomRight, double newTopRight) override; + void adjusterChanged(ThresholdAdjuster* a, int newBottom, int newTop) override; + void adjusterChanged(ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) override; + void adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) override; + + void setAdjusterBehavior (bool contrastadd, bool gammaadd, bool radiusadd, bool amountadd, bool dampingadd, bool iteradd, bool edgetoladd, bool haloctrladd); + void trimValues (rtengine::procparams::ProcParams* pp) override; +}; diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index f7e2991e1..64e44b3fb 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -93,7 +93,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit xtransrawexposure = Gtk::manage (new XTransRAWExposure ()); fattal = Gtk::manage (new FattalToneMapping ()); filmNegative = Gtk::manage (new FilmNegative ()); - + pdSharpening = Gtk::manage (new PdSharpening()); // So Demosaic, Line noise filter, Green Equilibration, Ca-Correction (garder le nom de section identique!) and Black-Level will be moved in a "Bayer sensor" tool, // and a separate Demosaic and Black Level tool will be created in an "X-Trans sensor" tool @@ -156,6 +156,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit addfavoritePanel (rawPanel, darkframe); addfavoritePanel (rawPanel, flatfield); addfavoritePanel (rawPanel, filmNegative); + addfavoritePanel (rawPanel, pdSharpening); int favoriteCount = 0; for(auto it = favorites.begin(); it != favorites.end(); ++it) { @@ -309,6 +310,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt preprocess->FoldableToolPanel::show(); flatfield->FoldableToolPanel::show(); filmNegative->FoldableToolPanel::show(); + pdSharpening->FoldableToolPanel::show(); retinex->FoldableToolPanel::setGrayedOut(false); return false; @@ -325,6 +327,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt preprocess->FoldableToolPanel::show(); flatfield->FoldableToolPanel::show(); filmNegative->FoldableToolPanel::show(); + pdSharpening->FoldableToolPanel::show(); retinex->FoldableToolPanel::setGrayedOut(false); return false; @@ -341,6 +344,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt preprocess->FoldableToolPanel::hide(); flatfield->FoldableToolPanel::show(); filmNegative->FoldableToolPanel::hide(); + pdSharpening->FoldableToolPanel::hide(); retinex->FoldableToolPanel::setGrayedOut(false); return false; @@ -356,6 +360,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt preprocess->FoldableToolPanel::hide(); flatfield->FoldableToolPanel::hide(); filmNegative->FoldableToolPanel::hide(); + pdSharpening->FoldableToolPanel::hide(); retinex->FoldableToolPanel::setGrayedOut(false); return false; @@ -368,6 +373,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt { rawPanelSW->set_sensitive(false); filmNegative->FoldableToolPanel::hide(); + pdSharpening->FoldableToolPanel::hide(); retinex->FoldableToolPanel::setGrayedOut(true); return false; @@ -484,7 +490,7 @@ void ToolPanelCoordinator::profileChange( lParams[1] = *mergedParams; pe.initFrom (lParams); - filterRawRefresh = pe.raw.isUnchanged() && pe.lensProf.isUnchanged() && pe.retinex.isUnchanged() && pe.filmNegative.isUnchanged(); + filterRawRefresh = pe.raw.isUnchanged() && pe.lensProf.isUnchanged() && pe.retinex.isUnchanged() && pe.filmNegative.isUnchanged() && pe.pdsharpening.isUnchanged(); } *params = *mergedParams; diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index a1b26b29f..b88fef124 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -77,6 +77,7 @@ #include "colortoning.h" #include "filmsimulation.h" #include "prsharpening.h" +#include "pdsharpening.h" #include "fattaltonemap.h" #include "localcontrast.h" #include "softlight.h" @@ -157,7 +158,7 @@ protected: FattalToneMapping *fattal; MetaDataPanel* metadata; FilmNegative* filmNegative; - + PdSharpening* pdSharpening; std::vector paramcListeners; rtengine::StagedImageProcessor* ipc;