Issue 2147: white balance slider now non-linear

This commit is contained in:
torger
2013-12-24 14:51:35 +01:00
parent e4e689c06f
commit 5970935529
3 changed files with 71 additions and 11 deletions

View File

@@ -27,7 +27,9 @@
#define MIN_RESET_BUTTON_HEIGHT 17 #define MIN_RESET_BUTTON_HEIGHT 17
Adjuster::Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep, double vdefault, Gtk::Image *imgIcon) { static double one2one(double val) { return val; }
Adjuster::Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep, double vdefault, Gtk::Image *imgIcon, double2double_fun slider2value_, double2double_fun value2slider_) {
Gtk::HBox *hbox2=NULL; Gtk::HBox *hbox2=NULL;
@@ -37,6 +39,8 @@ Adjuster::Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep
automatic = NULL; automatic = NULL;
eventPending = false; eventPending = false;
slider2value = slider2value_ ? slider2value_ : one2one;
value2slider = value2slider_ ? value2slider_ : one2one;
vMin = vmin; vMin = vmin;
vMax = vmax; vMax = vmax;
vStep = vstep; vStep = vstep;
@@ -224,14 +228,14 @@ void Adjuster::resetValue (bool toInitial) {
afterReset = true; afterReset = true;
if (toInitial) { if (toInitial) {
// resetting to the initial editing value, when the image has been loaded // resetting to the initial editing value, when the image has been loaded
slider->set_value (defaultVal); slider->set_value (addMode ? defaultVal : value2slider(defaultVal));
} }
else { else {
// resetting to the slider default value // resetting to the slider default value
if (addMode) if (addMode)
slider->set_value (0.); slider->set_value (0.);
else else
slider->set_value (ctorDefaultVal); slider->set_value (value2slider(ctorDefaultVal));
} }
} }
@@ -261,8 +265,8 @@ void Adjuster::setLimits (double vmin, double vmax, double vstep, double vdefaul
spin->set_value (shapeValue(vdefault)); spin->set_value (shapeValue(vdefault));
slider->set_digits (digits); slider->set_digits (digits);
slider->set_increments (vstep, 2.0*vstep); slider->set_increments (vstep, 2.0*vstep);
slider->set_range (vmin, vmax); slider->set_range (addMode ? vmin : value2slider(vmin), addMode ? vmax : value2slider(vmax));
slider->set_value (shapeValue(vdefault)); slider->set_value (addMode ? shapeValue(vdefault) : value2slider(shapeValue(vdefault)));
//defaultVal = shapeValue (vdefault); //defaultVal = shapeValue (vdefault);
sliderChange.block (false); sliderChange.block (false);
spinChange.block (false); spinChange.block (false);
@@ -271,6 +275,7 @@ void Adjuster::setLimits (double vmin, double vmax, double vstep, double vdefaul
void Adjuster::setAddMode(bool addM) { void Adjuster::setAddMode(bool addM) {
if (addM != addMode) { if (addM != addMode) {
// Switching the Adjuster to the new mode // Switching the Adjuster to the new mode
addMode = addM;
if (addM) { if (addM) {
// Switching to the relative mode // Switching to the relative mode
double range = -vMin + vMax; double range = -vMin + vMax;
@@ -281,7 +286,6 @@ void Adjuster::setAddMode(bool addM) {
// Switching to the absolute mode // Switching to the absolute mode
setLimits(vMin, vMax, vStep, defaultVal); setLimits(vMin, vMax, vStep, defaultVal);
} }
addMode = addM;
} }
} }
@@ -291,7 +295,7 @@ void Adjuster::spinChanged () {
delayConnection.disconnect (); delayConnection.disconnect ();
sliderChange.block (true); sliderChange.block (true);
slider->set_value (spin->get_value ()); slider->set_value (addMode ? spin->get_value () : value2slider(spin->get_value ()));
sliderChange.block (false); sliderChange.block (false);
if (delay==0) { if (delay==0) {
@@ -326,7 +330,7 @@ void Adjuster::sliderChanged () {
delayConnection.disconnect (); delayConnection.disconnect ();
spinChange.block (true); spinChange.block (true);
spin->set_value (slider->get_value ()); spin->set_value (addMode ? slider->get_value () : slider2value(slider->get_value ()));
spinChange.block (false); spinChange.block (false);
if (delay==0 || afterReset) { if (delay==0 || afterReset) {
@@ -360,7 +364,7 @@ void Adjuster::setValue (double a) {
spinChange.block (true); spinChange.block (true);
sliderChange.block (true); sliderChange.block (true);
spin->set_value (shapeValue (a)); spin->set_value (shapeValue (a));
slider->set_value (shapeValue (a)); slider->set_value (addMode ? shapeValue(a) : value2slider(shapeValue (a)));
sliderChange.block (false); sliderChange.block (false);
spinChange.block (false); spinChange.block (false);
afterReset = false; afterReset = false;

View File

@@ -32,6 +32,7 @@ class AdjusterListener {
virtual void adjusterAutoToggled (Adjuster* a, bool newval) {} virtual void adjusterAutoToggled (Adjuster* a, bool newval) {}
}; };
typedef double(*double2double_fun)(double val);
class Adjuster : public Gtk::VBox { class Adjuster : public Gtk::VBox {
@@ -70,12 +71,13 @@ class Adjuster : public Gtk::VBox {
double shapeValue (double a); double shapeValue (double a);
void refreshLabelStyle (); void refreshLabelStyle ();
double2double_fun value2slider, slider2value;
public: public:
int delay; int delay;
Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep, double vdefault, Gtk::Image *imgIcon=NULL); Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep, double vdefault, Gtk::Image *imgIcon=NULL, double2double_fun slider2value=NULL, double2double_fun value2slider=NULL);
virtual ~Adjuster (); virtual ~Adjuster ();
// Add an "Automatic" checkbox next to the reset button. // Add an "Automatic" checkbox next to the reset button.

View File

@@ -24,6 +24,7 @@
#define MINTEMP 1500 //1200 #define MINTEMP 1500 //1200
#define MAXTEMP 60000 //12000 #define MAXTEMP 60000 //12000
#define CENTERTEMP 4750
#define MINGREEN 0.02 #define MINGREEN 0.02
#define MAXGREEN 5.0 #define MAXGREEN 5.0
#define MINEQUAL 0.8 #define MINEQUAL 0.8
@@ -61,6 +62,59 @@ void WhiteBalance::cleanup () {
} }
} }
static double wbSlider2Temp(double sval) {
// slider range: 0 - 10000
double temp;
if (sval <= 5000) {
// linear below center-temp
temp = MINTEMP + (sval / 5000.0) * (CENTERTEMP - MINTEMP);
} else {
const double slope = (double)(CENTERTEMP - MINTEMP) / (MAXTEMP - CENTERTEMP);
double x = (sval - 5000) / 5000; // x 0..1
double y = x * slope + (1.0 - slope)*pow(x, 4.0);
//double y = pow(x, 4.0);
temp = CENTERTEMP + y * (MAXTEMP - CENTERTEMP);
}
if (temp < MINTEMP) temp = MINTEMP;
if (temp > MAXTEMP) temp = MAXTEMP;
return temp;
}
static double wbTemp2Slider(double temp) {
double sval;
if (temp <= CENTERTEMP) {
sval = ((temp - MINTEMP) / (CENTERTEMP - MINTEMP)) * 5000.0;
} else {
const double slope = (double)(CENTERTEMP - MINTEMP) / (MAXTEMP - CENTERTEMP);
const double y = (temp - CENTERTEMP) / (MAXTEMP - CENTERTEMP);
double x = pow(y, 0.25); // rough guess of x, will be a little lower
double y1;
double k = 0.1;
bool add = true;
// the y=f(x) function is a mess to invert, therefore we have this trial-refinement loop instead.
// from tests, worst case is about 20 iterations, ie no problem
for (;;) {
y1 = x * slope + (1.0 - slope)*pow(x, 4.0);
if (5000 * fabs(y1 - y) < 0.1) break;
if (y1 < y) {
if (!add) k /= 2;
x += k;
add = true;
} else {
if (add) k /= 2;
x -= k;
add = false;
}
}
sval = 5000.0 + x * 5000.0;
}
if (sval < 0) sval = 0;
if (sval > 10000) sval = 10000;
return sval;
}
WhiteBalance::WhiteBalance () : Gtk::VBox(), FoldableToolPanel(this), wbp(NULL), wblistener(NULL) { WhiteBalance::WhiteBalance () : Gtk::VBox(), FoldableToolPanel(this), wbp(NULL), wblistener(NULL) {
set_border_width(4); set_border_width(4);
@@ -181,7 +235,7 @@ WhiteBalance::WhiteBalance () : Gtk::VBox(), FoldableToolPanel(this), wbp(NULL),
pack_start (*spotbox, Gtk::PACK_SHRINK, 4); pack_start (*spotbox, Gtk::PACK_SHRINK, 4);
temp = Gtk::manage (new Adjuster (M("TP_WBALANCE_TEMPERATURE"), MINTEMP, MAXTEMP, 5, 4750)); temp = Gtk::manage (new Adjuster (M("TP_WBALANCE_TEMPERATURE"), MINTEMP, MAXTEMP, 5, CENTERTEMP, NULL, &wbSlider2Temp, &wbTemp2Slider));
green = Gtk::manage (new Adjuster (M("TP_WBALANCE_GREEN"), MINGREEN, MAXGREEN, 0.001, 1.0)); green = Gtk::manage (new Adjuster (M("TP_WBALANCE_GREEN"), MINGREEN, MAXGREEN, 0.001, 1.0));
equal = Gtk::manage (new Adjuster (M("TP_WBALANCE_EQBLUERED"), MINEQUAL, MAXEQUAL, 0.001, 1.0)); equal = Gtk::manage (new Adjuster (M("TP_WBALANCE_EQBLUERED"), MINEQUAL, MAXEQUAL, 0.001, 1.0));
cache_customTemp (0); cache_customTemp (0);