Patch for color shifts in higlight rolloff function. Behavior is improved but still not ideal.

This commit is contained in:
Emil Martinec 2010-10-23 18:46:56 -05:00
parent 7710252c9b
commit 3f697139a1
9 changed files with 294 additions and 269 deletions

View File

@ -690,7 +690,7 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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) { 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* outCurve1, int* outCurve2, unsigned int* outBeforeCCurveHistogram, int skip) {
double def_mul = pow (2.0, defmul); double def_mul = pow (2.0, defmul);
@ -735,7 +735,7 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
float toneslope=(shouldery-toey)/(shoulderx-toex); float toneslope=(shouldery-toey)/(shoulderx-toex);
if (shoulderx<1) {//a>1; positive EC if (shoulderx<1) {//a>1; positive EC
//move shoulder down if there is highlight rolloff //move shoulder down if there is highlight rolloff
shouldery = shouldery-(0.3)*(hlcompr/100.0); shouldery = shouldery-(0.2)*(hlcompr/100.0);
shoulderx = shoulderx - (1-shouldery)/toneslope; shoulderx = shoulderx - (1-shouldery)/toneslope;
} else {//a<1; negative EC } else {//a<1; negative EC
//if (shoulderx>1) { //if (shoulderx>1) {
@ -814,6 +814,11 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
//val = basecurve (val, a, black, D, hlcompr/100.0, shcompr/100.0); //val = basecurve (val, a, black, D, hlcompr/100.0, shcompr/100.0);
val = basecurve->getVal (val); val = basecurve->getVal (val);
outCurve1[i] = (int) (65535.0 * CLIPD(val));
// change to [0,1] range
val = (double)i / 65535.0;
// gamma correction // gamma correction
if (gamma_>0) if (gamma_>0)
val = gamma (val, gamma_, start, slope, mul, add); val = gamma (val, gamma_, start, slope, mul, add);
@ -853,6 +858,7 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
prev+=skip; prev+=skip;
continue; continue;
} }
outCurve1[i] = ( outCurve1[prev] * (skip - i%skip) + outCurve1[prev+skip] * (i%skip) ) / skip;
dcurve[i] = ( dcurve[prev] * (skip - i%skip) + dcurve[prev+skip] * (i%skip) ) / skip; dcurve[i] = ( dcurve[prev] * (skip - i%skip) + dcurve[prev+skip] * (i%skip) ) / skip;
} }
@ -899,12 +905,12 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
double val = contrastcurve->getVal (dcurve[i]); double val = contrastcurve->getVal (dcurve[i]);
if (igamma && gamma_>0) if (igamma && gamma_>0)
val = igamma2 (val); val = igamma2 (val);
outCurve[i] = (int) (65535.0 * CLIPD(val)); outCurve2[i] = (int) (65535.0 * CLIPD(val));
} }
} }
else else
for (int i=0; i<=0xffff; i++) for (int i=0; i<=0xffff; i++)
outCurve[i] = (int) (65535.0 * dcurve[i]); outCurve2[i] = (int) (65535.0 * dcurve[i]);
delete [] dcurve; delete [] dcurve;
} }

View File

@ -128,7 +128,7 @@ class CurveFactory {
public: 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 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); 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* outCurve1, int* outCurve2, unsigned int* outBeforeCCurveHistogram, int skip=1);
static void complexsgnCurve (double satclip, double satcompr, double saturation, double colormult, const std::vector<double>& curvePoints, int* outCurve, int skip=1); static void complexsgnCurve (double satclip, double satcompr, double saturation, double colormult, const std::vector<double>& curvePoints, int* outCurve, int skip=1);
}; };

View File

