Added better handling of failures loading icons, as Cairo generated exception were crashing app under windows. Minor fix to handling missing processing params to not alter the global defaults.

This commit is contained in:
sashavasko
2010-05-13 16:42:43 -05:00
commit 65ea3aff3e
572 changed files with 115958 additions and 0 deletions

432
rtengine/curves.cc Normal file
View File

@@ -0,0 +1,432 @@
/*
* 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>
#undef CLIPD
#define CLIPD(a) ((a)>0.0?((a)<1.0?(a):1.0):0.0)
namespace rtengine {
Curve::Curve (const std::vector<double>& p) : x(NULL), y(NULL), ypp(NULL) {
if (p.size()<3) {
kind = 0;
}
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 () {
delete [] x;
delete [] y;
delete [] ypp;
}
void Curve::spline_cubic_set () {
double* u = new double[N-1];
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) {
if (!kind)
return t;
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;
}
}
else {
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 (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;
}
}
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
res.resize (t.size());
for (int i=0; i<t.size(); i++)
res[i] = getVal(t[i]);
}
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);
}
}
/*
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;
// 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;
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;
}
delete tcurve;
/*
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::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 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;
// a: slope of the curve, black: starting point at the x axis
double a = pow (2.0, ecomp);
// curve without contrast
double* dcurve = new double[65536];
// 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;
// create a curve if needed
Curve* tcurve = NULL;
if (curvePoints.size()>0 && curvePoints[0]!=0)
tcurve = new Curve (curvePoints);
// 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;
// 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);
// 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 inverse gamma is needed, do it (standard sRGB inverse gamma is applied)
if (needigamma)
val = igamma2 (val);
// store result in a temporary array
dcurve[i] = CLIPD(val);
}
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;
}
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;
// 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++)
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::init () {
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 = 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);*/
}
}