New curve editor, first batch (parametric curves, overlaid histogram in curve area)

This commit is contained in:
ghorvath 2010-04-16 08:44:41 +00:00
parent fbcf2a187b
commit 71b74bbfd2
46 changed files with 1579 additions and 1248 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
option (WITH_RAWZOR "Build with Rawzor support" ON) option (WITH_RAWZOR "Build with Rawzor support" OFF)
add_subdirectory (rtexif) add_subdirectory (rtexif)
add_subdirectory (rtengine) add_subdirectory (rtengine)

View File

@ -24,264 +24,154 @@
#include <mytime.h> #include <mytime.h>
#include <string.h> #include <string.h>
#undef CLIPD
#define CLIPD(a) ((a)>0.0?((a)<1.0?(a):1.0):0.0)
namespace rtengine { namespace rtengine {
Curve::Curve (const char* iname, const char* descr) : islinear(false), isempty(false) { Curve::Curve (const std::vector<double>& p) : x(NULL), y(NULL), ypp(NULL) {
ypp = NULL; if (p.size()<3) {
name = iname; kind = 0;
char* buffer = new char[strlen(descr)+1];
strcpy (buffer, descr);
char* token = strtok (buffer, ",; \t\n");
std::vector<double> xv;
std::vector<double> yv;
while (token) {
double xd = atof (token);
token = strtok (NULL, ",; \t\n");
if (token) {
double yd = atof (token);
xv.push_back (xd);
yv.push_back (yd);
} }
token = strtok (NULL, ",; \t\n"); else {
} kind = p[0];
N = xv.size (); if (kind==-1 || kind==1) {
x = new double[N]; N = (p.size()-1)/2;
y = new double[N]; x = new double[N];
for (int i=0; i<N; i++) { y = new double[N];
x[i] = xv[i]; int ix = 1;
y[i] = yv[i]; for (int i=0; i<N; i++) {
} x[i] = p[ix++];
delete [] buffer; y[i] = p[ix++];
spline_cubic_set (); }
} if (kind==1)
spline_cubic_set ();
Curve::Curve (const char* iname, int iN, double ix[], double iy[]) : islinear(false), isempty(false) { }
if (kind==2) {
ypp = NULL; if (p.size()!=8 && p.size()!=9)
N = iN; kind = 0;
name = iname; else {
x = new double[N]; x = new double[9];
y = new double[N]; for (int i=0; i<4; i++)
for (int i=0; i<N; i++) { x[i] = p[i];
x[i] = ix[i]; for (int i=4; i<8; i++)
y[i] = iy[i]; x[i] = (p[i]+100.0)/200.0;
} if (p.size()<9)
spline_cubic_set (); x[8] = 1.0;
} else
x[8] = p[8]/100.0;
Curve::Curve (const std::vector<double>& p) { }
}
x = NULL; }
y = NULL; }
ypp = NULL;
name = "custom";
isempty = true;
N = p.size()/2;
if (N<2)
return;
int ix = 0;
islinear = p[ix++]<0;
x = new double[N];
y = new double[N];
for (int i=0; i<N; i++) {
x[i] = p[ix++];
y[i] = p[ix++];
}
if (N==2 && x[0]==0.0 && y[0]==0.0 && x[1]==1.0 && y[1]==1.0)
isempty = true;
else {
isempty = false;
spline_cubic_set ();
}
}
Curve::~Curve () { Curve::~Curve () {
if (x) delete [] x;
delete [] x; delete [] y;
if (y) delete [] ypp;
delete [] y;
if (ypp)
delete [] ypp;
}
void Curve::d3_np_fs (double a[], double b[]) {
/* ypp = new double [N];
for (int i=0; i<N; i++)
ypp[i] = b[i];
for (int i=1; i<N; i++) {
double xmult = a[2+(i-1)*3] / a[1+(i-1)*3];
a[1+i*3] = a[1+i*3] - xmult * a[0+i*3];
ypp[i] = ypp[i] - xmult * ypp[i-1];
}
ypp[N-1] = ypp[N-1] / a[1+(N-1)*3];
for (int i=N-2; 0<=i; i--)
ypp[i] = (ypp[i] - a[0+(i+1)*3] * ypp[i+1]) / a[1+i*3];*/
} }
void Curve::spline_cubic_set () { void Curve::spline_cubic_set () {
/* double *a; double* u = new double[N-1];
double *b;
int i;
a = new double [3*N];
b = new double [N];
//
// Set up the first equation.
//
b[0] = 0;
a[1+0*3] = 1.0E+00;
// a[0+1*3] = -1.0E+00;
a[0+1*3] = 0.0E+00;
//
// Set up the intermediate equations.
//
for (int i=1; i<N-1; i++)
{
b[i] = ( y[i+1] - y[i] ) / ( x[i+1] - x[i] )
- ( y[i] - y[i-1] ) / ( x[i] - x[i-1] );
a[2+(i-1)*3] = (x[i] - x[i-1]) / 6.0E+00;
a[1+ i *3] = (x[i+1] - x[i-1]) / 3.0E+00;
a[0+(i+1)*3] = (x[i+1] - x[i]) / 6.0E+00;
}
//
// Set up the last equation.
//
b[N-1] = 0;
a[2+(N-2)*3] = 0.0E+00;
// a[2+(N-2)*3] = -1.0E+00;
a[1+(N-1)*3] = 1.0E+00;
//
// Solve the linear system.
//
d3_np_fs (a, b);
delete [] a;
delete [] b;*/
double* u = new double[N-1];
if (ypp)
delete [] ypp; delete [] ypp;
ypp = new double [N]; ypp = new double [N];
ypp[0] = u[0] = 0.0; /* set lower boundary condition to "natural" */ ypp[0] = u[0] = 0.0; /* set lower boundary condition to "natural" */
for (int i = 1; i < N - 1; ++i) for (int i = 1; i < N - 1; ++i) {
{ double sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
double sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]); double p = sig * ypp[i - 1] + 2.0;
double p = sig * ypp[i - 1] + 2.0; ypp[i] = (sig - 1.0) / p;
ypp[i] = (sig - 1.0) / p; u[i] = ((y[i + 1] - y[i])
u[i] = ((y[i + 1] - y[i]) / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]));
/ (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1])); u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
} }
ypp[N - 1] = 0.0; ypp[N - 1] = 0.0;
for (int k = N - 2; k >= 0; --k) for (int k = N - 2; k >= 0; --k)
ypp[k] = ypp[k] * ypp[k + 1] + u[k]; ypp[k] = ypp[k] * ypp[k + 1] + u[k];
delete [] u; delete [] u;
} }
double Curve::getVal (double t) { double Curve::getVal (double t) {
//
// Determine the interval [ T(I), T(I+1) ] that contains TVAL.
// Values below T[0] or above T[N-1] use extrapolation.
//
if (isempty)
return t;
if (t>x[N-1]) if (!kind)
return y[N-1]; return t;
else if (t<x[0])
return y[0];
/* do a binary search for the right interval: */ if (kind==2) {
int k_lo = 0, k_hi = N - 1;
while (k_hi - k_lo > 1){ if (t<=1e-14)
int k = (k_hi + k_lo) / 2; return 0.0;
if (x[k] > t) double c = -log(2.0)/log(x[2]);
k_hi = k; double tv = exp(c*log(t));
else double base = pfull (tv, x[8], x[6], x[5]);
k_lo = k; double stretched = base<=1e-14 ? 0.0 : exp(log(base)/c);
}
base = pfull (0.5, x[8], x[6], x[5]);
double h = x[k_hi] - x[k_lo]; double fc = base<=1e-14 ? 0.0 : exp(log(base)/c); // value of the curve at the center point
if (islinear) if (t<x[2]) {
return y[k_lo] + (t - x[k_lo]) * ( y[k_hi] - y[k_lo] ) / h; // add shadows effect:
else { double sc = -log(2.0)/log(x[1]/x[2]);
double a = (x[k_hi] - t) / h; double stv = exp(sc*log(stretched/fc));
double b = (t - x[k_lo]) / h; double sbase = pfull (stv, x[8], x[7], 0.5);
return a*y[k_lo] + b*y[k_hi] + ((a*a*a - a)*ypp[k_lo] + (b*b*b - b)*ypp[k_hi]) * (h*h)/6.0; double sstretched = fc*(sbase<=1e-14 ? 0.0 : exp(log(sbase)/sc));
} return sstretched;
}
/* else {
if (t>x[N-1]) // add highlights effect:
return y[N-1]; double hc = -log(2.0)/log((x[3]-x[2])/(1-x[2]));
else if (t<x[0]) double htv = exp(hc*log((stretched-fc)/(1-fc)));
return y[0]; double hbase = pfull (htv, x[8], 0.5, x[4]);
double hstretched = fc + (1-fc)*(hbase<=1e-14 ? 0.0 : exp(log(hbase)/hc));
int ival = N - 2; return hstretched;
}
for (int i=0; i<N-1; i++)
if (t < x[i+1]) {
ival = i;
break;
} }
// else {
// In the interval I, the polynomial is in terms of a normalized if (t>x[N-1])
// coordinate between 0 and 1. return y[N-1];
// else if (t<x[0])
double dt = t - x[ival]; return y[0];
double h = x[ival+1] - x[ival];
if (islinear) { /* do a binary search for the right interval: */
return y[ival] + dt * ( y[ival+1] - y[ival] ) / h; int k_lo = 0, k_hi = N - 1;
} while (k_hi - k_lo > 1){
else int k = (k_hi + k_lo) / 2;
return y[ival] if (x[k] > t)
+ dt * ( ( y[ival+1] - y[ival] ) / h k_hi = k;
- ( ypp[ival+1] / 6.0E+00 + ypp[ival] / 3.0E+00 ) * h else
+ dt * ( 0.5E+00 * ypp[ival] k_lo = k;
+ dt * ( ( ypp[ival+1] - ypp[ival] ) / ( 6.0E+00 * h ) ) ) ); }
*/
double h = x[k_hi] - x[k_lo];
if (kind==-1)
return y[k_lo] + (t - x[k_lo]) * ( y[k_hi] - y[k_lo] ) / h;
else if (kind==1) {
double a = (x[k_hi] - t) / h;
double b = (t - x[k_lo]) / h;
double r = a*y[k_lo] + b*y[k_hi] + ((a*a*a - a)*ypp[k_lo] + (b*b*b - b)*ypp[k_hi]) * (h*h)/6.0;
if (r < 0.0) return 0.0;
if (r > 1.0) return 1.0;
return r;
}
else
return t;
}
} }
Glib::ustring Curve::getName () { void Curve::getVal (const std::vector<double>& t, std::vector<double>& res) {
// TODO!!!! can be made much faster!!! Binary search of getVal(double) at each point can be avoided
return name; res.resize (t.size());
for (int i=0; i<t.size(); i++)
res[i] = getVal(t[i]);
} }
std::map<std::string, Curve*> CurveFactory::curves;
/*double CurveFactory::centercontrast (double x, double b, double m) {
if (b==0)
return x;
if (b>0) {
if (x>m)
return m + (1.0-m) * tanh (b*(x-m)/(1.0-m)) / tanh (b);
else
return m - m * tanh (b*(m-x)/m) / tanh (b);
}
else {
if (x>m)
return 2.0*x - m - (1.0-m) * tanh (b*(x-m)/(1.0-m)) / tanh (b);
else
return 2.0*x - m + m * tanh (b*(m-x)/m) / tanh (b);
}
}
*/
double CurveFactory::centercontrast (double x, double b, double m) { double CurveFactory::centercontrast (double x, double b, double m) {
if (b==0) if (b==0)
@ -299,103 +189,7 @@ double CurveFactory::centercontrast (double x, double b, double m) {
return 2.0*x - m - m * tanh (b*(x-m)/m) / tanh (b); return 2.0*x - m - m * tanh (b*(x-m)/m) / tanh (b);
} }
} }
/*
double CurveFactory::contrast (double x, double a) {
if (a==0)
return x;
else if (a>0) {
double s = (1.0+exp(-0.5*a)) / (1.0+exp(-(x-0.5)*a)) * (exp(0.5*a)-exp(-(x-0.5)*a)) / (exp(0.5*a)-exp(-0.5*a));
return s;
}
else {
double s = (1.0+exp(-0.5*a)) / (1.0+exp(-(x-0.5)*a)) * (exp(0.5*a)-exp(-(x-0.5)*a)) / (exp(0.5*a)-exp(-0.5*a));
return 2*x - s;
}
}
double CurveFactory::brightness (double x, double a, double bd1, double bd2) {
if (a==1)
return x;
else if (a<1)
return a*x;
else {
if (x < 1.0/a-bd1)
return a*x;
else if (x > 1.0/a+bd2)
return 1;
else {
double d = bd1+bd2;
double s = - (-a*d*(1.0+a*(bd2-x))*(1.0+a*(bd2-x))*(-1.0+a*(bd1+x))-(2.0+a*(bd1+3.0*bd2-2.0*x))*(-1.0+a*(bd1+x))*(-1.0+a*(bd1+x)) + (-1.0+a*bd1)*(1.0+a*(bd2-x))*(1.0+a*(bd2-x))*(-2.0+a*(3.0*bd1+bd2+2.0*x))) / (a*a*a*d*d*d);
return s;
}
}
}
double CurveFactory::softClip (double x, double d1, double d2, double a, double b, double c, double d) {
if (x<1.0-d1)
return x;
else if (x>1.0+d2)
return 1.0;
else
return a*x*x*x + b*x*x + c*x + d;
}
double CurveFactory::dlower (const double b, const double m, const double c) {
return b / (tanh(b) * 2.0 * m);
}
double CurveFactory::dupper (const double b, const double m, const double c) {
return b / (tanh(b) * 2.0 * (c-m));
}
double CurveFactory::solve_lower (double m, double c, double deriv) {
double b_u = 2.0*m*deriv;
double b_l = 0.0;
double b;
while (b_u-b_l > 0.0000001) {
b = (b_u+b_l) / 2.0;
if (dlower(b,m,c)<deriv)
b_l = b;
else
b_u = b;
}
return b;
}
double CurveFactory::solve_upper (double m, double c, double deriv) {
double b_u = 2.0*(c-m)*deriv;
double b_l = 0.0;
double b;
while (b_u-b_l > 0.0000001) {
b = (b_u+b_l) / 2.0;
if (dupper(b,m,c)<deriv)
b_l = b;
else
b_u = b;
}
return b;
}
double CurveFactory::levels (double x, double b_lower, double b_upper, double m, double cmax) {
if (x<=m)
return (1.0 + tanh (b_lower*(x-m)/m) / tanh (b_lower)) / 2.0;
else
return (1.0 + tanh (b_upper*(x-m)/(cmax-m)) / tanh (b_upper)) / 2.0;
}
void CurveFactory::updateCurve3 (int* curve, int* ohistogram, const std::vector<double>& points, double defmul, double ecomp, int black, double hlcompr, double shcompr, double br, double contr, double gamma_, bool igamma, int skip) { void CurveFactory::updateCurve3 (int* curve, int* ohistogram, const std::vector<double>& points, double defmul, double ecomp, int black, double hlcompr, double shcompr, double br, double contr, double gamma_, bool igamma, int skip) {
double def_mul = pow (2.0, defmul); double def_mul = pow (2.0, defmul);
@ -418,6 +212,11 @@ void CurveFactory::updateCurve3 (int* curve, int* ohistogram, const std::vector<
bool needcontrast = contr>0.00001 || contr<-0.00001; bool needcontrast = contr>0.00001 || contr<-0.00001;
bool needigamma = !needcontrast && igamma && gamma_>0; bool needigamma = !needcontrast && igamma && gamma_>0;
// create a curve if needed
Curve* tcurve = NULL;
if (points.size()>0 && points[0]!=0)
tcurve = new Curve (points);
for (int i=0; i<=0xffff; i+= i<0xffff-skip ? skip : 1 ) { for (int i=0; i<=0xffff; i+= i<0xffff-skip ? skip : 1 ) {
double val = (double)i / 65535.0; double val = (double)i / 65535.0;
@ -428,8 +227,8 @@ void CurveFactory::updateCurve3 (int* curve, int* ohistogram, const std::vector<
val = basecurve (val, a, b, D, hlcompr/100.0, shcompr/100.0); val = basecurve (val, a, b, D, hlcompr/100.0, shcompr/100.0);
val = brightness (val, br/100.0); val = brightness (val, br/100.0);
// if (tcurve) if (tcurve)
// val = tcurve->getVal (val); val = tcurve->getVal (val);
if (needigamma) if (needigamma)
val = igamma2 (val); val = igamma2 (val);
@ -440,6 +239,7 @@ void CurveFactory::updateCurve3 (int* curve, int* ohistogram, const std::vector<
val = 0.0; val = 0.0;
dcurve[i] = val; dcurve[i] = val;
} }
delete tcurve;
/* /*
if (igamma) { if (igamma) {
FILE* f = fopen ("curve.txt","wt"); FILE* f = fopen ("curve.txt","wt");
@ -451,7 +251,7 @@ if (igamma) {
fclose (f); fclose (f);
} }
*/ */
/*
int prev = 0; int prev = 0;
for (int i=1; i<=0xffff-skip; i++) { for (int i=1; i<=0xffff-skip; i++) {
if (i%skip==0) { if (i%skip==0) {
@ -492,148 +292,128 @@ if (igamma) {
for (int i=0; i<=0xffff; i++) for (int i=0; i<=0xffff; i++)
curve[i] = (int) (65535.0 * dcurve[i]); curve[i] = (int) (65535.0 * dcurve[i]);
delete [] dcurve; delete [] dcurve;
} }*/
void CurveFactory::updateCurve2 (int* curve, int* ohistogram, const std::vector<double>& points, double ecomp, double br, int black, double hlcompr, double shcompr, double contr, double gamma_, bool igamma, int skip) { void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, double shcompr, double br, double contr, double defmul, double gamma_, bool igamma, const std::vector<double>& curvePoints, unsigned int* histogram, int* outCurve, unsigned int* outBeforeCCurveHistogram, int skip) {
double ec_mul = pow (2, ecomp); double def_mul = pow (2.0, defmul);
double bl = black / 65535.0;
double hi = pow (2.0,-br) + bl;
// compute parameters of the gamma curve // compute parameters of the gamma curve
double start = exp(gamma_*log( -0.099 / ((1.0/gamma_-1.0)*1.099 ))); double start = exp(gamma_*log( -0.099 / ((1.0/gamma_-1.0)*1.099 )));
double slope = 1.099 * pow (start, 1.0/gamma_-1) - 0.099/start; double slope = 1.099 * pow (start, 1.0/gamma_-1) - 0.099/start;
double mul = 1.099; double mul = 1.099;
double add = 0.099; double add = 0.099;
// compute parameters of the "levels" curve // theoretical maximum of the curve
shcompr /= 100.0; double D = gamma_>0 ? gamma (def_mul, gamma_, start, slope, mul, add) : def_mul;
hlcompr /= 100.0;
double correction = hlcompr<0.85 ? 1.0 : hlcompr+0.15;
correction = 1.0;
double d = pow (2.0,br);
double m = 0.5 / d + bl;
double c = (gamma_>0 ? gamma (ec_mul, gamma_, start, slope, mul, add) : ec_mul) * correction;
// double c = (gamma_>0 ? gamma (ec_mul, gamma_, start, slope, mul, add) : gamma2(ec_mul)) * correction;
double b_upper = solve_upper (m, c, d); // a: slope of the curve, black: starting point at the x axis
double b_lower = solve_lower (m, c, d); double a = pow (2.0, ecomp);
// generate curve without contrast (in double) // curve without contrast
double* dcurve = new double[65536];
// Curve* tcurve = curves[type];
Curve* tcurve = new Curve (points);
if (tcurve->isEmpty()) {
delete tcurve;
tcurve = NULL;
}
double* dcurve = new double[65536];
double bltanh = tanh (b_lower); // check if contrast curve is needed
double butanh = tanh (b_upper); bool needcontrast = contr>0.00001 || contr<-0.00001;
if (d * (c - bl) < 1) // check if inverse gamma is needed at the end
hlcompr = 0; bool needigamma = !needcontrast && igamma && gamma_>0;
bool needcontrast = contr>0.00001 || contr<-0.00001; // create a curve if needed
bool needigamma = !needcontrast && igamma && gamma_>0; Curve* tcurve = NULL;
if (curvePoints.size()>0 && curvePoints[0]!=0)
tcurve = new Curve (curvePoints);
for (int i=0; i<=0xffff; i+= i<0xffff-skip ? skip : 1 ) { // clear array that stores histogram valid before applying the custom curve
double val = (double)i / 65535.0; if (outBeforeCCurveHistogram)
val *= ec_mul; memset (outBeforeCCurveHistogram, 0, 256*sizeof(int));
if (gamma_>0)
val = gamma (val, gamma_, start, slope, mul, add); for (int i=0; i<=0xffff; i+= i<0xffff-skip ? skip : 1 ) {
// double sval = levels (val, b_lower, b_upper, m, c); // change to [0,1] rage
// Acceleration: double val = (double)i / 65535.0;
double sval;
if (val <= m) { // apply default multiplier (that is >1 if highlight recovery is on)
double ttag = 2.0 / (1.0 + exp (-2.0*b_lower*(val-m)/m)) - 1.0; val *= def_mul;
// sval = (1.0 + tanh (b_lower*(val-m)/m) / bltanh) / 2.0;
sval = (1.0 + ttag / bltanh) / 2.0;
}
else {
double ttag = 2.0 / (1.0 + exp (-2.0*b_upper*(val-m)/(c-m))) - 1.0;
// sval = (1.0 + tanh (b_upper*(val-m)/(c-m)) / butanh) / 2.0;
sval = (1.0 + ttag / butanh) / 2.0;
}
if (val<bl) // gamma correction
val = shcompr * sval; if (gamma_>0)
else if (val>hi) val = gamma (val, gamma_, start, slope, mul, add);
val = (1.0 - hlcompr) + hlcompr * sval;
else if (val<m) // apply base curve, thus, exposure compensation and black point with shadow and highlight protection
val = (1.0 - shcompr) * d * (val - bl) + shcompr * sval; val = basecurve (val, a, black, D, hlcompr/100.0, shcompr/100.0);
else
val = (1.0 - hlcompr) * d * (val - bl) + hlcompr * sval;
if (tcurve)
val = tcurve->getVal (val);
if (needigamma) // apply brightness curve
val = igamma2 (val); val = brightness (val, br/100.0);
// apply custom/parametric curve, if any
if (tcurve) {
if (outBeforeCCurveHistogram) {
double hval = val;
// if (needigamma)
// hval = igamma2 (hval);
int hi = (int)(255.0*CLIPD(hval));
outBeforeCCurveHistogram[hi]+=histogram[i] ;
}
val = tcurve->getVal (val);
}
if (val>1.0) // if inverse gamma is needed, do it (standard sRGB inverse gamma is applied)
val = 1.0; if (needigamma)
else if (val<0.0) val = igamma2 (val);
val = 0.0;
dcurve[i] = val;
}
int prev = 0; // store result in a temporary array
for (int i=1; i<=0xffff-skip; i++) { dcurve[i] = CLIPD(val);
if (i%skip==0) {
prev+=skip;
continue;
} }
dcurve[i] = ( dcurve[prev] * (skip - i%skip) + dcurve[prev+skip] * (i%skip) ) / skip; delete tcurve;
}
// if skip>1, let apply linear interpolation in the skipped points of the curve
if (needcontrast) { int prev = 0;
// compute mean luminance of the image with the curve applied for (int i=1; i<=0xffff-skip; i++) {
int sum = 0; if (i%skip==0) {
double avg = 0; prev+=skip;
for (int i=0; i<=0xffff; i++) { continue;
avg += dcurve[i] * ohistogram[i]; }
sum += ohistogram[i]; dcurve[i] = ( dcurve[prev] * (skip - i%skip) + dcurve[prev+skip] * (i%skip) ) / skip;
} }
avg /= sum;
// compute contrast parameter if (needcontrast) {
double contr_b = contr / 20; // compute mean luminance of the image with the curve applied
if (contr_b>=0 && contr_b < 0.00001) int sum = 0;
contr_b = 0.00001; double avg = 0;
else if (contr_b<0 && contr_b > -0.00001) for (int i=0; i<=0xffff; i++) {
contr_b = -0.00001; avg += dcurve[i] * histogram[i];
sum += histogram[i];
}
avg /= sum;
// apply contrast enhancement // compute contrast parameter
for (int i=0; i<=0xffff; i++) { double contr_b = contr / 20;
double val = centercontrast (dcurve[i], contr_b, avg); if (contr_b>=0 && contr_b < 0.00001)
if (igamma && gamma_>0) contr_b = 0.00001;
val = igamma2 (val); else if (contr_b<0 && contr_b > -0.00001)
if (val>1.0) val = 1.0; contr_b = -0.00001;
if (val<0.0) val = 0.0;
curve[i] = (int) (65535.0 * val); // apply contrast enhancement
for (int i=0; i<=0xffff; i++) {
double val = centercontrast (dcurve[i], contr_b, avg);
if (igamma && gamma_>0)
val = igamma2 (val);
outCurve[i] = (int) (65535.0 * CLIPD(val));
}
} }
} else
else for (int i=0; i<=0xffff; i++)
for (int i=0; i<=0xffff; i++) outCurve[i] = (int) (65535.0 * dcurve[i]);
curve[i] = (int) (65535.0 * dcurve[i]);
//if (igamma) {
// FILE* f = fopen ("curve.txt","wt");
// for (int i=0; i<65536; i++)
// fprintf (f, "%d\t%d\n", i, curve[i]);
// fclose (f);
//}
delete [] dcurve; delete [] dcurve;
} }
int CurveFactory::gammatab [65536]; int CurveFactory::gammatab [65536];
int CurveFactory::igammatab_srgb [65536]; int CurveFactory::igammatab_srgb [65536];
int CurveFactory::gammatab_srgb [65536]; int CurveFactory::gammatab_srgb [65536];
void CurveFactory::loadCurves (Glib::ustring fname) { void CurveFactory::init () {
for (int i=0; i<65536; i++) for (int i=0; i<65536; i++)
gammatab_srgb[i] = (int)(65535 * gamma2 (i/65535.0)); gammatab_srgb[i] = (int)(65535 * gamma2 (i/65535.0));
@ -641,38 +421,12 @@ void CurveFactory::loadCurves (Glib::ustring fname) {
igammatab_srgb[i] = (int)(65535 * igamma2 (i/65535.0)); igammatab_srgb[i] = (int)(65535 * igamma2 (i/65535.0));
for (int i=0; i<65536; i++) for (int i=0; i<65536; i++)
gammatab[i] = (int)(65535 * pow (i/65535.0, 0.454545)); gammatab[i] = (int)(65535 * pow (i/65535.0, 0.454545));
FILE* f = g_fopen (fname.c_str(), "rt"); /* FILE* f = fopen ("c.txt", "wt");
if (!f) for (int i=0; i<256; i++)
return; fprintf (f, "%g %g\n", i/255.0, clower (i/255.0, 2.0, 1.0));
fclose (f);*/
setlocale (LC_ALL, "C");
char* buffer = new char[1024];
while (buffer = fgets(buffer, 1024, f)) {
int es = 0;
int llen = strlen(buffer);
for (es = 0; es<llen && buffer[es]!='='; es++);
if (es<llen) {
buffer[es] = 0;
Curve* c = new Curve (strtok(buffer," \t"), buffer+es+1);
curves[c->getName()] = c;
}
}
delete buffer;
setlocale (LC_ALL, "");
} }
std::vector<Glib::ustring> CurveFactory::curveNames () {
std::vector<Glib::ustring> ret;
int ix = 0;
for (std::map<std::string, Curve*>::iterator i = curves.begin(); i!=curves.end(); i++)
ret.push_back (i->second->getName());
return ret;
}
} }

