rawTherapee/rtgui/compressgamut.cc
Daniel Gao 4969fdd989 Clean up framing compiler warnings
* Remove unused variables/dead code
* Add missing `.children = {}`
* Remove relative includes
2024-12-27 18:37:11 -05:00

366 lines
13 KiB
C++

/*
* This file is part of RawTherapee.
*
* Copyright (c) 2024 RawTherapee team
*
* 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 <https://www.gnu.org/licenses/>.
*/
/*
* tweaked from the original from https://github.com/jedypod/gamut-compress
* https://docs.acescentral.com/specifications/rgc/
*/
#include "compressgamut.h"
#include "eventmapper.h"
#include "rtengine/procparams.h"
using namespace rtengine;
using namespace rtengine::procparams;
const Glib::ustring Compressgamut::TOOL_NAME = "compressgamut";
Compressgamut::Compressgamut () : FoldableToolPanel(this, TOOL_NAME, M("TP_COMPRESSGAMUT_LABEL"), false, true)
{
auto m = ProcEventMapper::getInstance();
EvcgColorspace = m->newEvent(COMPR, "HISTORY_MSG_CG_COLORSPACE");//FIRST to reinit histogram
Evcgthc = m->newEvent(COMPR, "HISTORY_MSG_CG_CYANTH");
Evcgthm = m->newEvent(COMPR, "HISTORY_MSG_CG_MAGENTATH");
Evcgthy = m->newEvent(COMPR, "HISTORY_MSG_CG_YELLOWTH");
Evcgdc = m->newEvent(COMPR, "HISTORY_MSG_CG_CYANLIM");
Evcgdm = m->newEvent(COMPR, "HISTORY_MSG_CG_MAGENTALIM");
Evcgdy = m->newEvent(COMPR, "HISTORY_MSG_CG_YELLOWLIM");
Evcgroll = m->newEvent(COMPR, "HISTORY_MSG_CG_ROLLOFF");
Evcgpwr = m->newEvent(COMPR, "HISTORY_MSG_CG_VALUE");
Evcgenabled = m->newEvent(COMPR, "HISTORY_MSG_CG_ENABLED");
Gtk::Frame *iFrame = Gtk::manage(new Gtk::Frame(M("TP_COMPRESSGAMUT_MAIN_COLORSPACE")));
iFrame->set_label_align(0.025f, 0.5);
iFrame->set_tooltip_markup (M("TP_COMPRESSGAMUT_COLORSPACE_TOOLTIP"));
Gtk::Box *iVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
colorspace = Gtk::manage(new MyComboBoxText());
colorspace->append(M("TP_COMPRESSGAMUT_REC2020"));
colorspace->append(M("TP_COMPRESSGAMUT_PROPHOTO"));
colorspace->append(M("TP_COMPRESSGAMUT_ADOBE"));
colorspace->append(M("TP_COMPRESSGAMUT_SRGB"));
colorspace->append(M("TP_COMPRESSGAMUT_DCIP3"));
colorspace->append(M("TP_COMPRESSGAMUT_ACESP1"));
colorspace->set_active(3);
iVBox->pack_start(*colorspace);
iFrame->add(*iVBox);
pack_start(*iFrame);
colorspaceconn = colorspace->signal_changed().connect(sigc::mem_fun(*this, &Compressgamut::colorspaceChanged));
// Percentage of the core gamut to protect Limits
// Values calculated to protect all the colors of the ColorChecker Classic 24 as given by
// ISO 17321-1 and Ohta (1997)
th_c = Gtk::manage (new Adjuster (M("TP_COMPRESSGAMUT_CYANTH"), 0., 1., 0.001, 0.815));//0.25 sRGB 0.999 to avoid: 1 - th = 0
th_m = Gtk::manage (new Adjuster (M("TP_COMPRESSGAMUT_MAGENTATH"), 0., 1., 0.001, 0.803));//0.925 sRGB
th_y = Gtk::manage (new Adjuster (M("TP_COMPRESSGAMUT_YELLOWTH"), 0., 1., 0.001, 0.880));//0.934 sRGB
Gtk::Frame *thFrame = Gtk::manage(new Gtk::Frame(M("TP_COMPRESSGAMUT_THRESHOLD")));
thFrame->set_label_align(0.025f, 0.5);
Gtk::Box *thVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
thFrame->set_tooltip_markup (M("TP_COMPRESSGAMUT_THRESHOLD_TOOLTIP"));
thVBox->pack_start (*th_c);
thVBox->pack_start (*th_m);
thVBox->pack_start (*th_y);
thFrame->add(*thVBox);
pack_start(*thFrame, Gtk::PACK_SHRINK);
// from ACES https://docs.acescentral.com/specifications/rgc/#appendix-c-illustrations
// https://docs.acescentral.com/specifications/rgc/#appendix-d-ctl-reference-implementation
// Distance from achromatic which will be compressed to the gamut boundary
// Values calculated to encompass the encoding gamuts of common digital cinema cameras
d_c = Gtk::manage (new Adjuster (M("TP_COMPRESSGAMUT_CYANLIM"), 1.001, 2.0, 0.001, 1.147));//1.05 sRGB
d_m = Gtk::manage (new Adjuster (M("TP_COMPRESSGAMUT_MAGENTALIM"), 1.001, 2.0, 0.001, 1.264));//1.08 sRGB
d_y = Gtk::manage (new Adjuster (M("TP_COMPRESSGAMUT_YELLOWLIM"), 1.001, 2.0, 0.001, 1.312));//1.10 sRGB
Gtk::Frame *limFrame = Gtk::manage(new Gtk::Frame(M("TP_COMPRESSGAMUT_LIMIT")));
limFrame->set_label_align(0.025f, 0.5);
limFrame->set_tooltip_markup (M("TP_COMPRESSGAMUT_LIMIT_TOOLTIP"));
Gtk::Box *limVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
limVBox->pack_start (*d_c);
limVBox->pack_start (*d_m);
limVBox->pack_start (*d_y);
limFrame->add(*limVBox);
pack_start(*limFrame, Gtk::PACK_SHRINK);
// Aggressiveness of the compression curve Pwr
rolloff = Gtk::manage(new Gtk::CheckButton(M("TP_COMPRESSGAMUT_ROLLOFF")));
pwr = Gtk::manage (new Adjuster (M("TP_COMPRESSGAMUT_PWR"), 0.5, 2.0, 0.01, 1.2));
rolloffconn = rolloff->signal_toggled().connect (sigc::mem_fun (*this, &Compressgamut::rolloff_change));
Gtk::Frame *rollFrame = Gtk::manage(new Gtk::Frame());
rollFrame->set_label_align(0.025f, 0.5);
rollFrame->set_label_widget(*rolloff);
rolloff->set_active(true);
Gtk::Box *rollVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
rollFrame->set_tooltip_markup (M("TP_COMPRESSGAMUT_POWER_TOOLTIP"));
rollVBox->pack_start (*pwr);
rollFrame->add(*rollVBox);
pack_start(*rollFrame, Gtk::PACK_SHRINK);
th_c->setAdjusterListener (this);
th_m->setAdjusterListener (this);
th_y->setAdjusterListener (this);
d_c->setAdjusterListener (this);
d_m->setAdjusterListener (this);
d_y->setAdjusterListener (this);
pwr->setAdjusterListener (this);
show_all_children ();
}
void Compressgamut::read (const ProcParams* pp, const ParamsEdited* pedited)
{
disableListener ();
if (pedited) {
th_c->setEditedState (pedited->cg.th_c ? Edited : UnEdited);
th_m->setEditedState (pedited->cg.th_m ? Edited : UnEdited);
th_y->setEditedState (pedited->cg.th_y ? Edited : UnEdited);
d_c->setEditedState (pedited->cg.d_c ? Edited : UnEdited);
d_m->setEditedState (pedited->cg.d_m ? Edited : UnEdited);
d_y->setEditedState (pedited->cg.d_y ? Edited : UnEdited);
pwr->setEditedState (pedited->cg.pwr ? Edited : UnEdited);
set_inconsistent (multiImage && !pedited->cg.enabled);
rolloff->set_inconsistent (!pedited->cg.rolloff);
}
setEnabled (pp->cg.enabled);
rolloffconn.block (true);
rolloff->set_active (pp->cg.rolloff);
rolloffconn.block (false);
th_c->setValue(pp->cg.th_c);
th_m->setValue(pp->cg.th_m);
th_y->setValue(pp->cg.th_y);
d_c->setValue(pp->cg.d_c);
d_m->setValue(pp->cg.d_m);
d_y->setValue(pp->cg.d_y);
pwr->setValue(pp->cg.pwr);
colorspaceconn.block (true);
if (pp->cg.colorspace == "rec2020") {
colorspace->set_active(0);
} else if (pp->cg.colorspace == "prophoto") {
colorspace->set_active(1);
} else if (pp->cg.colorspace == "adobe") {
colorspace->set_active(2);
} else if (pp->cg.colorspace == "srgb") {
colorspace->set_active(3);
} else if (pp->cg.colorspace == "dcip3") {
colorspace->set_active(4);
} else if (pp->cg.colorspace == "acesp1") {
colorspace->set_active(5);
}
colorspaceconn.block (false);
rolloffconn.block (true);
rolloff->set_active (pp->cg.rolloff);
rolloffconn.block (false);
lastrolloff = pp->cg.rolloff;
rolloff_change();
colorspaceChanged();
enabledChanged ();
enableListener ();
}
void Compressgamut::write (ProcParams* pp, ParamsEdited* pedited)
{
pp->cg.th_c = th_c->getValue ();
pp->cg.th_m = th_m->getValue ();
pp->cg.th_y = th_y->getValue ();
pp->cg.d_c = d_c->getValue ();
pp->cg.d_m = d_m->getValue ();
pp->cg.d_y = d_y->getValue ();
pp->cg.pwr = pwr->getValue ();
pp->cg.rolloff = rolloff->get_active();
pp->cg.enabled = getEnabled();
if (colorspace->get_active_row_number() == 0) {
pp->cg.colorspace = "rec2020";
} else if (colorspace->get_active_row_number() == 1){
pp->cg.colorspace = "prophoto";
} else if (colorspace->get_active_row_number() == 2){
pp->cg.colorspace = "adobe";
} else if (colorspace->get_active_row_number() == 3){
pp->cg.colorspace = "srgb";
} else if (colorspace->get_active_row_number() == 4){
pp->cg.colorspace = "dcip3";
} else if (colorspace->get_active_row_number() == 5){
pp->cg.colorspace = "acesp1";
}
if (pedited) {
pedited->cg.th_c = th_c->getEditedState ();
pedited->cg.th_m = th_m->getEditedState ();
pedited->cg.th_y = th_y->getEditedState ();
pedited->cg.d_c = d_c->getEditedState ();
pedited->cg.d_m = d_m->getEditedState ();
pedited->cg.d_y = d_y->getEditedState ();
pedited->cg.pwr = pwr->getEditedState ();
pedited->cg.enabled = !get_inconsistent();
pedited->cg.colorspace = colorspace->get_active_row_number() != 6;
pedited->cg.rolloff = !rolloff->get_inconsistent();
}
}
void Compressgamut::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited)
{
th_c->setDefault (defParams->cg.th_c);
th_m->setDefault (defParams->cg.th_m);
th_y->setDefault (defParams->cg.th_y);
d_c->setDefault (defParams->cg.d_c);
d_m->setDefault (defParams->cg.d_m);
d_y->setDefault (defParams->cg.d_y);
pwr->setDefault (defParams->cg.pwr);
if (pedited) {
th_c->setDefaultEditedState (pedited->cg.th_c ? Edited : UnEdited);
th_m->setDefaultEditedState (pedited->cg.th_m ? Edited : UnEdited);
th_y->setDefaultEditedState (pedited->cg.th_y ? Edited : UnEdited);
d_c->setDefaultEditedState (pedited->cg.d_c ? Edited : UnEdited);
d_m->setDefaultEditedState (pedited->cg.d_m ? Edited : UnEdited);
d_y->setDefaultEditedState (pedited->cg.d_y ? Edited : UnEdited);
pwr->setDefaultEditedState (pedited->cg.pwr ? Edited : UnEdited);
} else {
th_c->setDefaultEditedState (Irrelevant);
th_m->setDefaultEditedState (Irrelevant);
th_y->setDefaultEditedState (Irrelevant);
d_c->setDefaultEditedState (Irrelevant);
d_m->setDefaultEditedState (Irrelevant);
d_y->setDefaultEditedState (Irrelevant);
pwr->setDefaultEditedState (Irrelevant);
}
}
void Compressgamut::adjusterChanged (Adjuster* a, double newval)
{
if (listener && getEnabled()) {
const Glib::ustring costr = Glib::ustring::format (a->getValue());
if (a == th_c) {
listener->panelChanged (Evcgthc, costr);
} else if (a == th_m) {
listener->panelChanged (Evcgthm, costr);
} else if (a == th_y) {
listener->panelChanged (Evcgthy, costr);
} else if (a == d_c) {
listener->panelChanged (Evcgdc, costr);
} else if (a == d_m) {
listener->panelChanged (Evcgdm, costr);
} else if (a == d_y) {
listener->panelChanged (Evcgdy, costr);
} else if (a == pwr) {
listener->panelChanged (Evcgpwr, costr);
}
}
}
void Compressgamut::rolloff_change()
{
if (rolloff->get_active()) {
pwr->set_sensitive(true);
} else {
pwr->set_sensitive(false);
}
if (batchMode) {
if (rolloff->get_inconsistent()) {
rolloff->set_inconsistent (false);
rolloffconn.block (true);
rolloff->set_active (false);
rolloffconn.block (false);
} else if (lastrolloff) {
rolloff->set_inconsistent (true);
}
lastrolloff = rolloff->get_active ();
}
if (listener) {
if (rolloff->get_active()) {
listener->panelChanged(Evcgroll, M("GENERAL_ENABLED"));
} else {
listener->panelChanged(Evcgroll, M("GENERAL_DISABLED"));
}
}
}
void Compressgamut::colorspaceChanged()
{
if (listener && getEnabled()) {
listener->panelChanged(EvcgColorspace, colorspace->get_active_text());
}
}
void Compressgamut::enabledChanged ()
{
if (listener) {
if (get_inconsistent()) {
listener->panelChanged (Evcgenabled, M("GENERAL_UNCHANGED"));
} else if (getEnabled()) {
listener->panelChanged (Evcgenabled, M("GENERAL_ENABLED"));
} else {
listener->panelChanged (Evcgenabled, M("GENERAL_DISABLED"));
}
}
}
void Compressgamut::setBatchMode (bool batchMode)
{
ToolPanel::setBatchMode (batchMode);
colorspace->append (M("GENERAL_UNCHANGED"));
th_c->showEditedCB ();
th_m->showEditedCB ();
th_y->showEditedCB ();
d_c->showEditedCB ();
d_m->showEditedCB ();
d_y->showEditedCB ();
pwr->showEditedCB ();
}
void Compressgamut::trimValues (rtengine::procparams::ProcParams* pp)
{
th_c->trimValue(pp->cg.th_c);
th_m->trimValue(pp->cg.th_m);
th_y->trimValue(pp->cg.th_y);
d_c->trimValue(pp->cg.d_c);
d_m->trimValue(pp->cg.d_m);
d_y->trimValue(pp->cg.d_y);
pwr->trimValue(pp->cg.pwr);
}