@ -158,12 +158,12 @@ void Crop::update (int todo, bool internal) {
// shadows & highlights & tone curve & convert to cielab // shadows & highlights & tone curve & convert to cielab
if (todo & M_RGBCURVE) if (todo & M_RGBCURVE)
parent->ipf.rgbProc (baseCrop, laboCrop, parent->tonecurve, cshmap); parent->ipf.rgbProc (baseCrop, laboCrop, parent->tonecurve1, parent->tonecurve2, cshmap);
// apply luminance operations // apply luminance operations
if (todo & (M_LUMINANCE+M_COLOR)) { if (todo & (M_LUMINANCE+M_COLOR)) {
parent->ipf.luminanceCurve (laboCrop, labnCrop, parent->lumacurve, 0, croph); parent->ipf.luminanceCurve (laboCrop, labnCrop, parent->lumacurve2, 0, croph);
parent->ipf.chrominanceCurve (laboCrop, labnCrop, 0, parent->chroma_acurve, 0, croph); parent->ipf.chrominanceCurve (laboCrop, labnCrop, 0, parent->chroma_acurve, 0, croph);
parent->ipf.chrominanceCurve (laboCrop, labnCrop, 1, parent->chroma_bcurve, 0, croph); parent->ipf.chrominanceCurve (laboCrop, labnCrop, 1, parent->chroma_bcurve, 0, croph);

View File

@ -144,8 +144,8 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
progress ("Exposure curve & CIELAB conversion...",100*readyphase/numofphases); progress ("Exposure curve & CIELAB conversion...",100*readyphase/numofphases);
if (todo & M_RGBCURVE) { if (todo & M_RGBCURVE) {
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); 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, tonecurve1, tonecurve2, bcrgbhist, scale==1 ? 1 : 1);
ipf.rgbProc (oprevi, oprevl, tonecurve, shmap); ipf.rgbProc (oprevi, oprevl, tonecurve1, tonecurve2, shmap);
// recompute luminance histogram // recompute luminance histogram
memset (lhist16, 0, 65536*sizeof(int)); memset (lhist16, 0, 65536*sizeof(int));
@ -156,7 +156,7 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
readyphase++; readyphase++;
if (todo & M_LUMACURVE) { if (todo & M_LUMACURVE) {
CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, params.labCurve.brightness, params.labCurve.contrast, 0.0, 0.0, false, params.labCurve.lcurve, lhist16, lumacurve, bcLhist, scale==1 ? 1 : 16); CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, params.labCurve.brightness, params.labCurve.contrast, 0.0, 0.0, false, params.labCurve.lcurve, lhist16, lumacurve1, lumacurve2, bcLhist, scale==1 ? 1 : 16);
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, chroma_acurve, scale==1 ? 1 : 16); CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, chroma_acurve, scale==1 ? 1 : 16);
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, chroma_bcurve, scale==1 ? 1 : 16); CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, chroma_bcurve, scale==1 ? 1 : 16);
} }
@ -212,7 +212,7 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
if (todo & (M_LUMINANCE+M_COLOR) ) { if (todo & (M_LUMINANCE+M_COLOR) ) {
progress ("Applying Luminance Curve...",100*readyphase/numofphases); progress ("Applying Luminance Curve...",100*readyphase/numofphases);
ipf.luminanceCurve (oprevl, nprevl, lumacurve, 0, pH); ipf.luminanceCurve (oprevl, nprevl, lumacurve2, 0, pH);
readyphase++; readyphase++;
progress ("Applying Color Boost...",100*readyphase/numofphases); progress ("Applying Color Boost...",100*readyphase/numofphases);

View File

@ -61,8 +61,11 @@ class ImProcCoordinator : public StagedImageProcessor {
void freeAll (); void freeAll ();
int tonecurve [65536]; int tonecurve1 [65536];
int lumacurve [65536]; int tonecurve2 [65536];
int lumacurve1 [65536];
int lumacurve2 [65536];
int chroma_acurve [65536]; int chroma_acurve [65536];
int chroma_bcurve [65536]; int chroma_bcurve [65536];

View File

@ -245,7 +245,7 @@ void ImProcFunctions::firstAnalysis (Image16* original, const ProcParams* params
delete [] hist; delete [] hist;
} }
void ImProcFunctions::rgbProc (Image16* working, LabImage* lab, int* tonecurve, SHMap* shmap) { void ImProcFunctions::rgbProc (Image16* working, LabImage* lab, int* tonecurve1, int* tonecurve2, SHMap* shmap) {
int h_th, s_th; int h_th, s_th;
if (shmap) { if (shmap) {
@ -321,9 +321,22 @@ void ImProcFunctions::rgbProc (Image16* working, LabImage* lab, int* tonecurve,
b = CLIP((int)(factor*b)); b = CLIP((int)(factor*b));
} }
} }
r = tonecurve[r]; /*r = tonecurve[r];
g = tonecurve[g]; g = tonecurve[g];
b = tonecurve[b]; b = tonecurve[b];*/
//int Y = (int)(0.299*r + 0.587*g + 0.114*b);
//float tonefactor = (Y>0 ? (float)tonecurve[Y]/Y : 0);
float rtonefactor = (r>0 ? (float)tonecurve1[r]/r : 0);
float gtonefactor = (g>0 ? (float)tonecurve1[g]/g : 0);
float btonefactor = (b>0 ? (float)tonecurve1[b]/b : 0);
float tonefactor = MIN(rtonefactor, MIN(gtonefactor,btonefactor));
r *= tonefactor;
g *= tonefactor;
b *= tonefactor;
r = tonecurve2[r];
g = tonecurve2[g];
b = tonecurve2[b];
int x = (toxyz[0][0] * r + toxyz[1][0] * g + toxyz[2][0] * b) >> 15; int x = (toxyz[0][0] * r + toxyz[1][0] * g + toxyz[2][0] * b) >> 15;
int y = (toxyz[0][1] * r + toxyz[1][1] * g + toxyz[2][1] * b) >> 15; int y = (toxyz[0][1] * r + toxyz[1][1] * g + toxyz[2][1] * b) >> 15;

View File

@ -79,7 +79,7 @@ class ImProcFunctions {
bool needsTransform (); bool needsTransform ();
void firstAnalysis (Image16* working, const ProcParams* params, unsigned int* vhist16, double gamma); void firstAnalysis (Image16* working, const ProcParams* params, unsigned int* vhist16, double gamma);
void rgbProc (Image16* working, LabImage* lab, int* tonecurve, SHMap* shmap); void rgbProc (Image16* working, LabImage* lab, int* tonecurve1, int* tonecurve2, SHMap* shmap);
void luminanceCurve (LabImage* lold, LabImage* lnew, int* curve, int row_from, int row_to); void luminanceCurve (LabImage* lold, LabImage* lnew, int* curve, int row_from, int row_to);
void chrominanceCurve (LabImage* lold, LabImage* lnew, int channel, int* curve, int row_from, int row_to); void chrominanceCurve (LabImage* lold, LabImage* lnew, int channel, int* curve, int row_from, int row_to);
void colorCurve (LabImage* lold, LabImage* lnew); void colorCurve (LabImage* lold, LabImage* lnew);

View File

@ -311,11 +311,12 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
if (params.toneCurve.autoexp && aeHistogram) if (params.toneCurve.autoexp && aeHistogram)
ipf.getAutoExp (aeHistogram, aeHistCompression, logDefGain, params.toneCurve.clip, br, bl); ipf.getAutoExp (aeHistogram, aeHistCompression, logDefGain, params.toneCurve.clip, br, bl);
int* curve = new int [65536]; int* curve1 = new int [65536];
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); int* curve2 = new int [65536];
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, curve1, curve2, NULL, 16);
LabImage* labView = new LabImage (baseImg); LabImage* labView = new LabImage (baseImg);
ipf.rgbProc (baseImg, labView, curve, shmap); ipf.rgbProc (baseImg, labView, curve1, curve2, shmap);
if (shmap) if (shmap)
delete shmap; delete shmap;
@ -327,15 +328,15 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
hist16[labView->L[i][j]]++; hist16[labView->L[i][j]]++;
// luminance processing // luminance processing
CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, params.labCurve.brightness, params.labCurve.contrast, 0.0, 0.0, false, params.labCurve.lcurve, hist16, curve, NULL, 16); CurveFactory::complexCurve (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, NULL, 16);
ipf.luminanceCurve (labView, labView, curve, 0, fh); ipf.luminanceCurve (labView, labView, curve2, 0, fh);
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, curve, 16); CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, curve1, 16);
ipf.chrominanceCurve (labView, labView, 0, curve, 0, fh); ipf.chrominanceCurve (labView, labView, 0, curve1, 0, fh);
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, curve, 16); CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, curve1, 16);
ipf.chrominanceCurve (labView, labView, 1, curve, 0, fh); ipf.chrominanceCurve (labView, labView, 1, curve1, 0, fh);
delete [] curve1;
delete [] curve; delete [] curve2;
delete [] hist16; delete [] hist16;
// color processing // color processing

