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 <sharpening.h>
24 using namespace rtengine
;
25 using namespace rtengine::procparams
;
27 Sharpening::Sharpening () : ToolPanel () {
29 enabled
= Gtk::manage (new Gtk::CheckButton (M("GENERAL_ENABLED")));
30 enabled
->set_active (true);
33 Gtk::HSeparator
*hsep6aa
= Gtk::manage (new Gtk::HSeparator());
34 pack_start(*hsep6aa
, Gtk::PACK_SHRINK
, 2);
37 Gtk::HBox
* hb
= Gtk::manage (new Gtk::HBox ());
38 hb
->set_border_width (4);
40 Gtk::Label
* ml
= Gtk::manage (new Gtk::Label (M("TP_SHARPENING_METHOD")+":"));
42 method
= Gtk::manage (new Gtk::ComboBoxText ());
43 method
->append_text (M("TP_SHARPENING_USM"));
44 method
->append_text (M("TP_SHARPENING_RLD"));
46 hb
->pack_start(*ml
, Gtk::PACK_SHRINK
, 4);
47 hb
->pack_start(*method
);
50 rld
= new Gtk::VBox ();
51 dradius
= Gtk::manage (new Adjuster (M("TP_SHARPENING_EDRADIUS"), 0.5, 2.5, 0.01, 0.75));
52 damount
= Gtk::manage (new Adjuster (M("TP_SHARPENING_RLD_AMOUNT"), 0.0, 100, 1, 75));
53 ddamping
= Gtk::manage (new Adjuster (M("TP_SHARPENING_RLD_DAMPING"), 0, 100, 1, 20));
54 diter
= Gtk::manage (new Adjuster (M("TP_SHARPENING_RLD_ITERATIONS"), 5, 100, 1, 30));
55 rld
->pack_start (*dradius
);
56 rld
->pack_start (*damount
);
57 rld
->pack_start (*ddamping
);
58 rld
->pack_start (*diter
);
65 usm
= new Gtk::VBox ();
69 Gtk::HSeparator
*hsep6a
= Gtk::manage (new Gtk::HSeparator());
70 amount
= Gtk::manage (new Adjuster (M("TP_SHARPENING_AMOUNT"), 1, 1000, 1, 150));
71 radius
= Gtk::manage (new Adjuster (M("TP_SHARPENING_RADIUS"), 0.3, 3, 0.01, 0.8));
72 threshold
= Gtk::manage (new Adjuster (M("TP_SHARPENING_THRESHOLD"), 0, 16384, 1024, 1));
73 pack_start(*hsep6a
, Gtk::PACK_SHRINK
, 2);
77 usm
->pack_start(*radius
);
78 usm
->pack_start(*amount
);
79 usm
->pack_start(*threshold
);
85 Gtk::HSeparator
*hsep6
= Gtk::manage (new Gtk::HSeparator());
86 edgesonly
= Gtk::manage (new Gtk::CheckButton (M("TP_SHARPENING_ONLYEDGES")));
87 edgesonly
->set_active (false);
88 edgebox
= new Gtk::VBox ();
89 eradius
= Gtk::manage (new Adjuster (M("TP_SHARPENING_EDRADIUS"), 0.5, 2.5, 0.1, 1.9));
90 etolerance
= Gtk::manage (new Adjuster (M("TP_SHARPENING_EDTOLERANCE"), 10, 10000, 100, 1000));
91 usm
->pack_start(*hsep6
, Gtk::PACK_SHRINK
, 2);
92 usm
->pack_start(*edgesonly
);
93 edgebox
->pack_start(*eradius
);
94 edgebox
->pack_start(*etolerance
);
96 edgebin
= Gtk::manage (new Gtk::VBox ());
97 usm
->pack_start (*edgebin
);
104 Gtk::HSeparator
*hsep6b
= Gtk::manage (new Gtk::HSeparator());
105 halocontrol
= Gtk::manage (new Gtk::CheckButton (M("TP_SHARPENING_HALOCONTROL")));
106 halocontrol
->set_active (false);
107 hcbox
= new Gtk::VBox ();
108 hcamount
= Gtk::manage (new Adjuster (M("TP_SHARPENING_HCAMOUNT"), 1, 100, 1, 75));
109 usm
->pack_start(*hsep6b
, Gtk::PACK_SHRINK
, 2);
110 usm
->pack_start(*halocontrol
);
111 hcbox
->pack_start(*hcamount
);
113 hcbin
= Gtk::manage (new Gtk::VBox ());
114 usm
->pack_start (*hcbin
);
117 halocontrol
->show ();
120 dradius
->setAdjusterListener (this);
121 damount
->setAdjusterListener (this);
122 ddamping
->setAdjusterListener (this);
123 diter
->setAdjusterListener (this);
124 radius
->setAdjusterListener (this);
125 amount
->setAdjusterListener (this);
126 threshold
->setAdjusterListener (this);
127 eradius
->setAdjusterListener (this);
128 etolerance
->setAdjusterListener (this);
129 hcamount
->setAdjusterListener (this);
131 edgebox
->reference ();
136 enaConn
= enabled
->signal_toggled().connect( sigc::mem_fun(*this, &Sharpening::enabled_toggled
) );
137 eonlyConn
= edgesonly
->signal_toggled().connect( sigc::mem_fun(*this, &Sharpening::edgesonly_toggled
) );
138 hcConn
= halocontrol
->signal_toggled().connect( sigc::mem_fun(*this, &Sharpening::halocontrol_toggled
) );
139 method
->signal_changed().connect( sigc::mem_fun(*this, &Sharpening::method_changed
) );
142 Sharpening::~Sharpening () {
151 void Sharpening::read (const ProcParams
* pp
, const ParamsEdited
* pedited
) {
156 amount
->setEditedState (pedited
->sharpening
.amount
? Edited
: UnEdited
);
157 radius
->setEditedState (pedited
->sharpening
.radius
? Edited
: UnEdited
);
158 threshold
->setEditedState (pedited
->sharpening
.threshold
? Edited
: UnEdited
);
159 eradius
->setEditedState (pedited
->sharpening
.edges_radius
? Edited
: UnEdited
);
160 etolerance
->setEditedState (pedited
->sharpening
.edges_tolerance
? Edited
: UnEdited
);
161 hcamount
->setEditedState (pedited
->sharpening
.halocontrol_amount
? Edited
: UnEdited
);
162 damount
->setEditedState (pedited
->sharpening
.deconvamount
? Edited
: UnEdited
);
163 dradius
->setEditedState (pedited
->sharpening
.deconvradius
? Edited
: UnEdited
);
164 diter
->setEditedState (pedited
->sharpening
.deconviter
? Edited
: UnEdited
);
165 ddamping
->setEditedState (pedited
->sharpening
.deconvdamping
? Edited
: UnEdited
);
167 enabled
->set_inconsistent (!pedited
->sharpening
.enabled
);
168 halocontrol
->set_inconsistent (!pedited
->sharpening
.halocontrol
);
169 edgesonly
->set_inconsistent (!pedited
->sharpening
.edgesonly
);
172 enaConn
.block (true);
173 enabled
->set_active (pp
->sharpening
.enabled
);
174 enaConn
.block (false);
175 lastEnabled
= pp
->sharpening
.enabled
;
177 eonlyConn
.block (true);
178 edgesonly
->set_active (pp
->sharpening
.edgesonly
);
179 eonlyConn
.block (false);
180 lastEdgesOnly
= pp
->sharpening
.edgesonly
;
183 halocontrol
->set_active (pp
->sharpening
.halocontrol
);
184 hcConn
.block (false);
185 lastHaloControl
= pp
->sharpening
.halocontrol
;
187 amount
->setValue (pp
->sharpening
.amount
);
188 radius
->setValue (pp
->sharpening
.radius
);
189 threshold
->setValue (pp
->sharpening
.threshold
);
190 eradius
->setValue (pp
->sharpening
.edges_radius
);
191 etolerance
->setValue (pp
->sharpening
.edges_tolerance
);
192 hcamount
->setValue (pp
->sharpening
.halocontrol_amount
);
194 dradius
->setValue (pp
->sharpening
.deconvradius
);
195 damount
->setValue (pp
->sharpening
.deconvamount
);
196 diter
->setValue (pp
->sharpening
.deconviter
);
197 ddamping
->setValue (pp
->sharpening
.deconvdamping
);
200 removeIfThere (edgebin
, edgebox
, false);
201 if (edgesonly
->get_active ())
202 edgebin
->pack_start (*edgebox
);
204 removeIfThere (hcbin
, hcbox
, false);
205 if (halocontrol
->get_active ())
206 hcbin
->pack_start (*hcbox
);
209 if (pedited
&& !pedited
->sharpening
.method
)
210 method
->set_active (2);
211 else if (pp
->sharpening
.method
=="usm")
212 method
->set_active (0);
213 else if (pp
->sharpening
.method
=="rld")
214 method
->set_active (1);
219 void Sharpening::write (ProcParams
* pp
, ParamsEdited
* pedited
) {
221 pp
->sharpening
.amount
= (int)amount
->getValue();
222 pp
->sharpening
.enabled
= enabled
->get_active ();
223 pp
->sharpening
.radius
= radius
->getValue ();
224 pp
->sharpening
.threshold
= (int)threshold
->getValue ();
225 pp
->sharpening
.edgesonly
= edgesonly
->get_active ();
226 pp
->sharpening
.edges_radius
= eradius
->getValue ();
227 pp
->sharpening
.edges_tolerance
= (int)etolerance
->getValue ();
228 pp
->sharpening
.halocontrol
= halocontrol
->get_active ();
229 pp
->sharpening
.halocontrol_amount
= (int)hcamount
->getValue ();
230 pp
->sharpening
.deconvradius
= dradius
->getValue ();
231 pp
->sharpening
.deconviter
= (int)diter
->getValue ();
232 pp
->sharpening
.deconvamount
= (int)damount
->getValue ();
233 pp
->sharpening
.deconvdamping
= (int)ddamping
->getValue ();
235 if (method
->get_active_row_number()==0)
236 pp
->sharpening
.method
= "usm";
237 else if (method
->get_active_row_number()==1)
238 pp
->sharpening
.method
= "rld";
241 pedited
->sharpening
.amount
= amount
->getEditedState ();
242 pedited
->sharpening
.radius
= radius
->getEditedState ();
243 pedited
->sharpening
.threshold
= threshold
->getEditedState ();
244 pedited
->sharpening
.edges_radius
= eradius
->getEditedState ();
245 pedited
->sharpening
.edges_tolerance
= etolerance
->getEditedState ();
246 pedited
->sharpening
.halocontrol_amount
= hcamount
->getEditedState ();
247 pedited
->sharpening
.deconvamount
= damount
->getEditedState ();
248 pedited
->sharpening
.deconvradius
= dradius
->getEditedState ();
249 pedited
->sharpening
.deconviter
= diter
->getEditedState ();
250 pedited
->sharpening
.deconvdamping
= ddamping
->getEditedState ();
251 pedited
->sharpening
.method
= method
->get_active_row_number()!=2;
252 pedited
->sharpening
.halocontrol
= !halocontrol
->get_inconsistent();
253 pedited
->sharpening
.edgesonly
= !edgesonly
->get_inconsistent();
254 pedited
->sharpening
.enabled
= !enabled
->get_inconsistent();
258 void Sharpening::setDefaults (const ProcParams
* defParams
, const ParamsEdited
* pedited
) {
260 amount
->setDefault (defParams
->sharpening
.amount
);
261 radius
->setDefault (defParams
->sharpening
.radius
);
262 threshold
->setDefault (defParams
->sharpening
.threshold
);
263 eradius
->setDefault (defParams
->sharpening
.edges_radius
);
264 etolerance
->setDefault (defParams
->sharpening
.edges_tolerance
);
265 hcamount
->setDefault (defParams
->sharpening
.halocontrol_amount
);
266 damount
->setDefault (defParams
->sharpening
.deconvamount
);
267 dradius
->setDefault (defParams
->sharpening
.deconvradius
);
268 diter
->setDefault (defParams
->sharpening
.deconviter
);
269 ddamping
->setDefault (defParams
->sharpening
.deconvdamping
);
272 amount
->setDefaultEditedState (pedited
->sharpening
.amount
? Edited
: UnEdited
);
273 radius
->setDefaultEditedState (pedited
->sharpening
.radius
? Edited
: UnEdited
);
274 threshold
->setDefaultEditedState (pedited
->sharpening
.threshold
? Edited
: UnEdited
);
275 eradius
->setDefaultEditedState (pedited
->sharpening
.edges_radius
? Edited
: UnEdited
);
276 etolerance
->setDefaultEditedState (pedited
->sharpening
.edges_tolerance
? Edited
: UnEdited
);
277 hcamount
->setDefaultEditedState (pedited
->sharpening
.halocontrol_amount
? Edited
: UnEdited
);
278 damount
->setDefaultEditedState (pedited
->sharpening
.deconvamount
? Edited
: UnEdited
);
279 dradius
->setDefaultEditedState (pedited
->sharpening
.deconvradius
? Edited
: UnEdited
);
280 diter
->setDefaultEditedState (pedited
->sharpening
.deconviter
? Edited
: UnEdited
);
281 ddamping
->setDefaultEditedState (pedited
->sharpening
.deconvdamping
? Edited
: UnEdited
);
284 amount
->setDefaultEditedState (Irrelevant
);
285 radius
->setDefaultEditedState (Irrelevant
);
286 threshold
->setDefaultEditedState (Irrelevant
);
287 eradius
->setDefaultEditedState (Irrelevant
);
288 etolerance
->setDefaultEditedState (Irrelevant
);
289 hcamount
->setDefaultEditedState (Irrelevant
);
290 damount
->setDefaultEditedState (Irrelevant
);
291 dradius
->setDefaultEditedState (Irrelevant
);
292 diter
->setDefaultEditedState (Irrelevant
);
293 ddamping
->setDefaultEditedState (Irrelevant
);
297 void Sharpening::adjusterChanged (Adjuster
* a
, double newval
) {
299 if (listener
&& enabled
->get_active()) {
302 if (a
==radius
|| a
==dradius
)
303 costr
= Glib::ustring::format (std::setw(3), std::fixed
, std::setprecision(2), a
->getValue());
305 costr
= Glib::ustring::format (std::setw(2), std::fixed
, std::setprecision(1), a
->getValue());
307 costr
= Glib::ustring::format ((int)a
->getValue());
310 listener
->panelChanged (EvShrAmount
, costr
);
312 listener
->panelChanged (EvShrRadius
, costr
);
313 else if (a
==threshold
)
314 listener
->panelChanged (EvShrThresh
, costr
);
316 listener
->panelChanged (EvShrEdgeRadius
, costr
);
317 else if (a
==etolerance
)
318 listener
->panelChanged (EvShrEdgeTolerance
, costr
);
319 else if (a
==hcamount
)
320 listener
->panelChanged (EvShrHaloAmount
, costr
);
322 listener
->panelChanged (EvShrDRadius
, costr
);
324 listener
->panelChanged (EvShrDAmount
, costr
);
325 else if (a
==ddamping
)
326 listener
->panelChanged (EvShrDDamping
, costr
);
328 listener
->panelChanged (EvShrDIterations
, costr
);
332 void Sharpening::enabled_toggled () {
335 if (enabled
->get_inconsistent()) {
336 enabled
->set_inconsistent (false);
337 enaConn
.block (true);
338 enabled
->set_active (false);
339 enaConn
.block (false);
341 else if (lastEnabled
)
342 enabled
->set_inconsistent (true);
344 lastEnabled
= enabled
->get_active ();
348 if (enabled
->get_active ())
349 listener
->panelChanged (EvShrEnabled
, M("GENERAL_ENABLED"));
351 listener
->panelChanged (EvShrEnabled
, M("GENERAL_DISABLED"));
355 void Sharpening::edgesonly_toggled () {
358 if (edgesonly
->get_inconsistent()) {
359 edgesonly
->set_inconsistent (false);
360 eonlyConn
.block (true);
361 edgesonly
->set_active (false);
362 eonlyConn
.block (false);
364 else if (lastEdgesOnly
)
365 edgesonly
->set_inconsistent (true);
367 lastEdgesOnly
= edgesonly
->get_active ();
371 removeIfThere (edgebin
, edgebox
, false);
372 if (edgesonly
->get_active ())
373 edgebin
->pack_start (*edgebox
);
376 if (listener
&& enabled
->get_active()) {
377 if (edgesonly
->get_active ())
378 listener
->panelChanged (EvShrEdgeOnly
, M("GENERAL_ENABLED"));
380 listener
->panelChanged (EvShrEdgeOnly
, M("GENERAL_DISABLED"));
384 void Sharpening::halocontrol_toggled () {
387 if (halocontrol
->get_inconsistent()) {
388 halocontrol
->set_inconsistent (false);
390 halocontrol
->set_active (false);
391 hcConn
.block (false);
393 else if (lastHaloControl
)
394 halocontrol
->set_inconsistent (true);
396 lastHaloControl
= halocontrol
->get_active ();
400 removeIfThere (hcbin
, hcbox
, false);
401 if (halocontrol
->get_active ())
402 hcbin
->pack_start (*hcbox
);
405 if (listener
&& enabled
->get_active()) {
406 if (halocontrol
->get_active ())
407 listener
->panelChanged (EvShrHaloControl
, M("GENERAL_ENABLED"));
409 listener
->panelChanged (EvShrHaloControl
, M("GENERAL_DISABLED"));
413 void Sharpening::method_changed () {
415 removeIfThere (this, usm
, false);
416 removeIfThere (this, rld
, false);
418 if (method
->get_active_row_number()==0)
420 else if (method
->get_active_row_number()==1)
423 if (listener
&& enabled
->get_active ())
424 listener
->panelChanged (EvShrMethod
, method
->get_active_text ());
428 void Sharpening::setBatchMode (bool batchMode
) {
430 ToolPanel::setBatchMode (batchMode
);
432 removeIfThere (hcbin
, hcbox
, false);
433 hcbin
->pack_start (*hcbox
);
434 removeIfThere (edgebin
, edgebox
, false);
435 edgebin
->pack_start (*edgebox
);
437 radius
->showEditedCB ();
438 amount
->showEditedCB ();
439 threshold
->showEditedCB ();
440 eradius
->showEditedCB ();
441 etolerance
->showEditedCB ();
442 hcamount
->showEditedCB ();
443 dradius
->showEditedCB ();
444 damount
->showEditedCB ();
445 ddamping
->showEditedCB ();
446 diter
->showEditedCB ();
447 method
->append_text ("(Unchanged)");
450 void Sharpening::setAdjusterBehavior (bool bamountadd
) {
452 if (!amountAdd
&& bamountadd
) {
453 amount
->setLimits (-100, 100, 1, 0);
454 damount
->setLimits (-100, 100, 1, 0);
456 else if (amountAdd
&& !bamountadd
) {
457 amount
->setLimits (1, 1000, 1, 150);
458 damount
->setLimits (0, 100, 1, 75);
460 amountAdd
= bamountadd
;