Bugfix for Directional Pyramid Denoising. Adding a Directional Pyramid Equalizer tool. This one serves the same function as the existing Wavelet Equalizer, but has much less artifacting; though it is a little slower to execute and has not yet been adapted for OpenMP implementation. There are also fewer levels on which the tool operates, though of course if there was a demand that could be altered. The controls are similar, though have been given separate luma and chroma controls. Each slider adjusts the factor by which a given detail band is amplified; factors larger than one increase contrast, while values smaller than one decrease contrast. The luma control alters contrast on various scales, each successive one twice as large as the previous one. The chroma control is similar, but does less since there is typically less chroma contrast on fine scales. One might use this to restore some of the color contrast lost in NR, or to remove color fringing by making the fine scale enhancement factor much less than one.

This commit is contained in:
Emil Martinec
2010-09-22 15:39:00 -05:00
parent b649b7cd8f
commit 539c39a92b
26 changed files with 1137 additions and 137 deletions

View File

@@ -25,7 +25,7 @@ set (BASESOURCEFILES
batchqueue.cc lwbutton.cc lwbuttonset.cc
batchqueuebuttonset.cc browserfilter.cc exiffiltersettings.cc
profilestore.cc partialpastedlg.cc
equalizer.cc)
equalizer.cc dirpyrequalizer.cc)
if (WIN32)
set (EXTRA_SRC windirmonitor.cc myicon.o)

281
rtgui/dirpyrequalizer.cc Normal file
View File