View File

@ -26,46 +26,25 @@
namespace rtengine { namespace rtengine {
class Curve {
protected:
int N;
double* x;
double* y;
double* ypp;
Glib::ustring name;
bool islinear;
bool isempty;
protected:
void d3_np_fs (double a[], double b[]);
void spline_cubic_set ();
public:
Curve (const char* iname, int iN, double ix[], double iy[]);
Curve (const char* iname, const char* descr);
Curve (const std::vector<double>& points);
~Curve ();
double getVal (double x);
Glib::ustring getName ();
bool isEmpty () { return isempty; }
};
class CurveFactory { class CurveFactory {
friend class Curve;
protected: protected:
static std::map<std::string, Curve*> curves; // look-up tables for the standard srgb gamma and its inverse (filled by init())
static int gammatab[65536];
static int igammatab_srgb[65536]; static int igammatab_srgb[65536];
static int gammatab_srgb[65536]; static int gammatab_srgb[65536];
// look-up tables for the simple exponential gamma
static int gammatab[65536];
// functions calculating the parameters of the contrast curve based on the desired slope at the center
static double solve_upper (double m, double c, double deriv); static double solve_upper (double m, double c, double deriv);
static double solve_lower (double m, double c, double deriv); static double solve_lower (double m, double c, double deriv);
static double dupper (const double b, const double m, const double c); static double dupper (const double b, const double m, const double c);
static double dlower (const double b, const double m, const double c); static double dlower (const double b, const double m, const double c);
// basic convex function between (0,0) and (1,1). m1 and m2 controls the slope at the start and end point
static inline double basel (double x, double m1, double m2) { static inline double basel (double x, double m1, double m2) {
if (x==0.0) if (x==0.0)
return 0.0; return 0.0;
@ -74,9 +53,11 @@ class CurveFactory {
double lx = log(x); double lx = log(x);
return m2*x + (1.0-m2)*(2.0 - exp(k*lx))*exp(l*lx); return m2*x + (1.0-m2)*(2.0 - exp(k*lx))*exp(l*lx);
} }
// basic concave function between (0,0) and (1,1). m1 and m2 controls the slope at the start and end point
static inline double baseu (double x, double m1, double m2) { static inline double baseu (double x, double m1, double m2) {
return 1.0 - basel(1.0-x, m1, m2); return 1.0 - basel(1.0-x, m1, m2);
} }
// convex curve between (0,0) and (1,1) with slope m at (0,0). hr controls the highlight recovery
static inline double cupper (double x, double m, double hr) { static inline double cupper (double x, double m, double hr) {
if (hr>1.0) if (hr>1.0)
return baseu (x, m, 2.0*(hr-1.0)/m); return baseu (x, m, 2.0*(hr-1.0)/m);
@ -86,10 +67,12 @@ class CurveFactory {
if (x<x1) return x*m; if (x<x1) return x*m;
return 1.0 - hr + hr*baseu((x-x1)/hr, m, 0); return 1.0 - hr + hr*baseu((x-x1)/hr, m, 0);
} }
// concave curve between (0,0) and (1,1) with slope m at (1,1). sr controls the shadow recovery
static inline double clower (double x, double m, double sr) { static inline double clower (double x, double m, double sr) {
return 1.0 - cupper(1.0-x, m, sr); return 1.0 - cupper(1.0-x, m, sr);
} }
static inline double basecurve (double x, double a, double b, double D, double hr, double sr) { // a: slope, b: black, D: max. x value // tone curve base. a: slope (from exp.comp.), b: black, D: max. x value (can be>1), hr,sr: highlight,shadow recovery
static inline double basecurve (double x, double a, double b, double D, double hr, double sr) {
double m = b+0.5/a<D ? b+0.5/a : D; double m = b+0.5/a<D ? b+0.5/a : D;
double y = (D-b)*a<0.5 ? (D-b)*a : 0.5; double y = (D-b)*a<0.5 ? (D-b)*a : 0.5;
if (x<=m) if (x<=m)
@ -99,12 +82,14 @@ class CurveFactory {
else else
return y+(x-m)*a; return y+(x-m)*a;
} }
// brightness curve at point x, only positive amount it supported
static inline double brightnessbase (double x, double amount) { static inline double brightnessbase (double x, double amount) {
if (x<0.5) if (x<0.5)
return x + amount*cupper(2.0*x, 4.5, 0.0)/3.0; return x + amount*cupper(2.0*x, 4.5, 0.0)/3.0;
else else
return x + amount*cupper(2.0-2.0*x, 1.5, 0.0)/3.0; return x + amount*cupper(2.0-2.0*x, 1.5, 0.0)/3.0;
} }
// brightness curve at point x, positive negative and zero amount are supported
static inline double brightness (double x, double amount) { static inline double brightness (double x, double amount) {
if (amount==0) if (amount==0)
return x; return x;
@ -113,34 +98,60 @@ class CurveFactory {
else else
return 1.0 - brightnessbase (1.0-x, -amount); return 1.0 - brightnessbase (1.0-x, -amount);
} }
public: public:
static inline double softClip (double x, double d1, double d2, double a, double b, double c, double d); static void init ();
static inline double contrast (double x, double a);
static inline double centercontrast (double x, double b, double m); static inline double centercontrast (double x, double b, double m);
static inline double brightness (double x, double a, double bd1, double bd2);
static inline double gamma (double x, double gamma, double start, double slope, double mul, double add){ // standard srgb gamma and its inverse
return (x <= start ? x*slope : exp(log(x)/gamma)*mul-add);
}
static inline double gamma2 (double x) { static inline double gamma2 (double x) {
return x <= 0.00304 ? x*12.92 : 1.055*exp(log(x)/2.4)-0.055; return x <= 0.00304 ? x*12.92 : 1.055*exp(log(x)/2.4)-0.055;
} }
static inline int gamma_srgb (int x) { return gammatab_srgb[x]; }
static inline int gamma (int x) { return gammatab[x]; }
static inline int igamma_srgb (int x) { return igammatab_srgb[x]; }
static inline double igamma2 (double x) { static inline double igamma2 (double x) {
return x <= 0.03928 ? x/12.92 : exp(log((x+0.055)/1.055)*2.4); return x <= 0.03928 ? x/12.92 : exp(log((x+0.055)/1.055)*2.4);
} }
static inline double levels (double x, double b_lower, double b_upper, double m, double cmax); // gamma function with adjustable parameters
static inline double gamma (double x, double gamma, double start, double slope, double mul, double add){
return (x <= start ? x*slope : exp(log(x)/gamma)*mul-add);
}
// gamma functions on [0,65535] based on look-up tables
static inline int gamma_srgb (int x) { return gammatab_srgb[x]; }
static inline int gamma (int x) { return gammatab[x]; }
static inline int igamma_srgb (int x) { return igammatab_srgb[x]; }
public: public:
static void loadCurves (Glib::ustring fname); // static void updateCurve3 (int* curve, int* ohistogram, const std::vector<double>& cpoints, double defmul, double ecomp, int black, double hlcompr, double shcompr, double br, double contr, double gamma_, bool igamma, int skip=1);
static void updateCurve2 (int* curve, int* ohistogram, const std::vector<double>& cpoints, double ecomp, double br, int black, double hlcompr, double shcompr, double contr, double gamma_, bool igamma, int skip=1); static void complexCurve (double ecomp, double black, double hlcompr, double shcompr, double br, double contr, double defmul, double gamma_, bool igamma, const std::vector<double>& curvePoints, unsigned int* histogram, int* outCurve, unsigned int* outBeforeCCurveHistogram, int skip=1);
static void updateCurve3 (int* curve, int* ohistogram, const std::vector<double>& cpoints, double defmul, double ecomp, int black, double hlcompr, double shcompr, double br, double contr, double gamma_, bool igamma, int skip=1);
static std::vector<Glib::ustring> curveNames (); };
class Curve {
protected:
int N;
double* x;
double* y;
double* ypp;
int kind; // = -1: linear interp., 0: empty, 1: spline interp., 2: parametric
protected:
void spline_cubic_set ();
static inline double p00 (double x, double prot) { return CurveFactory::clower (x, 2.0, prot); }
static inline double p11 (double x, double prot) { return CurveFactory::cupper (x, 2.0, prot); }
static inline double p01 (double x, double prot) { return x<=0.5 ? CurveFactory::clower (x*2, 2.0, prot)/2.0 : 0.5 + CurveFactory::cupper ((x-0.5)*2, 2.0, prot)/2.0; }
static inline double p10 (double x, double prot) { return x<=0.5 ? CurveFactory::cupper (x*2, 2.0, prot)/2.0 : 0.5 + CurveFactory::clower ((x-0.5)*2, 2.0, prot)/2.0; }
static inline double pfull (double x, double prot, double sh, double hl) { return (1-sh)*(1-hl)*p00(x,prot) + sh*hl*p11(x,prot) + (1-sh)*hl*p01(x,prot) + sh*(1-hl)*p10(x,prot); }
public:
Curve (const std::vector<double>& points);
~Curve ();
double getVal (double x);
void getVal (const std::vector<double>& t, std::vector<double>& res);
}; };
}; };

View File

@ -9258,7 +9258,7 @@ t4.set ();
// generate histogram for auto exposure // generate histogram for auto exposure
tpp->aeHistCompression = 3; tpp->aeHistCompression = 3;
tpp->aeHistogram = new int[65536>>tpp->aeHistCompression]; tpp->aeHistogram = new unsigned int[65536>>tpp->aeHistCompression];
memset (tpp->aeHistogram, 0, (65536>>tpp->aeHistCompression)*sizeof(int)); memset (tpp->aeHistogram, 0, (65536>>tpp->aeHistCompression)*sizeof(int));
int radd = 4; int radd = 4;
int gadd = 2; int gadd = 2;

View File

@ -83,7 +83,7 @@ class ImageSource : public InitialImage {
void increaseRef () { references++; } void increaseRef () { references++; }
void decreaseRef () { references--; if (!references) delete this; } void decreaseRef () { references--; if (!references) delete this; }
virtual int getAEHistogram (int* histogram, int& histcompr) {return 0;} virtual int getAEHistogram (unsigned int* histogram, int& histcompr) {return 0;}
// functions inherited from the InitialImage interface // functions inherited from the InitialImage interface
virtual Glib::ustring getFileName () { return fileName; } virtual Glib::ustring getFileName () { return fileName; }

View File

@ -154,7 +154,7 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
if (todo & M_AUTOEXP) { if (todo & M_AUTOEXP) {
if (params.toneCurve.autoexp) { if (params.toneCurve.autoexp) {
int aehist[65536]; int aehistcompr; unsigned int aehist[65536]; int aehistcompr;
imgsrc->getAEHistogram (aehist, aehistcompr); imgsrc->getAEHistogram (aehist, aehistcompr);
ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, params.toneCurve.expcomp, params.toneCurve.black); ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, params.toneCurve.expcomp, params.toneCurve.black);
if (aeListener) if (aeListener)
@ -163,7 +163,7 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
} }
progress ("Exposure curve & CIELAB conversion...",100*readyphase/numofphases); progress ("Exposure curve & CIELAB conversion...",100*readyphase/numofphases);
if (todo & M_RGBCURVE) { if (todo & M_RGBCURVE) {
CurveFactory::updateCurve3 (tonecurve, vhist16, params.toneCurve.curve, imgsrc->getDefGain(), params.toneCurve.expcomp, params.toneCurve.black, params.toneCurve.hlcompr, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, imgsrc->getGamma(), true); CurveFactory::complexCurve (params.toneCurve.expcomp, params.toneCurve.black/65535.0, params.toneCurve.hlcompr, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, imgsrc->getDefGain(), imgsrc->getGamma(), true, params.toneCurve.curve, vhist16, tonecurve, bcrgbhist, scale==1 ? 1 : 1);
ipf.rgbProc (oprevi, oprevl, &params, tonecurve, shmap); ipf.rgbProc (oprevi, oprevl, &params, tonecurve, shmap);
// recompute luminance histogram // recompute luminance histogram
@ -177,7 +177,7 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
readyphase++; readyphase++;
if (todo & M_LUMACURVE) { if (todo & M_LUMACURVE) {
CurveFactory::updateCurve2 (lumacurve, lhist16, params.lumaCurve.curve, 0, params.lumaCurve.brightness, params.lumaCurve.black, params.lumaCurve.hlcompr, params.lumaCurve.shcompr, params.lumaCurve.contrast, 0.0, false); CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, params.lumaCurve.brightness, params.lumaCurve.contrast, 0.0, 0.0, false, params.lumaCurve.curve, lhist16, lumacurve, bcLhist, scale==1 ? 1 : 16);
} }
if (todo & M_LUMINANCE) { if (todo & M_LUMINANCE) {
@ -246,7 +246,7 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
hy2 = MIN(pH,MAX(0,(params.crop.y+params.crop.h) / scale)); hy2 = MIN(pH,MAX(0,(params.crop.y+params.crop.h) / scale));
} }
updateHistograms (hx1, hy1, hx2, hy2); updateHistograms (hx1, hy1, hx2, hy2);
hListener->histogramChanged (rhist, ghist, bhist, Lhist); hListener->histogramChanged (rhist, ghist, bhist, Lhist, bcrgbhist, bcLhist);
} }
t9.set (); t9.set ();

View File

@ -64,10 +64,10 @@ class ImProcCoordinator : public StagedImageProcessor {
int tonecurve [65536]; int tonecurve [65536];
int lumacurve [65536]; int lumacurve [65536];
int vhist16[65536]; unsigned int vhist16[65536];
int lhist16[65536]; unsigned int lhist16[65536];
unsigned int rhist[256], ghist[256], bhist[256], Lhist[256]; unsigned int rhist[256], ghist[256], bhist[256], Lhist[256], bcrgbhist[256], bcLhist[256];
int fw, fh, tr, fullw, fullh; int fw, fh, tr, fullw, fullh;
int pW, pH; int pW, pH;

View File

@ -187,7 +187,7 @@ void ImProcFunctions::release () {
monitorTransform = NULL; monitorTransform = NULL;
} }
void ImProcFunctions::firstAnalysis_ (Image16* original, Glib::ustring wprofile, int* histogram, int* chroma_radius, int row_from, int row_to) { void ImProcFunctions::firstAnalysis_ (Image16* original, Glib::ustring wprofile, unsigned int* histogram, int* chroma_radius, int row_from, int row_to) {
TMatrix wprof = iccStore.workingSpaceMatrix (wprofile); TMatrix wprof = iccStore.workingSpaceMatrix (wprofile);
int toxyz[3][3]; int toxyz[3][3];
@ -242,11 +242,11 @@ void ImProcFunctions::firstAnalysis_ (Image16* original, Glib::ustring wprofile,
*chroma_radius = cradius; *chroma_radius = cradius;
} }
void ImProcFunctions::firstAnalysis (Image16* original, const ProcParams* params, int* histogram, double gamma) { void ImProcFunctions::firstAnalysis (Image16* original, const ProcParams* params, unsigned int* histogram, double gamma) {
int cr1, cr2; int cr1, cr2;
int* hist1 = new int[65536]; memset (hist1, 0, 65536*sizeof(int)); unsigned int* hist1 = new unsigned int[65536]; memset (hist1, 0, 65536*sizeof(int));
int* hist2 = new int[65536]; memset (hist2, 0, 65536*sizeof(int)); unsigned int* hist2 = new unsigned int[65536]; memset (hist2, 0, 65536*sizeof(int));
int H = original->height; int H = original->height;
@ -366,8 +366,6 @@ void ImProcFunctions::rgbProc_ (Image16* working, LabImage* lab, const ProcParam
b = CLIP((int)(factor*b-sub)); b = CLIP((int)(factor*b-sub));
} }
else { else {
if (i==100 && j==3500)
printf ("r=%d, %d, fact=%g, mapval=%d, %d\n", r, (int)(factor*r), factor, mapval, shmap->map[i][j]);
r = CLIP((int)(factor*r)); r = CLIP((int)(factor*r));
g = CLIP((int)(factor*g)); g = CLIP((int)(factor*g));
b = CLIP((int)(factor*b)); b = CLIP((int)(factor*b));
@ -2020,7 +2018,7 @@ void ImProcFunctions::resize_ (Image16* src, Image16* dst, ResizeParams params,
} }
} }
void ImProcFunctions::getAutoExp (int* histogram, int histcompr, double expcomp, double clip, double& br, int& bl) { void ImProcFunctions::getAutoExp (unsigned int* histogram, int histcompr, double expcomp, double clip, double& br, int& bl) {
double sum = 0; double sum = 0;
for (int i=0; i<65536>>histcompr; i++) for (int i=0; i<65536>>histcompr; i++)

View File

@ -60,7 +60,7 @@ class ImProcFunctions {
void lab2rgb_ (LabImage* lab, Image8* image, int row_from, int row_to); void lab2rgb_ (LabImage* lab, Image8* image, int row_from, int row_to);
void colorCurve_ (LabImage* lold, LabImage* lnew, const ProcParams* params, int row_from, int row_to, double* cmultiplier); void colorCurve_ (LabImage* lold, LabImage* lnew, const ProcParams* params, int row_from, int row_to, double* cmultiplier);
void sharpenHaloCtrl (LabImage* lab, const ProcParams* params, unsigned short** blurmap, unsigned short** base, int W, int row_from, int row_to); void sharpenHaloCtrl (LabImage* lab, const ProcParams* params, unsigned short** blurmap, unsigned short** base, int W, int row_from, int row_to);
void firstAnalysis_ (Image16* original, Glib::ustring wprofile, int* histogram, int* chroma_radius, int row_from, int row_to); void firstAnalysis_ (Image16* original, Glib::ustring wprofile, unsigned int* histogram, int* chroma_radius, int row_from, int row_to);
void resize_ (Image16* src, Image16* dst, ResizeParams params, int row_from, int row_to); void resize_ (Image16* src, Image16* dst, ResizeParams params, int row_from, int row_to);
void damping_ (float** aI, unsigned short** aO, float damping, int W, int rowfrom, int rowto); void damping_ (float** aI, unsigned short** aO, float damping, int W, int rowfrom, int rowto);
@ -86,7 +86,7 @@ class ImProcFunctions {
void release (); void release ();
void firstAnalysis (Image16* working, const ProcParams* params, int* vhist16, double gamma); void firstAnalysis (Image16* working, const ProcParams* params, unsigned int* vhist16, double gamma);
void rgbProc (Image16* working, LabImage* lab, const ProcParams* params, int* tonecurve, SHMap* shmap); void rgbProc (Image16* working, LabImage* lab, const ProcParams* params, int* tonecurve, SHMap* shmap);
void luminanceCurve (LabImage* lold, LabImage* lnew, int* curve, int row_from, int row_to); void luminanceCurve (LabImage* lold, LabImage* lnew, int* curve, int row_from, int row_to);
@ -107,7 +107,7 @@ class ImProcFunctions {
Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile); Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile);
Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile); Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile);
static void getAutoExp (int* histogram, int histcompr, double expcomp, double clip, double& br, int& bl); static void getAutoExp (unsigned int* histogram, int histcompr, double expcomp, double clip, double& br, int& bl);
}; };
}; };
#endif #endif

View File

@ -33,7 +33,7 @@ int init (const Settings* s) {
settings = s; settings = s;
iccStore.parseDir (s->iccDirectory); iccStore.parseDir (s->iccDirectory);
CurveFactory::loadCurves (""); CurveFactory::init ();
ImProcFunctions::initCache (); ImProcFunctions::initCache ();
delete dcrMutex; delete dcrMutex;
dcrMutex = new Glib::Mutex; dcrMutex = new Glib::Mutex;

View File

@ -28,7 +28,6 @@ namespace procparams {
ProcParams::ProcParams () { ProcParams::ProcParams () {
setDefaults (); setDefaults ();
} }
ProcParams* ProcParams::create () { ProcParams* ProcParams::create () {
@ -55,9 +54,6 @@ void ProcParams::setDefaults () {
lumaCurve.brightness = 0; lumaCurve.brightness = 0;
lumaCurve.contrast = 0; lumaCurve.contrast = 0;
lumaCurve.black = 0;
lumaCurve.hlcompr = 0;
lumaCurve.shcompr = 0;
lumaCurve.curve.clear (); lumaCurve.curve.clear ();
sharpening.enabled = true; sharpening.enabled = true;
@ -170,7 +166,7 @@ int ProcParams::save (Glib::ustring fname) const {
keyFile.set_boolean ("Exposure", "Auto", toneCurve.autoexp); keyFile.set_boolean ("Exposure", "Auto", toneCurve.autoexp);
keyFile.set_double ("Exposure", "Clip", toneCurve.clip); keyFile.set_double ("Exposure", "Clip", toneCurve.clip);
keyFile.set_double ("Exposure", "Compensation", toneCurve.expcomp); keyFile.set_double ("Exposure", "Compensation", toneCurve.expcomp);
keyFile.set_double ("Exposure", "Brightness", toneCurve.brightness); keyFile.set_integer ("Exposure", "Brightness", toneCurve.brightness);
keyFile.set_integer ("Exposure", "Contrast", toneCurve.contrast); keyFile.set_integer ("Exposure", "Contrast", toneCurve.contrast);
keyFile.set_integer ("Exposure", "Black", toneCurve.black); keyFile.set_integer ("Exposure", "Black", toneCurve.black);
keyFile.set_integer ("Exposure", "HighlightCompr", toneCurve.hlcompr); keyFile.set_integer ("Exposure", "HighlightCompr", toneCurve.hlcompr);
@ -187,11 +183,8 @@ int ProcParams::save (Glib::ustring fname) const {
keyFile.set_integer_list("Channel Mixer", "Blue", bmix); keyFile.set_integer_list("Channel Mixer", "Blue", bmix);
// save luma curve // save luma curve
keyFile.set_double ("Luminance Curve", "Brightness", lumaCurve.brightness); keyFile.set_integer ("Luminance Curve", "Brightness", lumaCurve.brightness);
keyFile.set_integer ("Luminance Curve", "Contrast", lumaCurve.contrast); keyFile.set_integer ("Luminance Curve", "Contrast", lumaCurve.contrast);
keyFile.set_integer ("Luminance Curve", "Black", lumaCurve.black);
keyFile.set_integer ("Luminance Curve", "HighlightCompr", lumaCurve.hlcompr);
keyFile.set_integer ("Luminance Curve", "ShadowCompr", lumaCurve.shcompr);
Glib::ArrayHandle<double> lcurve = lumaCurve.curve; Glib::ArrayHandle<double> lcurve = lumaCurve.curve;
keyFile.set_double_list("Luminance Curve", "Curve", lcurve); keyFile.set_double_list("Luminance Curve", "Curve", lcurve);
@ -346,7 +339,7 @@ if (keyFile.has_group ("Exposure")) {
if (keyFile.has_key ("Exposure", "Auto")) toneCurve.autoexp = keyFile.get_boolean ("Exposure", "Auto"); if (keyFile.has_key ("Exposure", "Auto")) toneCurve.autoexp = keyFile.get_boolean ("Exposure", "Auto");
if (keyFile.has_key ("Exposure", "Clip")) toneCurve.clip = keyFile.get_double ("Exposure", "Clip"); if (keyFile.has_key ("Exposure", "Clip")) toneCurve.clip = keyFile.get_double ("Exposure", "Clip");
if (keyFile.has_key ("Exposure", "Compensation")) toneCurve.expcomp = keyFile.get_double ("Exposure", "Compensation"); if (keyFile.has_key ("Exposure", "Compensation")) toneCurve.expcomp = keyFile.get_double ("Exposure", "Compensation");
if (keyFile.has_key ("Exposure", "Brightness")) toneCurve.brightness = keyFile.get_double ("Exposure", "Brightness"); if (keyFile.has_key ("Exposure", "Brightness")) toneCurve.brightness = keyFile.get_integer ("Exposure", "Brightness");
if (keyFile.has_key ("Exposure", "Contrast")) toneCurve.contrast = keyFile.get_integer ("Exposure", "Contrast"); if (keyFile.has_key ("Exposure", "Contrast")) toneCurve.contrast = keyFile.get_integer ("Exposure", "Contrast");
if (keyFile.has_key ("Exposure", "Black")) toneCurve.black = keyFile.get_integer ("Exposure", "Black"); if (keyFile.has_key ("Exposure", "Black")) toneCurve.black = keyFile.get_integer ("Exposure", "Black");
if (keyFile.has_key ("Exposure", "HighlightCompr")) toneCurve.hlcompr = keyFile.get_integer ("Exposure", "HighlightCompr"); if (keyFile.has_key ("Exposure", "HighlightCompr")) toneCurve.hlcompr = keyFile.get_integer ("Exposure", "HighlightCompr");
@ -369,13 +362,10 @@ if (keyFile.has_group ("Channel Mixer")) {
// load luma curve // load luma curve
if (keyFile.has_group ("Luminance Curve")) { if (keyFile.has_group ("Luminance Curve")) {
if (keyFile.has_key ("Luminance Curve", "Brightness")) lumaCurve.brightness = keyFile.get_double ("Luminance Curve", "Brightness"); if (keyFile.has_key ("Luminance Curve", "Brightness")) lumaCurve.brightness = keyFile.get_integer ("Luminance Curve", "Brightness");
if (keyFile.has_key ("Luminance Curve", "Contrast")) lumaCurve.contrast = keyFile.get_integer ("Luminance Curve", "Contrast"); if (keyFile.has_key ("Luminance Curve", "Contrast")) lumaCurve.contrast = keyFile.get_integer ("Luminance Curve", "Contrast");
if (keyFile.has_key ("Luminance Curve", "Black")) lumaCurve.black = keyFile.get_integer ("Luminance Curve", "Black");
if (keyFile.has_key ("Luminance Curve", "HighlightCompr")) lumaCurve.hlcompr = keyFile.get_integer ("Luminance Curve", "HighlightCompr");
if (keyFile.has_key ("Luminance Curve", "ShadowCompr")) lumaCurve.shcompr = keyFile.get_integer ("Luminance Curve", "ShadowCompr");
if (version>200) if (version>200)
if (keyFile.has_key ("Luminance Curve", "Curve")) lumaCurve.curve = keyFile.get_double_list ("Luminance Curve", "Curve"); if (keyFile.has_key ("Luminance Curve", "Curve")) lumaCurve.curve = keyFile.get_double_list ("Luminance Curve", "Curve");
} }
// load sharpening // load sharpening
@ -569,10 +559,7 @@ bool ProcParams::operator== (const ProcParams& other) {
&& toneCurve.expcomp == other.toneCurve.expcomp && toneCurve.expcomp == other.toneCurve.expcomp
&& lumaCurve.curve == other.lumaCurve.curve && lumaCurve.curve == other.lumaCurve.curve
&& lumaCurve.brightness == other.lumaCurve.brightness && lumaCurve.brightness == other.lumaCurve.brightness
&& lumaCurve.black == other.lumaCurve.black
&& lumaCurve.contrast == other.lumaCurve.contrast && lumaCurve.contrast == other.lumaCurve.contrast
&& lumaCurve.shcompr == other.lumaCurve.shcompr
&& lumaCurve.hlcompr == other.lumaCurve.hlcompr
&& sharpening.enabled == other.sharpening.enabled && sharpening.enabled == other.sharpening.enabled
&& sharpening.radius == other.sharpening.radius && sharpening.radius == other.sharpening.radius
&& sharpening.amount == other.sharpening.amount && sharpening.amount == other.sharpening.amount

View File

@ -26,28 +26,31 @@ namespace rtengine {
namespace procparams { namespace procparams {
/** /**
* Common parameters of the tone curve and the luminance curve * Parameters of the tone curve
*/ */
class CurveParams { class ToneCurveParams {
public:
std::vector<double> curve;
double brightness;
int black;
int contrast;
int shcompr;
int hlcompr;
};
/**
* Additional parameters of the tone curve (auto exposure related parameters)
*/
class ToneCurveParams : public CurveParams {
public: public:
bool autoexp; bool autoexp;
double clip; double clip;
double expcomp; double expcomp;
std::vector<double> curve;
int brightness;
int black;
int contrast;
int shcompr;
int hlcompr;
};
/**
* Parameters of the luminance curve
*/
class LCurveParams {
public:
std::vector<double> curve;
int brightness;
int contrast;
}; };
/** /**
@ -287,7 +290,7 @@ class ProcParams {
public: public:
ToneCurveParams toneCurve; ///< Tone curve parameters ToneCurveParams toneCurve; ///< Tone curve parameters
CurveParams lumaCurve; ///< CIELAB luminance curve parameters LCurveParams lumaCurve; ///< CIELAB luminance curve parameters
SharpeningParams sharpening; ///< Sharpening parameters SharpeningParams sharpening; ///< Sharpening parameters
ColorBoostParams colorBoost; ///< Color boost parameters ColorBoostParams colorBoost; ///< Color boost parameters
WBParams wb; ///< White balance parameters WBParams wb; ///< White balance parameters

View File

@ -1925,7 +1925,7 @@ void RawImageSource::hlRecovery (std::string method, unsigned short* red, unsign
HLRecovery_ColorPropagation (red, green, blue, i, sx1, width, skip); HLRecovery_ColorPropagation (red, green, blue, i, sx1, width, skip);
} }
int RawImageSource::getAEHistogram (int* histogram, int& histcompr) { int RawImageSource::getAEHistogram (unsigned int* histogram, int& histcompr) {
histcompr = 3; histcompr = 3;

View File

@ -112,7 +112,7 @@ class RawImageSource : public ImageSource {
ImageData* getImageData () { return idata; } ImageData* getImageData () { return idata; }
void setProgressListener (ProgressListener* pl) { plistener = pl; } void setProgressListener (ProgressListener* pl) { plistener = pl; }
int getAEHistogram (int* histogram, int& histcompr); int getAEHistogram (unsigned int* histogram, int& histcompr);
static void colorSpaceConversion (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], double& defgain); static void colorSpaceConversion (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], double& defgain);
static void inverse33 (double (*coeff)[3], double (*icoeff)[3]); static void inverse33 (double (*coeff)[3], double (*icoeff)[3]);

View File

@ -201,7 +201,7 @@ namespace rtengine {
* @param greenh is the array of size 256 containing the histogram of the green channel * @param greenh is the array of size 256 containing the histogram of the green channel
* @param blueh is the array of size 256 containing the histogram of the blue channel * @param blueh is the array of size 256 containing the histogram of the blue channel
* @param lumah is the array of size 256 containing the histogram of the luminance channel */ * @param lumah is the array of size 256 containing the histogram of the luminance channel */
virtual void histogramChanged (unsigned int* redh, unsigned int* greenh, unsigned int* blueh, unsigned int* lumah) {} virtual void histogramChanged (unsigned int* redh, unsigned int* greenh, unsigned int* blueh, unsigned int* lumah, unsigned int* bcrgbhist, unsigned int* bcLhist) {}
}; };
/** This listener is used when the auto exposure has been recomputed (e.g. when the clipping ratio changed). */ /** This listener is used when the auto exposure has been recomputed (e.g. when the clipping ratio changed). */

View File

@ -100,7 +100,7 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
// histogram computation // histogram computation
tpp->aeHistCompression = 3; tpp->aeHistCompression = 3;
tpp->aeHistogram = new int[65536>>tpp->aeHistCompression]; tpp->aeHistogram = new unsigned int[65536>>tpp->aeHistCompression];
memset (tpp->aeHistogram, 0, (65536>>tpp->aeHistCompression)*sizeof(int)); memset (tpp->aeHistogram, 0, (65536>>tpp->aeHistCompression)*sizeof(int));
int ix = 0; int ix = 0;
for (int i=0; i<img->height*img->width; i++) { for (int i=0; i<img->height*img->width; i++) {
@ -197,7 +197,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
logDefGain = 0.0; logDefGain = 0.0;
rmi = 1024.0 * rm * defGain / mul_lum; rmi = 1024.0 * rm * defGain / mul_lum;
gmi = 1024.0 * gm * defGain / mul_lum; gmi = 1024.0 * gm * defGain / mul_lum;
bmi = 1024.0 * bm * defGain / mul_lum; bmi = 1024.0 * bm * defGain / mul_lum;
} }
else { else {
rmi = 1024.0 * rm / mul_lum; rmi = 1024.0 * rm / mul_lum;
@ -213,7 +213,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
else else
rwidth = thumbImg->width * rheight / thumbImg->height; rwidth = thumbImg->width * rheight / thumbImg->height;
Image16* baseImg = thumbImg->resize (rwidth, rheight, interp); Image16* baseImg = thumbImg->resize (rwidth, rheight, interp);
if (params.coarse.rotate) { if (params.coarse.rotate) {
Image16* tmp = baseImg->rotate (params.coarse.rotate); Image16* tmp = baseImg->rotate (params.coarse.rotate);
@ -268,7 +268,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
int fh = baseImg->height; int fh = baseImg->height;
ImProcFunctions ipf; ImProcFunctions ipf;
int* hist16 = new int [65536]; unsigned int* hist16 = new unsigned int [65536];
ipf.firstAnalysis (baseImg, &params, hist16, isRaw ? 2.2 : 0.0); ipf.firstAnalysis (baseImg, &params, hist16, isRaw ? 2.2 : 0.0);
// perform transform // perform transform
@ -316,7 +316,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
ipf.getAutoExp (aeHistogram, aeHistCompression, logDefGain, params.toneCurve.clip, br, bl); ipf.getAutoExp (aeHistogram, aeHistCompression, logDefGain, params.toneCurve.clip, br, bl);
int* curve = new int [65536]; int* curve = new int [65536];
CurveFactory::updateCurve3 (curve, hist16, params.toneCurve.curve, logDefGain, br, bl, params.toneCurve.hlcompr, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, isRaw ? 2.2 : 0, true); CurveFactory::complexCurve (br, bl/65535.0, params.toneCurve.hlcompr, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, logDefGain, isRaw ? 2.2 : 0, true, params.toneCurve.curve, hist16, curve, NULL, 16);
LabImage* labView = new LabImage (baseImg); LabImage* labView = new LabImage (baseImg);
ipf.rgbProc (baseImg, labView, &params, curve, shmap); ipf.rgbProc (baseImg, labView, &params, curve, shmap);
@ -331,7 +331,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
hist16[labView->L[i][j]]++; hist16[labView->L[i][j]]++;
// luminance processing // luminance processing
CurveFactory::updateCurve2 (curve, hist16, params.lumaCurve.curve, 0, params.lumaCurve.brightness, params.lumaCurve.black, params.lumaCurve.hlcompr, params.lumaCurve.shcompr, params.lumaCurve.contrast, 0.0, false); CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, params.lumaCurve.brightness, params.lumaCurve.contrast, 0.0, 0.0, false, params.lumaCurve.curve, hist16, curve, NULL, 16);
ipf.luminanceCurve (labView, labView, curve, 0, fh); ipf.luminanceCurve (labView, labView, curve, 0, fh);
delete [] curve; delete [] curve;
@ -866,7 +867,7 @@ bool Thumbnail::readAEHistogram (const Glib::ustring& fname) {
if (!f) if (!f)
aeHistogram = NULL; aeHistogram = NULL;
else { else {
aeHistogram = new int[65536>>aeHistCompression]; aeHistogram = new unsigned int[65536>>aeHistCompression];
fread (aeHistogram, 1, (65536>>aeHistCompression)*sizeof(int), f); fread (aeHistogram, 1, (65536>>aeHistCompression)*sizeof(int), f);
fclose (f); fclose (f);
return true; return true;

View File

@ -46,7 +46,7 @@ namespace rtengine {
double camwbBlue; double camwbBlue;
double autowbTemp; double autowbTemp;
double autowbGreen; double autowbGreen;
int* aeHistogram; unsigned int* aeHistogram;
int aeHistCompression; int aeHistCompression;
int embProfileLength; int embProfileLength;
unsigned char* embProfileData; unsigned char* embProfileData;

View File

@ -88,7 +88,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
pl->setProgress (0.25); pl->setProgress (0.25);
// perform first analysis // perform first analysis
int* hist16 = new int[65536]; unsigned int* hist16 = new unsigned int[65536];
ipf.firstAnalysis (baseImg, &params, hist16, imgsrc->getGamma()); ipf.firstAnalysis (baseImg, &params, hist16, imgsrc->getGamma());
// perform transform // perform transform
@ -126,13 +126,14 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
int bl = params.toneCurve.black; int bl = params.toneCurve.black;
if (params.toneCurve.autoexp) { if (params.toneCurve.autoexp) {
int aehist[65536]; int aehistcompr; unsigned int aehist[65536]; int aehistcompr;
imgsrc->getAEHistogram (aehist, aehistcompr); imgsrc->getAEHistogram (aehist, aehistcompr);
ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, br, bl); ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, br, bl);
} }
int* curve = new int [65536]; int* curve = new int [65536];
CurveFactory::updateCurve3 (curve, hist16, params.toneCurve.curve, imgsrc->getDefGain(), br, bl, params.toneCurve.hlcompr, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, imgsrc->getGamma(), true);
CurveFactory::complexCurve (br, bl/65535.0, params.toneCurve.hlcompr, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, imgsrc->getDefGain(), imgsrc->getGamma(), true, params.toneCurve.curve, hist16, curve, NULL);
LabImage* labView = new LabImage (baseImg); LabImage* labView = new LabImage (baseImg);
ipf.rgbProc (baseImg, labView, &params, curve, shmap); ipf.rgbProc (baseImg, labView, &params, curve, shmap);
@ -150,7 +151,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
hist16[labView->L[i][j]]++; hist16[labView->L[i][j]]++;
// luminance processing // luminance processing
CurveFactory::updateCurve2 (curve, hist16, params.lumaCurve.curve, 0, params.lumaCurve.brightness, params.lumaCurve.black, params.lumaCurve.hlcompr, params.lumaCurve.shcompr, params.lumaCurve.contrast, 0.0, false); CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, params.lumaCurve.brightness, params.lumaCurve.contrast, 0.0, 0.0, false, params.lumaCurve.curve, hist16, curve, NULL);
ipf.luminanceCurve (labView, labView, curve, 0, fh); ipf.luminanceCurve (labView, labView, curve, 0, fh);
ipf.lumadenoise (labView, &params, 1, buffer); ipf.lumadenoise (labView, &params, 1, buffer);
ipf.sharpening (labView, &params, 1, (unsigned short**)buffer); ipf.sharpening (labView, &params, 1, (unsigned short**)buffer);

View File

@ -443,7 +443,7 @@ void StdImageSource::hlRecovery (unsigned short* red, unsigned short* green, uns
rtengine::hlRecovery (red, green, blue, img->height, img->width, i, sx1, sx2, skip, needhr, hrmap); rtengine::hlRecovery (red, green, blue, img->height, img->width, i, sx1, sx2, skip, needhr, hrmap);
} }
*/ */
int StdImageSource::getAEHistogram (int* histogram, int& histcompr) { int StdImageSource::getAEHistogram (unsigned int* histogram, int& histcompr) {
histcompr = 3; histcompr = 3;

View File

@ -49,7 +49,7 @@ class StdImageSource : public ImageSource {
ColorTemp getAutoWB (); ColorTemp getAutoWB ();
ColorTemp getSpotWB (std::vector<Coord2D> red, std::vector<Coord2D> green, std::vector<Coord2D>& blue, int tran); ColorTemp getSpotWB (std::vector<Coord2D> red, std::vector<Coord2D> green, std::vector<Coord2D>& blue, int tran);
int getAEHistogram (int* histogram, int& histcompr); int getAEHistogram (unsigned int* histogram, int& histcompr);
double getDefGain () { return 0.0; } double getDefGain () { return 0.0; }
double getGamma () { return 0.0; } double getGamma () { return 0.0; }

View File

@ -12,7 +12,7 @@ SET (BASESOURCEFILES
batchtoolpanelcoord.cc paramsedited.cc cropwindow.cc previewhandler.cc previewwindow.cc navigator.cc indclippedpanel.cc filterpanel.cc batchtoolpanelcoord.cc paramsedited.cc cropwindow.cc previewhandler.cc previewwindow.cc navigator.cc indclippedpanel.cc filterpanel.cc
cursormanager.cc rtwindow.cc renamedlg.cc recentbrowser.cc placesbrowser.cc filepanel.cc editorpanel.cc batchqueuepanel.cc cursormanager.cc rtwindow.cc renamedlg.cc recentbrowser.cc placesbrowser.cc filepanel.cc editorpanel.cc batchqueuepanel.cc
ilabel.cc thumbbrowserbase.cc adjuster.cc filebrowserentry.cc filebrowser.cc filethumbnailbuttonset.cc ilabel.cc thumbbrowserbase.cc adjuster.cc filebrowserentry.cc filebrowser.cc filethumbnailbuttonset.cc
cachemanager.cc cacheimagedata.cc cachemanager.cc cacheimagedata.cc shcselector.cc
clipboard.cc thumbimageupdater.cc bqentryupdater.cc clipboard.cc thumbimageupdater.cc bqentryupdater.cc
coarsepanel.cc cacorrection.cc colorshift.cc hlrec.cc chmixer.cc coarsepanel.cc cacorrection.cc colorshift.cc hlrec.cc chmixer.cc
colorboost.cc resize.cc icmpanel.cc crop.cc shadowshighlights.cc colorboost.cc resize.cc icmpanel.cc crop.cc shadowshighlights.cc

28
rtgui/addsetids.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef _ADDSETIDS_
#define _ADDSETIDS_
#define ADDSET_TC_EXPCOMP 0
#define ADDSET_TC_BRIGHTNESS 1
#define ADDSET_TC_BLACKLEVEL 2
#define ADDSET_TC_CONTRAST 3
#define ADDSET_SH_HIGHLIGHTS 4
#define ADDSET_SH_SHADOWS 5
#define ADDSET_SH_LOCALCONTRAST 6
#define ADDSET_LC_BRIGHTNESS 7
#define ADDSET_LC_CONTRAST 8
#define ADDSET_SHARP_AMOUNT 9
#define ADDSET_LD_EDGETOLERANCE 10
#define ADDSET_WB_TEMPERATURE 11
#define ADDSET_WB_GREEN 12
#define ADDSET_CBOOST_AMOUNT 13
#define ADDSET_CS_BLUEYELLOW 14
#define ADDSET_CS_GREENMAGENTA 15
#define ADDSET_ROTATE_DEGREE 16
#define ADDSET_DIST_AMOUNT 17
#define ADDSET_CA_BLUE 18
#define ADDSET_CA_RED 19
#define ADDSET_VIGN_AMOUNT 20
#define ADDSET_PARAM_NUM 21
#endif

View File

@ -21,6 +21,7 @@
#include <options.h> #include <options.h>
#include <filepanel.h> #include <filepanel.h>
#include <procparamchangers.h> #include <procparamchangers.h>
#include <addsetids.h>
using namespace rtengine::procparams; using namespace rtengine::procparams;
@ -119,43 +120,47 @@ void BatchToolPanelCoordinator::initSession () {
pparams = selected[0]->getProcParams (); pparams = selected[0]->getProcParams ();
coarse->initBatchBehavior (); coarse->initBatchBehavior ();
curve->setAdjusterBehavior (options.baBehav[0], options.baBehav[1], options.baBehav[2], options.baBehav[3]); curve->setAdjusterBehavior (options.baBehav[ADDSET_TC_EXPCOMP], options.baBehav[ADDSET_TC_BRIGHTNESS], options.baBehav[ADDSET_TC_BLACKLEVEL], options.baBehav[ADDSET_TC_CONTRAST]);
whitebalance->setAdjusterBehavior (options.baBehav[12], options.baBehav[13]); lcurve->setAdjusterBehavior (options.baBehav[ADDSET_LC_BRIGHTNESS], options.baBehav[ADDSET_LC_CONTRAST]);
vignetting->setAdjusterBehavior (options.baBehav[21]); whitebalance->setAdjusterBehavior (options.baBehav[ADDSET_WB_TEMPERATURE], options.baBehav[ADDSET_WB_GREEN]);
rotate->setAdjusterBehavior (options.baBehav[17]); vignetting->setAdjusterBehavior (options.baBehav[ADDSET_VIGN_AMOUNT]);
distortion->setAdjusterBehavior (options.baBehav[18]); rotate->setAdjusterBehavior (options.baBehav[ADDSET_ROTATE_DEGREE]);
cacorrection->setAdjusterBehavior (options.baBehav[19], options.baBehav[20]); distortion->setAdjusterBehavior (options.baBehav[ADDSET_DIST_AMOUNT]);
colorshift->setAdjusterBehavior (options.baBehav[15], options.baBehav[16]); cacorrection->setAdjusterBehavior (options.baBehav[ADDSET_CA_RED], options.baBehav[ADDSET_CA_BLUE]);
colorboost->setAdjusterBehavior (options.baBehav[14]); colorshift->setAdjusterBehavior (options.baBehav[ADDSET_CS_BLUEYELLOW], options.baBehav[ADDSET_CS_GREENMAGENTA]);
lumadenoise->setAdjusterBehavior (options.baBehav[11]); colorboost->setAdjusterBehavior (options.baBehav[ADDSET_CBOOST_AMOUNT]);
sharpening->setAdjusterBehavior (options.baBehav[10]); lumadenoise->setAdjusterBehavior (options.baBehav[ADDSET_LD_EDGETOLERANCE]);
shadowshighlights->setAdjusterBehavior (options.baBehav[4], options.baBehav[5], options.baBehav[6]); sharpening->setAdjusterBehavior (options.baBehav[ADDSET_SHARP_AMOUNT]);
shadowshighlights->setAdjusterBehavior (options.baBehav[ADDSET_SH_HIGHLIGHTS], options.baBehav[ADDSET_SH_SHADOWS], options.baBehav[ADDSET_SH_LOCALCONTRAST]);
if (options.baBehav[0]) pparams.toneCurve.expcomp = 0; if (options.baBehav[ADDSET_TC_EXPCOMP]) pparams.toneCurve.expcomp = 0;
if (options.baBehav[1]) pparams.toneCurve.brightness = 0; if (options.baBehav[ADDSET_TC_BRIGHTNESS]) pparams.toneCurve.brightness = 0;
if (options.baBehav[2]) pparams.toneCurve.black = 0; if (options.baBehav[ADDSET_TC_BLACKLEVEL]) pparams.toneCurve.black = 0;
if (options.baBehav[3]) pparams.toneCurve.contrast = 0; if (options.baBehav[ADDSET_TC_CONTRAST]) pparams.toneCurve.contrast = 0;
if (options.baBehav[4]) pparams.sh.highlights = 0; if (options.baBehav[ADDSET_SH_HIGHLIGHTS]) pparams.sh.highlights = 0;
if (options.baBehav[5]) pparams.sh.shadows = 0; if (options.baBehav[ADDSET_SH_SHADOWS]) pparams.sh.shadows = 0;
if (options.baBehav[6]) pparams.sh.localcontrast = 0; if (options.baBehav[ADDSET_SH_LOCALCONTRAST]) pparams.sh.localcontrast = 0;
if (options.baBehav[ADDSET_LC_BRIGHTNESS]) pparams.lumaCurve.brightness = 0;
if (options.baBehav[ADDSET_LC_CONTRAST]) pparams.lumaCurve.contrast = 0;
if (options.baBehav[10]) pparams.sharpening.amount = 0; if (options.baBehav[ADDSET_SHARP_AMOUNT]) pparams.sharpening.amount = 0;
if (options.baBehav[11]) pparams.lumaDenoise.edgetolerance = 0; if (options.baBehav[ADDSET_LD_EDGETOLERANCE]) pparams.lumaDenoise.edgetolerance = 0;
if (options.baBehav[12]) pparams.wb.temperature = 0; if (options.baBehav[ADDSET_WB_TEMPERATURE]) pparams.wb.temperature = 0;
if (options.baBehav[13]) pparams.wb.green = 0; if (options.baBehav[ADDSET_WB_GREEN]) pparams.wb.green = 0;
if (options.baBehav[14]) pparams.colorBoost.amount = 0; if (options.baBehav[ADDSET_CBOOST_AMOUNT]) pparams.colorBoost.amount = 0;
if (options.baBehav[15]) pparams.colorShift.a = 0; if (options.baBehav[ADDSET_CS_BLUEYELLOW]) pparams.colorShift.a = 0;
if (options.baBehav[16]) pparams.colorShift.b = 0; if (options.baBehav[ADDSET_CS_GREENMAGENTA]) pparams.colorShift.b = 0;
if (options.baBehav[17]) pparams.rotate.degree = 0; if (options.baBehav[ADDSET_ROTATE_DEGREE]) pparams.rotate.degree = 0;
if (options.baBehav[18]) pparams.distortion.amount = 0; if (options.baBehav[ADDSET_DIST_AMOUNT]) pparams.distortion.amount = 0;
if (options.baBehav[19]) pparams.cacorrection.red = 0; if (options.baBehav[ADDSET_CA_RED]) pparams.cacorrection.red = 0;
if (options.baBehav[20]) pparams.cacorrection.blue = 0; if (options.baBehav[ADDSET_CA_BLUE]) pparams.cacorrection.blue = 0;
if (options.baBehav[21]) pparams.vignetting.amount = 0; if (options.baBehav[ADDSET_VIGN_AMOUNT]) pparams.vignetting.amount = 0;
for (int i=0; i<toolPanels.size(); i++) { for (int i=0; i<toolPanels.size(); i++) {
toolPanels[i]->setDefaults (&pparams, &pparamsEdited); toolPanels[i]->setDefaults (&pparams, &pparamsEdited);
@ -260,7 +265,6 @@ CropGUIListener* BatchToolPanelCoordinator::startCropEditing (Thumbnail* thm) {
if (thm) { if (thm) {
int w, h; int w, h;
thm->getFinalSize (thm->getProcParams (), w, h); thm->getFinalSize (thm->getProcParams (), w, h);
printf ("final=%d %d\n", w, h);
crop->setDimensions (w, h); crop->setDimensions (w, h);
} }
return crop; return crop;

View File

@ -19,55 +19,125 @@
#include <curveeditor.h> #include <curveeditor.h>
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <guiutils.h>
#include <multilangmgr.h> #include <multilangmgr.h>
CurveEditor::CurveEditor () { CurveEditor::CurveEditor () : cl(NULL), activeParamControl(-1), realized(false), curveTypeIx(-1) {
curve = Gtk::manage (new MyCurve ()); Gtk::HBox* tsbox = Gtk::manage (new Gtk::HBox ());
Gtk::Label* tslab = Gtk::manage (new Gtk::Label ("Type:"));
curveType = Gtk::manage (new Gtk::ComboBoxText ());
tsbox->pack_start (*tslab, Gtk::PACK_SHRINK, 8);
tsbox->pack_start (*curveType);
pack_start (*tsbox);
curveType->append_text ("Linear");
curveType->append_text ("Parametric");
curveType->append_text ("Custom");
curveType->set_active (0);
// custom curve
customCurveBox = new Gtk::VBox ();
customCurve = Gtk::manage (new MyCurve ());
Gtk::AspectFrame* af = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false)); Gtk::AspectFrame* af = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
af->add (*curve); af->add (*customCurve);
curve->set_size_request (-1, 200); customCurve->set_size_request (-1, 200);
pack_start (*af, Gtk::PACK_EXPAND_WIDGET); customCurve->setType (Spline);
customCurveBox->pack_start (*af, Gtk::PACK_EXPAND_WIDGET);
Gtk::HBox* bbox = Gtk::manage (new Gtk::HBox ()); Gtk::HBox* bbox = Gtk::manage (new Gtk::HBox ());
linear = Gtk::manage (new Gtk::Button (M("CURVEEDITOR_LINEAR")));
save = Gtk::manage (new Gtk::Button ()); save = Gtk::manage (new Gtk::Button ());
Gtk::Image* saveImg = Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)); save->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)));
saveImg->show ();
save->add (*saveImg);
load = Gtk::manage (new Gtk::Button ()); load = Gtk::manage (new Gtk::Button ());
Gtk::Image* loadImg = Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-open"), Gtk::ICON_SIZE_BUTTON)); load->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-open"), Gtk::ICON_SIZE_BUTTON)));
loadImg->show ();
load->add (*loadImg);
bbox->pack_start (*linear); bbox->pack_end (*save, Gtk::PACK_EXPAND_WIDGET, 4);
bbox->pack_end (*save, Gtk::PACK_SHRINK, 4); bbox->pack_end (*load, Gtk::PACK_EXPAND_WIDGET, 4);
bbox->pack_end (*load, Gtk::PACK_SHRINK, 4);
pack_end (*bbox, Gtk::PACK_SHRINK, 2); customCurveBox->pack_end (*bbox, Gtk::PACK_SHRINK, 2);
show_all (); customCurveBox->show_all ();
linear->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::linearPressed) );
save->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::savePressed) ); save->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::savePressed) );
load->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::loadPressed) ); load->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::loadPressed) );
linear->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLINEAR"));
save->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE")); save->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
load->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD")); load->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD"));
// parametric curve
paramCurveBox = new Gtk::VBox ();
paramCurve = Gtk::manage (new MyCurve ());
Gtk::Table* ctab = Gtk::manage (new Gtk::Table (2,1));
Gtk::AspectFrame* afp = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
afp->add (*paramCurve);
paramCurve->set_size_request (200, 200);
paramCurve->setType (Parametric);
shcSelector = Gtk::manage (new SHCSelector ());
shcSelector->set_size_request (200, 20);
ctab->attach (*afp, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
ctab->attach (*shcSelector, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, 2, 2);
Gtk::HBox* tmpb = Gtk::manage (new Gtk::HBox ());
tmpb->pack_start (*ctab, true, false);
paramCurveBox->pack_start (*tmpb, true, true);
highlights = Gtk::manage (new Adjuster ("Highlights", -100, 100, 1, 0));
lights = Gtk::manage (new Adjuster ("Lights", -100, 100, 1, 0));
darks = Gtk::manage (new Adjuster ("Darks", -100, 100, 1, 0));
shadows = Gtk::manage (new Adjuster ("Shadows", -100, 100, 1, 0));
Gtk::EventBox* evhighlights = Gtk::manage (new Gtk::EventBox ());
Gtk::EventBox* evlights = Gtk::manage (new Gtk::EventBox ());
Gtk::EventBox* evdarks = Gtk::manage (new Gtk::EventBox ());
Gtk::EventBox* evshadows = Gtk::manage (new Gtk::EventBox ());
evhighlights->add (*highlights);
evlights->add (*lights);
evdarks->add (*darks);
evshadows->add (*shadows);
paramCurveBox->pack_start (*Gtk::manage (new Gtk::HSeparator ()));
paramCurveBox->pack_start (*evhighlights);
paramCurveBox->pack_start (*evlights);
paramCurveBox->pack_start (*evdarks);
paramCurveBox->pack_start (*evshadows);
paramCurveBox->show_all ();
customCurveBox->reference ();
paramCurveBox->reference ();
customCurve->setCurveListener (this);
paramCurve->setCurveListener (this);
shcSelector->setSHCListener (this);
highlights->setAdjusterListener (this);
lights->setAdjusterListener (this);
darks->setAdjusterListener (this);
shadows->setAdjusterListener (this);
evhighlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
evlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
evdarks->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
evshadows->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
typeconn = curveType->signal_changed().connect (sigc::mem_fun(*this, &CurveEditor::typeSelectionChanged) );
evhighlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterEntered), 4));
evlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterEntered), 5));
evdarks->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterEntered), 6));
evshadows->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterEntered), 7));
evhighlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterLeft), 4));
evlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterLeft), 5));
evdarks->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterLeft), 6));
evshadows->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterLeft), 7));
show_all ();
} }
void CurveEditor::linearPressed () { CurveEditor::~CurveEditor () {
std::vector<double> lcurve (5); delete customCurveBox;
lcurve[0] = 1.0; delete paramCurveBox;
lcurve[1] = 0.0;
lcurve[2] = 0.0;
lcurve[3] = 1.0;
lcurve[4] = 1.0;
curve->setPoints (lcurve);
curve->queue_draw ();
curve->notifyListener ();
} }
void CurveEditor::savePressed () { void CurveEditor::savePressed () {
@ -99,18 +169,7 @@ void CurveEditor::savePressed () {
std::string fname = dialog.get_filename(); std::string fname = dialog.get_filename();
bool hasext = true; if (getExtension (fname)!="rtc")
int dotpos = fname.find_last_of ('.');
if (dotpos==Glib::ustring::npos)
hasext = false;
int dirpos1 = fname.find_last_of ('/');
if (dirpos1!=Glib::ustring::npos || dirpos1>dotpos)
hasext = false;
int dirpos2 = fname.find_last_of ('\\');
if (dirpos2!=Glib::ustring::npos || dirpos2>dotpos)
hasext = false;
if (!hasext)
fname = fname + ".rtc"; fname = fname + ".rtc";
if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) { if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) {
@ -122,7 +181,7 @@ void CurveEditor::savePressed () {
} }
std::ofstream f (fname.c_str()); std::ofstream f (fname.c_str());
std::vector<double> p = curve->getPoints (); std::vector<double> p = customCurve->getPoints ();
int ix = 0; int ix = 0;
if (p[ix++]<0) if (p[ix++]<0)
f << "Linear\n"; f << "Linear\n";
@ -170,25 +229,165 @@ void CurveEditor::loadPressed () {
if (f) if (f)
p.push_back (x); p.push_back (x);
} }
curve->setPoints (p); customCurve->setPoints (p);
curve->queue_draw (); customCurve->queue_draw ();
curve->notifyListener (); customCurve->notifyListener ();
} }
} }
} }
void CurveEditor::on_realize () {
Gtk::VBox::on_realize();
realized = true;
setCurve (tmpCurve);
}
void CurveEditor::setCurve (const std::vector<double>& c) { void CurveEditor::setCurve (const std::vector<double>& c) {
if (c.size()>4) { tmpCurve = c;
curve->setPoints (c);
curve->queue_draw (); if (realized && curveType->get_active_row_number()<3) { // if it is not realized or "unchanged" is selected, just store the curve (prev line) and do not change gui
typeconn.block(true);
if (c.size()==0 || c[0]==0) {
curveType->set_active (0);
curveTypeIx = 0;
}
else if (c[0]==1) {
curveType->set_active (2);
curveTypeIx = 2;
customCurve->setPoints (c);
}
else if (c[0]==2) {
curveType->set_active (1);
curveTypeIx = 1;
paramCurve->setPoints (c);
shcSelector->setPositions (c[1], c[2], c[3]);
highlights->setValue (c[4]);
lights->setValue (c[5]);
darks->setValue (c[6]);
shadows->setValue (c[7]);
}
removeIfThere (this, customCurveBox, false);
removeIfThere (this, paramCurveBox, false);
if (curveType->get_active_row_number()==1)
pack_start (*paramCurveBox);
else if (curveType->get_active_row_number()==2)
pack_start (*customCurveBox);
typeconn.block(false);
} }
else
linearPressed ();
} }
std::vector<double> CurveEditor::getCurve () { std::vector<double> CurveEditor::getCurve () {
return curve->getPoints (); if (!realized || curveType->get_active_row_number()==3)
return tmpCurve;
if (curveTypeIx<=0) {
std::vector<double> lcurve (1);
lcurve[0] = 0.0;
return lcurve;
}
else if (curveTypeIx==1) {
std::vector<double> lcurve (8);
lcurve[0] = 2.0;
shcSelector->getPositions (lcurve[1], lcurve[2], lcurve[3]);
lcurve[4] = highlights->getValue ();
lcurve[5] = lights->getValue ();
lcurve[6] = darks->getValue ();
lcurve[7] = shadows->getValue ();
return lcurve;
}
else if (curveTypeIx==2)
return customCurve->getPoints ();
} }
void CurveEditor::typeSelectionChanged () {
removeIfThere (this, customCurveBox, false);
removeIfThere (this, paramCurveBox, false);
if (curveType->get_active_row_number()==1)
pack_start (*paramCurveBox);
else if (curveType->get_active_row_number()==2)
pack_start (*customCurveBox);
if (curveType->get_active_row_number()<3)
curveTypeIx = curveType->get_active_row_number();
curveChanged ();
}
void CurveEditor::curveChanged () {
if (cl)
cl->curveChanged ();
}
void CurveEditor::shcChanged () {
paramCurve->setPoints (getCurve());
if (cl)
cl->curveChanged ();
}
void CurveEditor::adjusterChanged (Adjuster* a, double newval) {
paramCurve->setPoints (getCurve());
if (cl)
cl->curveChanged ();
}
bool CurveEditor::adjusterEntered (GdkEventCrossing* ev, int ac) {
if (ev->detail != GDK_NOTIFY_INFERIOR) {
activeParamControl = ac;
paramCurve->setActiveParam (activeParamControl);
}
return true;
}
bool CurveEditor::adjusterLeft (GdkEventCrossing* ev, int ac) {
if (ev->detail != GDK_NOTIFY_INFERIOR) {
activeParamControl = -1;
paramCurve->setActiveParam (activeParamControl);
}
return true;
}
void CurveEditor::setBatchMode (bool batchMode) {
curveType->append_text ("(Unchanged)");
}
bool CurveEditor::isUnChanged () {
return curveType->get_active_row_number()==3;
}
void CurveEditor::setUnChanged (bool uc) {
if (uc) {
typeconn.block(true);
removeIfThere (this, customCurveBox, false);
removeIfThere (this, paramCurveBox, false);
curveType->set_active (3);
typeconn.block(false);
}
else {
typeconn.block(true);
curveType->set_active (-1); // hack: if it remains 3 (unchanged), then setcurve does not switch selection in the combo
setCurve (getCurve ());
typeconn.block(false);
}
}
void CurveEditor::updateBackgroundHistogram (unsigned int* hist) {
paramCurve->updateBackgroundHistogram (hist);
customCurve->updateBackgroundHistogram (hist);
}