View File

@ -126,12 +126,13 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, br, bl); ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, br, bl);
} }
int* curve = new int [65536]; int* curve1 = new int [65536];
int* curve2 = new int [65536];
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); 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, curve1, curve2, NULL);
LabImage* labView = new LabImage (baseImg); LabImage* labView = new LabImage (baseImg);
ipf.rgbProc (baseImg, labView, curve, shmap); ipf.rgbProc (baseImg, labView, curve1, curve2, shmap);
if (shmap) if (shmap)
delete shmap; delete shmap;
@ -147,18 +148,19 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
hist16[labView->L[i][j]]++; hist16[labView->L[i][j]]++;
// luminance processing // luminance processing
CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, params.labCurve.brightness, params.labCurve.contrast, 0.0, 0.0, false, params.labCurve.lcurve, hist16, curve, NULL); CurveFactory::complexCurve (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, NULL);
ipf.luminanceCurve (labView, labView, curve, 0, fh); ipf.luminanceCurve (labView, labView, curve2, 0, fh);
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, curve, 1); CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, curve1, 1);
ipf.chrominanceCurve (labView, labView, 0, curve, 0, fh); ipf.chrominanceCurve (labView, labView, 0, curve1, 0, fh);
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, curve, 1); CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, curve1, 1);
ipf.chrominanceCurve (labView, labView, 1, curve, 0, fh); ipf.chrominanceCurve (labView, labView, 1, curve1, 0, fh);
ipf.impulsedenoise (labView); ipf.impulsedenoise (labView);
ipf.lumadenoise (labView, buffer); ipf.lumadenoise (labView, buffer);
ipf.sharpening (labView, (unsigned short**)buffer); ipf.sharpening (labView, (unsigned short**)buffer);
delete [] curve; delete [] curve1;
delete [] curve2;
delete [] hist16; delete [] hist16;
// color processing // color processing