@@ -0,0 +1,281 @@
/*
* This file is part of RawTherapee.
*
* 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 <http://www.gnu.org/licenses/>.
*
* © 2010 Emil Martinec <ejmartin@uchicago.edu>
*/
#include <dirpyrequalizer.h>
using namespace rtengine;
using namespace rtengine::procparams;
DirPyrEqualizer::DirPyrEqualizer () : ToolPanel() {
enabled = Gtk::manage (new Gtk::CheckButton (M("GENERAL_ENABLED")));
enabled->set_active (true);
pack_start(*enabled);
enaConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrEqualizer::enabledToggled) );
Gtk::HSeparator *separator1 = Gtk::manage (new Gtk::HSeparator());
pack_start(*separator1, Gtk::PACK_SHRINK, 2);
Gtk::HBox * buttonBox1 = Gtk::manage (new Gtk::HBox());
pack_start(*buttonBox1, Gtk::PACK_SHRINK, 2);
Gtk::Button * lumacontrastMinusButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_MINUS")));
buttonBox1->pack_start(*lumacontrastMinusButton, Gtk::PACK_SHRINK, 2);
lumacontrastMinusPressedConn = lumacontrastMinusButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::lumacontrastMinusPressed));
Gtk::Button * lumaneutralButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMANEUTRAL")));
buttonBox1->pack_start(*lumaneutralButton, Gtk::PACK_SHRINK, 2);
lumaneutralPressedConn = lumaneutralButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::lumaneutralPressed));
Gtk::Button * lumacontrastPlusButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_PLUS")));
buttonBox1->pack_start(*lumacontrastPlusButton, Gtk::PACK_SHRINK, 2);
lumacontrastPlusPressedConn = lumacontrastPlusButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::lumacontrastPlusPressed));
buttonBox1->show_all_children();
Gtk::HSeparator *separator2 = Gtk::manage (new Gtk::HSeparator());
pack_start(*separator2, Gtk::PACK_SHRINK, 2);
for(int i = 0; i < 4; i++)
{
std::stringstream ss;
ss << i;
if(i == 0)
ss << " (" << M("TP_DIRPYREQUALIZER_LUMAFINEST") << ")";
if(i == 3)
ss << " (" << M("TP_DIRPYREQUALIZER_LUMACOARSEST") << ")";
multiplier[i] = new Adjuster (ss.str(), 0, 4, 0.01, 1.0);
multiplier[i]->setAdjusterListener(this);
pack_start(*multiplier[i]);
}
show_all_children ();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Gtk::HSeparator *separator3 = Gtk::manage (new Gtk::HSeparator());
pack_start(*separator3, Gtk::PACK_SHRINK, 2);
Gtk::HBox * buttonBox2 = Gtk::manage (new Gtk::HBox());
pack_start(*buttonBox2, Gtk::PACK_SHRINK, 2);
Gtk::Button * chromacontrastMinusButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_CHROMACONTRAST_MINUS")));
buttonBox2->pack_start(*chromacontrastMinusButton, Gtk::PACK_SHRINK, 2);
chromacontrastMinusPressedConn = chromacontrastMinusButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::chromacontrastMinusPressed));
Gtk::Button * chromaneutralButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_CHROMANEUTRAL")));
buttonBox2->pack_start(*chromaneutralButton, Gtk::PACK_SHRINK, 2);
chromaneutralPressedConn = chromaneutralButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::chromaneutralPressed));
Gtk::Button * chromacontrastPlusButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_CHROMACONTRAST_PLUS")));
buttonBox2->pack_start(*chromacontrastPlusButton, Gtk::PACK_SHRINK, 2);
chromacontrastPlusPressedConn = chromacontrastPlusButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::chromacontrastPlusPressed));
buttonBox2->show_all_children();
Gtk::HSeparator *separator4 = Gtk::manage (new Gtk::HSeparator());
pack_start(*separator4, Gtk::PACK_SHRINK, 2);
for(int i = 0; i < 4; i++)
{
std::stringstream ss;
ss << i;
if(i == 0)
ss << " (" << M("TP_DIRPYREQUALIZER_CHROMAFINEST") << ")";
if(i == 3)
ss << " (" << M("TP_DIRPYREQUALIZER_CHROMACOARSEST") << ")";
multiplier[i+4] = new Adjuster (ss.str(), 0, 4, 0.01, 1.0);
multiplier[i+4]->setAdjusterListener(this);
pack_start(*multiplier[i+4]);
}
show_all_children ();
}
DirPyrEqualizer::~DirPyrEqualizer () {
}
void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) {
disableListener ();
if (pedited) {
enabled->set_inconsistent (!pedited->dirpyrequalizer.enabled);
for(int i = 0; i < 8; i++) {
multiplier[i]->setEditedState (pedited->dirpyrequalizer.mult[i] ? Edited : UnEdited);
}
}
enaConn.block (true);
enabled->set_active (pp->dirpyrequalizer.enabled);
enaConn.block (false);
lastEnabled = pp->dirpyrequalizer.enabled;
for (int i = 0; i < 8; i++) {
multiplier[i]->setValue(pp->dirpyrequalizer.mult[i]);
}
enableListener ();
}
void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) {
pp->dirpyrequalizer.enabled = enabled->get_active ();
for (int i = 0; i < 8; i++) {
pp->dirpyrequalizer.mult[i] = (int) multiplier[i]->getValue();
}
if (pedited) {
pedited->dirpyrequalizer.enabled = !enabled->get_inconsistent();
for(int i = 0; i < 8; i++) {
pedited->dirpyrequalizer.mult[i] = multiplier[i]->getEditedState();
}
}
}
void DirPyrEqualizer::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
for (int i = 0; i < 8; i++) {
multiplier[i]->setDefault(defParams->dirpyrequalizer.mult[i]);
}
if (pedited) {
for (int i = 0; i < 8; i++) {
multiplier[i]->setDefaultEditedState(pedited->dirpyrequalizer.mult[i] ? Edited : UnEdited);
}
}
else {
for (int i = 0; i < 8; i++) {
multiplier[i]->setDefaultEditedState(Irrelevant);
}
}
}
void DirPyrEqualizer::setBatchMode (bool batchMode) {
ToolPanel::setBatchMode (batchMode);
for (int i = 0; i < 8; i++) {
multiplier[i]->showEditedCB();
}
}
void DirPyrEqualizer::adjusterChanged (Adjuster* a, double newval) {
if (listener && enabled->get_active()) {
std::stringstream ss;
ss << "(";
int i;
for (i = 0; i < 8; i++) {
if (i > 0) {
ss << ", ";
}
ss << static_cast<int>(multiplier[i]->getValue());
}
ss << ")";
listener->panelChanged (EvDirPyrEqualizer, ss.str());
}
}
void DirPyrEqualizer::enabledToggled () {
if (batchMode) {
if (enabled->get_inconsistent()) {
enabled->set_inconsistent (false);
enaConn.block (true);
enabled->set_active (false);
enaConn.block (false);
}
else if (lastEnabled)
enabled->set_inconsistent (true);
lastEnabled = enabled->get_active ();
}
if (listener) {
if (enabled->get_active ())
listener->panelChanged (EvDirPyrEqlEnabled, M("GENERAL_ENABLED"));
else
listener->panelChanged (EvDirPyrEqlEnabled, M("GENERAL_DISABLED"));
}
}
void DirPyrEqualizer::lumaneutralPressed () {
for (int i = 0; i < 4; i++) {
multiplier[i]->setValue(1.0);
adjusterChanged(multiplier[i], 1.0);
}
}
void DirPyrEqualizer::chromaneutralPressed () {
for (int i = 4; i < 8; i++) {
multiplier[i]->setValue(1.0);
adjusterChanged(multiplier[i], 1.0);
}
}
void DirPyrEqualizer::lumacontrastPlusPressed () {
for (int i = 0; i < 4; i++) {
float inc = 0.05 * (4 - i);
multiplier[i]->setValue(multiplier[i]->getValue() + inc);
adjusterChanged(multiplier[i], multiplier[i]->getValue());
}
}
void DirPyrEqualizer::chromacontrastPlusPressed () {
for (int i = 4; i < 8; i++) {
float inc = 0.05 * (8 - i);
multiplier[i]->setValue(multiplier[i]->getValue() + inc);
adjusterChanged(multiplier[i], multiplier[i]->getValue());
}
}
void DirPyrEqualizer::lumacontrastMinusPressed () {
for (int i = 0; i < 4; i++) {
float inc = -0.05 * (4 - i);
multiplier[i]->setValue(multiplier[i]->getValue() + inc);
adjusterChanged(multiplier[i], multiplier[i]->getValue());
}
}
void DirPyrEqualizer::chromacontrastMinusPressed () {
for (int i = 4; i < 8; i++) {
float inc = -0.05 * (8 - i);
multiplier[i]->setValue(multiplier[i]->getValue() + inc);
adjusterChanged(multiplier[i], multiplier[i]->getValue());
}
}

