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)
option (WITH_RAWZOR "Build with Rawzor support" ON)
option (WITH_RAWZOR "Build with Rawzor support" OFF)
add_subdirectory (rtexif)
add_subdirectory (rtengine)

View File

@ -24,264 +24,154 @@
#include <mytime.h>
#include <string.h>
#undef CLIPD
#define CLIPD(a) ((a)>0.0?((a)<1.0?(a):1.0):0.0)
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;
name = iname;
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);
if (p.size()<3) {
kind = 0;
}
token = strtok (NULL, ",; \t\n");
}
N = xv.size ();
x = new double[N];
y = new double[N];
for (int i=0; i<N; i++) {
x[i] = xv[i];
y[i] = yv[i];
}
delete [] buffer;
spline_cubic_set ();
}
Curve::Curve (const char* iname, int iN, double ix[], double iy[]) : islinear(false), isempty(false) {
ypp = NULL;
N = iN;
name = iname;
x = new double[N];
y = new double[N];
for (int i=0; i<N; i++) {
x[i] = ix[i];
y[i] = iy[i];
}
spline_cubic_set ();
}
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 ();
}
}
else {
kind = p[0];
if (kind==-1 || kind==1) {
N = (p.size()-1)/2;
x = new double[N];
y = new double[N];
int ix = 1;
for (int i=0; i<N; i++) {
x[i] = p[ix++];
y[i] = p[ix++];
}
if (kind==1)
spline_cubic_set ();
}
if (kind==2) {
if (p.size()!=8 && p.size()!=9)
kind = 0;
else {
x = new double[9];
for (int i=0; i<4; i++)
x[i] = p[i];
for (int i=4; i<8; i++)
x[i] = (p[i]+100.0)/200.0;
if (p.size()<9)
x[8] = 1.0;
else
x[8] = p[8]/100.0;
}
}
}
}
Curve::~Curve () {
if (x)
delete [] x;
if (y)
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];*/
delete [] x;
delete [] y;
delete [] ypp;
}
void Curve::spline_cubic_set () {
/* double *a;
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)
double* u = new double[N-1];
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)
{
double sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
double p = sig * ypp[i - 1] + 2.0;
ypp[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;
for (int i = 1; i < N - 1; ++i) {
double sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
double p = sig * ypp[i - 1] + 2.0;
ypp[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;
}
ypp[N - 1] = 0.0;
for (int k = N - 2; k >= 0; --k)
ypp[k] = ypp[k] * ypp[k + 1] + u[k];
ypp[N - 1] = 0.0;
for (int k = N - 2; k >= 0; --k)
ypp[k] = ypp[k] * ypp[k + 1] + u[k];
delete [] u;
delete [] u;
}
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])
return y[N-1];
else if (t<x[0])
return y[0];
if (!kind)
return t;
/* 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] > t)
k_hi = k;
else
k_lo = k;
}
double h = x[k_hi] - x[k_lo];
if (islinear)
return y[k_lo] + (t - x[k_lo]) * ( y[k_hi] - y[k_lo] ) / h;
else {
double a = (x[k_hi] - t) / h;
double b = (t - x[k_lo]) / h;
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;
}
/*
if (t>x[N-1])
return y[N-1];
else if (t<x[0])
return y[0];
int ival = N - 2;
for (int i=0; i<N-1; i++)
if (t < x[i+1]) {
ival = i;
break;
if (kind==2) {
if (t<=1e-14)
return 0.0;
double c = -log(2.0)/log(x[2]);
double tv = exp(c*log(t));
double base = pfull (tv, x[8], x[6], x[5]);
double stretched = base<=1e-14 ? 0.0 : exp(log(base)/c);
base = pfull (0.5, x[8], x[6], x[5]);
double fc = base<=1e-14 ? 0.0 : exp(log(base)/c); // value of the curve at the center point
if (t<x[2]) {
// add shadows effect:
double sc = -log(2.0)/log(x[1]/x[2]);
double stv = exp(sc*log(stretched/fc));
double sbase = pfull (stv, x[8], x[7], 0.5);
double sstretched = fc*(sbase<=1e-14 ? 0.0 : exp(log(sbase)/sc));
return sstretched;
}
else {
// add highlights effect:
double hc = -log(2.0)/log((x[3]-x[2])/(1-x[2]));
double htv = exp(hc*log((stretched-fc)/(1-fc)));
double hbase = pfull (htv, x[8], 0.5, x[4]);
double hstretched = fc + (1-fc)*(hbase<=1e-14 ? 0.0 : exp(log(hbase)/hc));
return hstretched;
}
}
//
// In the interval I, the polynomial is in terms of a normalized
// coordinate between 0 and 1.
//
double dt = t - x[ival];
double h = x[ival+1] - x[ival];
else {
if (t>x[N-1])
return y[N-1];
else if (t<x[0])
return y[0];
if (islinear) {
return y[ival] + dt * ( y[ival+1] - y[ival] ) / h;
}
else
return y[ival]
+ dt * ( ( y[ival+1] - y[ival] ) / h
- ( ypp[ival+1] / 6.0E+00 + ypp[ival] / 3.0E+00 ) * h
+ dt * ( 0.5E+00 * ypp[ival]
+ dt * ( ( ypp[ival+1] - ypp[ival] ) / ( 6.0E+00 * h ) ) ) );
*/
/* 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] > t)
k_hi = k;
else
k_lo = k;
}
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) {
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);
}
}
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) {
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 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 ) {
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 = brightness (val, br/100.0);
// if (tcurve)
// val = tcurve->getVal (val);
if (tcurve)
val = tcurve->getVal (val);
if (needigamma)
val = igamma2 (val);
@ -440,6 +239,7 @@ void CurveFactory::updateCurve3 (int* curve, int* ohistogram, const std::vector<
val = 0.0;
dcurve[i] = val;
}
delete tcurve;
/*
if (igamma) {
FILE* f = fopen ("curve.txt","wt");
@ -451,7 +251,7 @@ if (igamma) {
fclose (f);
}
*/
/*
int prev = 0;
for (int i=1; i<=0xffff-skip; i++) {
if (i%skip==0) {
@ -492,148 +292,128 @@ if (igamma) {
for (int i=0; i<=0xffff; i++)
curve[i] = (int) (65535.0 * dcurve[i]);
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 bl = black / 65535.0;
double hi = pow (2.0,-br) + bl;
double def_mul = pow (2.0, defmul);
// compute parameters of the gamma curve
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 mul = 1.099;
double add = 0.099;
// compute parameters of the gamma curve
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 mul = 1.099;
double add = 0.099;
// compute parameters of the "levels" curve
shcompr /= 100.0;
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;
// theoretical maximum of the curve
double D = gamma_>0 ? gamma (def_mul, gamma_, start, slope, mul, add) : def_mul;
double b_upper = solve_upper (m, c, d);
double b_lower = solve_lower (m, c, d);
// a: slope of the curve, black: starting point at the x axis
double a = pow (2.0, ecomp);
// generate curve without contrast (in double)
// Curve* tcurve = curves[type];
Curve* tcurve = new Curve (points);
if (tcurve->isEmpty()) {
delete tcurve;
tcurve = NULL;
}
double* dcurve = new double[65536];
// curve without contrast
double* dcurve = new double[65536];
double bltanh = tanh (b_lower);
double butanh = tanh (b_upper);
if (d * (c - bl) < 1)
hlcompr = 0;
// check if contrast curve is needed
bool needcontrast = contr>0.00001 || contr<-0.00001;
// check if inverse gamma is needed at the end
bool needigamma = !needcontrast && igamma && gamma_>0;
bool needcontrast = contr>0.00001 || contr<-0.00001;
bool needigamma = !needcontrast && igamma && gamma_>0;
// create a curve if needed
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 ) {
double val = (double)i / 65535.0;
val *= ec_mul;
if (gamma_>0)
val = gamma (val, gamma_, start, slope, mul, add);
// double sval = levels (val, b_lower, b_upper, m, c);
// Acceleration:
double sval;
if (val <= m) {
double ttag = 2.0 / (1.0 + exp (-2.0*b_lower*(val-m)/m)) - 1.0;
// 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;
}
// clear array that stores histogram valid before applying the custom curve
if (outBeforeCCurveHistogram)
memset (outBeforeCCurveHistogram, 0, 256*sizeof(int));
for (int i=0; i<=0xffff; i+= i<0xffff-skip ? skip : 1 ) {
// change to [0,1] rage
double val = (double)i / 65535.0;
// apply default multiplier (that is >1 if highlight recovery is on)
val *= def_mul;
if (val<bl)
val = shcompr * sval;
else if (val>hi)
val = (1.0 - hlcompr) + hlcompr * sval;
else if (val<m)
val = (1.0 - shcompr) * d * (val - bl) + shcompr * sval;
else
val = (1.0 - hlcompr) * d * (val - bl) + hlcompr * sval;
if (tcurve)
val = tcurve->getVal (val);
// gamma correction
if (gamma_>0)
val = gamma (val, gamma_, start, slope, mul, add);
// apply base curve, thus, exposure compensation and black point with shadow and highlight protection
val = basecurve (val, a, black, D, hlcompr/100.0, shcompr/100.0);
if (needigamma)
val = igamma2 (val);
// apply brightness curve
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)
val = 1.0;
else if (val<0.0)
val = 0.0;
dcurve[i] = val;
}
// if inverse gamma is needed, do it (standard sRGB inverse gamma is applied)
if (needigamma)
val = igamma2 (val);
int prev = 0;
for (int i=1; i<=0xffff-skip; i++) {
if (i%skip==0) {
prev+=skip;
continue;
// store result in a temporary array
dcurve[i] = CLIPD(val);
}
dcurve[i] = ( dcurve[prev] * (skip - i%skip) + dcurve[prev+skip] * (i%skip) ) / skip;
}
if (needcontrast) {
// compute mean luminance of the image with the curve applied
int sum = 0;
double avg = 0;
for (int i=0; i<=0xffff; i++) {
avg += dcurve[i] * ohistogram[i];
sum += ohistogram[i];
delete tcurve;
// if skip>1, let apply linear interpolation in the skipped points of the curve
int prev = 0;
for (int i=1; i<=0xffff-skip; i++) {
if (i%skip==0) {
prev+=skip;
continue;
}
dcurve[i] = ( dcurve[prev] * (skip - i%skip) + dcurve[prev+skip] * (i%skip) ) / skip;
}
avg /= sum;
// compute contrast parameter
double contr_b = contr / 20;
if (contr_b>=0 && contr_b < 0.00001)
contr_b = 0.00001;
else if (contr_b<0 && contr_b > -0.00001)
contr_b = -0.00001;
if (needcontrast) {
// compute mean luminance of the image with the curve applied
int sum = 0;
double avg = 0;
for (int i=0; i<=0xffff; i++) {
avg += dcurve[i] * histogram[i];
sum += histogram[i];
}
avg /= sum;
// 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);
if (val>1.0) val = 1.0;
if (val<0.0) val = 0.0;
curve[i] = (int) (65535.0 * val);
// compute contrast parameter
double contr_b = contr / 20;
if (contr_b>=0 && contr_b < 0.00001)
contr_b = 0.00001;
else if (contr_b<0 && contr_b > -0.00001)
contr_b = -0.00001;
// 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
for (int i=0; i<=0xffff; 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);
//}
else
for (int i=0; i<=0xffff; i++)
outCurve[i] = (int) (65535.0 * dcurve[i]);
delete [] dcurve;
}
int CurveFactory::gammatab [65536];
int CurveFactory::igammatab_srgb [65536];
int CurveFactory::gammatab_srgb [65536];
void CurveFactory::loadCurves (Glib::ustring fname) {
void CurveFactory::init () {
for (int i=0; i<65536; i++)
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));
for (int i=0; i<65536; i++)
gammatab[i] = (int)(65535 * pow (i/65535.0, 0.454545));
FILE* f = g_fopen (fname.c_str(), "rt");
if (!f)
return;
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, "");
/* FILE* f = fopen ("c.txt", "wt");
for (int i=0; i<256; i++)
fprintf (f, "%g %g\n", i/255.0, clower (i/255.0, 2.0, 1.0));
fclose (f);*/
}
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 {
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 {
friend class Curve;
protected:
static std::map<std::string, Curve*> curves;
static int gammatab[65536];
// look-up tables for the standard srgb gamma and its inverse (filled by init())
static int igammatab_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_lower (double m, double c, double deriv);
static double dupper (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) {
if (x==0.0)
return 0.0;
@ -74,9 +53,11 @@ class CurveFactory {
double lx = log(x);
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) {
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) {
if (hr>1.0)
return baseu (x, m, 2.0*(hr-1.0)/m);
@ -86,10 +67,12 @@ class CurveFactory {
if (x<x1) return x*m;
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) {
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 y = (D-b)*a<0.5 ? (D-b)*a : 0.5;
if (x<=m)
@ -99,12 +82,14 @@ class CurveFactory {
else
return y+(x-m)*a;
}
// brightness curve at point x, only positive amount it supported
static inline double brightnessbase (double x, double amount) {
if (x<0.5)
return x + amount*cupper(2.0*x, 4.5, 0.0)/3.0;
else
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) {
if (amount==0)
return x;
@ -113,34 +98,60 @@ class CurveFactory {
else
return 1.0 - brightnessbase (1.0-x, -amount);
}
public:
static inline double softClip (double x, double d1, double d2, double a, double b, double c, double d);
static inline double contrast (double x, double a);
static void init ();
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){
return (x <= start ? x*slope : exp(log(x)/gamma)*mul-add);
}
// standard srgb gamma and its inverse
static inline double gamma2 (double x) {
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) {
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:
static void loadCurves (Glib::ustring fname);
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 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 ();
// 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 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);
};
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
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));
int radd = 4;
int gadd = 2;

View File

@ -83,7 +83,7 @@ class ImageSource : public InitialImage {
void increaseRef () { references++; }
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
virtual Glib::ustring getFileName () { return fileName; }

View File

@ -154,7 +154,7 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
if (todo & M_AUTOEXP) {
if (params.toneCurve.autoexp) {
int aehist[65536]; int aehistcompr;
unsigned int aehist[65536]; int aehistcompr;
imgsrc->getAEHistogram (aehist, aehistcompr);
ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, params.toneCurve.expcomp, params.toneCurve.black);
if (aeListener)
@ -163,7 +163,7 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
}
progress ("Exposure curve & CIELAB conversion...",100*readyphase/numofphases);
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);
// recompute luminance histogram
@ -177,7 +177,7 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
readyphase++;
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) {
@ -246,7 +246,7 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
hy2 = MIN(pH,MAX(0,(params.crop.y+params.crop.h) / scale));
}
updateHistograms (hx1, hy1, hx2, hy2);
hListener->histogramChanged (rhist, ghist, bhist, Lhist);
hListener->histogramChanged (rhist, ghist, bhist, Lhist, bcrgbhist, bcLhist);
}
t9.set ();

View File

@ -64,10 +64,10 @@ class ImProcCoordinator : public StagedImageProcessor {
int tonecurve [65536];
int lumacurve [65536];
int vhist16[65536];
int lhist16[65536];
unsigned int vhist16[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 pW, pH;

View File

@ -187,7 +187,7 @@ void ImProcFunctions::release () {
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);
int toxyz[3][3];
@ -242,11 +242,11 @@ void ImProcFunctions::firstAnalysis_ (Image16* original, Glib::ustring wprofile,
*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* hist1 = new int[65536]; memset (hist1, 0, 65536*sizeof(int));
int* hist2 = new int[65536]; memset (hist2, 0, 65536*sizeof(int));
unsigned int* hist1 = new unsigned int[65536]; memset (hist1, 0, 65536*sizeof(int));
unsigned int* hist2 = new unsigned int[65536]; memset (hist2, 0, 65536*sizeof(int));
int H = original->height;
@ -366,8 +366,6 @@ void ImProcFunctions::rgbProc_ (Image16* working, LabImage* lab, const ProcParam
b = CLIP((int)(factor*b-sub));
}
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));
g = CLIP((int)(factor*g));
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;
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 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 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 damping_ (float** aI, unsigned short** aO, float damping, int W, int rowfrom, int rowto);
@ -86,7 +86,7 @@ class ImProcFunctions {
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 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);
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

View File

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

View File

@ -28,7 +28,6 @@ namespace procparams {
ProcParams::ProcParams () {
setDefaults ();
}
ProcParams* ProcParams::create () {
@ -55,9 +54,6 @@ void ProcParams::setDefaults () {
lumaCurve.brightness = 0;
lumaCurve.contrast = 0;
lumaCurve.black = 0;
lumaCurve.hlcompr = 0;
lumaCurve.shcompr = 0;
lumaCurve.curve.clear ();
sharpening.enabled = true;
@ -170,7 +166,7 @@ int ProcParams::save (Glib::ustring fname) const {
keyFile.set_boolean ("Exposure", "Auto", toneCurve.autoexp);
keyFile.set_double ("Exposure", "Clip", toneCurve.clip);
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", "Black", toneCurve.black);
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);
// 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", "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;
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", "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", "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", "Black")) toneCurve.black = keyFile.get_integer ("Exposure", "Black");
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
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", "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 (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 (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
@ -569,10 +559,7 @@ bool ProcParams::operator== (const ProcParams& other) {
&& toneCurve.expcomp == other.toneCurve.expcomp
&& lumaCurve.curve == other.lumaCurve.curve
&& lumaCurve.brightness == other.lumaCurve.brightness
&& lumaCurve.black == other.lumaCurve.black
&& lumaCurve.contrast == other.lumaCurve.contrast
&& lumaCurve.shcompr == other.lumaCurve.shcompr
&& lumaCurve.hlcompr == other.lumaCurve.hlcompr
&& sharpening.enabled == other.sharpening.enabled
&& sharpening.radius == other.sharpening.radius
&& sharpening.amount == other.sharpening.amount

View File

@ -26,28 +26,31 @@ namespace rtengine {
namespace procparams {
/**
* Common parameters of the tone curve and the luminance curve
* Parameters of the tone curve
*/
class CurveParams {
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 {
class ToneCurveParams {
public:
bool autoexp;
double clip;
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:
ToneCurveParams toneCurve; ///< Tone curve parameters
CurveParams lumaCurve; ///< CIELAB luminance curve parameters
LCurveParams lumaCurve; ///< CIELAB luminance curve parameters
SharpeningParams sharpening; ///< Sharpening parameters
ColorBoostParams colorBoost; ///< Color boost 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);
}
int RawImageSource::getAEHistogram (int* histogram, int& histcompr) {
int RawImageSource::getAEHistogram (unsigned int* histogram, int& histcompr) {
histcompr = 3;

View File

@ -112,7 +112,7 @@ class RawImageSource : public ImageSource {
ImageData* getImageData () { return idata; }
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 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 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 */
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). */

View File

@ -100,7 +100,7 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
// histogram computation
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));
int ix = 0;
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;
rmi = 1024.0 * rm * 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 {
rmi = 1024.0 * rm / mul_lum;
@ -213,7 +213,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
else
rwidth = thumbImg->width * rheight / thumbImg->height;
Image16* baseImg = thumbImg->resize (rwidth, rheight, interp);
Image16* baseImg = thumbImg->resize (rwidth, rheight, interp);
if (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;
ImProcFunctions ipf;
int* hist16 = new int [65536];
unsigned int* hist16 = new unsigned int [65536];
ipf.firstAnalysis (baseImg, &params, hist16, isRaw ? 2.2 : 0.0);
// 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);
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);
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]]++;
// 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);
delete [] curve;
@ -866,7 +867,7 @@ bool Thumbnail::readAEHistogram (const Glib::ustring& fname) {
if (!f)
aeHistogram = NULL;
else {
aeHistogram = new int[65536>>aeHistCompression];
aeHistogram = new unsigned int[65536>>aeHistCompression];
fread (aeHistogram, 1, (65536>>aeHistCompression)*sizeof(int), f);
fclose (f);
return true;

View File

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

View File

@ -88,7 +88,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
pl->setProgress (0.25);
// perform first analysis
int* hist16 = new int[65536];
unsigned int* hist16 = new unsigned int[65536];
ipf.firstAnalysis (baseImg, &params, hist16, imgsrc->getGamma());
// perform transform
@ -126,13 +126,14 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
int bl = params.toneCurve.black;
if (params.toneCurve.autoexp) {
int aehist[65536]; int aehistcompr;
unsigned int aehist[65536]; int aehistcompr;
imgsrc->getAEHistogram (aehist, aehistcompr);
ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, br, bl);
}
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);
ipf.rgbProc (baseImg, labView, &params, curve, shmap);
@ -150,7 +151,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
hist16[labView->L[i][j]]++;
// 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.lumadenoise (labView, &params, 1, 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);
}
*/
int StdImageSource::getAEHistogram (int* histogram, int& histcompr) {
int StdImageSource::getAEHistogram (unsigned int* histogram, int& histcompr) {
histcompr = 3;

View File

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

View File

@ -19,55 +19,125 @@
#include <curveeditor.h>
#include <fstream>
#include <string>
#include <guiutils.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));
af->add (*curve);
curve->set_size_request (-1, 200);
pack_start (*af, Gtk::PACK_EXPAND_WIDGET);
af->add (*customCurve);
customCurve->set_size_request (-1, 200);
customCurve->setType (Spline);
customCurveBox->pack_start (*af, Gtk::PACK_EXPAND_WIDGET);
Gtk::HBox* bbox = Gtk::manage (new Gtk::HBox ());
linear = Gtk::manage (new Gtk::Button (M("CURVEEDITOR_LINEAR")));
save = Gtk::manage (new Gtk::Button ());
Gtk::Image* saveImg = Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON));
saveImg->show ();
save->add (*saveImg);
save->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)));
load = Gtk::manage (new Gtk::Button ());
Gtk::Image* loadImg = Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-open"), Gtk::ICON_SIZE_BUTTON));
loadImg->show ();
load->add (*loadImg);
load->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-open"), Gtk::ICON_SIZE_BUTTON)));
bbox->pack_start (*linear);
bbox->pack_end (*save, Gtk::PACK_SHRINK, 4);
bbox->pack_end (*load, Gtk::PACK_SHRINK, 4);
bbox->pack_end (*save, Gtk::PACK_EXPAND_WIDGET, 4);
bbox->pack_end (*load, Gtk::PACK_EXPAND_WIDGET, 4);
pack_end (*bbox, Gtk::PACK_SHRINK, 2);
show_all ();
customCurveBox->pack_end (*bbox, Gtk::PACK_SHRINK, 2);
customCurveBox->show_all ();
linear->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::linearPressed) );
save->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::savePressed) );
load->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::loadPressed) );
linear->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLINEAR"));
save->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
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);
lcurve[0] = 1.0;
lcurve[1] = 0.0;
lcurve[2] = 0.0;
lcurve[3] = 1.0;
lcurve[4] = 1.0;
curve->setPoints (lcurve);
curve->queue_draw ();
curve->notifyListener ();
delete customCurveBox;
delete paramCurveBox;
}
void CurveEditor::savePressed () {
@ -99,18 +169,7 @@ void CurveEditor::savePressed () {
std::string fname = dialog.get_filename();
bool hasext = true;
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)
if (getExtension (fname)!="rtc")
fname = fname + ".rtc";
if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) {
@ -122,7 +181,7 @@ void CurveEditor::savePressed () {
}
std::ofstream f (fname.c_str());
std::vector<double> p = curve->getPoints ();
std::vector<double> p = customCurve->getPoints ();
int ix = 0;
if (p[ix++]<0)
f << "Linear\n";
@ -170,25 +229,165 @@ void CurveEditor::loadPressed () {
if (f)
p.push_back (x);
}
curve->setPoints (p);
curve->queue_draw ();
curve->notifyListener ();
customCurve->setPoints (p);
customCurve->queue_draw ();
customCurve->notifyListener ();
}
}
}
void CurveEditor::on_realize () {
Gtk::VBox::on_realize();
realized = true;
setCurve (tmpCurve);
}
void CurveEditor::setCurve (const std::vector<double>& c) {
if (c.size()>4) {
curve->setPoints (c);
curve->queue_draw ();
tmpCurve = c;
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 () {
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 <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::Button* linear;
Gtk::ComboBoxText* curveType;
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* load;
CurveListener* cl;
bool realized;
std::vector<double> tmpCurve;
int curveTypeIx;
int activeParamControl;
sigc::connection typeconn;
public:
CurveEditor ();
void setCurveListener (CurveListener* cl) { curve->setCurveListener (cl); }
void linearPressed ();
virtual ~CurveEditor ();
void setBatchMode (bool batchMode);
bool isUnChanged ();
void setUnChanged (bool uc);
void on_realize ();
void setCurveListener (CurveListener* l) { cl = l; }
void savePressed ();
void loadPressed ();
void typeSelectionChanged ();
void setCurve (const std::vector<double>& c);
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->setPreviewScale (10);
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->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 rtengine::ProgressListener,
public ThumbnailListener,
public HistoryBeforeLineListener {
public HistoryBeforeLineListener,
public rtengine::HistogramListener {
protected:
Gtk::Label *progressLabel;
@ -121,6 +122,9 @@ class EditorPanel : public Gtk::VBox,
// HistoryBeforeLineListener
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
void info_toggled ();
void hideHistoryActivated ();

View File

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

View File

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

View File

@ -51,7 +51,7 @@ void ImageArea::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;
cfo.set_antialias (Cairo::ANTIALIAS_SUBPIXEL);

View File

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

View File

@ -17,11 +17,13 @@
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mycurve.h>
#include <curves.h>
#include <string.h>
#define RADIUS 3 /* radius of the 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;
curve.type = Spline;
@ -36,373 +38,340 @@ MyCurve::MyCurve () : listener(NULL) {
curve.x.push_back(1);
curve.y.push_back(1);
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[]) {
double* u = new double[n-1];
y2[0] = u[0] = 0.0; /* set lower boundary condition to "natural" */
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;
MyCurve::~MyCurve () {
if (mcih->pending)
mcih->destroyed = true;
else
delete mcih;
}
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> 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: */
double prev =- 1.0;
int active = 0;
int firstact = -1;
for (int i = 0; i < num; ++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.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;
// calculate remaining points
std::vector<double> curveDescr = getPoints ();
rtengine::Curve* rtcurve = new rtengine::Curve (curveDescr);
std::vector<double> t;
t.resize (veclen);
for (int i = 0; i < veclen; i++)
t[i] = (double) i / (veclen - 1.0);
rtcurve->getVal (t, vector);
delete rtcurve;
return vector;
}
void MyCurve::interpolate (int width, int height) {
this->height = height;
point.clear ();
std::vector<double> vector = get_vector (width);
this->height = height;
for (int i = 0; i < width; ++i) {
Gdk::Point p (RADIUS + i, RADIUS + height - (int)((height-1) * vector[i] + 0.5));
point.push_back (p);
}
}
this->height = height;
point.resize (width);
std::vector<double> vector = get_vector (width);
this->height = height;
for (int i = 0; i < width; ++i)
point[i] = Gdk::Point (RADIUS + i, RADIUS + height - (int)((height-1) * vector[i] + 0.5));
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) {
if (!pixmap)
return;
if (!pixmap)
return;
if (this->height != height || point.size() != width)
interpolate (width, height);
// re-calculate curve if dimensions changed
if (this->height != height || point.size() != width)
interpolate (width, height);
Gtk::StateType state = Gtk::STATE_NORMAL;
if (!is_sensitive())
state = Gtk::STATE_INSENSITIVE;
Gtk::StateType state = Gtk::STATE_NORMAL;
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: */
// gtk_paint_flat_box (style->gobj(), pixmap->gobj(), GTK_STATE_NORMAL, GTK_SHADOW_NONE,
// NULL, (GtkWidget*)gobj(), "curve_bg", 0, 0, , height + RADIUS * 2);
// histogram in the background
if (bghistvalid) {
// 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_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 ();
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
cr->set_line_width (1.0);
/* draw the grid lines: (XXX make more meaningful) */
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);
// 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 ();
// draw upper and lower bounds
if (curve.type==Parametric && activeParam>0 && lpoint.size()>1 && upoint.size()>1) {
cr->set_source_rgba (0.0, 0.0, 0.0, 0.15);
cr->move_to (upoint[0].get_x(), upoint[0].get_y());
for (int i=1; i<upoint.size(); 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());
for (int i=lpoint.size()-2; i>=0; i--)
cr->line_to (lpoint[i].get_x(), lpoint[i].get_y());
cr->line_to (upoint[0].get_x(), upoint[0].get_y());
cr->fill ();
}
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
cr->set_line_width (1.0);
cr->set_source_rgb (0.0, 0.0, 0.0);
cr->move_to (point[0].get_x(), point[0].get_y());
for (int i=1; i<point.size(); i++)
cr->line_to (point[i].get_x(), point[i].get_y());
cr->stroke ();
// draw curve
cr->set_source_rgb (0.0, 0.0, 0.0);
cr->move_to (point[0].get_x(), point[0].get_y());
for (int i=1; i<point.size(); i++)
cr->line_to (point[i].get_x(), point[i].get_y());
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);
double y = height - ((height-1) * curve.y[i] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, height);
cr->arc (x, y, RADIUS, 0, 2*M_PI);
cr->fill ();
}
/* draw a bullet: */
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);
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) {
Gdk::CursorType new_type = cursor_type;
int src, dst;
GdkEventMotion *mevent;
std::vector<double>::iterator itx, ity;
Gdk::CursorType new_type = cursor_type;
int src, dst;
GdkEventMotion *mevent;
std::vector<double>::iterator itx, ity;
bool retval = false;
bool retval = false;
int width = get_allocation().get_width() - RADIUS * 2;
int height = get_allocation().get_height() - RADIUS * 2;
int width = get_allocation().get_width() - RADIUS * 2;
int height = get_allocation().get_height() - RADIUS * 2;
if ((width < 0) || (height < 0))
return false;
if ((width < 0) || (height < 0))
return false;
/* get the pointer position */
int tx, ty;
Gdk::ModifierType gm;
get_window()->get_pointer (tx, ty, gm);
int x = CLAMP ((tx - RADIUS), 0, width-1);
int y = CLAMP ((ty - RADIUS), 0, height-1);
/* get the pointer position */
int tx, ty;
Gdk::ModifierType gm;
get_window()->get_pointer (tx, ty, gm);
int x = CLAMP ((tx - RADIUS), 0, width-1);
int y = CLAMP ((ty - RADIUS), 0, height-1);
unsigned int distance = ~0U;
int num = curve.x.size();
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);
unsigned int distance = ~0U;
int num = curve.x.size();
int closest_point = 0;
int rightbound = width + RADIUS * 2 + MIN_DISTANCE;
if (grab_point + 1 < num)
rightbound = (int)((width-1)*curve.x[grab_point+1]+0.5);
if (curve.type!=Parametric) {
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;
}
}
}
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 ();
}
break;
}
switch (event->type) {
case Gdk::CONFIGURE:
if (pixmap)
pixmap.clear ();
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:
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) {
cursor_type = new_type;
@ -410,49 +379,63 @@ bool MyCurve::handleEvents (GdkEvent* event) {
get_window ()->set_cursor (*cursor);
delete cursor;
}
retval = true;
break;
default:
break;
}
return retval;
}
std::vector<double> MyCurve::getPoints () {
std::vector<double> result;
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) {
if (curve.type==Parametric) {
result.push_back (+2.0);
for (int i=0; i<curve.x.size(); 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;
}
void MyCurve::setPoints (const std::vector<double>& p) {
int ix = 0;
if (p[ix++]>0)
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++]);
int t = p[ix++];
if (t==2) {
curve.type = Parametric;
curve.x.clear ();
curve.y.clear ();
for (int i=1; i<p.size(); i++)
curve.x.push_back (p[ix++]);
}
else {
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 ();
bool pi = pixmap;
queue_draw ();
}
void MyCurve::setType (CurveType t) {
@ -462,6 +445,52 @@ void MyCurve::setType (CurveType t) {
}
void MyCurve::notifyListener () {
if (listener)
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 <vector>
#include <curvelistener.h>
class CurveListener {
public:
virtual void curveChanged () {}
};
enum CurveType {Linear, Spline};
enum CurveType {Linear, Spline, Parametric};
class CurveDescr {
public:
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 {
friend int mchistupdate (void* data);
protected:
CurveListener* listener;
CurveDescr curve;
Gdk::CursorType cursor_type;
@ -47,16 +52,20 @@ class MyCurve : public Gtk::DrawingArea {
int grab_point;
int last;
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 interpolate (int width, int height);
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:
MyCurve ();
~MyCurve ();
void setCurveListener (CurveListener* cl) { listener = cl; }
std::vector<double> getPoints ();
@ -64,6 +73,8 @@ class MyCurve : public Gtk::DrawingArea {
void setType (CurveType t);
bool handleEvents (GdkEvent* event);
void notifyListener ();
void setActiveParam (int ac);
void updateBackgroundHistogram (unsigned int* hist);
};
#endif

View File

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

View File

@ -19,6 +19,7 @@
#include <paramsedited.h>
#include <string.h>
#include <options.h>
#include <addsetids.h>
ParamsEdited::ParamsEdited () {
@ -38,10 +39,7 @@ void ParamsEdited::set (bool v) {
toneCurve.expcomp = v;
lumaCurve.curve = v;
lumaCurve.brightness = v;
lumaCurve.black = v;
lumaCurve.contrast = v;
lumaCurve.shcompr = v;
lumaCurve.hlcompr = v;
sharpening.enabled = v;
sharpening.radius = 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;
lumaCurve.curve = lumaCurve.curve && p.lumaCurve.curve == other.lumaCurve.curve;
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.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.radius = sharpening.radius && p.sharpening.radius == other.sharpening.radius;
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) {
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.black) toEdit.toneCurve.black = options.baBehav[2] ? 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.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[ADDSET_TC_BLACKLEVEL] ? toEdit.toneCurve.black + mods.toneCurve.black : mods.toneCurve.black;
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.hlcompr) toEdit.toneCurve.hlcompr = mods.toneCurve.hlcompr;
if (toneCurve.autoexp) toEdit.toneCurve.autoexp = mods.toneCurve.autoexp;
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.brightness) toEdit.lumaCurve.brightness = mods.lumaCurve.brightness;
if (lumaCurve.black) toEdit.lumaCurve.black = mods.lumaCurve.black;
if (lumaCurve.contrast) toEdit.lumaCurve.contrast = mods.lumaCurve.contrast;
if (lumaCurve.shcompr) toEdit.lumaCurve.shcompr = mods.lumaCurve.shcompr;
if (lumaCurve.hlcompr) toEdit.lumaCurve.hlcompr = mods.lumaCurve.hlcompr;
if (sharpening.enabled) toEdit.sharpening.enabled = mods.sharpening.enabled;
if (sharpening.radius) toEdit.sharpening.radius = mods.sharpening.radius;
if (sharpening.amount) toEdit.sharpening.amount = options.baBehav[10] ? toEdit.sharpening.amount + mods.sharpening.amount : mods.sharpening.amount;
if (sharpening.threshold) toEdit.sharpening.threshold = mods.sharpening.threshold;
if (sharpening.edgesonly) toEdit.sharpening.edgesonly = mods.sharpening.edgesonly;
if (sharpening.edges_radius) toEdit.sharpening.edges_radius = mods.sharpening.edges_radius;
if (sharpening.edges_tolerance) toEdit.sharpening.edges_tolerance = mods.sharpening.edges_tolerance;
if (sharpening.halocontrol) toEdit.sharpening.halocontrol = mods.sharpening.halocontrol;
if (sharpening.halocontrol_amount) toEdit.sharpening.halocontrol_amount = mods.sharpening.halocontrol_amount;
if (sharpening.method) toEdit.sharpening.method = mods.sharpening.method;
if (sharpening.deconvamount) toEdit.sharpening.deconvamount = options.baBehav[10] ? toEdit.sharpening.deconvamount + mods.sharpening.deconvamount : mods.sharpening.deconvamount;
if (sharpening.deconvradius) toEdit.sharpening.deconvradius = mods.sharpening.deconvradius;
if (sharpening.deconviter) toEdit.sharpening.deconviter = mods.sharpening.deconviter;
if (sharpening.deconvdamping) toEdit.sharpening.deconvdamping = mods.sharpening.deconvdamping;
if (colorBoost.amount) toEdit.colorBoost.amount = options.baBehav[14] ? toEdit.colorBoost.amount + mods.colorBoost.amount : mods.colorBoost.amount;
if (colorBoost.avoidclip) toEdit.colorBoost.avoidclip = mods.colorBoost.avoidclip;
if (colorBoost.enable_saturationlimiter) toEdit.colorBoost.enable_saturationlimiter = mods.colorBoost.enable_saturationlimiter;
if (colorBoost.saturationlimit) toEdit.colorBoost.saturationlimit = mods.colorBoost.saturationlimit;
if (wb.method) toEdit.wb.method = mods.wb.method;
if (wb.green) toEdit.wb.green = options.baBehav[13] ? toEdit.wb.green + mods.wb.green : mods.wb.green;
if (wb.temperature) toEdit.wb.temperature = options.baBehav[12] ? toEdit.wb.temperature + mods.wb.temperature : mods.wb.temperature;
if (colorShift.a) toEdit.colorShift.a = options.baBehav[15] ? toEdit.colorShift.a + mods.colorShift.a : mods.colorShift.a;
if (colorShift.b) toEdit.colorShift.b = options.baBehav[16] ? toEdit.colorShift.b + mods.colorShift.b : mods.colorShift.b;
if (lumaDenoise.enabled) toEdit.lumaDenoise.enabled = mods.lumaDenoise.enabled;
if (lumaDenoise.radius) toEdit.lumaDenoise.radius = mods.lumaDenoise.radius;
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 (lumaCurve.brightness) toEdit.lumaCurve.brightness = options.baBehav[ADDSET_LC_BRIGHTNESS] ? toEdit.lumaCurve.brightness + mods.lumaCurve.brightness : mods.lumaCurve.brightness;
if (lumaCurve.contrast) toEdit.lumaCurve.contrast = options.baBehav[ADDSET_LC_CONTRAST] ? toEdit.lumaCurve.contrast + mods.lumaCurve.contrast : mods.lumaCurve.contrast;
if (sharpening.enabled) toEdit.sharpening.enabled = mods.sharpening.enabled;
if (sharpening.radius) toEdit.sharpening.radius = mods.sharpening.radius;
if (sharpening.amount) toEdit.sharpening.amount = options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.amount + mods.sharpening.amount : mods.sharpening.amount;
if (sharpening.threshold) toEdit.sharpening.threshold = mods.sharpening.threshold;
if (sharpening.edgesonly) toEdit.sharpening.edgesonly = mods.sharpening.edgesonly;
if (sharpening.edges_radius) toEdit.sharpening.edges_radius = mods.sharpening.edges_radius;
if (sharpening.edges_tolerance) toEdit.sharpening.edges_tolerance = mods.sharpening.edges_tolerance;
if (sharpening.halocontrol) toEdit.sharpening.halocontrol = mods.sharpening.halocontrol;
if (sharpening.halocontrol_amount) toEdit.sharpening.halocontrol_amount = mods.sharpening.halocontrol_amount;
if (sharpening.method) toEdit.sharpening.method = mods.sharpening.method;
if (sharpening.deconvamount) toEdit.sharpening.deconvamount = options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.deconvamount + mods.sharpening.deconvamount : mods.sharpening.deconvamount;
if (sharpening.deconvradius) toEdit.sharpening.deconvradius = mods.sharpening.deconvradius;
if (sharpening.deconviter) toEdit.sharpening.deconviter = mods.sharpening.deconviter;
if (sharpening.deconvdamping) toEdit.sharpening.deconvdamping = mods.sharpening.deconvdamping;
if (colorBoost.amount) toEdit.colorBoost.amount = options.baBehav[ADDSET_CBOOST_AMOUNT] ? toEdit.colorBoost.amount + mods.colorBoost.amount : mods.colorBoost.amount;
if (colorBoost.avoidclip) toEdit.colorBoost.avoidclip = mods.colorBoost.avoidclip;
if (colorBoost.enable_saturationlimiter)toEdit.colorBoost.enable_saturationlimiter = mods.colorBoost.enable_saturationlimiter;
if (colorBoost.saturationlimit) toEdit.colorBoost.saturationlimit = mods.colorBoost.saturationlimit;
if (wb.method) toEdit.wb.method = mods.wb.method;
if (wb.green) toEdit.wb.green = options.baBehav[ADDSET_WB_GREEN] ? toEdit.wb.green + mods.wb.green : mods.wb.green;
if (wb.temperature) toEdit.wb.temperature = options.baBehav[ADDSET_WB_TEMPERATURE] ? toEdit.wb.temperature + mods.wb.temperature : mods.wb.temperature;
if (colorShift.a) toEdit.colorShift.a = options.baBehav[ADDSET_CS_BLUEYELLOW] ? toEdit.colorShift.a + mods.colorShift.a : mods.colorShift.a;
if (colorShift.b) toEdit.colorShift.b = options.baBehav[ADDSET_CS_GREENMAGENTA] ? toEdit.colorShift.b + mods.colorShift.b : mods.colorShift.b;
if (lumaDenoise.enabled) toEdit.lumaDenoise.enabled = mods.lumaDenoise.enabled;
if (lumaDenoise.radius) toEdit.lumaDenoise.radius = mods.lumaDenoise.radius;
if (lumaDenoise.edgetolerance) toEdit.lumaDenoise.edgetolerance = options.baBehav[ADDSET_LD_EDGETOLERANCE] ? 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.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.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.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 (crop.enabled) toEdit.crop.enabled = mods.crop.enabled;
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 (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 (distortion.amount) toEdit.distortion.amount = options.baBehav[18] ? 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.blue) toEdit.cacorrection.blue = options.baBehav[20] ? 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 (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[ADDSET_CA_RED] ? toEdit.cacorrection.red + mods.cacorrection.red : mods.cacorrection.red;
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[ADDSET_VIGN_AMOUNT] ? toEdit.vignetting.amount + mods.vignetting.amount : mods.vignetting.amount;
if (vignetting.radius) toEdit.vignetting.radius = mods.vignetting.radius;
if (chmixer.red[0]) toEdit.chmixer.red[0] = mods.chmixer.red[0];
if (chmixer.red[1]) toEdit.chmixer.red[1] = mods.chmixer.red[1];

View File

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

View File

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

View File

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

View File

@ -22,10 +22,10 @@
#include <gtkmm.h>
#include <adjuster.h>
#include <toolpanel.h>
//#include <curveeditor.h>
//#include <mycurve.h>
#include <curveeditor.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:
Gtk::HBox* abox;
@ -39,15 +39,14 @@ class ToneCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, p
Adjuster* contrast;
bool expAdd, blackAdd, brAdd, contrAdd, clipDirty, lastAuto;
sigc::connection autoconn;
// CurveEditor* shape;
// Gtk::Expander* curvexp;
CurveEditor* shape;
Gtk::Expander* curvexp;
double nextBr;
int nextBl;
public:
ToneCurve ();
virtual ~ToneCurve ();
void read (const rtengine::procparams::ProcParams* pp, const 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);
bool autoExpComputed_ ();
void enableAll ();
/* void curveChanged ();
void curveChanged ();
void expandCurve (bool isExpanded);
bool isCurveExpanded ();*/
bool isCurveExpanded ();
void updateCurveBackgroundHistogram (unsigned* hist);
};
#endif

View File

@ -36,7 +36,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) {
lumadenoise = Gtk::manage (new LumaDenoise ());
colordenoise = Gtk::manage (new ColorDenoise ());
sharpening = Gtk::manage (new Sharpening ());
// lcurve = Gtk::manage (new LCurve ());
lcurve = Gtk::manage (new LCurve ());
colorboost = Gtk::manage (new ColorBoost ());
colorshift = Gtk::manage (new ColorShift ());
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 (colorPanel, colorboost, M("TP_COLORBOOST_LABEL")); toolPanels.push_back (colorboost);
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, colordenoise, M("TP_COLORDENOISE_LABEL")); toolPanels.push_back (colordenoise);
addPanel (transformPanel, crop, M("TP_CROP_LABEL")); toolPanels.push_back (crop);
@ -249,26 +249,23 @@ void ToolPanelCoordinator::closeImage () {
void ToolPanelCoordinator::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())
expList[i]->set_expanded (options.tpOpen[i]);
if (options.crvOpen.size()>1) {
if (options.crvOpen.size()>1)
curve->expandCurve (options.crvOpen[0]);
lcurve->expandCurve (options.crvOpen[1]);
}*/
}
void ToolPanelCoordinator::writeOptions () {
crop->writeOptions ();
/* options.tpOpen.clear ();
options.tpOpen.clear ();
for (int i=0; i<expList.size(); i++)
options.tpOpen.push_back (expList[i]->get_expanded ());
options.crvOpen.clear ();
options.crvOpen.push_back (curve->isCurveExpanded());
options.crvOpen.push_back (lcurve->isCurveExpanded());*/
}
@ -353,3 +350,9 @@ int ToolPanelCoordinator::getSpotWBRectSize () {
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 <colordenoise.h>
#include <sharpening.h>
//#include <lcurve.h>
#include <lcurve.h>
#include <exifpanel.h>
#include <iptcpanel.h>
#include <crop.h>
@ -54,7 +54,7 @@ class ImageEditorCoordinator;
class ToolPanelCoordinator : public ToolPanelListener,
public ProfileChangeListener,
public WBProvider,
public RotateListener ,
public RotateListener,
public SpotWBListener,
public CropPanelListener,
public ICMPanelListener,
@ -79,7 +79,7 @@ class ToolPanelCoordinator : public ToolPanelListener,
LumaDenoise* lumadenoise;
ColorDenoise* colordenoise;
Sharpening* sharpening;
// LCurve* lcurve;
LCurve* lcurve;
std::vector<PParamsChangeListener*> paramcListeners;
@ -109,7 +109,8 @@ class ToolPanelCoordinator : public ToolPanelListener,
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)
void addPParamsChangeListener (PParamsChangeListener* pp) { paramcListeners.push_back (pp); }