View File

@ -21,22 +21,58 @@
#include <gtkmm.h> #include <gtkmm.h>
#include <mycurve.h> #include <mycurve.h>
#include <shcselector.h>
#include <adjuster.h>
class CurveEditor : public Gtk::VBox { class CurveEditor : public Gtk::VBox, public CurveListener, public SHCListener, public AdjusterListener {
MyCurve* curve; Gtk::ComboBoxText* curveType;
Gtk::Button* linear; Gtk::VBox* paramCurveBox;
Gtk::VBox* customCurveBox;
MyCurve* customCurve;
MyCurve* paramCurve;
SHCSelector* shcSelector;
Adjuster* highlights;
Adjuster* lights;
Adjuster* darks;
Adjuster* shadows;
Gtk::Button* save; Gtk::Button* save;
Gtk::Button* load; Gtk::Button* load;
CurveListener* cl;
bool realized;
std::vector<double> tmpCurve;
int curveTypeIx;
int activeParamControl;
sigc::connection typeconn;
public: public:
CurveEditor (); CurveEditor ();
void setCurveListener (CurveListener* cl) { curve->setCurveListener (cl); } virtual ~CurveEditor ();
void linearPressed (); void setBatchMode (bool batchMode);
bool isUnChanged ();
void setUnChanged (bool uc);
void on_realize ();
void setCurveListener (CurveListener* l) { cl = l; }
void savePressed (); void savePressed ();
void loadPressed (); void loadPressed ();
void typeSelectionChanged ();
void setCurve (const std::vector<double>& c); void setCurve (const std::vector<double>& c);
std::vector<double> getCurve (); std::vector<double> getCurve ();
void curveChanged ();
void shcChanged ();
void adjusterChanged (Adjuster* a, double newval);
bool adjusterEntered (GdkEventCrossing* ev, int ac);
bool adjusterLeft (GdkEventCrossing* ev, int ac);
void updateBackgroundHistogram (unsigned int* hist);
}; };

