1 /*
2  *  This file is part of RawTherapee.
3  *
4  *  Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
5  *
6  *  RawTherapee is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  RawTherapee is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with RawTherapee.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 #pragma once
20 
21 #include <memory>
22 
23 #include "coord2d.h"
24 #include "gamutwarning.h"
25 #include "pipettebuffer.h"
26 
27 template<typename T>
28 class LUT;
29 
30 using LUTu = LUT<uint32_t>;
31 using LUTf = LUT<float>;
32 
33 template<typename T, const size_t num>
34 class multi_array2D;
35 namespace rtengine
36 {
37 
38 class ColorAppearance;
39 class ColorGradientCurve;
40 class DCPProfile;
41 class DCPProfileApplyState;
42 class FlatCurve;
43 class FramesMetaData;
44 class LensCorrection;
45 class NoiseCurve;
46 class OpacityCurve;
47 class ToneCurve;
48 class WavCurve;
49 class WavOpacityCurveBY;
50 class WavOpacityCurveRG;
51 class WavOpacityCurveW;
52 class WavOpacityCurveWL;
53 
54 class CieImage;
55 class Image8;
56 class Imagefloat;
57 class LabImage;
58 class wavelet_decomposition;
59 
60 namespace procparams
61 {
62 
63 class ProcParams;
64 
65 struct ColorManagementParams;
66 struct DirPyrDenoiseParams;
67 struct SharpeningParams;
68 struct VignettingParams;
69 struct WaveletParams;
70 
71 }
72 
73 enum RenderingIntent : int;
74 
75 class ImProcFunctions
76 {
77     cmsHTRANSFORM monitorTransform;
78     std::unique_ptr<GamutWarning> gamutWarning;
79 
80     const procparams::ProcParams* params;
81     double scale;
82     bool multiThread;
83 
84     void calcVignettingParams(int oW, int oH, const procparams::VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul);
85 
86     void transformLuminanceOnly(Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH);
87     void transformGeneral(bool highQuality, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap, bool useOriginalBuffer);
88     void transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap, bool useOriginalBuffer);
89 
90     bool needsCA() const;
91     bool needsDistortion() const;
92     bool needsRotation() const;
93     bool needsPerspective() const;
94     bool needsGradient() const;
95     bool needsVignetting() const;
96     bool needsLCP() const;
97     bool needsLensfun() const;
98 //   static cmsUInt8Number* Mempro = NULL;
99 
100 
101 public:
102     enum class Median {
103         TYPE_3X3_SOFT,
104         TYPE_3X3_STRONG,
105         TYPE_5X5_SOFT,
106         TYPE_5X5_STRONG,
107         TYPE_7X7,
108         TYPE_9X9
109     };
110 
111     double lumimul[3];
112 
113     explicit ImProcFunctions(const procparams::ProcParams* iparams, bool imultiThread = true)
monitorTransform(nullptr)114         : monitorTransform(nullptr), params(iparams), scale(1), multiThread(imultiThread), lumimul{} {}
115     ~ImProcFunctions();
needsLuminanceOnly()116     bool needsLuminanceOnly()
117     {
118         return !(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP() || needsLensfun()) && (needsVignetting() || needsPCVignetting() || needsGradient());
119     }
120     void setScale(double iscale);
121 
122     bool needsTransform(int oW, int oH, int rawRotationDeg, const FramesMetaData *metadata) const;
123     bool needsPCVignetting() const;
124 
125     void firstAnalysis(const Imagefloat* const working, const procparams::ProcParams &params, LUTu & vhist16);
126     void updateColorProfiles(const Glib::ustring& monitorProfile, RenderingIntent monitorIntent, bool softProof, bool gamutCheck);
127     void rgbProc(Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, const LUTf& hltonecurve, const LUTf& shtonecurve, const LUTf& tonecurve,
128                  int sat, const LUTf& rCurve, const LUTf& gCurve, const LUTf& bCurve, float satLimit, float satLimitOpacity, const ColorGradientCurve& ctColorCurve,
129                  const OpacityCurve& ctOpacityCurve, bool opautili, const LUTf& clcurve, const LUTf& cl2curve, const ToneCurve& customToneCurve1,
130                  const ToneCurve& customToneCurve2, const ToneCurve& customToneCurvebw1, const ToneCurve& customToneCurvebw2,
131                  double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf,
132                  const DCPProfileApplyState& asIn, LUTu& histToneCurve, size_t chunkSize = 1, bool measure = false);
133     void rgbProc(Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, const LUTf& hltonecurve, const LUTf& shtonecurve, const LUTf& tonecurve,
134                  int sat, const LUTf& rCurve, const LUTf& gCurve, const LUTf& bCurve, float satLimit, float satLimitOpacity, const ColorGradientCurve& ctColorCurve,
135                  const OpacityCurve& ctOpacityCurve, bool opautili, const LUTf& clcurve, const LUTf& cl2curve, const ToneCurve& customToneCurve1,
136                  const ToneCurve& customToneCurve2, const ToneCurve& customToneCurvebw1, const ToneCurve& customToneCurvebw2,
137                  double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr,
138                  int hlcomprthresh, DCPProfile *dcpProf, const DCPProfileApplyState& asIn, LUTu& histToneCurve, size_t chunkSize = 1, bool measure = false);
139     void labtoning(float r, float g, float b, float &ro, float &go, float &bo, int algm, int metchrom, int twoc, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, const LUTf & clToningcurve, const LUTf & cl2Toningcurve, float iplow, float iphigh, double wp[3][3], double wip[3][3]);
140     void toning2col(float r, float g, float b, float &ro, float &go, float &bo, float iplow, float iphigh, float rl, float gl, float bl, float rh, float gh, float bh, float SatLow, float SatHigh, float balanS, float balanH, float reducac, int mode, int preser, float strProtect);
141     void toningsmh(float r, float g, float b, float &ro, float &go, float &bo, float RedLow, float GreenLow, float BlueLow, float RedMed, float GreenMed, float BlueMed, float RedHigh, float GreenHigh, float BlueHigh, float reducac, int mode, float strProtect);
142     void toningsmh2(float r, float g, float b, float &ro, float &go, float &bo, float low[3], float satLow, float med[3], float satMed, float high[3], float satHigh, float reducac, int mode, int preser);
143     void secondeg_begin(float reducac, float vend, float &aam, float &bbm);
144     void secondeg_end(float reducac, float vinf, float &aa, float &bb, float &cc);
145 
146     void retreavergb(float &r, float &g, float &b);
147     void moyeqt(Imagefloat* working, float &moyS, float &eqty);
148 
149     void luminanceCurve(LabImage* lold, LabImage* lnew, const LUTf &curve);
150     void ciecam_02float(CieImage* ncie, float adap, int pW, int pwb, LabImage* lab, const procparams::ProcParams* params,
151                         const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3,
152                         LUTu &histLCAM, LUTu &histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, float &d, float &dj, float &yb, int rtt,
153                         bool showSharpMask = false);
154     void chromiLuminanceCurve(PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, const LUTf& acurve, const LUTf& bcurve, const LUTf& satcurve, const LUTf& satclcurve, const LUTf& clcurve, LUTf &curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histLurve);
155     void vibrance(LabImage* lab);         //Jacques' vibrance
156 //    void colorCurve       (LabImage* lold, LabImage* lnew);
157     void sharpening(LabImage* lab, const procparams::SharpeningParams &sharpenParam, bool showMask = false);
158     void sharpeningcam(CieImage* ncie, float** buffer, bool showMask = false);
159     void transform(Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, int rawRotationDeg, bool fullImage, bool useOriginalBuffer = false);
160     float resizeScale(const procparams::ProcParams* params, int fw, int fh, int &imw, int &imh);
161     void lab2monitorRgb(LabImage* lab, Image8* image);
162     void resize(Imagefloat* src, Imagefloat* dst, float dScale);
163     void Lanczos(const LabImage* src, LabImage* dst, float scale);
164     void Lanczos(const Imagefloat* src, Imagefloat* dst, float scale);
165 
166     void deconvsharpening(float** luminance, float** buffer, const float* const * blend, int W, int H, const procparams::SharpeningParams &sharpenParam, double Scale);
167     void MLsharpen(LabImage* lab); // Manuel's clarity / sharpening
168     void MLmicrocontrast(float** luminance, int W, int H);   //Manuel's microcontrast
169     void MLmicrocontrast(LabImage* lab);   //Manuel's microcontrast
170     void MLmicrocontrastcam(CieImage* ncie);   //Manuel's microcontrast
171 
172     void impulsedenoise(LabImage* lab);   //Emil's impulse denoise
173     void impulsedenoisecam(CieImage* ncie, float **buffers[3]);
174     void impulse_nr(LabImage* lab, double thresh);
175     void impulse_nrcam(CieImage* ncie, double thresh, float **buffers[3]);
176 
177     void dirpyrdenoise(LabImage* src);    //Emil's pyramid denoise
178     void dirpyrequalizer(LabImage* lab, int scale);  //Emil's wavelet
179 
180 
181     void EPDToneMapResid(float * WavCoeffs_L0, unsigned int Iterates,  int skip, struct cont_params& cp, int W_L, int H_L, float max0, float min0);
182     void CompressDR(float *Source, int W_L, int H_L, float Compression, float DetailBoost);
183     void ContrastResid(float * WavCoeffs_L0, struct cont_params &cp, int W_L, int H_L, float max0, float min0);
184 
185     void EPDToneMap(LabImage *lab, unsigned int Iterates = 0, int skip = 1);
186     void EPDToneMapCIE(CieImage *ncie, float a_w, float c_, int Wid, int Hei, float minQ, float maxQ, unsigned int Iterates = 0, int skip = 1);
187 
188     // pyramid denoise
189 //    procparams::DirPyrDenoiseParams dnparams;
190     void dirpyr(LabImage* data_fine, LabImage* data_coarse, int level, LUTf &rangefn_L, LUTf &rangefn_ab,
191                 int pitch, int scale, const int luma, int chroma);
192     void idirpyr(LabImage* data_coarse, LabImage* data_fine, int level, LUTf &rangefn_L, LUTf & nrwt_l, LUTf & nrwt_ab,
193                  int pitch, int scale, const int luma, const int chroma/*, LUTf & Lcurve, LUTf & abcurve*/);
194 
195     void Tile_calc(int tilesize, int overlap, int kall, int imwidth, int imheight, int &numtiles_W, int &numtiles_H, int &tilewidth, int &tileheight, int &tileWskip, int &tileHskip);
196     void ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveBY & waOpacityCurveBY,  const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, LUTf &wavclCurve, int skip);
197 
198     void WaveletcontAllL(LabImage * lab, float **varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_L,
199                          struct cont_params &cp, int skip, float *mean, float *sigma, float *MaxP, float *MaxN,  const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* ChCurve, bool Chutili);
200     void WaveletcontAllLfinal(wavelet_decomposition &WaveletCoeffs_L, struct cont_params &cp, float *mean, float *sigma, float *MaxP, const WavOpacityCurveWL & waOpacityCurveWL);
201     void WaveletcontAllAB(LabImage * lab, float **varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_a, const WavOpacityCurveW & waOpacityCurveW,
202                           struct cont_params &cp, const bool useChannelA);
203     void WaveletAandBAllAB(wavelet_decomposition &WaveletCoeffs_a, wavelet_decomposition &WaveletCoeffs_b,
204                            struct cont_params &cp, FlatCurve* hhcurve, bool hhutili);
205     void ContAllL(float **koeLi, float *maxkoeLi, bool lipschitz, int maxlvl, LabImage * lab, float **varhue, float **varchrom, float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, struct cont_params &cp,
206                   int W_L, int H_L, int skip, float *mean, float *sigma, float *MaxP, float *MaxN,  const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* ChCurve, bool Chutili);
207     void finalContAllL(float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, struct cont_params &cp,
208                        int W_L, int H_L, float *mean, float *sigma, float *MaxP, const WavOpacityCurveWL & waOpacityCurveWL);
209     void ContAllAB(LabImage * lab, int maxlvl, float **varhue, float **varchrom, float ** WavCoeffs_a, float * WavCoeffs_a0, int level, int dir, const WavOpacityCurveW & waOpacityCurveW, struct cont_params &cp,
210                    int W_ab, int H_ab, const bool useChannelA);
211     void Evaluate2(wavelet_decomposition &WaveletCoeffs_L,
212                    float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN);
213     void Eval2(float ** WavCoeffs_L, int level,
214                int W_L, int H_L, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN);
215 
216     void Aver(float * HH_Coeffs, int datalen, float &averagePlus, float &averageNeg, float &max, float &min);
217     void Sigma(float * HH_Coeffs, int datalen, float averagePlus, float averageNeg, float &sigmaPlus, float &sigmaNeg);
218     void calckoe(float ** WavCoeffs_LL, const struct cont_params& cp, float ** koeLi, int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC = nullptr);
219 
220 
221 
222     void Median_Denoise(float **src, float **dst, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = nullptr);
223     void Median_Denoise(float **src, float **dst, float upperBound, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = nullptr);
224     void RGB_denoise(int kall, Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, float * ch_M, float *max_r, float *max_b, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, const NoiseCurve & noiseLCurve, const NoiseCurve & noiseCCurve, float &nresi, float &highresi);
225     void RGB_denoise_infoGamCurve(const procparams::DirPyrDenoiseParams & dnparams, const bool isRAW, LUTf &gamcurve, float &gam, float &gamthresh, float &gamslope);
226     void RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, bool isRAW, const LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false);
227     void RGBtile_denoise(float * fLblox, int hblproc, float noisevar_Ldetail);     //for DCT
228     void RGBoutput_tile_row(float *bloxrow_L, float ** Ldetail, float ** tilemask_out, int height, int width, int top);
229     bool WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge);
230     bool WaveletDenoiseAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb);
231     void WaveletDenoiseAll_info(int levwav, const wavelet_decomposition &WaveletCoeffs_a,
232                                 const wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float & minblueaut, int schoice, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
233                                 float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb);
234 
235     bool WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3]);
236     bool WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float noisevar_ab,
237                                       const bool useNoiseCCurve,  bool autoch, bool denoiseMethodRgb);
238     void ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, float *noisevarlum, float * madL, float * vari, int edge);
239     void ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir,
240                      float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * madaab = nullptr, bool madCalculated = false);
241     void ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b,
242                         int W_ab, int H_ab, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, int schoice, int lvl, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
243                         float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb);
244     void Noise_residualAB(const wavelet_decomposition &WaveletCoeffs_ab, float &chresid, float &chmaxresid, bool denoiseMethodRgb);
245     void calcautodn_info(float &chaut, float &delta, int Nb, int levaut, float maxmax, float lumema, float chromina, int mode, int lissage, float redyel, float skinc, float nsknc);
246     float Mad(const float * DataList, int datalen);
247     float MadRgb(const float * DataList, int datalen);
248 
249     // pyramid wavelet
250     void dirpyr_equalizer(const float * const * src, float ** dst, int srcwidth, int srcheight, const float * const * l_a, const float * const * l_b, const double * mult, double dirpyrThreshold, double skinprot, float b_l, float t_l, float t_r, int scale);    //Emil's directional pyramid wavelet
251     void dirpyr_equalizercam(const CieImage* ncie, float ** src, float ** dst, int srcwidth, int srcheight, const float * const * h_p, const float * const * C_p,  const double * mult, const double dirpyrThreshold, const double skinprot, float b_l, float t_l, float t_r, int scale);    //Emil's directional pyramid wavelet
252     void defringe(LabImage* lab);
253     void defringecam(CieImage* ncie);
254     void badpixcam(CieImage* ncie, double rad, int thr, int mode, float chrom, bool hotbad);
255     void badpixlab(LabImage* lab, double rad, int thr, float chrom);
256 
257     void PF_correct_RT(LabImage * lab, double radius, int thresh);
258     void PF_correct_RTcam(CieImage * ncie, double radius, int thresh);
259     void Badpixelscam(CieImage * ncie, double radius, int thresh, int mode, float chrom, bool hotbad);
260     void BadpixelsLab(LabImage * lab, double radius, int thresh, float chrom);
261 
262     void dehaze(Imagefloat *rgb);
263     void ToneMapFattal02(Imagefloat *rgb);
264     void localContrast(LabImage *lab);
265     void colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread);
266     void shadowsHighlights(LabImage *lab);
267     void softLight(LabImage *lab);
268     void labColorCorrectionRegions(LabImage *lab);
269 
270     Image8*     lab2rgb(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool consider_histogram_settings = true);
271     Imagefloat*    lab2rgbOut(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm);
272     // CieImage *ciec;
273     void workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, const Glib::ustring &profile, double gampos, double slpos, cmsHTRANSFORM &transform, bool normalizeIn = true, bool normalizeOut = true, bool keepTransForm = false) const;
274 
275     bool transCoord(int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr) const;
276     bool transCoord(int W, int H, const std::vector<Coord2D> &src, std::vector<Coord2D> &red,  std::vector<Coord2D> &green, std::vector<Coord2D> &blue, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr) const;
277     static void getAutoExp(const LUTu & histogram, int histcompr, double clip, double& expcomp, int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh);
278     static double getAutoDistor(const Glib::ustring& fname, int thumb_size);
279     double getTransformAutoFill(int oW, int oH, const LensCorrection *pLCPMap = nullptr) const;
280     void rgb2lab(const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace);
281     void lab2rgb(const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace);
282 };
283 
284 }
285