Patch from issue 1267: "New Threshold curve widget", used in USM Sharpening and Vibrance

This commit is contained in:
natureh
2012-06-19 23:01:25 +02:00
parent b5176679b8
commit a9286155e8
49 changed files with 5685 additions and 4202 deletions

View File

@@ -21,12 +21,159 @@
#include <glibmm.h>
#include <vector>
#include <cassert>
#include <cstdio>
#include <cmath>
class ParamsEdited;
namespace rtengine {
namespace procparams {
template <typename T>
class Threshold {
public:
T value[4];
protected:
bool initEq1;
bool _isDouble;
#ifndef NDEBUG
unsigned int part[5];
#endif
public:
Threshold (T val1, T val2, bool startAtOne) {
initEq1 = startAtOne;
value[0] = val1;
value[1] = val2;
value[2] = T(0);
value[3] = T(0);
_isDouble = false;
}
Threshold (T val1, T val2, T val3, T val4, bool startAtOne) {
initEq1 = startAtOne;
value[0] = val1;
value[1] = val2;
value[2] = val3;
value[3] = val4;
_isDouble = true;
}
// for convenience, since 'values' is public
void setValues(T val1, T val2) {
value[0] = val1;
value[1] = val2;
}
// for convenience, since 'values' is public
void setValues(T val1, T val2, T val3, T val4) {
value[0] = val1;
value[1] = val2;
value[2] = val3;
value[3] = val4;
}
bool isDouble() const { return _isDouble; }
// RT: Type of the returned value
// RV: Type of the value on the X axis
// RV2: Type of the maximum value on the Y axis
template <typename RT, typename RV, typename RV2>
RT multiply(RV x, RV2 yMax) const {
double val = double(x);
if (initEq1) {
if (_isDouble) {
if (val == double(value[2]) && double(value[2]) == double(value[3]))
// this handle the special case where the 2 right values are the same, then bottom one is sent back,
// useful if one wants to keep the bottom value even beyond the x max bound
return RT(0.);
if (val >= double(value[3]))
return RT(yMax);
if (val > double(value[2]))
return RT(double(yMax)*(val-double(value[2]))/(double(value[3])-double(value[2])));
}
if (val >= double(value[0]))
return RT(0);
if (val > double(value[1]))
return RT(double(yMax)*(1.-(val-double(value[0]))/(double(value[1])-double(value[0]))));
return RT(yMax);
}
else {
if (_isDouble) {
if (val == double(value[2]) && double(value[2]) == double(value[3]))
// this handle the special case where the 2 right values are the same, then top one is sent back,
// useful if one wants to keep the top value even beyond the x max bound
return RT(yMax);
if (val >= double(value[2]))
return RT(0);
if (val > double(value[3]))
return RT(double(yMax)*(1.-(val-double(value[3]))/(double(value[2])-double(value[3]))));
}
if (val >= double(value[1]))
return RT(yMax);
if (val > double(value[0]))
return RT(double(yMax)*(val-double(value[0]))/(double(value[1])-double(value[0])));
return RT(0);
}
}
// RT: Type of the returned value
// RV: Type of the value on the X axis
/*template <typename RT, typename RV>
RT getRatio(RV val) const {
double val = double(val);
if (initEq1) {
if (_isDouble) { // assuming that simple thresholds will be more frequent
if (val >= double(value[3]))
return RT(1);
if (val > double(value[2]))
return (val-double(value[2]))/(double(value[3])-double(value[2]));
}
if (val >= double(value[1]))
return RT(0);
if (val > double(value[0]))
return 1.-(val-double(value[0]))/(double(value[1])-double(value[0]));
return RT(1);
}
else {
if (_isDouble) { // assuming that simple thresholds will be more frequent
if (val >= double(value[3]))
return RT(0);
if (val > double(value[2]))
return 1.-(val-double(value[2]))/(double(value[3])-double(value[2]));
}
if (val >= double(value[1]))
return RT(1);
if (val > double(value[0]))
return (val-double(value[0]))/(double(value[1])-double(value[0]));
return RT(0);
}
}*/
Threshold<T> & operator= (const Threshold<T> &rhs) {
value[0] = rhs.value[0];
value[1] = rhs.value[1];
value[2] = rhs.value[2];
value[3] = rhs.value[3];
initEq1 = rhs.initEq1;
_isDouble = rhs._isDouble;
return *this;
}
bool operator== (const Threshold<T> &rhs) const {
if (_isDouble)
return fabs(value[0]-rhs.value[0])<1e-10
&& fabs(value[1]-rhs.value[1])<1e-10
&& fabs(value[2]-rhs.value[2])<1e-10
&& fabs(value[3]-rhs.value[3])<1e-10;
else
return fabs(value[0]-rhs.value[0])<1e-10
&& fabs(value[1]-rhs.value[1])<1e-10;
}
};
/**
* Parameters of the tone curve
*/
@@ -81,20 +228,22 @@ class RGBCurvesParams {
class SharpeningParams {
public:
bool enabled;
double radius;
int amount;
int threshold;
bool edgesonly;
double edges_radius;
int edges_tolerance;
bool halocontrol;
int halocontrol_amount;
Glib::ustring method;
int deconvamount;
double deconvradius;
int deconviter;
int deconvdamping;
bool enabled;
double radius;
int amount;
Threshold<int> threshold;
bool edgesonly;
double edges_radius;
int edges_tolerance;
bool halocontrol;
int halocontrol_amount;
Glib::ustring method;
int deconvamount;
double deconvradius;
int deconviter;
int deconvdamping;
SharpeningParams() : threshold(20, 80, 2000, 1200, false) {};
};
class SharpenEdgeParams {
public:
@@ -117,13 +266,15 @@ class SharpenMicroParams {
class VibranceParams {
public:
bool enabled;
int pastels;
int saturated;
int psthreshold;
bool protectskins;
bool avoidcolorshift;
bool pastsattog;
bool enabled;
int pastels;
int saturated;
Threshold<int> psthreshold;
bool protectskins;
bool avoidcolorshift;
bool pastsattog;
VibranceParams() : psthreshold(1, 75, false) {};
};
/**