28
rtgui/curvelistener.h Normal file
View File

@ -0,0 +1,28 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* 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/>.
*/
#ifndef _CURVELISTENER_
#define _CURVELISTENER_
class CurveListener {
public:
virtual void curveChanged () {}
};
#endif

View File

@ -285,7 +285,7 @@ void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) {
ipc->setPreviewImageListener (previewHandler); ipc->setPreviewImageListener (previewHandler);
ipc->setPreviewScale (10); ipc->setPreviewScale (10);
tpc->initImage (ipc, tmb->getType()==FT_Raw); tpc->initImage (ipc, tmb->getType()==FT_Raw);
ipc->setHistogramListener (histogramPanel); ipc->setHistogramListener (this);
// iarea->fitZoom (); // tell to the editorPanel that the next image has to be fitted to the screen // iarea->fitZoom (); // tell to the editorPanel that the next image has to be fitted to the screen
iarea->imageArea->setPreviewHandler (previewHandler); iarea->imageArea->setPreviewHandler (previewHandler);
@ -799,3 +799,8 @@ void EditorPanel::beforeAfterToggled () {
} }
} }
void EditorPanel::histogramChanged (unsigned int* rh, unsigned int* gh, unsigned int* bh, unsigned int* lh, unsigned int* bcrgb, unsigned int* bcl) {
histogramPanel->histogramChanged (rh, gh, bh, lh);
tpc->updateCurveBackgroundHistogram (bcrgb, bcl);
}

View File

