2 * This file is part of RawTherapee.
4 * Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
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.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
19 #include <tonecurve.h>
21 #include <sigc++/class_slot.h>
25 using namespace rtengine
;
26 using namespace rtengine::procparams
;
28 ToneCurve::ToneCurve () : ToolPanel(), expAdd(false), blackAdd(false), brAdd(false), contrAdd(false) {
30 //----------- Auto Levels ----------------------------------
31 abox
= Gtk::manage (new Gtk::HBox ());
32 abox
->set_border_width (2);
34 autolevels
= Gtk::manage (new Gtk::ToggleButton (M("TP_EXPOSURE_AUTOLEVELS")));
35 autoconn
= autolevels
->signal_toggled().connect( sigc::mem_fun(*this, &ToneCurve::autolevels_toggled
) );
37 sclip
= Gtk::manage (new Gtk::SpinButton ());
38 sclip
->set_range (0.0, 0.9999);
39 sclip
->set_increments (0.0001, 0.01);
40 sclip
->set_value (0.002);
41 sclip
->set_digits (4);
42 sclip
->signal_value_changed().connect( sigc::mem_fun(*this, &ToneCurve::clip_changed
) );
44 abox
->pack_start (*autolevels
);
45 abox
->pack_end (*sclip
);
46 abox
->pack_end (*Gtk::manage (new Gtk::Label (M("TP_EXPOSURE_CLIP"))));
49 pack_start (*Gtk::manage (new Gtk::HSeparator()));
51 //----------- Exposure Compensation ------------------------
52 expcomp
= new Adjuster (M("TP_EXPOSURE_EXPCOMP"), -5, 5, 0.01, 0);
53 pack_start (*expcomp
);
54 hlcompr
= Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRHIGHLIGHTS"), 0, 150, 1, 0));
55 pack_start (*hlcompr
);
57 //----------- Black Level ----------------------------------
58 black
= Gtk::manage (new Adjuster (M("TP_EXPOSURE_BLACKLEVEL"), 0, 32768, 1, 0));
60 shcompr
= Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRSHADOWS"), 0, 150, 1, 0));
61 pack_start (*shcompr
);
63 pack_start (*Gtk::manage (new Gtk::HSeparator()));
65 //---------Brightness / Contrast -------------------------
66 brightness
= Gtk::manage (new Adjuster (M("TP_EXPOSURE_BRIGHTNESS"), -100, 100, 1, 0));
67 pack_start (*brightness
);
68 contrast
= Gtk::manage (new Adjuster (M("TP_EXPOSURE_CONTRAST"), -100, 100, 1, 0));
69 pack_start (*contrast
);
72 //----------- Curve ------------------------------
73 pack_start (*Gtk::manage (new Gtk::HSeparator()));
75 shape = Gtk::manage (new CurveEditor ());
76 shape->setCurveListener (this);
77 curvexp = Gtk::manage (new Gtk::Expander (M("TP_EXPOSURE_CURVEEDITOR")));
78 curvexp->add (*shape);
80 pack_start (*curvexp, Gtk::PACK_SHRINK, 4);
82 // --------- Set Up Listeners -------------
83 expcomp
->setAdjusterListener (this);
84 brightness
->setAdjusterListener (this);
85 black
->setAdjusterListener (this);
86 hlcompr
->setAdjusterListener (this);
87 shcompr
->setAdjusterListener (this);
88 contrast
->setAdjusterListener (this);
91 ToneCurve::~ToneCurve () {
96 void ToneCurve::read (const ProcParams
* pp
, const ParamsEdited
* pedited
) {
101 expcomp
->setEditedState (pedited
->toneCurve
.expcomp
? Edited
: UnEdited
);
102 black
->setEditedState (pedited
->toneCurve
.black
? Edited
: UnEdited
);
103 hlcompr
->setEditedState (pedited
->toneCurve
.hlcompr
? Edited
: UnEdited
);
104 shcompr
->setEditedState (pedited
->toneCurve
.shcompr
? Edited
: UnEdited
);
105 brightness
->setEditedState (pedited
->toneCurve
.brightness
? Edited
: UnEdited
);
106 contrast
->setEditedState (pedited
->toneCurve
.contrast
? Edited
: UnEdited
);
107 autolevels
->set_inconsistent (!pedited
->toneCurve
.autoexp
);
108 clipDirty
= pedited
->toneCurve
.clip
;
111 autoconn
.block (true);
112 autolevels
->set_active (pp
->toneCurve
.autoexp
);
113 autoconn
.block (false);
114 lastAuto
= pp
->toneCurve
.autoexp
;
115 sclip
->set_value (pp
->toneCurve
.clip
);
117 expcomp
->setValue (pp
->toneCurve
.expcomp
);
118 black
->setValue (pp
->toneCurve
.black
);
119 hlcompr
->setValue (pp
->toneCurve
.hlcompr
);
120 shcompr
->setValue (pp
->toneCurve
.shcompr
);
121 brightness
->setValue (pp
->toneCurve
.brightness
);
122 contrast
->setValue (pp
->toneCurve
.contrast
);
123 // shape->setCurve (pp->toneCurve.curve);
128 void ToneCurve::write (ProcParams
* pp
, ParamsEdited
* pedited
) {
130 pp
->toneCurve
.autoexp
= autolevels
->get_active();
131 pp
->toneCurve
.clip
= sclip
->get_value ();
132 pp
->toneCurve
.expcomp
= expcomp
->getValue ();
133 pp
->toneCurve
.black
= (int)black
->getValue ();
134 pp
->toneCurve
.hlcompr
= (int)hlcompr
->getValue ();
135 pp
->toneCurve
.shcompr
= (int)shcompr
->getValue ();
136 pp
->toneCurve
.brightness
= (int)brightness
->getValue ();
137 pp
->toneCurve
.contrast
= (int)contrast
->getValue ();
138 // pp->toneCurve.curve = shape->getCurve ();
141 pedited
->toneCurve
.expcomp
= expcomp
->getEditedState ();
142 pedited
->toneCurve
.black
= black
->getEditedState ();
143 pedited
->toneCurve
.hlcompr
= hlcompr
->getEditedState ();
144 pedited
->toneCurve
.shcompr
= shcompr
->getEditedState ();
145 pedited
->toneCurve
.brightness
= brightness
->getEditedState ();
146 pedited
->toneCurve
.contrast
= contrast
->getEditedState ();
147 pedited
->toneCurve
.autoexp
= !autolevels
->get_inconsistent();
148 pedited
->toneCurve
.clip
= clipDirty
;
152 void ToneCurve::setDefaults (const ProcParams
* defParams
, const ParamsEdited
* pedited
) {
154 expcomp
->setDefault (defParams
->toneCurve
.expcomp
);
155 brightness
->setDefault (defParams
->toneCurve
.brightness
);
156 black
->setDefault (defParams
->toneCurve
.black
);
157 hlcompr
->setDefault (defParams
->toneCurve
.hlcompr
);
158 shcompr
->setDefault (defParams
->toneCurve
.shcompr
);
159 contrast
->setDefault (defParams
->toneCurve
.contrast
);
162 expcomp
->setDefaultEditedState (pedited
->toneCurve
.expcomp
? Edited
: UnEdited
);
163 black
->setDefaultEditedState (pedited
->toneCurve
.black
? Edited
: UnEdited
);
164 hlcompr
->setDefaultEditedState (pedited
->toneCurve
.hlcompr
? Edited
: UnEdited
);
165 shcompr
->setDefaultEditedState (pedited
->toneCurve
.shcompr
? Edited
: UnEdited
);
166 brightness
->setDefaultEditedState (pedited
->toneCurve
.brightness
? Edited
: UnEdited
);
167 contrast
->setDefaultEditedState (pedited
->toneCurve
.contrast
? Edited
: UnEdited
);
170 expcomp
->setDefaultEditedState (Irrelevant
);
171 black
->setDefaultEditedState (Irrelevant
);
172 hlcompr
->setDefaultEditedState (Irrelevant
);
173 shcompr
->setDefaultEditedState (Irrelevant
);
174 brightness
->setDefaultEditedState (Irrelevant
);
175 contrast
->setDefaultEditedState (Irrelevant
);
179 /*void ToneCurve::curveChanged () {
182 listener->panelChanged (EvToneCurve, M("HISTORY_CUSTOMCURVE"));
186 void ToneCurve::adjusterChanged (Adjuster
* a
, double newval
) {
188 if (autolevels
->get_active() && (a
==expcomp
|| a
==black
|| a
==hlcompr
|| a
==shcompr
)) {
189 autolevels
->set_active (false);
190 autolevels
->set_inconsistent (false);
198 costr
= Glib::ustring::format (std::setw(3), std::fixed
, std::setprecision(2), a
->getValue());
200 costr
= Glib::ustring::format ((int)a
->getValue());
203 listener
->panelChanged (EvExpComp
, costr
);
204 else if (a
==brightness
)
205 listener
->panelChanged (EvBrightness
, costr
);
207 listener
->panelChanged (EvBlack
, costr
);
208 else if (a
==contrast
)
209 listener
->panelChanged (EvContrast
, costr
);
211 listener
->panelChanged (EvHLCompr
, costr
);
213 listener
->panelChanged (EvSHCompr
, costr
);
216 void ToneCurve::autolevels_toggled () {
219 if (autolevels
->get_inconsistent()) {
220 autolevels
->set_inconsistent (false);
221 autoconn
.block (true);
222 autolevels
->set_active (false);
223 autoconn
.block (false);
226 autolevels
->set_inconsistent (true);
228 lastAuto
= autolevels
->get_active ();
231 if (!batchMode
&& autolevels
->get_active() && listener
) {
232 listener
->panelChanged (EvAutoExp
, M("GENERAL_ENABLED"));
237 expcomp
->setEditedState (UnEdited
);
238 black
->setEditedState (UnEdited
);
240 expcomp
->setValue (0);
243 listener
->panelChanged (EvAutoExp
, M("GENERAL_ENABLED"));
247 void ToneCurve::clip_changed () {
250 if (autolevels
->get_active() && listener
)
251 Glib::signal_idle().connect (sigc::mem_fun(*this, &ToneCurve::clip_changed_
));
254 bool ToneCurve::clip_changed_ () {
257 listener
->panelChanged (EvClip
, Glib::ustring::format (std::setprecision(5), sclip
->get_value()));
264 void ToneCurve::waitForAutoExp () {
266 sclip
->set_sensitive (false);
267 expcomp
->setEnabled (false);
268 brightness
->setEnabled (false);
269 black
->setEnabled (false);
270 hlcompr
->setEnabled (false);
271 shcompr
->setEnabled (false);
272 contrast
->setEnabled (false);
273 // shape->set_sensitive (false);
276 int aexpcomputed (void* data
) {
279 ((ToneCurve
*)data
)->autoExpComputed_ ();
284 void ToneCurve::autoExpChanged (double br
, int bl
) {
288 g_idle_add (aexpcomputed
, this);
291 // Glib::signal_idle().connect (sigc::mem_fun(*this, &ToneCurve::autoExpComputed_));
294 void ToneCurve::enableAll () {
296 sclip
->set_sensitive (true);
297 expcomp
->setEnabled (true);
298 brightness
->setEnabled (true);
299 black
->setEnabled (true);
300 hlcompr
->setEnabled (true);
301 shcompr
->setEnabled (true);
302 contrast
->setEnabled (true);
303 // shape->set_sensitive (true);
306 bool ToneCurve::autoExpComputed_ () {
310 expcomp
->setValue (nextBr
);
311 black
->setValue (nextBl
);
318 void ToneCurve::expandCurve (bool isExpanded) {
320 curvexp->set_expanded (isExpanded);
323 bool ToneCurve::isCurveExpanded () {
325 return curvexp->get_expanded ();
329 void ToneCurve::setBatchMode (bool batchMode
) {
331 removeIfThere (abox
, autolevels
, false);
332 autolevels
= Gtk::manage (new Gtk::CheckButton (M("TP_EXPOSURE_AUTOLEVELS")));
333 autoconn
= autolevels
->signal_toggled().connect( sigc::mem_fun(*this, &ToneCurve::autolevels_toggled
) );
334 abox
->pack_start (*autolevels
);
336 ToolPanel::setBatchMode (batchMode
);
337 expcomp
->showEditedCB ();
338 black
->showEditedCB ();
339 hlcompr
->showEditedCB ();
340 shcompr
->showEditedCB ();
341 brightness
->showEditedCB ();
342 contrast
->showEditedCB ();
345 void ToneCurve::setAdjusterBehavior (bool expadd
, bool bradd
, bool blackadd
, bool contradd
) {
347 if (!expAdd
&& expadd
|| expAdd
&& !expadd
)
348 expcomp
->setLimits (-5, 5, 0.01, 0);
349 if (!blackAdd
&& blackadd
)
350 black
->setLimits (0, 16384, 1, 0);
351 else if (blackAdd
&& !blackadd
)
352 black
->setLimits (0, 32768, 1, 0);
353 if (!brAdd
&& bradd
|| brAdd
&& !bradd
)
354 brightness
->setLimits (-100, 100, 0.01, 0);
355 if (!contrAdd
&& contradd
|| contrAdd
&& !contradd
)
356 contrast
->setLimits (-100, 100, 0.01, 0);