Bugfix for Lab saturation limiter; improvements to Green Equilibration. Bugfix for building in XCode.

This commit is contained in:
Emil Martinec 2011-02-13 14:32:09 -06:00
parent 4b9a9eda13
commit d2eb8bd48a
12 changed files with 161 additions and 220 deletions

View File

@ -3,6 +3,16 @@
string (TOUPPER ${BUILD_TYPE} UPPER_CMAKE_BUILD_TYPE)
# wee look for the hg command in this paths by order of preference
find_file(HG_CMD hg PATHS "/opt/local/bin" "/usr/local/bin" "/usr/bin")
find_file(HG_CMD hg)
if (HG_CMD STREQUAL HG_CMD-NOTFOUND)
message(FATAL_ERROR "hg command not found!")
else (HG_CMD STREQUAL HG_CMD-NOTFOUND)
message(STATUS "hg command found: ${HG_CMD}")
endif (HG_CMD STREQUAL HG_CMD-NOTFOUND)
set (OUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/AboutThisBuild.txt")
set (VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/rtgui/version.h")
set (SHELL "/bin/bash")
@ -11,8 +21,8 @@ set (SHELL "/bin/bash")
add_custom_target (AboutFile ALL
COMMAND rm -f ${OUT_FILE}
COMMAND rm -f ${VERSION_FILE}
COMMAND for i in \$\( hg branch \)\; do echo Branch: $i >${OUT_FILE}\; done
COMMAND hg parents --template=\"Version: {latesttag}.{latesttagdistance}\\nChangset: {node|short}\\n\" >>${OUT_FILE}
COMMAND for i in \$\( ${HG_CMD} -R \"${CMAKE_CURRENT_SOURCE_DIR}\" branch \)\; do echo Branch: $i >${OUT_FILE}\; done
COMMAND ${HG_CMD} -R \"${CMAKE_CURRENT_SOURCE_DIR}\" parents --template=\"Version: {latesttag}.{latesttagdistance}\\nChangset: {node|short}\\n\" >>${OUT_FILE}
COMMAND for i in \$\( gcc -dumpversion \) \;do echo Compiler: GCC $i >>${OUT_FILE} \; done
COMMAND echo Processor: ${PROC_LABEL} >>${OUT_FILE}
COMMAND echo Bit depth: ${PROC_BIT_DEPTH} >>${OUT_FILE}
@ -22,6 +32,6 @@ add_custom_target (AboutFile ALL
COMMAND if [ \"${OPTION_OMP}\" = \"ON\" ] \; then echo OpenMP support: Yes >>${OUT_FILE} \;else echo OpenMP support: No >>${OUT_FILE} \;fi
COMMAND if [ \"${WITH_MYFILE_MMAP}\" = \"ON\" ] \; then echo MMAP support: Yes >>${OUT_FILE} \; else echo MMAP support: No >>${OUT_FILE} \;fi
COMMAND if [ \"${WITH_RAWZOR}\" = \"ON\" ] \; then echo Rawzor support: Yes >>${OUT_FILE} \;else echo Rawzor support: No >>${OUT_FILE} \;fi
COMMAND hg parents --template=\"// This file is automatically generated by the Makefile \; DO NOT EDIT!\\n// You can \(should\) also tell mercurial to ignore it.\\n\\n\#ifndef _VERSION_\\n\#define _VERSION_\\n\\n\#define VERSION \\"{latesttag}.{latesttagdistance}\\"\\n\#define TAGDISTANCE {latesttagdistance}\\n\\n\#endif\\n\" >${VERSION_FILE}
COMMAND ${HG_CMD} -R \"${CMAKE_CURRENT_SOURCE_DIR}\" parents --template=\"// This file is automatically generated by the Makefile \; DO NOT EDIT!\\n// You can \(should\) also tell mercurial to ignore it.\\n\\n\#ifndef _VERSION_\\n\#define _VERSION_\\n\\n\#define VERSION \\"{latesttag}.{latesttagdistance}\\"\\n\#define TAGDISTANCE {latesttagdistance}\\n\\n\#endif\\n\" >${VERSION_FILE}
COMMENT "Creating the about file"
)

View File

@ -1,9 +1,9 @@
#00 default translation file
#01 Developers should add translations to this file and then run 'generateDifferences.sh' script to update other locales.
ABOUT_TAB_BUILD;Version
ABOUT_TAB_CREDITS;Credits
ABOUT_TAB_LICENSE;License
ABOUT_TAB_SPLASH;Splash
ABOUT_TAB_BUILD;Version
ABOUT_TAB_CREDITS;Credits
ABOUT_TAB_LICENSE;License
ABOUT_TAB_SPLASH;Splash
ADJUSTER_RESET_TO_DEFAULT;Reset to default
BATCHQUEUE_AUTOSTART;Auto start
BATCH_PROCESSING;Batch processing
@ -698,7 +698,7 @@ TP_LABCURVE_BRIGHTNESS;Brightness
TP_LABCURVE_CONTRAST;Contrast
TP_LABCURVE_CURVEEDITOR;Luminance Curve
TP_LABCURVE_ENABLESATLIMITER;Enable saturation limiter
TP_LABCURVE_LABEL;Lab Curves
TP_LABCURVE_LABEL;Lab Adjustments
TP_LABCURVE_SATLIMIT;Saturation limit
TP_LABCURVE_SATURATION;Saturation
TP_LENSGEOM_AUTOCROP;Auto Crop

View File

@ -372,14 +372,6 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) {
fabs((rgb[indx-4][1]-rgb[indx-4][c])-(rgb[indx][1]-rgb[indx][c])) - \
fabs((rgb[indx-4][1]-rgb[indx-4][c])-(rgb[indx+4][1]-rgb[indx+4][c])));
/*ghpfv = fabs(fabs(rgb[indx][1]-rgb[indx+v4][1])+fabs(rgb[indx][1]-rgb[indx-v4][1]) - \
fabs(rgb[indx+v4][1]-rgb[indx-v4][1]));
ghpfh = fabs(fabs(rgb[indx][1]-rgb[indx+4][1])+fabs(rgb[indx][1]-rgb[indx-4][1]) - \
fabs(rgb[indx+4][1]-rgb[indx-4][1]));
rbhpfv[indx] = fabs(ghpfv - fabs(fabs(rgb[indx][c]-rgb[indx+v4][c])+fabs(rgb[indx][c]-rgb[indx-v4][c]) - \
fabs(rgb[indx+v4][c]-rgb[indx-v4][c])));
rbhpfh[indx] = fabs(ghpfh - fabs(fabs(rgb[indx][c]-rgb[indx+4][c])+fabs(rgb[indx][c]-rgb[indx-4][c]) - \
fabs(rgb[indx+4][c]-rgb[indx-4][c])));*/
glpfv = 0.25*(2*rgb[indx][1]+rgb[indx+v2][1]+rgb[indx-v2][1]);
glpfh = 0.25*(2*rgb[indx][1]+rgb[indx+2][1]+rgb[indx-2][1]);
@ -408,7 +400,7 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) {
coeff[0][0][c] += gradwt*deltgrb*deltgrb;
coeff[0][1][c] += gradwt*gdiff*deltgrb;
coeff[0][2][c] += gradwt*gdiff*gdiff;
areawt[0][c]+=1;
areawt[0][c]++;
//horizontal
@ -420,7 +412,7 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) {
coeff[1][0][c] += gradwt*deltgrb*deltgrb;
coeff[1][1][c] += gradwt*gdiff*deltgrb;
coeff[1][2][c] += gradwt*gdiff*gdiff;
areawt[1][c]+=1;
areawt[1][c]++;
// In Mathematica,
@ -430,68 +422,7 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) {
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*
for (rr=4; rr < rr1-4; rr++)
for (cc=4+(FC(rr,2)&1), indx=rr*TS+cc, c = FC(rr,cc); cc < cc1-4; cc+=2, indx+=2) {
rbhpfv[indx] = SQR(fabs((rgb[indx][1]-rgb[indx][c])-(rgb[indx+v4][1]-rgb[indx+v4][c])) + \
fabs((rgb[indx-v4][1]-rgb[indx-v4][c])-(rgb[indx][1]-rgb[indx][c])) - \
fabs((rgb[indx-v4][1]-rgb[indx-v4][c])-(rgb[indx+v4][1]-rgb[indx+v4][c])));
rbhpfh[indx] = SQR(fabs((rgb[indx][1]-rgb[indx][c])-(rgb[indx+4][1]-rgb[indx+4][c])) + \
fabs((rgb[indx-4][1]-rgb[indx-4][c])-(rgb[indx][1]-rgb[indx][c])) - \
fabs((rgb[indx-4][1]-rgb[indx-4][c])-(rgb[indx+4][1]-rgb[indx+4][c])));
glpfv = 0.25*(2*rgb[indx][1]+rgb[indx+v2][1]+rgb[indx-v2][1]);
glpfh = 0.25*(2*rgb[indx][1]+rgb[indx+2][1]+rgb[indx-2][1]);
rblpfv[indx] = eps+fabs(glpfv - 0.25*(2*rgb[indx][c]+rgb[indx+v2][c]+rgb[indx-v2][c]));
rblpfh[indx] = eps+fabs(glpfh - 0.25*(2*rgb[indx][c]+rgb[indx+2][c]+rgb[indx-2][c]));
grblpfv[indx] = glpfv + 0.25*(2*rgb[indx][c]+rgb[indx+v2][c]+rgb[indx-v2][c]);
grblpfh[indx] = glpfh + 0.25*(2*rgb[indx][c]+rgb[indx+2][c]+rgb[indx-2][c]);
}
for (c=0;c<3;c++) {areawt[0][c]=areawt[1][c]=0;}
// along line segments, find the point along each segment that minimizes the color variance
// averaged over the tile; evaluate for up/down and left/right away from R/B grid point
for (rr=rrmin+8; rr < rrmax-8; rr++)
for (cc=ccmin+8+(FC(rr,2)&1), indx=rr*TS+cc, c = FC(rr,cc); cc < ccmax-8; cc+=2, indx+=2) {
if (rgb[indx][c]>0.8*clip_pt || Gtmp[indx]>0.8*clip_pt) continue;
//in linear interpolation, color differences are a quadratic function of interpolation position;
//solve for the interpolation position that minimizes color difference variance over the tile
//vertical
gdiff=0.3125*(rgb[indx+TS][1]-rgb[indx-TS][1])+0.09375*(rgb[indx+TS+1][1]-rgb[indx-TS+1][1]+rgb[indx+TS-1][1]-rgb[indx-TS-1][1]);
deltgrb=(rgb[indx][c]-rgb[indx][1])-0.5*((rgb[indx-v4][c]-rgb[indx-v4][1])+(rgb[indx+v4][c]-rgb[indx+v4][1]));
gradwt=fabs(0.25*rbhpfv[indx]+0.125*(rbhpfv[indx+2]+rbhpfv[indx-2]) );//*(grblpfv[indx-v2]+grblpfv[indx+v2])/(eps+0.1*grblpfv[indx-v2]+rblpfv[indx-v2]+0.1*grblpfv[indx+v2]+rblpfv[indx+v2]);
if (gradwt>eps) {
coeff[0][0][c] += gradwt*deltgrb*deltgrb;
coeff[0][1][c] += gradwt*gdiff*deltgrb;
coeff[0][2][c] += gradwt*gdiff*gdiff;
areawt[0][c]++;
}
//horizontal
gdiff=0.3125*(rgb[indx+1][1]-rgb[indx-1][1])+0.09375*(rgb[indx+1+TS][1]-rgb[indx-1+TS][1]+rgb[indx+1-TS][1]-rgb[indx-1-TS][1]);
deltgrb=(rgb[indx][c]-rgb[indx][1])-0.5*((rgb[indx-4][c]-rgb[indx-4][1])+(rgb[indx+4][c]-rgb[indx+4][1]));
gradwt=fabs(0.25*rbhpfh[indx]+0.125*(rbhpfh[indx+v2]+rbhpfh[indx-v2]) );//*(grblpfh[indx-2]+grblpfh[indx+2])/(eps+0.1*grblpfh[indx-2]+rblpfh[indx-2]+0.1*grblpfh[indx+2]+rblpfh[indx+2]);
if (gradwt>eps) {
coeff[1][0][c] += gradwt*deltgrb*deltgrb;
coeff[1][1][c] += gradwt*gdiff*deltgrb;
coeff[1][2][c] += gradwt*gdiff*gdiff;
areawt[1][c]++;
}
// In Mathematica,
// f[x_]=Expand[Total[Flatten[
// ((1-x) RotateLeft[Gint,shift1]+x RotateLeft[Gint,shift2]-cfapad)^2[[dv;;-1;;2,dh;;-1;;2]]]]];
// extremum = -.5Coefficient[f[x],x]/Coefficient[f[x],x^2]
}*/
for (c=0; c<3; c+=2){
for (j=0; j<2; j++) {// vert/hor
//printf("hblock %d vblock %d j %d c %d areawt %d \n",hblock,vblock,j,c,areawt[j][c]);
@ -518,7 +449,7 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) {
if (fabs(CAshift[j][c])<2.0) {
blockave[j][c] += CAshift[j][c];
blocksqave[j][c] += SQR(CAshift[j][c]);
blockdenom[j][c] += 1;
blockdenom[j][c] ++;
}
}//vert/hor
}//color

View File

@ -302,7 +302,7 @@ void Curve::getVal (const std::vector<double>& t, std::vector<double>& res) {
}
void CurveFactory::complexsgnCurve (double saturation, const std::vector<double>& curvePoints, float* outCurve, int skip) {
void CurveFactory::complexsgnCurve (double saturation, bool satlimit, double satlimthresh, const std::vector<double>& curvePoints, float* outCurve, int skip) {
//colormult = chroma_scale for Lab manipulations
@ -316,14 +316,32 @@ void CurveFactory::complexsgnCurve (double saturation, const std::vector<double>
std::vector<double> satcurvePoints;
satcurvePoints.push_back((double)((CurveType)NURBS));
if (saturation>0) {
double satslope = (0.5+2*saturation/500.0)/(0.5-2*saturation/500.0);
double scale = (satlimthresh/100.1);
if (!satlimit) scale=100/100.1;
satcurvePoints.push_back(0); //black point. Value in [0 ; 1] range
satcurvePoints.push_back(0); //black point. Value in [0 ; 1] range
satcurvePoints.push_back(0.25+saturation/500.0); //toe point
satcurvePoints.push_back(0.25-saturation/500.0); //value at toe point
satcurvePoints.push_back(0.75-saturation/500.0); //shoulder point
satcurvePoints.push_back(0.75+saturation/500.0); //value at shoulder point
//if (satlimit) {
satcurvePoints.push_back(0.5-0.5*scale); //toe point
satcurvePoints.push_back(0.5-0.5*scale); //value at toe point
satcurvePoints.push_back(0.5-(0.5/satslope)*scale); //toe point
satcurvePoints.push_back(0.5-0.5*scale); //value at toe point
satcurvePoints.push_back(0.5+(0.5/satslope)*scale); //shoulder point
satcurvePoints.push_back(0.5+0.5*scale); //value at shoulder point
satcurvePoints.push_back(0.5+0.5*scale); //shoulder point
satcurvePoints.push_back(0.5+0.5*scale); //value at shoulder point
/*} else {
satcurvePoints.push_back(0.25+saturation/500.0); //toe point
satcurvePoints.push_back(0.25-saturation/500.0); //value at toe point
satcurvePoints.push_back(0.75-saturation/500.0); //shoulder point
satcurvePoints.push_back(0.75+saturation/500.0); //value at shoulder point
}*/
satcurvePoints.push_back(1); // white point
satcurvePoints.push_back(1); // value at white point

View File

@ -157,7 +157,7 @@ class CurveFactory {
public:
// 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 hlcomprthresh, double shcompr, double br, double contr, double defmul, double gamma_, bool igamma, const std::vector<double>& curvePoints, unsigned int* histogram, float* hlCurve, float* shCurve, int* outCurve, unsigned int* outBeforeCCurveHistogram, int skip=1);
static void complexsgnCurve (double saturation, const std::vector<double>& curvePoints, float* outCurve, int skip=1);
static void complexsgnCurve (double saturation, bool satlimit, double satlimthresh, const std::vector<double>& curvePoints, float* outCurve, int skip=1);
};

View File

@ -1,6 +1,27 @@
// CFA pixel cleaning via directional average
// © Emil Martinec
// 2/18/2010
////////////////////////////////////////////////////////////////
//
// Green Equilibration via directional average
//
// copyright (c) 2008-2010 Emil Martinec <ejmartin@uchicago.edu>
//
//
// code dated: February 12, 2011
//
// green_equil_RT.cc 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.
//
// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////
#define TS 256 // Tile size
#include <math.h>
@ -20,7 +41,6 @@ void RawImageSource::green_equilibrate(float thresh)
static const int v1=TS, v2=2*TS, v3=3*TS, /*v4=4*TS,*/ p1=-TS+1, p2=-2*TS+2, p3=-3*TS+3, m1=TS+1, m2=2*TS+2, m3=3*TS+3;
int height=H, width=W; //for RT only
int top, left;
int verbose=1;
@ -68,16 +88,12 @@ void RawImageSource::green_equilibrate(float thresh)
int numcols = right - left;
int row, col;
int rr, cc, c, indx;
int rr, cc, indx;
int vote1, vote2;
float val1;
float gin, gse, gsw, gne, gnw, wtse, wtsw, wtne, wtnw;
float gu, gd, gl, gr;
float mcorr, pcorr;
float ginterp;
float diffvarh, diffvarv, hvwt;
// rgb from input CFA data
/* rgb values should be floating point number between 0 and 1
@ -92,47 +108,58 @@ void RawImageSource::green_equilibrate(float thresh)
//The green equilibration algorithm starts here
//%%%%%%%%%%%%%%%%%%%%%%%%%
// To the extent possible under law, Manuel Llorens <manuelllorens@gmail.com>
// has waived all copyright and related or neighboring rights to this work.
// This code is licensed under CC0 v1.0, see license information at
// http://creativecommons.org/publicdomain/zero/1.0/
double d1,d2,c1,c2;
int o1_1,o1_2,o1_3,o1_4;
int o2_1,o2_2,o2_3,o2_4;
//%%%%%%%%%%%%%%%%%%%%%%
for (rr=2; rr < numrows-2; rr++)
//for (cc=3-(FC(rr,2)&1), indx=rr*TS+cc; cc < numcols-2; cc+=2, indx+=2) {
for (indx=rr*TS+2; indx < rr*TS+numcols-2; indx++) {
for (cc=3-(FC(rr,2)&1), indx=rr*TS+cc; cc < numcols-2; cc+=2, indx+=2) {
if (FC(rr,indx)&1) {
pcorr = (cfa[indx+p1]-cfa[indx])*(cfa[indx-p1]-cfa[indx]);
mcorr = (cfa[indx+m1]-cfa[indx])*(cfa[indx-m1]-cfa[indx]);
if (pcorr>0 && mcorr>0) {checker[indx]=1;} else {checker[indx]=0;}
//checker[indx]=1;//test what happens if we always interpolate
} else {
gu=cfa[indx-v1]+0.5*(cfa[indx]-cfa[indx-v2]);
gd=cfa[indx+v1]+0.5*(cfa[indx]-cfa[indx+v2]);
gl=cfa[indx-1]+0.5*(cfa[indx]-cfa[indx-2]);
gr=cfa[indx+1]+0.5*(cfa[indx]-cfa[indx+2]);
gdiffh[indx] = SQR((gl-gr)/(eps+gl+gr));
gdiffv[indx] = SQR((gu-gd)/(eps+gu+gd));
//gvar[indx] = 0.25*(gu*gu+gd*gd+gl*gl+gr*gr)-SQR(0.25*(gu+gd+gl+gr));
}
pcorr = (cfa[indx+p1]-cfa[indx])*(cfa[indx-p1]-cfa[indx]);
mcorr = (cfa[indx+m1]-cfa[indx])*(cfa[indx-m1]-cfa[indx]);
if (pcorr>0 && mcorr>0) {checker[indx]=1;} else {checker[indx]=0;}
//checker[indx]=1;//test what happens if we always interpolate
}
//now smooth the cfa data
for (rr=6; rr < numrows-6; rr++)
for (rr=6; rr < numrows-6; rr+=2)
for (cc=7-(FC(rr,2)&1), indx=rr*TS+cc; cc < numcols-6; cc+=2, indx+=2) {
if (checker[indx]) {
//%%%%%%%%%%%%%%%%%%%%%%
//neighbor checking code from Manuel Llorens Garcia
o1_1=cfa[(rr-1)*TS+cc-1];
o1_2=cfa[(rr-1)*TS+cc+1];
o1_3=cfa[(rr+1)*TS+cc-1];
o1_4=cfa[(rr+1)*TS+cc+1];
o2_1=cfa[(rr-2)*TS+cc];
o2_2=cfa[(rr+2)*TS+cc];
o2_3=cfa[(rr)*TS+cc-2];
o2_4=cfa[(rr)*TS+cc+2];
diffvarh = eps+(gdiffh[indx-v1]+gdiffh[indx-1]+gdiffh[indx+1]+gdiffh[indx+v1]);
diffvarv = eps+(gdiffv[indx-v1]+gdiffv[indx-1]+gdiffv[indx+1]+gdiffv[indx+v1]);
hvwt = fabs(diffvarv-diffvarh)/(diffvarv+diffvarh);
d1=(o1_1+o1_2+o1_3+o1_4)/4.0;
d2=(o2_1+o2_2+o2_3+o2_4)/4.0;
c1=(fabs(o1_1-o1_2)+fabs(o1_1-o1_3)+fabs(o1_1-o1_4)+fabs(o1_2-o1_3)+fabs(o1_3-o1_4)+fabs(o1_2-o1_4))/6.0;
c2=(fabs(o2_1-o2_2)+fabs(o2_1-o2_3)+fabs(o2_1-o2_4)+fabs(o2_2-o2_3)+fabs(o2_3-o2_4)+fabs(o2_2-o2_4))/6.0;
//%%%%%%%%%%%%%%%%%%%%%%
vote1=(checker[indx-v2]+checker[indx-2]+checker[indx+2]+checker[indx+v2]);
vote2=(checker[indx-m1]+checker[indx+p1]+checker[indx-p1]+checker[indx+m1]);
if (vote1>0 && vote2>0 && hvwt<diffthresh) {
if (vote1>0 && vote2>0 && (c1+c2)<4*thresh*fabs(d1-d2)) {
//pixel interpolation
gin=cfa[indx];
gse=(cfa[indx+m1])+0.5*(cfa[indx]-cfa[indx+m2]);
@ -149,10 +176,7 @@ void RawImageSource::green_equilibrate(float thresh)
ginterp=(gse*wtse+gnw*wtnw+gne*wtne+gsw*wtsw)/(wtse+wtnw+wtne+wtsw);
if (/*(SQR(ginterp-gin) > 0.125*(gvar[indx-1]+gvar[indx+1]+gvar[indx-v1]+gvar[indx+v1])) &&*/ ((ginterp-gin) < thresh*(ginterp+gin)) ) {
cfa[indx]=0.5*(ginterp+gin);
}
cfa[indx]=ginterp;//0.5*(ginterp+gin);
}
}
}
@ -160,15 +184,14 @@ void RawImageSource::green_equilibrate(float thresh)
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// copy smoothed results back to image matrix
for (rr=border; rr < numrows-border; rr++)
for (rr=border; rr < numrows-border; rr+=2)
for (row=rr+top, cc=border+1-(FC(rr,2)&1), indx=rr*TS+cc; cc < numcols-border; cc+=2, indx+=2) {
if (cfa[indx]<1) continue;
col = cc + left;
//c = FC(row,col);
//image[row*width + col][c] = CLIP((int)(cfa[indx] + 0.5)); //for dcraw implementation
rawData[row][col] = CLIP((int)(cfa[indx] + 0.5));
}
// clean up
}
free(buffer);

View File

@ -221,8 +221,10 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
if (todo & M_LUMACURVE) {
CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, 0.0, params.labCurve.brightness, params.labCurve.contrast, 0.0, 0.0, false, \
params.labCurve.lcurve, lhist16, dummy1, dummy2, lumacurve, bcLhist, scale==1 ? 1 : 16);
CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.acurve, chroma_acurve, scale==1 ? 1 : 16);
CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.bcurve, chroma_bcurve, scale==1 ? 1 : 16);
CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.enable_saturationlimiter, params.labCurve.saturationlimit, \
params.labCurve.acurve, chroma_acurve, scale==1 ? 1 : 16);
CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.enable_saturationlimiter, params.labCurve.saturationlimit, \
params.labCurve.bcurve, chroma_bcurve, scale==1 ? 1 : 16);
}