65
rtgui/dirpyrequalizer.h Normal file
View File

@@ -0,0 +1,65 @@
/*
* This file is part of RawTherapee.
*
* 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 <http://www.gnu.org/licenses/>.
*
* © 2010 Emil Martinec <ejmartin@uchicago.edu>
*/
#ifndef DIRPYREQUALIZER_H_INCLUDED
#define DIRPYREQUALIZER_H_INCLUDED
#include <gtkmm.h>
#include <adjuster.h>
#include <toolpanel.h>
class DirPyrEqualizer : public Gtk::VBox, public AdjusterListener, public ToolPanel
{
protected:
Gtk::CheckButton * enabled;
Adjuster* multiplier[8];
sigc::connection enaConn;
sigc::connection lumaneutralPressedConn;
sigc::connection lumacontrastPlusPressedConn;
sigc::connection lumacontrastMinusPressedConn;
sigc::connection chromaneutralPressedConn;
sigc::connection chromacontrastPlusPressedConn;
sigc::connection chromacontrastMinusPressedConn;
bool lastEnabled;
public:
DirPyrEqualizer ();
virtual ~DirPyrEqualizer ();
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
void setBatchMode (bool batchMode);
void adjusterChanged (Adjuster* a, double newval);
void enabledToggled ();
void lumaneutralPressed ();
void lumacontrastPlusPressed ();
void lumacontrastMinusPressed ();
void chromaneutralPressed ();
void chromacontrastPlusPressed ();
void chromacontrastMinusPressed ();
};
#endif

View File

