679 lines
17 KiB
C++
Executable File
679 lines
17 KiB
C++
Executable File
/*
|
|
* 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 <glib.h>
|
|
#include <glib/gstdio.h>
|
|
#include <curves.h>
|
|
#include <math.h>
|
|
#include <vector>
|
|
#include <mytime.h>
|
|
#include <string.h>
|
|
|
|
namespace rtengine {
|
|
|
|
Curve::Curve (const char* iname, const char* descr) : islinear(false), isempty(false) {
|
|
|
|
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);
|
|
}
|
|
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 ();
|
|
}
|
|
}
|
|
|
|
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];*/
|
|
}
|
|
|
|
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)
|
|
delete [] ypp;
|
|
ypp = new double [N];
|
|
|
|
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;
|
|
}
|
|
|
|
ypp[N - 1] = 0.0;
|
|
for (int k = N - 2; k >= 0; --k)
|
|
ypp[k] = ypp[k] * ypp[k + 1] + u[k];
|
|
|
|
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];
|
|
|
|
/* 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;
|
|
}
|
|
//
|
|
// 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];
|
|
|
|
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 ) ) ) );
|
|
*/
|
|
}
|
|
|
|
Glib::ustring Curve::getName () {
|
|
|
|
return name;
|
|
}
|
|
|
|
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)
|
|
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*(x-m)/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*(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);
|
|
|
|
// 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;
|
|
|
|
// theoretical maximum of the curve
|
|
double D = gamma_>0 ? gamma (def_mul, gamma_, start, slope, mul, add) : def_mul;
|
|
|
|
double a = pow (2.0, ecomp);
|
|
double b = black / 65535.0;
|
|
|
|
// curve without contrast
|
|
double* dcurve = new double[65536];
|
|
|
|
bool needcontrast = contr>0.00001 || contr<-0.00001;
|
|
bool needigamma = !needcontrast && igamma && gamma_>0;
|
|
|
|
for (int i=0; i<=0xffff; i+= i<0xffff-skip ? skip : 1 ) {
|
|
|
|
double val = (double)i / 65535.0;
|
|
val *= def_mul;
|
|
if (gamma_>0)
|
|
val = gamma (val, gamma_, start, slope, mul, add);
|
|
|
|
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 (needigamma)
|
|
val = igamma2 (val);
|
|
|
|
if (val>1.0)
|
|
val = 1.0;
|
|
else if (val<0.0)
|
|
val = 0.0;
|
|
dcurve[i] = val;
|
|
}
|
|
/*
|
|
if (igamma) {
|
|
FILE* f = fopen ("curve.txt","wt");
|
|
for (int i=0; i<65536; i++)
|
|
// fprintf (f, "%g\t%g\n", i/65535.0, basel(i/65535.0, 2, 0));
|
|
fprintf (f, "%g\t%g\n", i/65535.0, clower(i/65535.0, 0.500015/0.5, 1.5));
|
|
// fprintf (f, "%g\t%g\n", i/65535.0, basecurve(i/65535.0, 1.25701, 0, 1.47694, 1.0, 1.0));
|
|
// fprintf (f, "%g\t%g\n", i/65535.0, dcurve[i]);
|
|
fclose (f);
|
|
}
|
|
*/
|
|
|
|
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;
|
|
}
|
|
|
|
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];
|
|
}
|
|
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;
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
else
|
|
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) {
|
|
|
|
double ec_mul = pow (2, ecomp);
|
|
double bl = black / 65535.0;
|
|
double hi = pow (2.0,-br) + bl;
|
|
|
|
// 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;
|
|
|
|
double b_upper = solve_upper (m, c, d);
|
|
double b_lower = solve_lower (m, c, d);
|
|
|
|
// 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];
|
|
|
|
double bltanh = tanh (b_lower);
|
|
double butanh = tanh (b_upper);
|
|
|
|
if (d * (c - bl) < 1)
|
|
hlcompr = 0;
|
|
|
|
bool needcontrast = contr>0.00001 || contr<-0.00001;
|
|
bool needigamma = !needcontrast && igamma && gamma_>0;
|
|
|
|
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;
|
|
}
|
|
|
|
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);
|
|
|
|
if (needigamma)
|
|
val = igamma2 (val);
|
|
|
|
if (val>1.0)
|
|
val = 1.0;
|
|
else if (val<0.0)
|
|
val = 0.0;
|
|
dcurve[i] = val;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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];
|
|
}
|
|
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;
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
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);
|
|
//}
|
|
|
|
delete [] dcurve;
|
|
}
|
|
|
|
int CurveFactory::gammatab [65536];
|
|
int CurveFactory::igammatab_srgb [65536];
|
|
int CurveFactory::gammatab_srgb [65536];
|
|
|
|
void CurveFactory::loadCurves (Glib::ustring fname) {
|
|
|
|
for (int i=0; i<65536; i++)
|
|
gammatab_srgb[i] = (int)(65535 * gamma2 (i/65535.0));
|
|
for (int i=0; i<65536; i++)
|
|
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, "");
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|