View File

@ -451,32 +451,6 @@ void ImProcFunctions::chrominanceCurve (LabImage* lold, LabImage* lnew, float* a
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double* cmultiplier = new double [181021];
double c = (0.5+2*params->labCurve.saturation/500.0) / (0.5-2*params->labCurve.saturation/500.0);
if (params->labCurve.enable_saturationlimiter && c>1) {
// re-generate color multiplier lookup table
double d = params->labCurve.saturationlimit * chroma_scale / 3.0;
double alpha = 0.5;
double threshold1 = alpha * d;
double threshold2 = c*d*(alpha+1.0) - d;
for (int i=0; i<=181020; i++) { // lookup table stores multipliers with a 0.25 chrominance resolution
double chrominance = (double)i/4;
if (chrominance < threshold1)
cmultiplier[i] = c;
else if (chrominance < d)
cmultiplier[i] = (c / (2.0*d*(alpha-1.0)) * (chrominance-d)*(chrominance-d) + c*d/2.0 * (alpha+1.0) ) / chrominance;
else if (chrominance < threshold2)
cmultiplier[i] = (1.0 / (2.0*d*(c*(alpha+1.0)-2.0)) * (chrominance-d)*(chrominance-d) + c*d/2.0 * (alpha+1.0) ) / chrominance;
else
cmultiplier[i] = 1.0;
}
}
#pragma omp parallel for if (multiThread)
for (int i=0; i<H; i++)
for (int j=0; j<W; j++) {
@ -484,45 +458,27 @@ void ImProcFunctions::chrominanceCurve (LabImage* lold, LabImage* lnew, float* a
int oa = lold->a[i][j];
int ob = lold->b[i][j];
int atmp = (int)acurve[oa+32768]-32768;
int btmp = (int)bcurve[ob+32768]-32768;
int chroma = (int)(4.0 * sqrt(SQR(oa) + SQR(ob)));
double wanted_c = c;
if (params->labCurve.enable_saturationlimiter && c>1) {
wanted_c = cmultiplier [MIN(chroma,181020)];
}
double real_c = wanted_c;
if (wanted_c >= 1.0 && params->labCurve.avoidclip) {
double cclip = 100000;
double cr = tightestroot ((double)lnew->L[i][j]/655.35, (double)(oa)/chroma_scale, (double)(ob)/chroma_scale, 3.079935, -1.5371515, -0.54278342);
double cg = tightestroot ((double)lnew->L[i][j]/655.35, (double)(oa)/chroma_scale, (double)(ob)/chroma_scale, -0.92123418, 1.87599, 0.04524418);
double cb = tightestroot ((double)lnew->L[i][j]/655.35, (double)(oa)/chroma_scale, (double)(ob)/chroma_scale, 0.052889682, -0.20404134, 1.15115166);
if (cr>1.0 && cr<cclip) cclip = cr;
if (cg>1.0 && cg<cclip) cclip = cg;
if (cb>1.0 && cb<cclip) cclip = cb;
if (cclip<100000) {
real_c = -cclip + 2.0*cclip / (1.0+exp(-2.0*wanted_c/cclip));
if (real_c<1.0)
real_c = 1.0;
}
float atmp = acurve[oa+32768]-32768;
float btmp = bcurve[ob+32768]-32768;
double real_c = 1.0;
if (params->labCurve.avoidclip) {
double Lclip = MIN(lnew->L[i][j]/655.35,100.0);
double cr = tightestroot (Lclip, (double)atmp/chroma_scale, (double)btmp/chroma_scale, 3.079935, -1.5371515, -0.54278342);
double cg = tightestroot (Lclip, (double)atmp/chroma_scale, (double)btmp/chroma_scale, -0.92123418, 1.87599, 0.04524418);
double cb = tightestroot (Lclip, (double)atmp/chroma_scale, (double)btmp/chroma_scale, 0.052889682, -0.20404134, 1.15115166);
if (cr>0 && cr<real_c) real_c = cr;
if (cg>0 && cg<real_c) real_c = cg;
if (cb>0 && cb<real_c) real_c = cb;
//if (i%100==50 && j%100==50) printf ("(i,j)=(%d,%d) c= %f, rmax= %f \n", i, j, c, real_c);//diagnostic
}
int nna = (int)((oa) * real_c );
int nnb = (int)((ob) * real_c );
if (4.0*sqrt(SQR(atmp)+SQR(btmp)) > chroma) {
lnew->a[i][j] = CLIPTO(nna,-32000,32000);
lnew->b[i][j] = CLIPTO(nnb,-32000,32000);
} else {
lnew->a[i][j] = CLIPTO(atmp,-32000,32000);
lnew->b[i][j] = CLIPTO(btmp,-32000,32000);
}
int nna = (int)((atmp) * real_c );
int nnb = (int)((btmp) * real_c );
lnew->a[i][j] = CLIPTO(nna,-32000,32000);
lnew->b[i][j] = CLIPTO(nnb,-32000,32000);
}
delete [] cmultiplier;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}

View File

@ -65,7 +65,7 @@ void ProcParams::setDefaults () {
labCurve.saturation = 0;
labCurve.avoidclip = false;
labCurve.enable_saturationlimiter = false;
labCurve.saturationlimit = 50;
labCurve.saturationlimit = 40;
labCurve.lcurve.clear ();
labCurve.acurve.clear ();
labCurve.bcurve.clear ();

View File

@ -717,8 +717,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
// luminance processing
CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, 0.0, params.labCurve.brightness, params.labCurve.contrast, 0.0, 0.0, false, params.labCurve.lcurve, hist16, curve1, curve2, curve, NULL, 16);
ipf.luminanceCurve (labView, labView, curve);
CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.acurve, curve1, 16);
CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.bcurve, curve2, 16);
CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.enable_saturationlimiter, params.labCurve.saturationlimit, params.labCurve.acurve, curve1, 16);
CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.enable_saturationlimiter, params.labCurve.saturationlimit, params.labCurve.bcurve, curve2, 16);
ipf.chrominanceCurve (labView, labView, curve1, curve2);
delete [] curve1;

