New curve editor, first batch (parametric curves, overlaid histogram in curve area)
This commit is contained in:
parent
fbcf2a187b
commit
71b74bbfd2
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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; }
|
||||
|
@ -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, ¶ms, 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 ();
|
||||
|
@ -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;
|
||||
|
@ -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++)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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). */
|
||||
|
@ -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, ¶ms, 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, ¶ms, 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;
|
||||
|
@ -46,7 +46,7 @@ namespace rtengine {
|
||||
double camwbBlue;
|
||||
double autowbTemp;
|
||||
double autowbGreen;
|
||||
int* aeHistogram;
|
||||
unsigned int* aeHistogram;
|
||||
int aeHistCompression;
|
||||
int embProfileLength;
|
||||
unsigned char* embProfileData;
|
||||
|
@ -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, ¶ms, 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, ¶ms, 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, ¶ms, 1, buffer);
|
||||
ipf.sharpening (labView, ¶ms, 1, (unsigned short**)buffer);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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
28
rtgui/addsetids.h
Normal 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
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
28
rtgui/curvelistener.h
Normal 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
|
@ -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);
|
||||
}
|
||||
|
@ -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 ();
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
#include <histogrampanel.h>
|
||||
#include <multilangmgr.h>
|
||||
#include <string.h>
|
||||
|
||||
HistogramPanel::HistogramPanel () {
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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);
|
||||
|
105
rtgui/lcurve.cc
105
rtgui/lcurve.cc
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
731
rtgui/mycurve.cc
731
rtgui/mycurve.cc
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
166
rtgui/shcselector.cc
Normal 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
61
rtgui/shcselector.h
Normal 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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user