@@ -851,8 +851,8 @@ bool EditorPanel::idle_sentToGimp(ProgressConnector<int> *pc,rtengine::IImage16*
void EditorPanel::saveOptions () {
options.historyPanelWidth = hpanedl->get_position ();
options.toolPanelWidth = vboxright->get_width ();//older code
//options.historyPanelWidth = hpanedl->get_position ();//older code
//options.toolPanelWidth = vboxright->get_width ();//older code
//options.toolPanelWidth = hpanedr->get_position ();//Hombre's change which screws up OSX build
}

View File

@@ -161,9 +161,9 @@ bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnector<rtengine::Initial
void FilePanel::saveOptions () {
options.dirBrowserWidth = dirpaned->get_position ();
options.dirBrowserHeight = placespaned->get_position ();
options.browserToolPanelWidth = get_position();
//options.dirBrowserWidth = dirpaned->get_position ();
//options.dirBrowserHeight = placespaned->get_position ();
//options.browserToolPanelWidth = get_position();
if (options.startupDir==STARTUPDIR_LAST && fileCatalog->lastSelectedDir ()!="")
options.startupPath = fileCatalog->lastSelectedDir ();
fileCatalog->closeDir ();

View File

@@ -126,9 +126,12 @@ void ParamsEdited::set (bool v) {
icm.working = v;
icm.output = v;
equalizer.enabled = v;
dirpyrequalizer.enabled = v;
for(int i = 0; i < 8; i++)
{
equalizer.c[i] = v;
dirpyrequalizer.mult[i] = v;
}
exif.clear ();
iptc.clear ();
@@ -250,6 +253,10 @@ void ParamsEdited::initFrom (const std::vector<rtengine::procparams::ProcParams>
for(int i = 0; i < 8; i++) {
equalizer.c[i] = equalizer.c[i] && p.equalizer.c[i] == other.equalizer.c[i];
}
dirpyrequalizer.enabled = dirpyrequalizer.enabled && p.dirpyrequalizer.enabled == other.dirpyrequalizer.enabled;
for(int i = 0; i < 8; i++) {
dirpyrequalizer.mult[i] = dirpyrequalizer.mult[i] && p.dirpyrequalizer.mult[i] == other.dirpyrequalizer.mult[i];
}
// exif = exif && p.exif==other.exif
// iptc = other.iptc;
}
@@ -361,6 +368,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
for(int i = 0; i < 8; i++) {
if(equalizer.c[i]) toEdit.equalizer.c[i] = mods.equalizer.c[i];
}
if (dirpyrequalizer.enabled) toEdit.dirpyrequalizer.enabled = mods.dirpyrequalizer.enabled;
for(int i = 0; i < 8; i++) {
if(dirpyrequalizer.mult[i]) toEdit.dirpyrequalizer.mult[i] = mods.dirpyrequalizer.mult[i];
}
// if (exif) toEdit.exif==mo.exif = mods.exif==other.exif;
// if (iptc;) toEdit.iptc==other.iptc; = mods.iptc==other.iptc;;
}

View File

@@ -239,6 +239,13 @@ class EqualizerParamsEdited {
bool c[8];
};
class DirPyrEqualizerParamsEdited {
public:
bool enabled;
bool mult[8];
};
class ExifPairEdited {
public:
@@ -282,6 +289,7 @@ class ParamsEdited {
ResizeParamsEdited resize;
ColorManagementParamsEdited icm;
EqualizerParamsEdited equalizer;
DirPyrEqualizerParamsEdited dirpyrequalizer;
std::vector<ExifPairEdited> exif;
std::vector<IPTCPairEdited> iptc;

View File

@@ -56,6 +56,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) {
exifpanel = Gtk::manage (new ExifPanel ());
iptcpanel = Gtk::manage (new IPTCPanel ());
equalizer = Gtk::manage (new Equalizer ());
dirpyrequalizer = Gtk::manage (new DirPyrEqualizer ());
addPanel (colorPanel, whitebalance, M("TP_WBALANCE_LABEL")); toolPanels.push_back (whitebalance);
addPanel (exposurePanel, curve, M("TP_EXPOSURE_LABEL")); toolPanels.push_back (curve);
@@ -70,6 +71,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) {
addPanel (detailsPanel, lumadenoise, M("TP_LUMADENOISE_LABEL")); toolPanels.push_back (lumadenoise);
addPanel (detailsPanel, colordenoise, M("TP_COLORDENOISE_LABEL")); toolPanels.push_back (colordenoise);
addPanel (detailsPanel, dirpyrdenoise, M("TP_DIRPYRDENOISE_LABEL")); toolPanels.push_back (dirpyrdenoise);
addPanel (detailsPanel, dirpyrequalizer, M("TP_DIRPYREQUALIZER_LABEL")); toolPanels.push_back (dirpyrequalizer);
addPanel (detailsPanel, equalizer, M("TP_EQUALIZER_LABEL")); toolPanels.push_back (equalizer);
addPanel (transformPanel, crop, M("TP_CROP_LABEL")); toolPanels.push_back (crop);
addPanel (transformPanel, resize, M("TP_RESIZE_LABEL")); toolPanels.push_back (resize);

View File

@@ -54,6 +54,7 @@
#include <lensgeom.h>
#include <lensgeomlistener.h>
#include <equalizer.h>
#include <dirpyrequalizer.h>
class ImageEditorCoordinator;
@@ -92,6 +93,7 @@ class ToolPanelCoordinator : public ToolPanelListener,
Sharpening* sharpening;
LCurve* lcurve;
Equalizer * equalizer;
DirPyrEqualizer * dirpyrequalizer;
std::vector<PParamsChangeListener*> paramcListeners;