View File

@ -163,8 +163,8 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
// luminance processing
CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, 0.0, params.labCurve.brightness, params.labCurve.contrast, 0.0, 0.0, false, params.labCurve.lcurve, hist16, curve1, curve2, curve, NULL);
ipf.luminanceCurve (labView, labView, curve);
CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.acurve, curve1, 1);
CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.bcurve, curve2, 1);
CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.enable_saturationlimiter, params.labCurve.saturationlimit, params.labCurve.acurve, curve1, 1);
CurveFactory::complexsgnCurve (params.labCurve.saturation, params.labCurve.enable_saturationlimiter, params.labCurve.saturationlimit, params.labCurve.bcurve, curve2, 1);
ipf.chrominanceCurve (labView, labView, curve1, curve2);
ipf.impulsedenoise (labView);

View File

@ -36,6 +36,28 @@ LCurve::LCurve () : Gtk::VBox(), FoldableToolPanel(this), brAdd(false), contrAdd
pack_start (*saturation);
saturation->show ();
//%%%%%%%%%%%%%%%%%%
pack_start (*Gtk::manage (new Gtk::HSeparator()));
avoidclip = Gtk::manage (new Gtk::CheckButton (M("TP_LABCURVE_AVOIDCOLORCLIP")));
pack_start (*avoidclip);
pack_start (*Gtk::manage (new Gtk::HSeparator()));
enablelimiter = Gtk::manage (new Gtk::CheckButton (M("TP_LABCURVE_ENABLESATLIMITER")));
pack_start (*enablelimiter);
saturationlimiter = new Adjuster (M("TP_LABCURVE_SATLIMIT"), 0, 100, 0.1, 40);
saturationlimiter->show ();
saturationlimiter->reference ();
//saturation->setAdjusterListener (this);
saturationlimiter->setAdjusterListener (this);
acconn = avoidclip->signal_toggled().connect( sigc::mem_fun(*this, &LCurve::avoidclip_toggled) );
elconn = enablelimiter->signal_toggled().connect( sigc::mem_fun(*this, &LCurve::enablelimiter_toggled) );
//%%%%%%%%%%%%%%%%%%%
Gtk::HSeparator *hsep3 = Gtk::manage (new Gtk::HSeparator());
hsep3->show ();
@ -57,27 +79,6 @@ LCurve::LCurve () : Gtk::VBox(), FoldableToolPanel(this), brAdd(false), contrAdd
contrast->setAdjusterListener (this);
saturation->setAdjusterListener (this);
//%%%%%%%%%%%%%%%%%%
pack_start (*Gtk::manage (new Gtk::HSeparator()));
avoidclip = Gtk::manage (new Gtk::CheckButton (M("TP_LABCURVE_AVOIDCOLORCLIP")));
pack_start (*avoidclip);
pack_start (*Gtk::manage (new Gtk::HSeparator()));
enablelimiter = Gtk::manage (new Gtk::CheckButton (M("TP_LABCURVE_ENABLESATLIMITER")));
pack_start (*enablelimiter);
saturationlimiter = new Adjuster (M("TP_LABCURVE_SATLIMIT"), 0, 200, 0.1, 100);
saturationlimiter->show ();
saturationlimiter->reference ();
//saturation->setAdjusterListener (this);
saturationlimiter->setAdjusterListener (this);
acconn = avoidclip->signal_toggled().connect( sigc::mem_fun(*this, &LCurve::avoidclip_toggled) );
elconn = enablelimiter->signal_toggled().connect( sigc::mem_fun(*this, &LCurve::enablelimiter_toggled) );
//%%%%%%%%%%%%%%%%%%%
}