@ -44,7 +44,8 @@ class EditorPanel : public Gtk::VBox,
public PParamsChangeListener, public PParamsChangeListener,
public rtengine::ProgressListener, public rtengine::ProgressListener,
public ThumbnailListener, public ThumbnailListener,
public HistoryBeforeLineListener { public HistoryBeforeLineListener,
public rtengine::HistogramListener {
protected: protected:
Gtk::Label *progressLabel; Gtk::Label *progressLabel;
@ -121,6 +122,9 @@ class EditorPanel : public Gtk::VBox,
// HistoryBeforeLineListener // HistoryBeforeLineListener
void historyBeforeLineChanged (const rtengine::procparams::ProcParams& params); void historyBeforeLineChanged (const rtengine::procparams::ProcParams& params);
// HistogramListener
void histogramChanged (unsigned int* rh, unsigned int* gh, unsigned int* bh, unsigned int* lh, unsigned int* bcrgb, unsigned int* bcl);
// event handlers // event handlers
void info_toggled (); void info_toggled ();
void hideHistoryActivated (); void hideHistoryActivated ();

View File

@ -18,6 +18,7 @@
*/ */
#include <histogrampanel.h> #include <histogrampanel.h>
#include <multilangmgr.h> #include <multilangmgr.h>
#include <string.h>
HistogramPanel::HistogramPanel () { HistogramPanel::HistogramPanel () {

View File

@ -21,7 +21,6 @@
#include <gtkmm.h> #include <gtkmm.h>
#include <glibmm.h> #include <glibmm.h>
#include <rtengine.h>
class HistogramArea; class HistogramArea;
struct HistogramAreaIdleHelper { struct HistogramAreaIdleHelper {
@ -74,7 +73,7 @@ class HistogramArea : public Gtk::DrawingArea {
void styleChanged (const Glib::RefPtr<Gtk::Style>& style); void styleChanged (const Glib::RefPtr<Gtk::Style>& style);
}; };
class HistogramPanel : public Gtk::HBox, public rtengine::HistogramListener { class HistogramPanel : public Gtk::HBox {
protected: protected:

View File

@ -51,7 +51,7 @@ void ImageArea::on_realize()
{ {
Gtk::DrawingArea::on_realize(); Gtk::DrawingArea::on_realize();
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK);
Cairo::FontOptions cfo; Cairo::FontOptions cfo;
cfo.set_antialias (Cairo::ANTIALIAS_SUBPIXEL); cfo.set_antialias (Cairo::ANTIALIAS_SUBPIXEL);

View File

@ -22,29 +22,17 @@
using namespace rtengine; using namespace rtengine;
using namespace rtengine::procparams; using namespace rtengine::procparams;
LCurve::LCurve () : ToolPanel() { LCurve::LCurve () : ToolPanel(), brAdd(false), contrAdd(false) {
Gtk::HBox* abox = Gtk::manage (new Gtk::HBox ()); Gtk::HBox* abox = Gtk::manage (new Gtk::HBox ());
abox->set_border_width (2); abox->set_border_width (2);
brightness = Gtk::manage (new Adjuster (M("TP_LUMACURVE_BRIGHTNESS"), -2, 2, 0.01, 0)); brightness = Gtk::manage (new Adjuster (M("TP_LUMACURVE_BRIGHTNESS"), -100, 100, 0.01, 0));
hlcompr = Gtk::manage (new Adjuster (M("TP_LUMACURVE_COMPRHIGHLIGHTS"), 0, 100, 1, 0)); contrast = Gtk::manage (new Adjuster (M("TP_LUMACURVE_CONTRAST"), -100, 100, 1, 0));
black = Gtk::manage (new Adjuster (M("TP_LUMACURVE_BLACKLEVEL"), 0, 32768, 1, 0));
shcompr = Gtk::manage (new Adjuster (M("TP_LUMACURVE_COMPRSHADOWS"), 0, 100, 1, 0));
contrast = Gtk::manage (new Adjuster (M("TP_LUMACURVE_CONTRAST"), -50, 50, 1, 0));
pack_start (*brightness); pack_start (*brightness);
brightness->show (); brightness->show ();
pack_start (*hlcompr);
hlcompr->show ();
pack_start (*black);
black->show ();
pack_start (*shcompr);
shcompr->show ();
pack_start (*contrast); pack_start (*contrast);
contrast->show (); contrast->show ();
@ -56,51 +44,55 @@ LCurve::LCurve () : ToolPanel() {
shape->show (); shape->show ();
shape->setCurveListener (this); shape->setCurveListener (this);
curvexp = Gtk::manage (new Gtk::Expander (M("TP_LUMACURVE_CURVEEDITOR"))); pack_start (*shape, Gtk::PACK_SHRINK, 4);
curvexp->show ();
curvexp->add (*shape);
pack_start (*curvexp, Gtk::PACK_SHRINK, 4);
brightness->setAdjusterListener (this); brightness->setAdjusterListener (this);
hlcompr->setAdjusterListener (this);
black->setAdjusterListener (this);
shcompr->setAdjusterListener (this);
contrast->setAdjusterListener (this); contrast->setAdjusterListener (this);
} }
void LCurve::read (const ProcParams* pp) { void LCurve::read (const ProcParams* pp, const ParamsEdited* pedited) {
disableListener (); disableListener ();
brightness->setValue (pp->lumaCurve.brightness); if (pedited) {
black->setValue (pp->lumaCurve.black); brightness->setEditedState (pedited->lumaCurve.brightness ? Edited : UnEdited);
hlcompr->setValue (pp->lumaCurve.hlcompr); contrast->setEditedState (pedited->lumaCurve.contrast ? Edited : UnEdited);
shcompr->setValue (pp->lumaCurve.shcompr); shape->setUnChanged (!pedited->lumaCurve.curve);
}
brightness->setValue (pp->lumaCurve.brightness);
contrast->setValue (pp->lumaCurve.contrast); contrast->setValue (pp->lumaCurve.contrast);
shape->setCurve (pp->lumaCurve.curve); shape->setCurve (pp->lumaCurve.curve);
enableListener (); enableListener ();
} }
void LCurve::write (ProcParams* pp) { void LCurve::write (ProcParams* pp, ParamsEdited* pedited) {
pp->lumaCurve.brightness = brightness->getValue (); pp->lumaCurve.brightness = brightness->getValue ();
pp->lumaCurve.black = (int)black->getValue ();
pp->lumaCurve.hlcompr = (int)hlcompr->getValue ();
pp->lumaCurve.shcompr = (int)shcompr->getValue ();
pp->lumaCurve.contrast = (int)contrast->getValue (); pp->lumaCurve.contrast = (int)contrast->getValue ();
pp->lumaCurve.curve = shape->getCurve (); pp->lumaCurve.curve = shape->getCurve ();
if (pedited) {
pedited->lumaCurve.brightness = brightness->getEditedState ();
pedited->lumaCurve.contrast = contrast->getEditedState ();
pedited->lumaCurve.curve = !shape->isUnChanged ();
}
} }
void LCurve::setDefaults (const ProcParams* defParams) { void LCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
brightness->setDefault (defParams->lumaCurve.brightness); brightness->setDefault (defParams->lumaCurve.brightness);
black->setDefault (defParams->lumaCurve.black);
hlcompr->setDefault (defParams->lumaCurve.hlcompr);
shcompr->setDefault (defParams->lumaCurve.shcompr);
contrast->setDefault (defParams->lumaCurve.contrast); contrast->setDefault (defParams->lumaCurve.contrast);
if (pedited) {
brightness->setDefaultEditedState (pedited->lumaCurve.brightness ? Edited : UnEdited);
contrast->setDefaultEditedState (pedited->lumaCurve.contrast ? Edited : UnEdited);
}
else {
brightness->setDefaultEditedState (Irrelevant);
contrast->setDefaultEditedState (Irrelevant);
}
} }
void LCurve::curveChanged () { void LCurve::curveChanged () {
@ -122,22 +114,31 @@ void LCurve::adjusterChanged (Adjuster* a, double newval) {
if (a==brightness) if (a==brightness)
listener->panelChanged (EvLBrightness, costr); listener->panelChanged (EvLBrightness, costr);
else if (a==black)
listener->panelChanged (EvLBlack, costr);
else if (a==contrast) else if (a==contrast)
listener->panelChanged (EvLContrast, costr); listener->panelChanged (EvLContrast, costr);
else if (a==hlcompr)
listener->panelChanged (EvLHLCompr, costr);
else if (a==shcompr)
listener->panelChanged (EvLSHCompr, costr);
} }
void LCurve::expandCurve (bool isExpanded) {
void LCurve::setBatchMode (bool batchMode) {
curvexp->set_expanded (isExpanded);
} ToolPanel::setBatchMode (batchMode);
brightness->showEditedCB ();
bool LCurve::isCurveExpanded () { contrast->showEditedCB ();
return curvexp->get_expanded (); shape->setBatchMode (batchMode);
} }
void LCurve::setAdjusterBehavior (bool bradd, bool contradd) {
if (!brAdd && bradd || brAdd && !bradd)
brightness->setLimits (-100, 100, 1, 0);
if (!contrAdd && contradd || contrAdd && !contradd)
contrast->setLimits (-100, 100, 1, 0);
brAdd = bradd;
contrAdd = contradd;
}
void LCurve::updateCurveBackgroundHistogram (unsigned* hist) {
shape->updateBackgroundHistogram (hist);
}

View File

@ -29,25 +29,23 @@ class LCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, publ
protected: protected:
Adjuster* brightness; Adjuster* brightness;
Adjuster* black;
Adjuster* contrast; Adjuster* contrast;
Adjuster* hlcompr;
Adjuster* shcompr;
CurveEditor* shape; CurveEditor* shape;
Gtk::Expander* curvexp; bool brAdd, contrAdd;
public: public:
LCurve (); LCurve ();
void read (const rtengine::procparams::ProcParams* pp); void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
void write (rtengine::procparams::ProcParams* pp); void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
void setDefaults (const rtengine::procparams::ProcParams* defParams); void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
void setBatchMode (bool batchMode);
void setAdjusterBehavior (bool bradd, bool contradd);
void curveChanged (); void curveChanged ();
void adjusterChanged (Adjuster* a, double newval); void adjusterChanged (Adjuster* a, double newval);
void expandCurve (bool isExpanded); void updateCurveBackgroundHistogram (unsigned* hist);
bool isCurveExpanded ();
}; };
#endif #endif

View File

@ -17,11 +17,13 @@
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>. * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <mycurve.h> #include <mycurve.h>
#include <curves.h>
#include <string.h>
#define RADIUS 3 /* radius of the control points */ #define RADIUS 3 /* radius of the control points */
#define MIN_DISTANCE 8 /* min distance between control points */ #define MIN_DISTANCE 8 /* min distance between control points */
MyCurve::MyCurve () : listener(NULL) { MyCurve::MyCurve () : listener(NULL), activeParam(-1), bghistvalid(false) {
cursor_type = Gdk::TOP_LEFT_ARROW; cursor_type = Gdk::TOP_LEFT_ARROW;
curve.type = Spline; curve.type = Spline;
@ -36,373 +38,340 @@ MyCurve::MyCurve () : listener(NULL) {
curve.x.push_back(1); curve.x.push_back(1);
curve.y.push_back(1); curve.y.push_back(1);
curve.type = Spline; curve.type = Spline;
mcih = new MyCurveIdleHelper;
mcih->myCurve = this;
mcih->destroyed = false;
mcih->pending = 0;
} }
void MyCurve::spline_solve (int n, double x[], double y[], double y2[]) { MyCurve::~MyCurve () {
double* u = new double[n-1]; if (mcih->pending)
mcih->destroyed = true;
y2[0] = u[0] = 0.0; /* set lower boundary condition to "natural" */ else
delete mcih;
for (int i = 1; i < n - 1; ++i)
{
double sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
double p = sig * y2[i - 1] + 2.0;
y2[i] = (sig - 1.0) / p;
u[i] = ((y[i + 1] - y[i])
/ (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]));
u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
}
y2[n - 1] = 0.0;
for (int k = n - 2; k >= 0; --k)
y2[k] = y2[k] * y2[k + 1] + u[k];
delete [] u;
} }
double MyCurve::spline_eval (int n, double x[], double y[], double y2[], double val) {
if (val>x[n-1])
return y[n-1];
else if (val<x[0])
return y[0];
/* do a binary search for the right interval: */
int k_lo = 0, k_hi = n - 1;
while (k_hi - k_lo > 1){
int k = (k_hi + k_lo) / 2;
if (x[k] > val)
k_hi = k;
else
k_lo = k;
}
double h = x[k_hi] - x[k_lo];
double a = (x[k_hi] - val) / h;
double b = (val - x[k_lo]) / h;
return a*y[k_lo] + b*y[k_hi] + ((a*a*a - a)*y2[k_lo] + (b*b*b - b)*y2[k_hi]) * (h*h)/6.0;
}
std::vector<double> MyCurve::get_vector (int veclen) { std::vector<double> MyCurve::get_vector (int veclen) {
std::vector<double> vector; std::vector<double> vector;
vector.resize (veclen);
int num = curve.x.size(); if (curve.type != Parametric) {
// count active points:
double prev =- 1.0;
int active = 0;
int firstact = -1;
for (int i = 0; i < curve.x.size(); ++i)
if (curve.x[i] > prev) {
if (firstact < 0)
firstact = i;
prev = curve.x[i];
++active;
}
// handle degenerate case:
if (active < 2) {
double ry;
if (active > 0)
ry = curve.y[firstact];
else
ry = 0.0;
if (ry < 0.0) ry = 0.0;
if (ry > 1.0) ry = 1.0;
for (int x = 0; x < veclen; ++x)
vector[x] = ry;
return vector;
}
}
/* count active points: */ // calculate remaining points
double prev =- 1.0; std::vector<double> curveDescr = getPoints ();
int active = 0; rtengine::Curve* rtcurve = new rtengine::Curve (curveDescr);
int firstact = -1; std::vector<double> t;
for (int i = 0; i < num; ++i) t.resize (veclen);
if (curve.x[i] > prev) { for (int i = 0; i < veclen; i++)
if (firstact < 0) t[i] = (double) i / (veclen - 1.0);
firstact = i; rtcurve->getVal (t, vector);
prev = curve.x[i]; delete rtcurve;
++active; return vector;
}
/* handle degenerate case: */
if (active < 2) {
double ry;
if (active > 0)
ry = curve.y[firstact];
else
ry = 0.0;
if (ry < 0.0) ry = 0.0;
if (ry > 1.0) ry = 1.0;
for (int x = 0; x < veclen; ++x)
vector.push_back(ry);
return vector;
}
if (curve.type==Spline) {
double* mem = new double [3*active];
double* xv = mem;
double* yv = mem + active;
double* y2v = mem + 2*active;
prev = -1.0;
int dst = 0;
for (int i = 0; i < num; ++i) {
if (curve.x[i] > prev) {
prev = curve.x[i];
xv[dst] = curve.x[i];
yv[dst] = curve.y[i];
dst++;
}
}
spline_solve (active, xv, yv, y2v);
double dx = 1.0 / (veclen - 1);
double rx = 0.0;
for (int x = 0; x < veclen; ++x, rx += dx) {
double ry = spline_eval (active, xv, yv, y2v, rx);
if (ry < 0.0) ry = 0;
if (ry > 1.0) ry = 1.0;
vector.push_back (ry);
}
delete [] mem;
}
else if (curve.type==Linear) {
double dx = 1.0 / (veclen - 1);
double rx = 0;
double ry = 0;
double dy = 0.0;
int i = firstact;
for (int x = 0; x < veclen; ++x, rx += dx) {
if (rx >= curve.x[i]) {
if (rx > curve.x[i])
ry = 0.0;
dy = 0.0;
int next = i + 1;
while (next < num && curve.x[next] <= curve.x[i])
++next;
if (next < num) {
double delta_x = curve.x[next] - curve.x[i];
dy = (curve.y[next] - curve.y[i]) / delta_x;
dy *= dx;
ry = curve.y[i];
i = next;
}
}
if (rx<curve.x[0])
vector.push_back (curve.y[0]);
else if (rx>curve.x[num-1])
vector.push_back (curve.y[num-1]);
else
vector.push_back (ry);
ry += dy;
}
}
return vector;
} }
void MyCurve::interpolate (int width, int height) { void MyCurve::interpolate (int width, int height) {
this->height = height; this->height = height;
point.clear (); point.resize (width);
std::vector<double> vector = get_vector (width); std::vector<double> vector = get_vector (width);
this->height = height; this->height = height;
for (int i = 0; i < width; ++i) { for (int i = 0; i < width; ++i)
Gdk::Point p (RADIUS + i, RADIUS + height - (int)((height-1) * vector[i] + 0.5)); point[i] = Gdk::Point (RADIUS + i, RADIUS + height - (int)((height-1) * vector[i] + 0.5));
point.push_back (p); upoint.clear ();
} lpoint.clear ();
}
if (curve.type==Parametric && activeParam>0) {
double tmp = curve.x[activeParam-1];
if (activeParam>=4) {
upoint.resize(width);
lpoint.resize(width);
curve.x[activeParam-1] = 100;
vector = get_vector (width);
for (int i = 0; i < width; ++i)
upoint[i] = Gdk::Point (RADIUS + i, RADIUS + height - (int)((height-1) * vector[i] + 0.5));
curve.x[activeParam-1] = -100;
vector = get_vector (width);
for (int i = 0; i < width; ++i)
lpoint[i] = Gdk::Point (RADIUS + i, RADIUS + height - (int)((height-1) * vector[i] + 0.5));
curve.x[activeParam-1] = tmp;
}
}
}
void MyCurve::draw (int width, int height) { void MyCurve::draw (int width, int height) {
if (!pixmap) if (!pixmap)
return; return;
if (this->height != height || point.size() != width) // re-calculate curve if dimensions changed
interpolate (width, height); if (this->height != height || point.size() != width)
interpolate (width, height);
Gtk::StateType state = Gtk::STATE_NORMAL;
if (!is_sensitive()) Gtk::StateType state = Gtk::STATE_NORMAL;
state = Gtk::STATE_INSENSITIVE; if (!is_sensitive())
state = Gtk::STATE_INSENSITIVE;
Glib::RefPtr<Gtk::Style> style = get_style (); Glib::RefPtr<Gtk::Style> style = get_style ();
Cairo::RefPtr<Cairo::Context> cr = pixmap->create_cairo_context();
Cairo::RefPtr<Cairo::Context> cr = pixmap->create_cairo_context(); // bounding rectangle
Gdk::Color c = style->get_bg (state);
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
cr->rectangle (0, 0, width + RADIUS*2, height + RADIUS*2);
cr->fill ();
/* clear the pixmap: */ // histogram in the background
// gtk_paint_flat_box (style->gobj(), pixmap->gobj(), GTK_STATE_NORMAL, GTK_SHADOW_NONE, if (bghistvalid) {
// NULL, (GtkWidget*)gobj(), "curve_bg", 0, 0, , height + RADIUS * 2); // find heighest bin
int histheight = 0;
for (int i=0; i<256; i++)
if (bghist[i]>histheight)
histheight = bghist[i];
// draw histogram
cr->set_line_width (1.0);
double stepSize = (width-1) / 256.0;
cr->move_to (0, height-1);
cr->set_source_rgb (0.75, 0.75, 0.75);
for (int i=0; i<256; i++) {
double val = bghist[i] * (double)(height-2) / histheight;
if (val>height-1)
val = height-1;
if (i>0)
cr->line_to (i*stepSize, height-1-val);
}
cr->line_to (width-1, height-1);
cr->fill ();
}
// pixmap->draw_rectangle (style->get_bg_gc (state), false, 0, 0, width + RADIUS*2 - 1, height + RADIUS*2 - 1); // draw the grid lines:
cr->set_line_width (1.0);
c = style->get_dark (state);
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
cr->set_antialias (Cairo::ANTIALIAS_NONE);
for (int i = 0; i < 5; i++) {
cr->move_to (RADIUS, i * height / 4 + RADIUS);
cr->line_to (width + RADIUS, i * height / 4 + RADIUS);
cr->move_to (i * width / 4 + RADIUS, RADIUS);
cr->line_to (i * width / 4 + RADIUS, height + RADIUS);
}
cr->stroke ();
// draw f(x)=x line
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
std::valarray<double> ds (1);
ds[0] = 4;
cr->set_dash (ds, 0);
cr->move_to (RADIUS, height + RADIUS);
cr->line_to (width + RADIUS, RADIUS);
cr->stroke ();
cr->unset_dash ();
Gdk::Color c = style->get_bg (state); cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); cr->set_line_width (1.0);
cr->rectangle (0, 0, width + RADIUS*2, height + RADIUS*2);
cr->fill ();
/* draw the grid lines: (XXX make more meaningful) */ // draw upper and lower bounds
cr->set_line_width (1.0); if (curve.type==Parametric && activeParam>0 && lpoint.size()>1 && upoint.size()>1) {
c = style->get_dark (state); cr->set_source_rgba (0.0, 0.0, 0.0, 0.15);
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); cr->move_to (upoint[0].get_x(), upoint[0].get_y());
cr->set_antialias (Cairo::ANTIALIAS_NONE); for (int i=1; i<upoint.size(); i++)
for (int i = 0; i < 5; i++) { cr->line_to (upoint[i].get_x(), upoint[i].get_y());
cr->line_to (lpoint[lpoint.size()-1].get_x(), lpoint[lpoint.size()-1].get_y());
cr->move_to (RADIUS, i * height / 4 + RADIUS); for (int i=lpoint.size()-2; i>=0; i--)
cr->line_to (width + RADIUS, i * height / 4 + RADIUS); cr->line_to (lpoint[i].get_x(), lpoint[i].get_y());
cr->move_to (i * width / 4 + RADIUS, RADIUS); cr->line_to (upoint[0].get_x(), upoint[0].get_y());
cr->line_to (i * width / 4 + RADIUS, height + RADIUS); cr->fill ();
// pixmap->draw_line (style->get_dark_gc (state), RADIUS, i * height / 4 + RADIUS, width + RADIUS, i * height / 4 + RADIUS); }
// pixmap->draw_line (style->get_dark_gc (state), i * width / 4 + RADIUS, RADIUS, i * width / 4 + RADIUS, height + RADIUS);
}
cr->stroke ();
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); // draw curve
cr->set_line_width (1.0); cr->set_source_rgb (0.0, 0.0, 0.0);
cr->set_source_rgb (0.0, 0.0, 0.0); cr->move_to (point[0].get_x(), point[0].get_y());
cr->move_to (point[0].get_x(), point[0].get_y()); for (int i=1; i<point.size(); i++)
for (int i=1; i<point.size(); i++) cr->line_to (point[i].get_x(), point[i].get_y());
cr->line_to (point[i].get_x(), point[i].get_y()); cr->stroke ();
cr->stroke ();
for (int i = 0; i < curve.x.size(); ++i) { // draw bullets
if (curve.type!=Parametric)
for (int i = 0; i < curve.x.size(); ++i) {
double x = ((width-1) * curve.x[i] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, width);
double y = height - ((height-1) * curve.y[i] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, height);
double x = ((width-1) * curve.x[i] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, width); cr->arc (x, y, RADIUS, 0, 2*M_PI);
double y = height - ((height-1) * curve.y[i] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, height); cr->fill ();
}
/* draw a bullet: */ get_window()->draw_drawable (style->get_fg_gc (state), pixmap, 0, 0, 0, 0, width + RADIUS * 2, height + RADIUS * 2);
cr->arc (x, y, RADIUS, 0, 2*M_PI);
cr->fill ();
}
get_window()->draw_drawable (style->get_fg_gc (state), pixmap, 0, 0, 0, 0, width + RADIUS * 2, height + RADIUS * 2);
} }
bool MyCurve::handleEvents (GdkEvent* event) { bool MyCurve::handleEvents (GdkEvent* event) {
Gdk::CursorType new_type = cursor_type; Gdk::CursorType new_type = cursor_type;
int src, dst; int src, dst;
GdkEventMotion *mevent; GdkEventMotion *mevent;
std::vector<double>::iterator itx, ity; std::vector<double>::iterator itx, ity;
bool retval = false; bool retval = false;
int width = get_allocation().get_width() - RADIUS * 2; int width = get_allocation().get_width() - RADIUS * 2;
int height = get_allocation().get_height() - RADIUS * 2; int height = get_allocation().get_height() - RADIUS * 2;
if ((width < 0) || (height < 0)) if ((width < 0) || (height < 0))
return false; return false;
/* get the pointer position */ /* get the pointer position */
int tx, ty; int tx, ty;
Gdk::ModifierType gm; Gdk::ModifierType gm;
get_window()->get_pointer (tx, ty, gm); get_window()->get_pointer (tx, ty, gm);
int x = CLAMP ((tx - RADIUS), 0, width-1); int x = CLAMP ((tx - RADIUS), 0, width-1);
int y = CLAMP ((ty - RADIUS), 0, height-1); int y = CLAMP ((ty - RADIUS), 0, height-1);
unsigned int distance = ~0U; unsigned int distance = ~0U;
int num = curve.x.size(); int num = curve.x.size();
int closest_point = 0; int closest_point = 0;
for (int i = 0; i < num; ++i) {
int cx = (int)((width-1) * curve.x[i] + 0.5); //project (c->ctlpoint[i][0], min_x, c->max_x, width);
if ((unsigned int) abs (x - cx) < distance) {
distance = abs (x - cx);
closest_point = i;
}
}
switch (event->type) {
case Gdk::CONFIGURE:
if (pixmap)
pixmap.clear ();
/* fall through */
case Gdk::EXPOSE:
if (!pixmap) {
pixmap = Gdk::Pixmap::create (get_window(), get_allocation().get_width(), get_allocation().get_height());
interpolate (width, height);
}
draw (width, height);
break;
case Gdk::BUTTON_PRESS:
add_modal_grab ();
new_type = Gdk::PLUS;
switch (curve.type) {
case Linear:
case Spline:
if (distance > MIN_DISTANCE) {
/* insert a new control point */
if (num > 0) {
int cx = (int)((width-1)*curve.x[closest_point]+0.5);
if (x > cx)
++closest_point;
}
itx = curve.x.begin();
ity = curve.y.begin();
for (int i=0; i<closest_point; i++) { itx++; ity++; }
curve.x.insert (itx, 0);
curve.y.insert (ity, 0);
num++;
}
grab_point = closest_point;
curve.x[grab_point] = (double) x / (width-1);
curve.y[grab_point] = (double) (height-y) / (height-1);
interpolate (width, height);
notifyListener ();
break;
}
draw (width, height);
retval = true;
break;
case Gdk::BUTTON_RELEASE:
remove_modal_grab ();
/* delete inactive points: */
itx = curve.x.begin();
ity = curve.y.begin();
for (src = dst = 0; src < num; ++src) {
if (curve.x[src] >= 0.0) {
curve.x[dst] = curve.x[src];
curve.y[dst] = curve.y[src];
++dst;
++itx;
++ity;
}
}
if (dst < src) {
curve.x.erase (itx, curve.x.end());
curve.y.erase (ity, curve.y.end());
if (curve.x.size() <= 0) {
curve.x.push_back (0);
curve.y.push_back (0);
interpolate (width, height);
draw (width, height);
}
}
new_type = Gdk::FLEUR;
grab_point = -1;
retval = true;
notifyListener ();
break;
case Gdk::MOTION_NOTIFY:
mevent = (GdkEventMotion *) event;
switch (curve.type) {
case Linear:
case Spline:
if (grab_point == -1) {
/* if no point is grabbed... */
if (distance <= MIN_DISTANCE)
new_type = Gdk::FLEUR;
else
new_type = Gdk::PLUS;
}
else {
/* drag the grabbed point */
new_type = Gdk::FLEUR;
int leftbound = -MIN_DISTANCE;
if (grab_point > 0)
leftbound = (int)((width-1)*curve.x[grab_point-1]+0.5);
int rightbound = width + RADIUS * 2 + MIN_DISTANCE; if (curve.type!=Parametric) {
if (grab_point + 1 < num) for (int i = 0; i < num; ++i) {
rightbound = (int)((width-1)*curve.x[grab_point+1]+0.5); int cx = (int)((width-1) * curve.x[i] + 0.5); //project (c->ctlpoint[i][0], min_x, c->max_x, width);
if ((unsigned int) abs (x - cx) < distance) {
distance = abs (x - cx);
closest_point = i;
}
}
}
if (tx <= leftbound || tx >= rightbound || ty > height + RADIUS * 2 + MIN_DISTANCE || ty < -MIN_DISTANCE) switch (event->type) {
curve.x[grab_point] = -1.0; case Gdk::CONFIGURE:
else { if (pixmap)
curve.x[grab_point] = (double) x / (width-1); pixmap.clear ();
curve.y[grab_point] = (double) (height-y) / (height-1);
} case Gdk::EXPOSE:
interpolate (width, height); if (!pixmap) {
draw (width, height); pixmap = Gdk::Pixmap::create (get_window(), get_allocation().get_width(), get_allocation().get_height());
notifyListener (); interpolate (width, height);
} }
break; draw (width, height);
} break;
case Gdk::BUTTON_PRESS:
if (curve.type!=Parametric) {
add_modal_grab ();
new_type = Gdk::PLUS;
if (distance > MIN_DISTANCE) {
/* insert a new control point */
if (num > 0) {
int cx = (int)((width-1)*curve.x[closest_point]+0.5);
if (x > cx)
++closest_point;
}
itx = curve.x.begin();
ity = curve.y.begin();
for (int i=0; i<closest_point; i++) { itx++; ity++; }
curve.x.insert (itx, 0);
curve.y.insert (ity, 0);
num++;
}
grab_point = closest_point;
curve.x[grab_point] = (double) x / (width-1);
curve.y[grab_point] = (double) (height-y) / (height-1);
interpolate (width, height);
notifyListener ();
break;
}
draw (width, height);
retval = true;
break;
case Gdk::BUTTON_RELEASE:
if (curve.type!=Parametric) {
remove_modal_grab ();
/* delete inactive points: */
itx = curve.x.begin();
ity = curve.y.begin();
for (src = dst = 0; src < num; ++src)
if (curve.x[src] >= 0.0) {
curve.x[dst] = curve.x[src];
curve.y[dst] = curve.y[src];
++dst;
++itx;
++ity;
}
if (dst < src) {
curve.x.erase (itx, curve.x.end());
curve.y.erase (ity, curve.y.end());
if (curve.x.size() <= 0) {
curve.x.push_back (0);
curve.y.push_back (0);
interpolate (width, height);
draw (width, height);
}
}
new_type = Gdk::FLEUR;
grab_point = -1;
retval = true;
notifyListener ();
}
break;
case Gdk::MOTION_NOTIFY:
mevent = (GdkEventMotion *) event;
if (curve.type == Linear || curve.type == Spline) {
if (grab_point == -1) {
/* if no point is grabbed... */
if (distance <= MIN_DISTANCE)
new_type = Gdk::FLEUR;
else
new_type = Gdk::PLUS;
}
else {
/* drag the grabbed point */
new_type = Gdk::FLEUR;
int leftbound = -MIN_DISTANCE;
if (grab_point > 0)
leftbound = (int)((width-1)*curve.x[grab_point-1]+0.5);
int rightbound = width + RADIUS * 2 + MIN_DISTANCE;
if (grab_point + 1 < num)
rightbound = (int)((width-1)*curve.x[grab_point+1]+0.5);
if (tx <= leftbound || tx >= rightbound || ty > height + RADIUS * 2 + MIN_DISTANCE || ty < -MIN_DISTANCE)
curve.x[grab_point] = -1.0;
else {
curve.x[grab_point] = (double) x / (width-1);
curve.y[grab_point] = (double) (height-y) / (height-1);
}
interpolate (width, height);
draw (width, height);
notifyListener ();
}
}
if (new_type != cursor_type) { if (new_type != cursor_type) {
cursor_type = new_type; cursor_type = new_type;
@ -410,49 +379,63 @@ bool MyCurve::handleEvents (GdkEvent* event) {
get_window ()->set_cursor (*cursor); get_window ()->set_cursor (*cursor);
delete cursor; delete cursor;
} }
retval = true; retval = true;
break; break;
default: default:
break; break;
} }
return retval; return retval;
} }
std::vector<double> MyCurve::getPoints () { std::vector<double> MyCurve::getPoints () {
std::vector<double> result; std::vector<double> result;
if (curve.type==Linear) if (curve.type==Parametric) {
result.push_back (-1.0); result.push_back (+2.0);
else for (int i=0; i<curve.x.size(); i++)
result.push_back (+1.0);
for (int i=0; i<curve.x.size(); i++)
if (curve.x[i]>=0) {
result.push_back (curve.x[i]); result.push_back (curve.x[i]);
result.push_back (curve.y[i]); }
} else {
if (curve.type==Linear)
result.push_back (-1.0);
else
result.push_back (+1.0);
for (int i=0; i<curve.x.size(); i++)
if (curve.x[i]>=0) {
result.push_back (curve.x[i]);
result.push_back (curve.y[i]);
}
}
return result; return result;
} }
void MyCurve::setPoints (const std::vector<double>& p) { void MyCurve::setPoints (const std::vector<double>& p) {
int ix = 0; int ix = 0;
if (p[ix++]>0) int t = p[ix++];
curve.type = Spline; if (t==2) {
else curve.type = Parametric;
curve.type = Linear; curve.x.clear ();
curve.y.clear ();
curve.x.clear (); for (int i=1; i<p.size(); i++)
curve.y.clear (); curve.x.push_back (p[ix++]);
for (int i=0; i<p.size()/2; i++) { }
curve.x.push_back (p[ix++]); else {
curve.y.push_back (p[ix++]); if (t==1)
curve.type = Spline;
else
curve.type = Linear;
curve.x.clear ();
curve.y.clear ();
for (int i=0; i<p.size()/2; i++) {
curve.x.push_back (p[ix++]);
curve.y.push_back (p[ix++]);
}
activeParam = -1;
} }
pixmap.clear (); pixmap.clear ();
bool pi = pixmap; queue_draw ();
} }
void MyCurve::setType (CurveType t) { void MyCurve::setType (CurveType t) {
@ -462,6 +445,52 @@ void MyCurve::setType (CurveType t) {
} }
void MyCurve::notifyListener () { void MyCurve::notifyListener () {
if (listener) if (listener)
listener->curveChanged (); listener->curveChanged ();
} }
void MyCurve::setActiveParam (int ac) {
activeParam = ac;
pixmap.clear ();
queue_draw ();
}
int mchistupdate (void* data) {
gdk_threads_enter ();
MyCurveIdleHelper* mcih = (MyCurveIdleHelper*)data;
if (mcih->destroyed) {
if (mcih->pending == 1)
delete mcih;
else
mcih->pending--;
gdk_threads_leave ();
return 0;
}
mcih->myCurve->pixmap.clear ();
mcih->myCurve->queue_draw ();
mcih->pending--;
gdk_threads_leave ();
return 0;
}
void MyCurve::updateBackgroundHistogram (unsigned int* hist) {
if (hist!=NULL) {
memcpy (bghist, hist, 256*sizeof(unsigned int));
bghistvalid = true;
}
else
bghistvalid = false;
mcih->pending++;
g_idle_add (mchistupdate, mcih);
}

View File

@ -21,24 +21,29 @@
#include <gtkmm.h> #include <gtkmm.h>
#include <vector> #include <vector>
#include <curvelistener.h>
class CurveListener { enum CurveType {Linear, Spline, Parametric};
public:
virtual void curveChanged () {}
};
enum CurveType {Linear, Spline};
class CurveDescr { class CurveDescr {
public: public:
CurveType type; CurveType type;
std::vector<double> x, y; std::vector<double> x, y; // in case of parametric curves the curve parameters are stored in vector x. In other cases these vectors store the coordinates of the bullets.
};
class MyCurve;
struct MyCurveIdleHelper {
MyCurve* myCurve;
bool destroyed;
int pending;
}; };
class MyCurve : public Gtk::DrawingArea { class MyCurve : public Gtk::DrawingArea {
friend int mchistupdate (void* data);
protected:
CurveListener* listener; CurveListener* listener;
CurveDescr curve; CurveDescr curve;
Gdk::CursorType cursor_type; Gdk::CursorType cursor_type;
@ -47,16 +52,20 @@ class MyCurve : public Gtk::DrawingArea {
int grab_point; int grab_point;
int last; int last;
std::vector<Gdk::Point> point; std::vector<Gdk::Point> point;
std::vector<Gdk::Point> upoint;
std::vector<Gdk::Point> lpoint;
int activeParam;
unsigned int bghist[256];
bool bghistvalid;
MyCurveIdleHelper* mcih;
protected:
void draw (int width, int height); void draw (int width, int height);
void interpolate (int width, int height); void interpolate (int width, int height);
std::vector<double> get_vector (int veclen); std::vector<double> get_vector (int veclen);
double spline_eval (int n, double x[], double y[], double y2[], double val);
void spline_solve (int n, double x[], double y[], double y2[]);
public: public:
MyCurve (); MyCurve ();
~MyCurve ();
void setCurveListener (CurveListener* cl) { listener = cl; } void setCurveListener (CurveListener* cl) { listener = cl; }
std::vector<double> getPoints (); std::vector<double> getPoints ();
@ -64,6 +73,8 @@ class MyCurve : public Gtk::DrawingArea {
void setType (CurveType t); void setType (CurveType t);
bool handleEvents (GdkEvent* event); bool handleEvents (GdkEvent* event);
void notifyListener (); void notifyListener ();
void setActiveParam (int ac);
void updateBackgroundHistogram (unsigned int* hist);
}; };
#endif #endif

View File

@ -22,6 +22,7 @@
#include <glib/gstdio.h> #include <glib/gstdio.h>
#include <sstream> #include <sstream>
#include <multilangmgr.h> #include <multilangmgr.h>
#include <addsetids.h>
Options options; Options options;
Glib::ustring versionString = "v3.0 alpha 1"; Glib::ustring versionString = "v3.0 alpha 1";
@ -107,8 +108,8 @@ void Options::setDefaults () {
thumbnailZoomRatios.push_back (1.0); thumbnailZoomRatios.push_back (1.0);
overlayedFileNames = true; overlayedFileNames = true;
int babehav[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}; int babehav[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0};
baBehav = std::vector<int> (babehav, babehav+22); baBehav = std::vector<int> (babehav, babehav+ADDSET_PARAM_NUM);
rtSettings.dualThreadEnabled = true; rtSettings.dualThreadEnabled = true;
rtSettings.demosaicMethod = "eahd"; rtSettings.demosaicMethod = "eahd";

View File

@ -19,6 +19,7 @@
#include <paramsedited.h> #include <paramsedited.h>
#include <string.h> #include <string.h>
#include <options.h> #include <options.h>
#include <addsetids.h>
ParamsEdited::ParamsEdited () { ParamsEdited::ParamsEdited () {
@ -38,10 +39,7 @@ void ParamsEdited::set (bool v) {
toneCurve.expcomp = v; toneCurve.expcomp = v;
lumaCurve.curve = v; lumaCurve.curve = v;
lumaCurve.brightness = v; lumaCurve.brightness = v;
lumaCurve.black = v;
lumaCurve.contrast = v; lumaCurve.contrast = v;
lumaCurve.shcompr = v;
lumaCurve.hlcompr = v;
sharpening.enabled = v; sharpening.enabled = v;
sharpening.radius = v; sharpening.radius = v;
sharpening.amount = v; sharpening.amount = v;
@ -145,10 +143,7 @@ void ParamsEdited::initFrom (const std::vector<rtengine::procparams::ProcParams>
toneCurve.expcomp = toneCurve.expcomp && p.toneCurve.expcomp == other.toneCurve.expcomp; toneCurve.expcomp = toneCurve.expcomp && p.toneCurve.expcomp == other.toneCurve.expcomp;
lumaCurve.curve = lumaCurve.curve && p.lumaCurve.curve == other.lumaCurve.curve; lumaCurve.curve = lumaCurve.curve && p.lumaCurve.curve == other.lumaCurve.curve;
lumaCurve.brightness = lumaCurve.brightness && p.lumaCurve.brightness == other.lumaCurve.brightness; lumaCurve.brightness = lumaCurve.brightness && p.lumaCurve.brightness == other.lumaCurve.brightness;
lumaCurve.black = lumaCurve.black && p.lumaCurve.black == other.lumaCurve.black;
lumaCurve.contrast = lumaCurve.contrast && p.lumaCurve.contrast == other.lumaCurve.contrast; lumaCurve.contrast = lumaCurve.contrast && p.lumaCurve.contrast == other.lumaCurve.contrast;
lumaCurve.shcompr = lumaCurve.shcompr && p.lumaCurve.shcompr == other.lumaCurve.shcompr;
lumaCurve.hlcompr = lumaCurve.hlcompr && p.lumaCurve.hlcompr == other.lumaCurve.hlcompr;
sharpening.enabled = sharpening.enabled && p.sharpening.enabled == other.sharpening.enabled; sharpening.enabled = sharpening.enabled && p.sharpening.enabled == other.sharpening.enabled;
sharpening.radius = sharpening.radius && p.sharpening.radius == other.sharpening.radius; sharpening.radius = sharpening.radius && p.sharpening.radius == other.sharpening.radius;
sharpening.amount = sharpening.amount && p.sharpening.amount == other.sharpening.amount; sharpening.amount = sharpening.amount && p.sharpening.amount == other.sharpening.amount;
@ -233,55 +228,52 @@ void ParamsEdited::initFrom (const std::vector<rtengine::procparams::ProcParams>
void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rtengine::procparams::ProcParams& mods) { void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rtengine::procparams::ProcParams& mods) {
if (toneCurve.curve) toEdit.toneCurve.curve = mods.toneCurve.curve; if (toneCurve.curve) toEdit.toneCurve.curve = mods.toneCurve.curve;
if (toneCurve.brightness) toEdit.toneCurve.brightness = options.baBehav[1] ? toEdit.toneCurve.brightness + mods.toneCurve.brightness : mods.toneCurve.brightness; if (toneCurve.brightness) toEdit.toneCurve.brightness = options.baBehav[ADDSET_TC_BRIGHTNESS] ? toEdit.toneCurve.brightness + mods.toneCurve.brightness : mods.toneCurve.brightness;
if (toneCurve.black) toEdit.toneCurve.black = options.baBehav[2] ? toEdit.toneCurve.black + mods.toneCurve.black : mods.toneCurve.black; if (toneCurve.black) toEdit.toneCurve.black = options.baBehav[ADDSET_TC_BLACKLEVEL] ? toEdit.toneCurve.black + mods.toneCurve.black : mods.toneCurve.black;
if (toneCurve.contrast) toEdit.toneCurve.contrast = options.baBehav[3] ? toEdit.toneCurve.contrast + mods.toneCurve.contrast : mods.toneCurve.contrast; if (toneCurve.contrast) toEdit.toneCurve.contrast = options.baBehav[ADDSET_TC_CONTRAST] ? toEdit.toneCurve.contrast + mods.toneCurve.contrast : mods.toneCurve.contrast;
if (toneCurve.shcompr) toEdit.toneCurve.shcompr = mods.toneCurve.shcompr; if (toneCurve.shcompr) toEdit.toneCurve.shcompr = mods.toneCurve.shcompr;
if (toneCurve.hlcompr) toEdit.toneCurve.hlcompr = mods.toneCurve.hlcompr; if (toneCurve.hlcompr) toEdit.toneCurve.hlcompr = mods.toneCurve.hlcompr;
if (toneCurve.autoexp) toEdit.toneCurve.autoexp = mods.toneCurve.autoexp; if (toneCurve.autoexp) toEdit.toneCurve.autoexp = mods.toneCurve.autoexp;
if (toneCurve.clip) toEdit.toneCurve.clip = mods.toneCurve.clip; if (toneCurve.clip) toEdit.toneCurve.clip = mods.toneCurve.clip;
if (toneCurve.expcomp) toEdit.toneCurve.expcomp = options.baBehav[0] ? toEdit.toneCurve.expcomp + mods.toneCurve.expcomp : mods.toneCurve.expcomp; if (toneCurve.expcomp) toEdit.toneCurve.expcomp = options.baBehav[ADDSET_TC_EXPCOMP] ? toEdit.toneCurve.expcomp + mods.toneCurve.expcomp : mods.toneCurve.expcomp;
if (lumaCurve.curve) toEdit.lumaCurve.curve = mods.lumaCurve.curve; if (lumaCurve.curve) toEdit.lumaCurve.curve = mods.lumaCurve.curve;
if (lumaCurve.brightness) toEdit.lumaCurve.brightness = mods.lumaCurve.brightness; if (lumaCurve.brightness) toEdit.lumaCurve.brightness = options.baBehav[ADDSET_LC_BRIGHTNESS] ? toEdit.lumaCurve.brightness + mods.lumaCurve.brightness : mods.lumaCurve.brightness;
if (lumaCurve.black) toEdit.lumaCurve.black = mods.lumaCurve.black; if (lumaCurve.contrast) toEdit.lumaCurve.contrast = options.baBehav[ADDSET_LC_CONTRAST] ? toEdit.lumaCurve.contrast + mods.lumaCurve.contrast : mods.lumaCurve.contrast;
if (lumaCurve.contrast) toEdit.lumaCurve.contrast = mods.lumaCurve.contrast; if (sharpening.enabled) toEdit.sharpening.enabled = mods.sharpening.enabled;
if (lumaCurve.shcompr) toEdit.lumaCurve.shcompr = mods.lumaCurve.shcompr; if (sharpening.radius) toEdit.sharpening.radius = mods.sharpening.radius;
if (lumaCurve.hlcompr) toEdit.lumaCurve.hlcompr = mods.lumaCurve.hlcompr; if (sharpening.amount) toEdit.sharpening.amount = options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.amount + mods.sharpening.amount : mods.sharpening.amount;
if (sharpening.enabled) toEdit.sharpening.enabled = mods.sharpening.enabled; if (sharpening.threshold) toEdit.sharpening.threshold = mods.sharpening.threshold;
if (sharpening.radius) toEdit.sharpening.radius = mods.sharpening.radius; if (sharpening.edgesonly) toEdit.sharpening.edgesonly = mods.sharpening.edgesonly;
if (sharpening.amount) toEdit.sharpening.amount = options.baBehav[10] ? toEdit.sharpening.amount + mods.sharpening.amount : mods.sharpening.amount; if (sharpening.edges_radius) toEdit.sharpening.edges_radius = mods.sharpening.edges_radius;
if (sharpening.threshold) toEdit.sharpening.threshold = mods.sharpening.threshold; if (sharpening.edges_tolerance) toEdit.sharpening.edges_tolerance = mods.sharpening.edges_tolerance;
if (sharpening.edgesonly) toEdit.sharpening.edgesonly = mods.sharpening.edgesonly; if (sharpening.halocontrol) toEdit.sharpening.halocontrol = mods.sharpening.halocontrol;
if (sharpening.edges_radius) toEdit.sharpening.edges_radius = mods.sharpening.edges_radius; if (sharpening.halocontrol_amount) toEdit.sharpening.halocontrol_amount = mods.sharpening.halocontrol_amount;
if (sharpening.edges_tolerance) toEdit.sharpening.edges_tolerance = mods.sharpening.edges_tolerance; if (sharpening.method) toEdit.sharpening.method = mods.sharpening.method;
if (sharpening.halocontrol) toEdit.sharpening.halocontrol = mods.sharpening.halocontrol; if (sharpening.deconvamount) toEdit.sharpening.deconvamount = options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.deconvamount + mods.sharpening.deconvamount : mods.sharpening.deconvamount;
if (sharpening.halocontrol_amount) toEdit.sharpening.halocontrol_amount = mods.sharpening.halocontrol_amount; if (sharpening.deconvradius) toEdit.sharpening.deconvradius = mods.sharpening.deconvradius;
if (sharpening.method) toEdit.sharpening.method = mods.sharpening.method; if (sharpening.deconviter) toEdit.sharpening.deconviter = mods.sharpening.deconviter;
if (sharpening.deconvamount) toEdit.sharpening.deconvamount = options.baBehav[10] ? toEdit.sharpening.deconvamount + mods.sharpening.deconvamount : mods.sharpening.deconvamount; if (sharpening.deconvdamping) toEdit.sharpening.deconvdamping = mods.sharpening.deconvdamping;
if (sharpening.deconvradius) toEdit.sharpening.deconvradius = mods.sharpening.deconvradius; if (colorBoost.amount) toEdit.colorBoost.amount = options.baBehav[ADDSET_CBOOST_AMOUNT] ? toEdit.colorBoost.amount + mods.colorBoost.amount : mods.colorBoost.amount;
if (sharpening.deconviter) toEdit.sharpening.deconviter = mods.sharpening.deconviter; if (colorBoost.avoidclip) toEdit.colorBoost.avoidclip = mods.colorBoost.avoidclip;
if (sharpening.deconvdamping) toEdit.sharpening.deconvdamping = mods.sharpening.deconvdamping; if (colorBoost.enable_saturationlimiter)toEdit.colorBoost.enable_saturationlimiter = mods.colorBoost.enable_saturationlimiter;
if (colorBoost.amount) toEdit.colorBoost.amount = options.baBehav[14] ? toEdit.colorBoost.amount + mods.colorBoost.amount : mods.colorBoost.amount; if (colorBoost.saturationlimit) toEdit.colorBoost.saturationlimit = mods.colorBoost.saturationlimit;
if (colorBoost.avoidclip) toEdit.colorBoost.avoidclip = mods.colorBoost.avoidclip; if (wb.method) toEdit.wb.method = mods.wb.method;
if (colorBoost.enable_saturationlimiter) toEdit.colorBoost.enable_saturationlimiter = mods.colorBoost.enable_saturationlimiter; if (wb.green) toEdit.wb.green = options.baBehav[ADDSET_WB_GREEN] ? toEdit.wb.green + mods.wb.green : mods.wb.green;
if (colorBoost.saturationlimit) toEdit.colorBoost.saturationlimit = mods.colorBoost.saturationlimit; if (wb.temperature) toEdit.wb.temperature = options.baBehav[ADDSET_WB_TEMPERATURE] ? toEdit.wb.temperature + mods.wb.temperature : mods.wb.temperature;
if (wb.method) toEdit.wb.method = mods.wb.method; if (colorShift.a) toEdit.colorShift.a = options.baBehav[ADDSET_CS_BLUEYELLOW] ? toEdit.colorShift.a + mods.colorShift.a : mods.colorShift.a;
if (wb.green) toEdit.wb.green = options.baBehav[13] ? toEdit.wb.green + mods.wb.green : mods.wb.green; if (colorShift.b) toEdit.colorShift.b = options.baBehav[ADDSET_CS_GREENMAGENTA] ? toEdit.colorShift.b + mods.colorShift.b : mods.colorShift.b;
if (wb.temperature) toEdit.wb.temperature = options.baBehav[12] ? toEdit.wb.temperature + mods.wb.temperature : mods.wb.temperature; if (lumaDenoise.enabled) toEdit.lumaDenoise.enabled = mods.lumaDenoise.enabled;
if (colorShift.a) toEdit.colorShift.a = options.baBehav[15] ? toEdit.colorShift.a + mods.colorShift.a : mods.colorShift.a; if (lumaDenoise.radius) toEdit.lumaDenoise.radius = mods.lumaDenoise.radius;
if (colorShift.b) toEdit.colorShift.b = options.baBehav[16] ? toEdit.colorShift.b + mods.colorShift.b : mods.colorShift.b; if (lumaDenoise.edgetolerance) toEdit.lumaDenoise.edgetolerance = options.baBehav[ADDSET_LD_EDGETOLERANCE] ? toEdit.lumaDenoise.edgetolerance + mods.lumaDenoise.edgetolerance : mods.lumaDenoise.edgetolerance;
if (lumaDenoise.enabled) toEdit.lumaDenoise.enabled = mods.lumaDenoise.enabled; if (colorDenoise.enabled) toEdit.colorDenoise.enabled = mods.colorDenoise.enabled;
if (lumaDenoise.radius) toEdit.lumaDenoise.radius = mods.lumaDenoise.radius; if (colorDenoise.amount) toEdit.colorDenoise.amount = mods.colorDenoise.amount;
if (lumaDenoise.edgetolerance) toEdit.lumaDenoise.edgetolerance = options.baBehav[11] ? toEdit.lumaDenoise.edgetolerance + mods.lumaDenoise.edgetolerance : mods.lumaDenoise.edgetolerance;
if (colorDenoise.enabled) toEdit.colorDenoise.enabled = mods.colorDenoise.enabled;
if (colorDenoise.amount) toEdit.colorDenoise.amount = mods.colorDenoise.amount;
if (sh.enabled) toEdit.sh.enabled = mods.sh.enabled; if (sh.enabled) toEdit.sh.enabled = mods.sh.enabled;
if (sh.hq) toEdit.sh.hq = mods.sh.hq; if (sh.hq) toEdit.sh.hq = mods.sh.hq;
if (sh.highlights) toEdit.sh.highlights = options.baBehav[4] ? toEdit.sh.highlights + mods.sh.highlights : mods.sh.highlights; if (sh.highlights) toEdit.sh.highlights = options.baBehav[ADDSET_SH_HIGHLIGHTS] ? toEdit.sh.highlights + mods.sh.highlights : mods.sh.highlights;
if (sh.htonalwidth) toEdit.sh.htonalwidth = mods.sh.htonalwidth; if (sh.htonalwidth) toEdit.sh.htonalwidth = mods.sh.htonalwidth;
if (sh.shadows) toEdit.sh.shadows = options.baBehav[5] ? toEdit.sh.shadows + mods.sh.shadows : mods.sh.shadows; if (sh.shadows) toEdit.sh.shadows = options.baBehav[ADDSET_SH_SHADOWS] ? toEdit.sh.shadows + mods.sh.shadows : mods.sh.shadows;
if (sh.stonalwidth) toEdit.sh.stonalwidth = mods.sh.stonalwidth; if (sh.stonalwidth) toEdit.sh.stonalwidth = mods.sh.stonalwidth;
if (sh.localcontrast) toEdit.sh.localcontrast = options.baBehav[6] ? toEdit.sh.localcontrast + mods.sh.localcontrast : mods.sh.localcontrast; if (sh.localcontrast) toEdit.sh.localcontrast = options.baBehav[ADDSET_SH_LOCALCONTRAST] ? toEdit.sh.localcontrast + mods.sh.localcontrast : mods.sh.localcontrast;
if (sh.radius) toEdit.sh.radius = mods.sh.radius; if (sh.radius) toEdit.sh.radius = mods.sh.radius;
if (crop.enabled) toEdit.crop.enabled = mods.crop.enabled; if (crop.enabled) toEdit.crop.enabled = mods.crop.enabled;
if (crop.x) toEdit.crop.x = mods.crop.x; if (crop.x) toEdit.crop.x = mods.crop.x;
@ -297,10 +289,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
if (coarse.vflip) toEdit.coarse.vflip = mods.coarse.vflip ? !toEdit.coarse.vflip : toEdit.coarse.vflip; if (coarse.vflip) toEdit.coarse.vflip = mods.coarse.vflip ? !toEdit.coarse.vflip : toEdit.coarse.vflip;
if (rotate.degree) toEdit.rotate.degree = options.baBehav[17] ? toEdit.rotate.degree + mods.rotate.degree : mods.rotate.degree; if (rotate.degree) toEdit.rotate.degree = options.baBehav[17] ? toEdit.rotate.degree + mods.rotate.degree : mods.rotate.degree;
if (rotate.fill) toEdit.rotate.fill = mods.rotate.fill; if (rotate.fill) toEdit.rotate.fill = mods.rotate.fill;
if (distortion.amount) toEdit.distortion.amount = options.baBehav[18] ? toEdit.distortion.amount + mods.distortion.amount : mods.distortion.amount; if (distortion.amount) toEdit.distortion.amount = options.baBehav[ADDSET_DIST_AMOUNT] ? toEdit.distortion.amount + mods.distortion.amount : mods.distortion.amount;
if (cacorrection.red) toEdit.cacorrection.red = options.baBehav[19] ? toEdit.cacorrection.red + mods.cacorrection.red : mods.cacorrection.red; if (cacorrection.red) toEdit.cacorrection.red = options.baBehav[ADDSET_CA_RED] ? toEdit.cacorrection.red + mods.cacorrection.red : mods.cacorrection.red;
if (cacorrection.blue) toEdit.cacorrection.blue = options.baBehav[20] ? toEdit.cacorrection.blue + mods.cacorrection.blue : mods.cacorrection.blue; if (cacorrection.blue) toEdit.cacorrection.blue = options.baBehav[ADDSET_CA_BLUE] ? toEdit.cacorrection.blue + mods.cacorrection.blue : mods.cacorrection.blue;
if (vignetting.amount) toEdit.vignetting.amount = options.baBehav[21] ? toEdit.vignetting.amount + mods.vignetting.amount : mods.vignetting.amount; if (vignetting.amount) toEdit.vignetting.amount = options.baBehav[ADDSET_VIGN_AMOUNT] ? toEdit.vignetting.amount + mods.vignetting.amount : mods.vignetting.amount;
if (vignetting.radius) toEdit.vignetting.radius = mods.vignetting.radius; if (vignetting.radius) toEdit.vignetting.radius = mods.vignetting.radius;
if (chmixer.red[0]) toEdit.chmixer.red[0] = mods.chmixer.red[0]; if (chmixer.red[0]) toEdit.chmixer.red[0] = mods.chmixer.red[0];
if (chmixer.red[1]) toEdit.chmixer.red[1] = mods.chmixer.red[1]; if (chmixer.red[1]) toEdit.chmixer.red[1] = mods.chmixer.red[1];

View File

@ -24,7 +24,7 @@
#include <rtengine.h> #include <rtengine.h>
#include <procparams.h> #include <procparams.h>
class CurveParamsEdited { class ToneCurveParamsEdited {
public: public:
bool curve; bool curve;
@ -33,16 +33,19 @@ class CurveParamsEdited {
bool contrast; bool contrast;
bool shcompr; bool shcompr;
bool hlcompr; bool hlcompr;
};
class ToneCurveParamsEdited : public CurveParamsEdited {
public:
bool autoexp; bool autoexp;
bool clip; bool clip;
bool expcomp; bool expcomp;
}; };
class LCurveParamsEdited {
public:
bool brightness;
bool contrast;
bool curve;
};
class SharpeningParamsEdited { class SharpeningParamsEdited {
public: public:
@ -217,7 +220,7 @@ class ParamsEdited {
public: public:
ToneCurveParamsEdited toneCurve; ToneCurveParamsEdited toneCurve;
CurveParamsEdited lumaCurve; LCurveParamsEdited lumaCurve;
SharpeningParamsEdited sharpening; SharpeningParamsEdited sharpening;
ColorBoostParamsEdited colorBoost; ColorBoostParamsEdited colorBoost;
WBParamsEdited wb; WBParamsEdited wb;

View File

@ -21,6 +21,7 @@
#include <multilangmgr.h> #include <multilangmgr.h>
#include <splash.h> #include <splash.h>
#include <cachemanager.h> #include <cachemanager.h>
#include <addsetids.h>
extern Options options; extern Options options;
extern Glib::ustring argv0; extern Glib::ustring argv0;
@ -126,74 +127,74 @@ Gtk::Widget* Preferences::getBatchProcPanel () {
mi = behModel->append (); mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_EXPOSURE_LABEL")); mi->set_value (behavColumns.label, M("TP_EXPOSURE_LABEL"));
appendBehavList (mi, M("TP_EXPOSURE_EXPCOMP"), false); appendBehavList (mi, M("TP_EXPOSURE_EXPCOMP"), ADDSET_TC_EXPCOMP, false);
appendBehavList (mi, M("TP_EXPOSURE_BRIGHTNESS"), false); appendBehavList (mi, M("TP_EXPOSURE_BRIGHTNESS"), ADDSET_TC_BRIGHTNESS, false);
appendBehavList (mi, M("TP_EXPOSURE_BLACKLEVEL"), false); appendBehavList (mi, M("TP_EXPOSURE_BLACKLEVEL"), ADDSET_TC_BLACKLEVEL, false);
appendBehavList (mi, M("TP_EXPOSURE_CONTRAST"), false); appendBehavList (mi, M("TP_EXPOSURE_CONTRAST"), ADDSET_TC_CONTRAST, false);
mi = behModel->append (); mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_SHADOWSHLIGHTS_LABEL")); mi->set_value (behavColumns.label, M("TP_SHADOWSHLIGHTS_LABEL"));
appendBehavList (mi, M("TP_SHADOWSHLIGHTS_HIGHLIGHTS"), false); appendBehavList (mi, M("TP_SHADOWSHLIGHTS_HIGHLIGHTS"), ADDSET_SH_HIGHLIGHTS, false);
appendBehavList (mi, M("TP_SHADOWSHLIGHTS_SHADOWS"), false); appendBehavList (mi, M("TP_SHADOWSHLIGHTS_SHADOWS"), ADDSET_SH_SHADOWS, false);
appendBehavList (mi, M("TP_SHADOWSHLIGHTS_LOCALCONTR"), false); appendBehavList (mi, M("TP_SHADOWSHLIGHTS_LOCALCONTR"), ADDSET_SH_LOCALCONTRAST, false);
mi = behModel->append (); mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_LUMACURVE_LABEL")); mi->set_value (behavColumns.label, M("TP_LUMACURVE_LABEL"));
appendBehavList (mi, M("TP_LUMACURVE_BRIGHTNESS"), false); appendBehavList (mi, M("TP_LUMACURVE_BRIGHTNESS"), ADDSET_LC_BRIGHTNESS, false);
appendBehavList (mi, M("TP_LUMACURVE_BLACKLEVEL"), false); appendBehavList (mi, M("TP_LUMACURVE_CONTRAST"), ADDSET_LC_CONTRAST, false);
appendBehavList (mi, M("TP_LUMACURVE_CONTRAST"), false);
mi = behModel->append (); mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_SHARPENING_LABEL")); mi->set_value (behavColumns.label, M("TP_SHARPENING_LABEL"));
appendBehavList (mi, M("TP_SHARPENING_AMOUNT"), false); appendBehavList (mi, M("TP_SHARPENING_AMOUNT"), ADDSET_SHARP_AMOUNT, false);
mi = behModel->append (); mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_LUMADENOISE_LABEL")); mi->set_value (behavColumns.label, M("TP_LUMADENOISE_LABEL"));
appendBehavList (mi, M("TP_LUMADENOISE_EDGETOLERANCE"), true); appendBehavList (mi, M("TP_LUMADENOISE_EDGETOLERANCE"), ADDSET_LD_EDGETOLERANCE, true);
mi = behModel->append (); mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_WBALANCE_LABEL")); mi->set_value (behavColumns.label, M("TP_WBALANCE_LABEL"));
appendBehavList (mi, M("TP_WBALANCE_TEMPERATURE"), true); appendBehavList (mi, M("TP_WBALANCE_TEMPERATURE"), ADDSET_WB_TEMPERATURE, true);
appendBehavList (mi, M("TP_WBALANCE_GREEN"), true); appendBehavList (mi, M("TP_WBALANCE_GREEN"), ADDSET_WB_GREEN, true);
mi = behModel->append (); mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_COLORBOOST_LABEL")); mi->set_value (behavColumns.label, M("TP_COLORBOOST_LABEL"));
appendBehavList (mi, M("TP_COLORBOOST_AMOUNT"), false); appendBehavList (mi, M("TP_COLORBOOST_AMOUNT"), ADDSET_CBOOST_AMOUNT, false);
mi = behModel->append (); mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_COLORSHIFT_LABEL")); mi->set_value (behavColumns.label, M("TP_COLORSHIFT_LABEL"));
appendBehavList (mi, M("TP_COLORSHIFT_BLUEYELLOW"), false); appendBehavList (mi, M("TP_COLORSHIFT_BLUEYELLOW"), ADDSET_CS_BLUEYELLOW, false);
appendBehavList (mi, M("TP_COLORSHIFT_GREENMAGENTA"), false); appendBehavList (mi, M("TP_COLORSHIFT_GREENMAGENTA"), ADDSET_CS_GREENMAGENTA, false);
mi = behModel->append (); mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_ROTATE_LABEL")); mi->set_value (behavColumns.label, M("TP_ROTATE_LABEL"));
appendBehavList (mi, M("TP_ROTATE_DEGREE"), false); appendBehavList (mi, M("TP_ROTATE_DEGREE"), ADDSET_ROTATE_DEGREE, false);
mi = behModel->append (); mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_DISTORTION_LABEL")); mi->set_value (behavColumns.label, M("TP_DISTORTION_LABEL"));
appendBehavList (mi, M("TP_DISTORTION_AMOUNT"), false); appendBehavList (mi, M("TP_DISTORTION_AMOUNT"), ADDSET_DIST_AMOUNT, false);
mi = behModel->append (); mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_CACORRECTION_LABEL")); mi->set_value (behavColumns.label, M("TP_CACORRECTION_LABEL"));
appendBehavList (mi, M("TP_CACORRECTION_BLUE"), true); appendBehavList (mi, M("TP_CACORRECTION_BLUE"), ADDSET_CA_BLUE, true);
appendBehavList (mi, M("TP_CACORRECTION_RED"), true); appendBehavList (mi, M("TP_CACORRECTION_RED"), ADDSET_CA_RED, true);
mi = behModel->append (); mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_VIGNETTING_LABEL")); mi->set_value (behavColumns.label, M("TP_VIGNETTING_LABEL"));
appendBehavList (mi, M("TP_VIGNETTING_AMOUNT"), false); appendBehavList (mi, M("TP_VIGNETTING_AMOUNT"), ADDSET_VIGN_AMOUNT, false);
behTreeView->expand_all (); behTreeView->expand_all ();
return mvbpp; return mvbpp;
} }
void Preferences::appendBehavList (Gtk::TreeModel::iterator& parent, Glib::ustring label, bool set) { void Preferences::appendBehavList (Gtk::TreeModel::iterator& parent, Glib::ustring label, int id, bool set) {
Gtk::TreeModel::iterator ci = behModel->append (parent->children()); Gtk::TreeModel::iterator ci = behModel->append (parent->children());
ci->set_value (behavColumns.label, label); ci->set_value (behavColumns.label, label);
ci->set_value (behavColumns.visible, true); ci->set_value (behavColumns.visible, true);
ci->set_value (behavColumns.badd, !set); ci->set_value (behavColumns.badd, !set);
ci->set_value (behavColumns.bset, set); ci->set_value (behavColumns.bset, set);
ci->set_value (behavColumns.addsetid, id);
} }
void Preferences::behAddRadioToggled (const Glib::ustring& path) { void Preferences::behAddRadioToggled (const Glib::ustring& path) {
@ -703,10 +704,10 @@ void Preferences::storePreferences () {
moptions.paramsLoadLocation = (PPLoadLocation)loadParamsPreference->get_active_row_number (); moptions.paramsLoadLocation = (PPLoadLocation)loadParamsPreference->get_active_row_number ();
int i = 0; int i = 0;
moptions.baBehav.clear (); moptions.baBehav.resize (ADDSET_PARAM_NUM);
for (Gtk::TreeIter sections=behModel->children().begin(); sections!=behModel->children().end(); sections++) for (Gtk::TreeIter sections=behModel->children().begin(); sections!=behModel->children().end(); sections++)
for (Gtk::TreeIter adjs=sections->children().begin(); adjs!=sections->children().end(); adjs++) for (Gtk::TreeIter adjs=sections->children().begin(); adjs!=sections->children().end(); adjs++)
moptions.baBehav.push_back (adjs->get_value (behavColumns.badd)); moptions.baBehav[adjs->get_value (behavColumns.addsetid)] = adjs->get_value (behavColumns.badd);
} }
void Preferences::fillPreferences () { void Preferences::fillPreferences () {
@ -784,13 +785,16 @@ void Preferences::fillPreferences () {
addc.block (true); addc.block (true);
setc.block (true); setc.block (true);
int i = 0; if (moptions.baBehav.size() == ADDSET_PARAM_NUM) {
for (Gtk::TreeIter sections=behModel->children().begin(); sections!=behModel->children().end(); sections++) for (int i=0; i<moptions.baBehav.size(); i++)
for (Gtk::TreeIter adjs=sections->children().begin(); adjs!=sections->children().end(); adjs++) for (Gtk::TreeIter sections=behModel->children().begin(); sections!=behModel->children().end(); sections++)
if (moptions.baBehav.size()>i) { for (Gtk::TreeIter adjs=sections->children().begin(); adjs!=sections->children().end(); adjs++)
adjs->set_value (behavColumns.badd, moptions.baBehav[i]==1); if (adjs->get_value (behavColumns.addsetid) == i) {
adjs->set_value (behavColumns.bset, moptions.baBehav[i++]!=1); adjs->set_value (behavColumns.badd, moptions.baBehav[i]==1);
} adjs->set_value (behavColumns.bset, moptions.baBehav[i]!=1);
break;
}
}
addc.block (false); addc.block (false);
setc.block (false); setc.block (false);

View File

@ -42,7 +42,8 @@ class Preferences : public Gtk::Dialog {
Gtk::TreeModelColumn<bool> badd; Gtk::TreeModelColumn<bool> badd;
Gtk::TreeModelColumn<bool> bset; Gtk::TreeModelColumn<bool> bset;
Gtk::TreeModelColumn<bool> visible; Gtk::TreeModelColumn<bool> visible;
BehavColumns() { add(label); add(badd); add(bset); add(visible);} Gtk::TreeModelColumn<int> addsetid;
BehavColumns() { add(label); add(badd); add(bset); add(visible); add(addsetid); }
}; };
Glib::RefPtr<Gtk::TreeStore> behModel; Glib::RefPtr<Gtk::TreeStore> behModel;
BehavColumns behavColumns; BehavColumns behavColumns;
@ -108,7 +109,7 @@ class Preferences : public Gtk::Dialog {
void themeChanged (); void themeChanged ();
void appendBehavList (Gtk::TreeModel::iterator& parent, Glib::ustring label, bool set); void appendBehavList (Gtk::TreeModel::iterator& parent, Glib::ustring label, int id, bool set);
Gtk::Widget* getProcParamsPanel (); Gtk::Widget* getProcParamsPanel ();
Gtk::Widget* getColorManagementPanel (); Gtk::Widget* getColorManagementPanel ();

166
rtgui/shcselector.cc Normal file
View File

@ -0,0 +1,166 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* 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/>.
*/
#include <shcselector.h>
#include <iomanip>
SHCSelector::SHCSelector() : movingPosition(-1), cl(NULL) {
positions[0] = 0.25;
positions[1] = 0.5;
positions[2] = 0.75;
}
void SHCSelector::setPositions (double spos, double cpos, double hpos) {
positions[0] = spos;
positions[1] = cpos;
positions[2] = hpos;
queue_draw ();
}
void SHCSelector::getPositions (double& spos, double& cpos, double& hpos) {
spos = positions[0];
cpos = positions[1];
hpos = positions[2];
}
void SHCSelector::on_realize() {
Gtk::DrawingArea::on_realize();
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
}
bool SHCSelector::on_expose_event(GdkEventExpose* event) {
Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
int w = get_width ();
int h = get_height ();
wslider = h *2.0 / 5.0;
Gdk::Color bgc = get_style()->get_bg (Gtk::STATE_NORMAL);
Gdk::Color fgc = get_style()->get_text (Gtk::STATE_NORMAL);
// clear bg
cr->set_source_rgb (bgc.get_red_p(), bgc.get_green_p(), bgc.get_blue_p());
cr->rectangle (0, 0, w, h);
cr->fill();
// draw gradient background
Cairo::RefPtr< Cairo::LinearGradient > bggradient = Cairo::LinearGradient::create (0, 0, w, 0);
bggradient->add_color_stop_rgb (0, 0, 0, 0);
bggradient->add_color_stop_rgb (1, 1, 1, 1);
cr->set_line_width (1.0);
cr->set_source (bggradient);
cr->rectangle (0.5, h*2.0/7.0 + 0.5, w-0.5, h*3.0/7.0-0.5);
cr->fill_preserve();
cr->set_source_rgb (fgc.get_red_p(), fgc.get_green_p(), fgc.get_blue_p());
cr->stroke ();
// draw sliders
cr->set_line_width (1.0);
for (int i=0; i<3; i++) {
cr->move_to (w*positions[i]-wslider/2+0.5, h-0.5);
cr->line_to (w*positions[i]-wslider/2+0.5, wslider/2 + 0.5);
cr->line_to (w*positions[i], 0.5);
cr->line_to (w*positions[i]+wslider/2-0.5, wslider/2 + 0.5);
cr->line_to (w*positions[i]+wslider/2-0.5, h-0.5);
cr->line_to (w*positions[i]-wslider/2+0.5, h-0.5);
cr->set_source_rgb (bgc.get_red_p(), bgc.get_green_p(), bgc.get_blue_p());
cr->fill_preserve ();
cr->set_source_rgb (fgc.get_red_p(), fgc.get_green_p(), fgc.get_blue_p());
cr->stroke ();
}
// draw text for the slider that is being moved
Glib::RefPtr<Pango::Context> context = get_pango_context () ;
cr->set_line_width (0.5);
if (movingPosition >= 0) {
int i = movingPosition;
Glib::RefPtr<Pango::Layout> layout = create_pango_layout(Glib::ustring::format(std::setprecision(2), positions[i]));
cr->move_to (w*positions[i]+wslider/2-0.5, 0);
cr->set_source_rgb (bgc.get_red_p(), bgc.get_green_p(), bgc.get_blue_p());
layout->add_to_cairo_context (cr);
cr->fill_preserve ();
cr->stroke ();
cr->move_to (w*positions[i]+wslider/2+0.5, 1);
layout->add_to_cairo_context (cr);
cr->fill_preserve ();
cr->stroke ();
cr->set_source_rgb (fgc.get_red_p(), fgc.get_green_p(), fgc.get_blue_p());
cr->move_to (w*positions[i]+wslider/2, 0.5);
layout->add_to_cairo_context (cr);
cr->fill_preserve ();
cr->stroke ();
}
}
bool SHCSelector::on_button_press_event (GdkEventButton* event) {
// check if a slider is under the cursor
int w = get_width ();
movingPosition = -1;
for (int i=0; i<3; i++)
if (event->x > w*positions[i]-wslider/2 && event->x < w*positions[i]+wslider/2) {
movingPosition = i;
tmpX = event->x;
tmpPos = positions[i];
break;
}
queue_draw ();
}
bool SHCSelector::on_button_release_event (GdkEventButton* event) {
if (movingPosition >= 0) {
movingPosition = -1;
queue_draw ();
}
}
bool SHCSelector::on_motion_notify_event (GdkEventMotion* event) {
if (movingPosition >= 0) {
int w = get_width ();
positions[movingPosition] = tmpPos + (event->x - tmpX) / w;
if (positions[movingPosition] < 0)
positions[movingPosition] = 0.0;
else if (movingPosition > 0 && positions[movingPosition] < positions[movingPosition-1]+wslider/w)
positions[movingPosition] = positions[movingPosition-1]+wslider/w;
if (positions[movingPosition] > 1.0)
positions[movingPosition] = 1.0;
else if (movingPosition <3 && positions[movingPosition] > positions[movingPosition+1]-wslider/w)
positions[movingPosition] = positions[movingPosition+1]-wslider/w;
if (cl)
cl->shcChanged ();
queue_draw ();
}
}
void SHCSelector::styleChanged (const Glib::RefPtr<Gtk::Style>& style) {
queue_draw ();
}

61
rtgui/shcselector.h Normal file
View File

@ -0,0 +1,61 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* 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/>.
*/
#ifndef _SHCSELECTOR_
#define _SHCSELECTOR_
#include <gtkmm.h>
class SHCListener {
public:
virtual void shcChanged () {}
};
class SHCSelector : public Gtk::DrawingArea {
protected:
Glib::RefPtr<Gdk::GC> gc_;
Glib::RefPtr<Gdk::Pixmap> backBuffer;
int movingPosition;
double tmpX, tmpPos;
double positions[3];
double wslider;
SHCListener* cl;
public:
SHCSelector();
void setSHCListener (SHCListener* l) { cl = l;; }
void setPositions (double spos, double cpos, double hpos);
void getPositions (double& spos, double& cpos, double& hpos);
void on_realize();
bool on_expose_event(GdkEventExpose* event);
bool on_button_press_event (GdkEventButton* event);
bool on_button_release_event (GdkEventButton* event);
bool on_motion_notify_event (GdkEventMotion* event);
void styleChanged (const Glib::RefPtr<Gtk::Style>& style);
};
#endif

View File

@ -49,7 +49,7 @@ ToneCurve::ToneCurve () : ToolPanel(), expAdd(false), blackAdd(false), brAdd(fal
pack_start (*Gtk::manage (new Gtk::HSeparator())); pack_start (*Gtk::manage (new Gtk::HSeparator()));
//----------- Exposure Compensation ------------------------ //----------- Exposure Compensation ------------------------
expcomp = new Adjuster (M("TP_EXPOSURE_EXPCOMP"), -5, 5, 0.01, 0); expcomp = Gtk::manage (new Adjuster (M("TP_EXPOSURE_EXPCOMP"), -5, 5, 0.01, 0));
pack_start (*expcomp); pack_start (*expcomp);
hlcompr = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRHIGHLIGHTS"), 0, 150, 1, 0)); hlcompr = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRHIGHLIGHTS"), 0, 150, 1, 0));
pack_start (*hlcompr); pack_start (*hlcompr);
@ -68,7 +68,7 @@ ToneCurve::ToneCurve () : ToolPanel(), expAdd(false), blackAdd(false), brAdd(fal
contrast = Gtk::manage (new Adjuster (M("TP_EXPOSURE_CONTRAST"), -100, 100, 1, 0)); contrast = Gtk::manage (new Adjuster (M("TP_EXPOSURE_CONTRAST"), -100, 100, 1, 0));
pack_start (*contrast); pack_start (*contrast);
/*
//----------- Curve ------------------------------ //----------- Curve ------------------------------
pack_start (*Gtk::manage (new Gtk::HSeparator())); pack_start (*Gtk::manage (new Gtk::HSeparator()));
@ -78,7 +78,7 @@ ToneCurve::ToneCurve () : ToolPanel(), expAdd(false), blackAdd(false), brAdd(fal
curvexp->add (*shape); curvexp->add (*shape);
pack_start (*curvexp, Gtk::PACK_SHRINK, 4); pack_start (*curvexp, Gtk::PACK_SHRINK, 4);
*/
// --------- Set Up Listeners ------------- // --------- Set Up Listeners -------------
expcomp->setAdjusterListener (this); expcomp->setAdjusterListener (this);
brightness->setAdjusterListener (this); brightness->setAdjusterListener (this);
@ -88,11 +88,6 @@ ToneCurve::ToneCurve () : ToolPanel(), expAdd(false), blackAdd(false), brAdd(fal
contrast->setAdjusterListener (this); contrast->setAdjusterListener (this);
} }
ToneCurve::~ToneCurve () {
delete expcomp;
}
void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) {
disableListener (); disableListener ();
@ -106,6 +101,7 @@ void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) {
contrast->setEditedState (pedited->toneCurve.contrast ? Edited : UnEdited); contrast->setEditedState (pedited->toneCurve.contrast ? Edited : UnEdited);
autolevels->set_inconsistent (!pedited->toneCurve.autoexp); autolevels->set_inconsistent (!pedited->toneCurve.autoexp);
clipDirty = pedited->toneCurve.clip; clipDirty = pedited->toneCurve.clip;
shape->setUnChanged (!pedited->toneCurve.curve);
} }
autoconn.block (true); autoconn.block (true);
@ -120,7 +116,7 @@ void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) {
shcompr->setValue (pp->toneCurve.shcompr); shcompr->setValue (pp->toneCurve.shcompr);
brightness->setValue (pp->toneCurve.brightness); brightness->setValue (pp->toneCurve.brightness);
contrast->setValue (pp->toneCurve.contrast); contrast->setValue (pp->toneCurve.contrast);
// shape->setCurve (pp->toneCurve.curve); shape->setCurve (pp->toneCurve.curve);
enableListener (); enableListener ();
} }
@ -135,7 +131,7 @@ void ToneCurve::write (ProcParams* pp, ParamsEdited* pedited) {
pp->toneCurve.shcompr = (int)shcompr->getValue (); pp->toneCurve.shcompr = (int)shcompr->getValue ();
pp->toneCurve.brightness = (int)brightness->getValue (); pp->toneCurve.brightness = (int)brightness->getValue ();
pp->toneCurve.contrast = (int)contrast->getValue (); pp->toneCurve.contrast = (int)contrast->getValue ();
// pp->toneCurve.curve = shape->getCurve (); pp->toneCurve.curve = shape->getCurve ();
if (pedited) { if (pedited) {
pedited->toneCurve.expcomp = expcomp->getEditedState (); pedited->toneCurve.expcomp = expcomp->getEditedState ();
@ -144,8 +140,9 @@ void ToneCurve::write (ProcParams* pp, ParamsEdited* pedited) {
pedited->toneCurve.shcompr = shcompr->getEditedState (); pedited->toneCurve.shcompr = shcompr->getEditedState ();
pedited->toneCurve.brightness = brightness->getEditedState (); pedited->toneCurve.brightness = brightness->getEditedState ();
pedited->toneCurve.contrast = contrast->getEditedState (); pedited->toneCurve.contrast = contrast->getEditedState ();
pedited->toneCurve.autoexp = !autolevels->get_inconsistent(); pedited->toneCurve.autoexp = !autolevels->get_inconsistent();
pedited->toneCurve.clip = clipDirty; pedited->toneCurve.clip = clipDirty;
pedited->toneCurve.curve = !shape->isUnChanged ();
} }
} }
@ -176,13 +173,13 @@ void ToneCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pe
} }
} }
/*void ToneCurve::curveChanged () { void ToneCurve::curveChanged () {
if (listener) { if (listener) {
listener->panelChanged (EvToneCurve, M("HISTORY_CUSTOMCURVE")); listener->panelChanged (EvToneCurve, M("HISTORY_CUSTOMCURVE"));
} }
} }
*/
void ToneCurve::adjusterChanged (Adjuster* a, double newval) { void ToneCurve::adjusterChanged (Adjuster* a, double newval) {
if (autolevels->get_active() && (a==expcomp || a==black || a==hlcompr || a==shcompr)) { if (autolevels->get_active() && (a==expcomp || a==black || a==hlcompr || a==shcompr)) {
@ -270,7 +267,7 @@ void ToneCurve::waitForAutoExp () {
hlcompr->setEnabled (false); hlcompr->setEnabled (false);
shcompr->setEnabled (false); shcompr->setEnabled (false);
contrast->setEnabled (false); contrast->setEnabled (false);
// shape->set_sensitive (false); shape->set_sensitive (false);
} }
int aexpcomputed (void* data) { int aexpcomputed (void* data) {
@ -287,7 +284,6 @@ void ToneCurve::autoExpChanged (double br, int bl) {
nextBr = br; nextBr = br;
g_idle_add (aexpcomputed, this); g_idle_add (aexpcomputed, this);
// Glib::signal_idle().connect (sigc::mem_fun(*this, &ToneCurve::autoExpComputed_)); // Glib::signal_idle().connect (sigc::mem_fun(*this, &ToneCurve::autoExpComputed_));
} }
@ -300,7 +296,7 @@ void ToneCurve::enableAll () {
hlcompr->setEnabled (true); hlcompr->setEnabled (true);
shcompr->setEnabled (true); shcompr->setEnabled (true);
contrast->setEnabled (true); contrast->setEnabled (true);
// shape->set_sensitive (true); shape->set_sensitive (true);
} }
bool ToneCurve::autoExpComputed_ () { bool ToneCurve::autoExpComputed_ () {
@ -314,7 +310,6 @@ bool ToneCurve::autoExpComputed_ () {
return false; return false;
} }
/*
void ToneCurve::expandCurve (bool isExpanded) { void ToneCurve::expandCurve (bool isExpanded) {
curvexp->set_expanded (isExpanded); curvexp->set_expanded (isExpanded);
@ -324,7 +319,7 @@ bool ToneCurve::isCurveExpanded () {
return curvexp->get_expanded (); return curvexp->get_expanded ();
} }
*/
void ToneCurve::setBatchMode (bool batchMode) { void ToneCurve::setBatchMode (bool batchMode) {
@ -340,6 +335,8 @@ void ToneCurve::setBatchMode (bool batchMode) {
shcompr->showEditedCB (); shcompr->showEditedCB ();
brightness->showEditedCB (); brightness->showEditedCB ();
contrast->showEditedCB (); contrast->showEditedCB ();
shape->setBatchMode (batchMode);
} }
void ToneCurve::setAdjusterBehavior (bool expadd, bool bradd, bool blackadd, bool contradd) { void ToneCurve::setAdjusterBehavior (bool expadd, bool bradd, bool blackadd, bool contradd) {
@ -351,9 +348,9 @@ void ToneCurve::setAdjusterBehavior (bool expadd, bool bradd, bool blackadd, boo
else if (blackAdd && !blackadd) else if (blackAdd && !blackadd)
black->setLimits (0, 32768, 1, 0); black->setLimits (0, 32768, 1, 0);
if (!brAdd && bradd || brAdd && !bradd) if (!brAdd && bradd || brAdd && !bradd)
brightness->setLimits (-100, 100, 0.01, 0); brightness->setLimits (-100, 100, 1, 0);
if (!contrAdd && contradd || contrAdd && !contradd) if (!contrAdd && contradd || contrAdd && !contradd)
contrast->setLimits (-100, 100, 0.01, 0); contrast->setLimits (-100, 100, 1, 0);
expAdd = expadd; expAdd = expadd;
blackAdd = blackadd; blackAdd = blackadd;
@ -361,3 +358,7 @@ void ToneCurve::setAdjusterBehavior (bool expadd, bool bradd, bool blackadd, boo
contrAdd = contradd; contrAdd = contradd;
} }
void ToneCurve::updateCurveBackgroundHistogram (unsigned* hist) {
shape->updateBackgroundHistogram (hist);
}

View File

@ -22,10 +22,10 @@
#include <gtkmm.h> #include <gtkmm.h>
#include <adjuster.h> #include <adjuster.h>
#include <toolpanel.h> #include <toolpanel.h>
//#include <curveeditor.h> #include <curveeditor.h>
//#include <mycurve.h> #include <mycurve.h>
class ToneCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, public rtengine::AutoExpListener/*, public CurveListener */{ class ToneCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, public rtengine::AutoExpListener, public CurveListener {
protected: protected:
Gtk::HBox* abox; Gtk::HBox* abox;
@ -39,15 +39,14 @@ class ToneCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, p
Adjuster* contrast; Adjuster* contrast;
bool expAdd, blackAdd, brAdd, contrAdd, clipDirty, lastAuto; bool expAdd, blackAdd, brAdd, contrAdd, clipDirty, lastAuto;
sigc::connection autoconn; sigc::connection autoconn;
// CurveEditor* shape; CurveEditor* shape;
// Gtk::Expander* curvexp; Gtk::Expander* curvexp;
double nextBr; double nextBr;
int nextBl; int nextBl;
public: public:
ToneCurve (); ToneCurve ();
virtual ~ToneCurve ();
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
@ -63,9 +62,10 @@ class ToneCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, p
void autoExpChanged (double br, int bl); void autoExpChanged (double br, int bl);
bool autoExpComputed_ (); bool autoExpComputed_ ();
void enableAll (); void enableAll ();
/* void curveChanged (); void curveChanged ();
void expandCurve (bool isExpanded); void expandCurve (bool isExpanded);
bool isCurveExpanded ();*/ bool isCurveExpanded ();
void updateCurveBackgroundHistogram (unsigned* hist);
}; };
#endif #endif

View File

@ -36,7 +36,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) {
lumadenoise = Gtk::manage (new LumaDenoise ()); lumadenoise = Gtk::manage (new LumaDenoise ());
colordenoise = Gtk::manage (new ColorDenoise ()); colordenoise = Gtk::manage (new ColorDenoise ());
sharpening = Gtk::manage (new Sharpening ()); sharpening = Gtk::manage (new Sharpening ());
// lcurve = Gtk::manage (new LCurve ()); lcurve = Gtk::manage (new LCurve ());
colorboost = Gtk::manage (new ColorBoost ()); colorboost = Gtk::manage (new ColorBoost ());
colorshift = Gtk::manage (new ColorShift ()); colorshift = Gtk::manage (new ColorShift ());
distortion = Gtk::manage (new Distortion ()); distortion = Gtk::manage (new Distortion ());
@ -60,7 +60,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) {
addPanel (detailsPanel, sharpening, M("TP_SHARPENING_LABEL")); toolPanels.push_back (sharpening); addPanel (detailsPanel, sharpening, M("TP_SHARPENING_LABEL")); toolPanels.push_back (sharpening);
addPanel (colorPanel, colorboost, M("TP_COLORBOOST_LABEL")); toolPanels.push_back (colorboost); addPanel (colorPanel, colorboost, M("TP_COLORBOOST_LABEL")); toolPanels.push_back (colorboost);
addPanel (colorPanel, colorshift, M("TP_COLORSHIFT_LABEL")); toolPanels.push_back (colorshift); addPanel (colorPanel, colorshift, M("TP_COLORSHIFT_LABEL")); toolPanels.push_back (colorshift);
/* addPanel (exposurePanel, lcurve, M("TP_LUMACURVE_LABEL")); toolPanels.push_back (lcurve);*/ addPanel (exposurePanel, lcurve, M("TP_LUMACURVE_LABEL")); toolPanels.push_back (lcurve);
addPanel (detailsPanel, lumadenoise, M("TP_LUMADENOISE_LABEL")); toolPanels.push_back (lumadenoise); addPanel (detailsPanel, lumadenoise, M("TP_LUMADENOISE_LABEL")); toolPanels.push_back (lumadenoise);
addPanel (detailsPanel, colordenoise, M("TP_COLORDENOISE_LABEL")); toolPanels.push_back (colordenoise); addPanel (detailsPanel, colordenoise, M("TP_COLORDENOISE_LABEL")); toolPanels.push_back (colordenoise);
addPanel (transformPanel, crop, M("TP_CROP_LABEL")); toolPanels.push_back (crop); addPanel (transformPanel, crop, M("TP_CROP_LABEL")); toolPanels.push_back (crop);
@ -249,26 +249,23 @@ void ToolPanelCoordinator::closeImage () {
void ToolPanelCoordinator::readOptions () { void ToolPanelCoordinator::readOptions () {
crop->readOptions (); crop->readOptions ();
/* for (int i=0; i<options.tpOpen.size(); i++) for (int i=0; i<options.tpOpen.size(); i++)
if (i<expList.size()) if (i<expList.size())
expList[i]->set_expanded (options.tpOpen[i]); expList[i]->set_expanded (options.tpOpen[i]);
if (options.crvOpen.size()>1) { if (options.crvOpen.size()>1)
curve->expandCurve (options.crvOpen[0]); curve->expandCurve (options.crvOpen[0]);
lcurve->expandCurve (options.crvOpen[1]);
}*/
} }
void ToolPanelCoordinator::writeOptions () { void ToolPanelCoordinator::writeOptions () {
crop->writeOptions (); crop->writeOptions ();
/* options.tpOpen.clear (); options.tpOpen.clear ();
for (int i=0; i<expList.size(); i++) for (int i=0; i<expList.size(); i++)
options.tpOpen.push_back (expList[i]->get_expanded ()); options.tpOpen.push_back (expList[i]->get_expanded ());
options.crvOpen.clear (); options.crvOpen.clear ();
options.crvOpen.push_back (curve->isCurveExpanded()); options.crvOpen.push_back (curve->isCurveExpanded());
options.crvOpen.push_back (lcurve->isCurveExpanded());*/
} }
@ -353,3 +350,9 @@ int ToolPanelCoordinator::getSpotWBRectSize () {
return whitebalance->getSize (); return whitebalance->getSize ();
} }
void ToolPanelCoordinator::updateCurveBackgroundHistogram (unsigned* histrgb, unsigned* histl) {
curve->updateCurveBackgroundHistogram (histrgb);
lcurve->updateCurveBackgroundHistogram (histl);
}

View File

@ -34,7 +34,7 @@
#include <lumadenoise.h> #include <lumadenoise.h>
#include <colordenoise.h> #include <colordenoise.h>
#include <sharpening.h> #include <sharpening.h>
//#include <lcurve.h> #include <lcurve.h>
#include <exifpanel.h> #include <exifpanel.h>
#include <iptcpanel.h> #include <iptcpanel.h>
#include <crop.h> #include <crop.h>
@ -54,7 +54,7 @@ class ImageEditorCoordinator;
class ToolPanelCoordinator : public ToolPanelListener, class ToolPanelCoordinator : public ToolPanelListener,
public ProfileChangeListener, public ProfileChangeListener,
public WBProvider, public WBProvider,
public RotateListener , public RotateListener,
public SpotWBListener, public SpotWBListener,
public CropPanelListener, public CropPanelListener,
public ICMPanelListener, public ICMPanelListener,
@ -79,7 +79,7 @@ class ToolPanelCoordinator : public ToolPanelListener,
LumaDenoise* lumadenoise; LumaDenoise* lumadenoise;
ColorDenoise* colordenoise; ColorDenoise* colordenoise;
Sharpening* sharpening; Sharpening* sharpening;
// LCurve* lcurve; LCurve* lcurve;
std::vector<PParamsChangeListener*> paramcListeners; std::vector<PParamsChangeListener*> paramcListeners;
@ -109,7 +109,8 @@ class ToolPanelCoordinator : public ToolPanelListener,
ToolPanelCoordinator (); ToolPanelCoordinator ();
~ToolPanelCoordinator (); ~ToolPanelCoordinator ();
bool getChangedState () { return hasChanged; } bool getChangedState () { return hasChanged; }
void updateCurveBackgroundHistogram (unsigned* histrgb, unsigned* histl);
// multiple listeners can be added that are notified on changes (typical: profile panel and the history) // multiple listeners can be added that are notified on changes (typical: profile panel and the history)
void addPParamsChangeListener (PParamsChangeListener* pp) { paramcListeners.push_back (pp); } void addPParamsChangeListener (PParamsChangeListener* pp) { paramcListeners.push_back (pp); }