1 /* -*- C++ -*-
2  *
3  *  This file is part of RawTherapee.
4  *
5  *  Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
6  *
7  *  RawTherapee is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  RawTherapee is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with RawTherapee.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 #pragma once
21 
22 #include "rtengine.h"
23 #include "improcfun.h"
24 #include "image8.h"
25 #include "image16.h"
26 #include "imagesource.h"
27 #include "procevents.h"
28 #include "dcrop.h"
29 #include "LUT.h"
30 #include "../rtgui/threadutils.h"
31 
32 namespace rtengine {
33 
34 using namespace procparams;
35 
36 class Crop;
37 
38 /** @brief Manages the image processing, espc. of the preview windows
39   *
40   * There is one ImProcCoordinator per edit panel.
41   *
42   * The ImProcCoordinator handle an sized down image representation of the full image, that is used when paning
43   * and in the Navigator object.
44   *
45   * Each ImProcCoordinator handles an rtengine::Crop list, which process images too with their own pipeline,
46   * but using this class' LUT and other precomputed parameters. The main preview area is displaying a non framed Crop object,
47   * while detail windows are framed Crop objects.
48   */
49 class ImProcCoordinator : public StagedImageProcessor, public HistogramObservable
50 {
51 
52     friend class Crop;
53 
54 protected:
55     Imagefloat *orig_prev;
56     Imagefloat *oprevi;
57     Imagefloat *spotprev;
58     Imagefloat *bufs_[3];
59     std::array<bool, 4> pipeline_stop_;
60 
61     Imagefloat *drcomp_11_dcrop_cache; // global cache for dynamicRangeCompression used in 1:1 detail windows (except when denoise is active)
62     Image8 *previmg;  // displayed image in monitor color space, showing the output profile as well (soft-proofing enabled, which then correspond to workimg) or not
63     Image8 *workimg;  // internal image in output color space for analysis
64 
65     ImageSource* imgsrc;
66 
67     ColorTemp currWB;
68     ColorTemp autoWB;
69 
70     double lastAwbEqual;
71 
72     ImProcFunctions ipf;
73     DCPProfile::ApplyState dcpApplyState;
74 
75     Glib::ustring monitorProfile;
76     RenderingIntent monitorIntent;
77     bool softProof;
78     bool gamutCheck;
79     bool sharpMask;
80 
81     int scale;
82     bool highDetailPreprocessComputed;
83     bool highDetailRawComputed;
84     bool allocated;
85 
86     void freeAll ();
87 
88     // Precomputed values used by DetailedCrop ----------------------------------------------
89 
90     LUTu vhist16;
91     LUTu histRed, histRedRaw;
92     LUTu histGreen, histGreenRaw;
93     LUTu histBlue, histBlueRaw;
94     LUTu histLuma, histToneCurve, histLCurve, histCCurve;
95     LUTu /*histLLCurve,*/ histLCAM, histCCAM, histChroma, histLRETI;
96 
97     bool hist_lrgb_dirty;
98     /// Used to simulate a lazy update of the raw histogram.
99     bool hist_raw_dirty;
100     int vectorscopeScale;
101     bool vectorscope_hc_dirty, vectorscope_hs_dirty;
102     array2D<int> vectorscope_hc, vectorscope_hs;
103     /// Waveform's intensity. Same as height of reference image.
104     int waveformScale;
105     bool waveform_dirty;
106     array2D<int> waveformRed, waveformGreen, waveformBlue, waveformLuma;
107     // ------------------------------------------------------------------------------------
108 
109     int fw, fh, tr, fullw, fullh;
110     int pW, pH;
111 
112     ProgressListener* plistener;
113     PreviewImageListener* imageListener;
114     AutoExpListener* aeListener;
115     AutoWBListener* awbListener;
116     FlatFieldAutoClipListener *flatFieldAutoClipListener;
117     AutoContrastListener *bayerAutoContrastListener;
118     AutoContrastListener *xtransAutoContrastListener;
119     FrameCountListener *frameCountListener;
120     ImageTypeListener *imageTypeListener;
121     FilmNegListener *filmNegListener;
122 
123     AutoChromaListener* adnListener;
124 
125     HistogramListener* hListener;
126     std::vector<SizeListener*> sizeListeners;
127 
128     AutoLogListener *autoLogListener;
129     AutoDeconvRadiusListener *autoRadiusListener;
130 
131     std::vector<Crop*> crops;
132 
133     bool resultValid;
134 
135     MyMutex minit;  // to gain mutually exclusive access to ... to what exactly?
136     void backupParams();
137     void restoreParams();
138 
139     void progress (Glib::ustring str, int pr);
140     void reallocAll ();
141     void allocCache (Imagefloat* &imgfloat);
142     void setScale (int prevscale);
143     void updatePreviewImage (int todo, bool panningRelatedChange);
144     void updateWB();
145 
146     void notifyHistogramChanged();
147     /// Updates L, R, G, and B histograms. Returns true unless not updated.
148     bool updateLRGBHistograms();
149     /// Updates the H-C vectorscope. Returns true unless not updated.
150     bool updateVectorscopeHC();
151     /// Updates the H-S vectorscope. Returns true unless not updated.
152     bool updateVectorscopeHS();
153     /// Updates all waveforms. Returns true unless not updated.
154     bool updateWaveforms();
155 
156     MyMutex mProcessing;
157     ProcParams params;
158     ProcParams paramsBackup;
159     TweakOperator* tweakOperator;
160 
161     // for optimization purpose, the output profile, output rendering intent and
162     // output BPC will trigger a regeneration of the profile on parameter change only
163     // and automatically
164     Glib::ustring lastOutputProfile;
165     RenderingIntent lastOutputIntent;
166     bool lastOutputBPC;
167 
168     // members of the updater:
169     Glib::Thread* thread;
170     MyMutex updaterThreadStart;
171     MyMutex paramsUpdateMutex;
172     int  changeSinceLast;
173     bool updaterRunning;
174     ProcParams nextParams;
175     bool destroying;
176     void startProcessing ();
177     void process ();
178     bool highQualityComputed;
179     cmsHTRANSFORM customTransformIn;
180     cmsHTRANSFORM customTransformOut;
181 public:
182 
183     ImProcCoordinator ();
184     ~ImProcCoordinator () override;
185     void assign     (ImageSource* imgsrc);
186 
getParams(procparams::ProcParams * dst)187     void        getParams (procparams::ProcParams* dst) override
188     {
189         *dst = params;
190     }
191 
192     void        startProcessing (int changeCode) override;
193     ProcParams* beginUpdateParams () override;
194     void        endUpdateParams (ProcEvent change) override;  // must be called after beginUpdateParams, triggers update
195     void        endUpdateParams (int changeFlags) override;
196     void        stopProcessing () override;
197 
198 
setPreviewScale(int scale)199     void setPreviewScale    (int scale) override
200     {
201         setScale (scale);
202     }
getPreviewScale()203     int  getPreviewScale    () override
204     {
205         return scale;
206     }
207 
208     //void fullUpdatePreviewImage  ();
209 
getFullWidth()210     int getFullWidth () override
211     {
212         return fullw;
213     }
getFullHeight()214     int getFullHeight () override
215     {
216         return fullh;
217     }
218 
getPreviewWidth()219     int getPreviewWidth () override
220     {
221         return pW;
222     }
getPreviewHeight()223     int getPreviewHeight () override
224     {
225         return pH;
226     }
227 
228     DetailedCrop* createCrop  (::EditDataProvider *editDataProvider, bool isDetailWindow) override;
229     void setTweakOperator (TweakOperator *tOperator) override;
230     void unsetTweakOperator (TweakOperator *tOperator) override;
231 
232     bool getAutoWB   (double& temp, double& green, double equal) override;
233     void getCamWB    (double& temp, double& green) override;
234     void getSpotWB   (int x, int y, int rectSize, double& temp, double& green) override;
235     void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) override;
236     bool getFilmNegativeExponents(int xA, int yA, int xB, int yB, std::array<float, 3>& newExps) override;
237     bool getImageSpotValues(int x, int y, int spotSize, std::array<float, 3>& rawValues) override;
238     bool getHighQualComputed() override;
239     void setHighQualComputed() override;
240     void setMonitorProfile (const Glib::ustring& profile, RenderingIntent intent) override;
241     void getMonitorProfile (Glib::ustring& profile, RenderingIntent& intent) const override;
242     void setSoftProofing   (bool softProof, bool gamutCheck) override;
243     void getSoftProofing   (bool &softProof, bool &gamutCheck) override;
244     void setSharpMask      (bool sharpMask) override;
updateTryLock()245     bool updateTryLock () override
246     {
247         return updaterThreadStart.trylock();
248     }
updateUnLock()249     void updateUnLock () override
250     {
251         updaterThreadStart.unlock();
252     }
253 
setProgressListener(ProgressListener * pl)254     void setProgressListener (ProgressListener* pl) override
255     {
256         plistener = pl;
257     }
setPreviewImageListener(PreviewImageListener * il)258     void setPreviewImageListener    (PreviewImageListener* il) override
259     {
260         imageListener = il;
261     }
setSizeListener(SizeListener * il)262     void setSizeListener     (SizeListener* il) override
263     {
264         sizeListeners.push_back (il);
265     }
delSizeListener(SizeListener * il)266     void delSizeListener     (SizeListener* il) override
267     {
268         std::vector<SizeListener*>::iterator it = std::find (sizeListeners.begin(), sizeListeners.end(), il);
269 
270         if (it != sizeListeners.end()) {
271             sizeListeners.erase (it);
272         }
273     }
setAutoExpListener(AutoExpListener * ael)274     void setAutoExpListener  (AutoExpListener* ael) override
275     {
276         aeListener = ael;
277     }
setHistogramListener(HistogramListener * h)278     void setHistogramListener (HistogramListener *h) override
279     {
280         if (hListener) {
281             hListener->setObservable(nullptr);
282         }
283         hListener = h;
284         if (h) {
285             h->setObservable(this);
286         }
287     }
setAutoWBListener(AutoWBListener * awb)288     void setAutoWBListener   (AutoWBListener* awb) override
289     {
290         awbListener = awb;
291     }
setAutoChromaListener(AutoChromaListener * adn)292     void setAutoChromaListener  (AutoChromaListener* adn) override
293     {
294         adnListener = adn;
295     }
296 
setFrameCountListener(FrameCountListener * fcl)297     void setFrameCountListener  (FrameCountListener* fcl) override
298     {
299         frameCountListener = fcl;
300     }
301 
setFlatFieldAutoClipListener(FlatFieldAutoClipListener * ffacl)302     void setFlatFieldAutoClipListener  (FlatFieldAutoClipListener* ffacl) override
303     {
304         flatFieldAutoClipListener = ffacl;
305     }
setBayerAutoContrastListener(AutoContrastListener * acl)306     void setBayerAutoContrastListener  (AutoContrastListener* acl) override
307     {
308         bayerAutoContrastListener = acl;
309     }
310 
setXtransAutoContrastListener(AutoContrastListener * acl)311     void setXtransAutoContrastListener  (AutoContrastListener* acl) override
312     {
313         xtransAutoContrastListener = acl;
314     }
315 
setImageTypeListener(ImageTypeListener * itl)316     void setImageTypeListener  (ImageTypeListener* itl) override
317     {
318         imageTypeListener = itl;
319     }
320 
setFilmNegListener(FilmNegListener * fnl)321     void setFilmNegListener(FilmNegListener* fnl) override
322     {
323         filmNegListener = fnl;
324     }
325 
setAutoLogListener(AutoLogListener * l)326     void setAutoLogListener(AutoLogListener *l) override
327     {
328         autoLogListener = l;
329     }
330 
setAutoDeconvRadiusListener(AutoDeconvRadiusListener * l)331     void setAutoDeconvRadiusListener(AutoDeconvRadiusListener *l) override
332     {
333         autoRadiusListener = l;
334     }
335 
336     void saveInputICCReference (const Glib::ustring& fname, bool apply_wb) override;
337 
getInitialImage()338     InitialImage*  getInitialImage () override
339     {
340         return imgsrc;
341     }
342 
getCustomTransformIn()343     cmsHTRANSFORM& getCustomTransformIn ()
344     {
345         return customTransformIn;
346     }
347 
getCustomTransformOut()348     cmsHTRANSFORM& getCustomTransformOut ()
349     {
350         return customTransformOut;
351     }
352 
353     bool getDeltaELCH(EditUniqueID id, int x, int y, float &L, float &C, float &H) override;
354 
355     ImProcFunctions::DenoiseInfoStore denoiseInfoStore;
356 
357     void requestUpdateHistogram() override;
358     void requestUpdateHistogramRaw() override;
359     void requestUpdateVectorscopeHC() override;
360     void requestUpdateVectorscopeHS() override;
361     void requestUpdateWaveform() override;
362 };
363 
364 } // namespace rtengine
365