Patch for color shifts in higlight rolloff function. Behavior is improved but still not ideal.
This commit is contained in:
parent
7710252c9b
commit
3f697139a1
@ -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);
|
||||
|
||||
@ -735,7 +735,7 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
|
||||
float toneslope=(shouldery-toey)/(shoulderx-toex);
|
||||
if (shoulderx<1) {//a>1; positive EC
|
||||
//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;
|
||||
} else {//a<1; negative EC
|
||||
//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->getVal (val);
|
||||
|
||||
outCurve1[i] = (int) (65535.0 * CLIPD(val));
|
||||
|
||||
// change to [0,1] range
|
||||
val = (double)i / 65535.0;
|
||||
|
||||
// gamma correction
|
||||
if (gamma_>0)
|
||||
val = gamma (val, gamma_, start, slope, mul, add);
|
||||
@ -853,6 +858,7 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
|
||||
prev+=skip;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -899,12 +905,12 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
|
||||
double val = contrastcurve->getVal (dcurve[i]);
|
||||
if (igamma && gamma_>0)
|
||||
val = igamma2 (val);
|
||||
outCurve[i] = (int) (65535.0 * CLIPD(val));
|
||||
outCurve2[i] = (int) (65535.0 * CLIPD(val));
|
||||
}
|
||||
}
|
||||
else
|
||||
for (int i=0; i<=0xffff; i++)
|
||||
outCurve[i] = (int) (65535.0 * dcurve[i]);
|
||||
outCurve2[i] = (int) (65535.0 * dcurve[i]);
|
||||
delete [] dcurve;
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,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 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);
|
||||
|
||||
};
|
||||
|
@ -158,12 +158,12 @@ void Crop::update (int todo, bool internal) {
|
||||
|
||||
// shadows & highlights & tone curve & convert to cielab
|
||||
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
|
||||
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, 1, parent->chroma_bcurve, 0, croph);
|
||||
|
||||
|
@ -144,8 +144,8 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
|
||||
|
||||
progress ("Exposure curve & CIELAB conversion...",100*readyphase/numofphases);
|
||||
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);
|
||||
ipf.rgbProc (oprevi, oprevl, tonecurve, shmap);
|
||||
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, tonecurve1, tonecurve2, shmap);
|
||||
|
||||
// recompute luminance histogram
|
||||
memset (lhist16, 0, 65536*sizeof(int));
|
||||
@ -156,7 +156,7 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
|
||||
readyphase++;
|
||||
|
||||
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.bcurve, chroma_bcurve, scale==1 ? 1 : 16);
|
||||
}
|
||||
@ -212,7 +212,7 @@ void ImProcCoordinator::updatePreviewImage (int todo) {
|
||||
|
||||
if (todo & (M_LUMINANCE+M_COLOR) ) {
|
||||
progress ("Applying Luminance Curve...",100*readyphase/numofphases);
|
||||
ipf.luminanceCurve (oprevl, nprevl, lumacurve, 0, pH);
|
||||
ipf.luminanceCurve (oprevl, nprevl, lumacurve2, 0, pH);
|
||||
|
||||
readyphase++;
|
||||
progress ("Applying Color Boost...",100*readyphase/numofphases);
|
||||
|
@ -61,10 +61,13 @@ class ImProcCoordinator : public StagedImageProcessor {
|
||||
|
||||
void freeAll ();
|
||||
|
||||
int tonecurve [65536];
|
||||
int lumacurve [65536];
|
||||
int chroma_acurve [65536];
|
||||
int chroma_bcurve [65536];
|
||||
int tonecurve1 [65536];
|
||||
int tonecurve2 [65536];
|
||||
|
||||
int lumacurve1 [65536];
|
||||
int lumacurve2 [65536];
|
||||
int chroma_acurve [65536];
|
||||
int chroma_bcurve [65536];
|
||||
|
||||
unsigned int vhist16[65536];
|
||||
unsigned int lhist16[65536];
|
||||
|
@ -245,7 +245,7 @@ void ImProcFunctions::firstAnalysis (Image16* original, const ProcParams* params
|
||||
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;
|
||||
if (shmap) {
|
||||
@ -321,10 +321,23 @@ void ImProcFunctions::rgbProc (Image16* working, LabImage* lab, int* tonecurve,
|
||||
b = CLIP((int)(factor*b));
|
||||
}
|
||||
}
|
||||
r = tonecurve[r];
|
||||
/*r = tonecurve[r];
|
||||
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 y = (toxyz[0][1] * r + toxyz[1][1] * g + toxyz[2][1] * b) >> 15;
|
||||
int z = (toxyz[0][2] * r + toxyz[1][2] * g + toxyz[2][2] * b) >> 15;
|
||||
|
@ -79,7 +79,7 @@ class ImProcFunctions {
|
||||
bool needsTransform ();
|
||||
|
||||
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 chrominanceCurve (LabImage* lold, LabImage* lnew, int channel, int* curve, int row_from, int row_to);
|
||||
void colorCurve (LabImage* lold, LabImage* lnew);
|
||||
|
@ -311,11 +311,12 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
|
||||
if (params.toneCurve.autoexp && aeHistogram)
|
||||
ipf.getAutoExp (aeHistogram, aeHistCompression, logDefGain, params.toneCurve.clip, br, bl);
|
||||
|
||||
int* curve = 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* 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, logDefGain, isRaw ? 2.2 : 0, true, params.toneCurve.curve, hist16, curve1, curve2, NULL, 16);
|
||||
|
||||
LabImage* labView = new LabImage (baseImg);
|
||||
ipf.rgbProc (baseImg, labView, curve, shmap);
|
||||
ipf.rgbProc (baseImg, labView, curve1, curve2, shmap);
|
||||
|
||||
if (shmap)
|
||||
delete shmap;
|
||||
@ -327,15 +328,15 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
|
||||
hist16[labView->L[i][j]]++;
|
||||
|
||||
// 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);
|
||||
ipf.luminanceCurve (labView, labView, curve, 0, fh);
|
||||
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, curve, 16);
|
||||
ipf.chrominanceCurve (labView, labView, 0, curve, 0, fh);
|
||||
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, curve, 16);
|
||||
ipf.chrominanceCurve (labView, labView, 1, curve, 0, fh);
|
||||
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, curve2, 0, fh);
|
||||
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, curve1, 16);
|
||||
ipf.chrominanceCurve (labView, labView, 0, curve1, 0, fh);
|
||||
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, curve1, 16);
|
||||
ipf.chrominanceCurve (labView, labView, 1, curve1, 0, fh);
|
||||
|
||||
|
||||
delete [] curve;
|
||||
delete [] curve1;
|
||||
delete [] curve2;
|
||||
delete [] hist16;
|
||||
|
||||
// color processing
|
||||
|
@ -1,239 +1,241 @@
|
||||
/*
|
||||
* 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 <rtengine.h>
|
||||
#include <colortemp.h>
|
||||
#include <imagesource.h>
|
||||
#include <improcfun.h>
|
||||
#include <curves.h>
|
||||
#include <iccstore.h>
|
||||
#include <processingjob.h>
|
||||
#include <glibmm.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#undef THREAD_PRIORITY_NORMAL
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* pl) {
|
||||
|
||||
errorCode = 0;
|
||||
|
||||
ProcessingJobImpl* job = (ProcessingJobImpl*) pjob;
|
||||
|
||||
if (pl) {
|
||||
pl->setProgressStr ("Processing...");
|
||||
pl->setProgress (0.0);
|
||||
}
|
||||
|
||||
InitialImage* ii = job->initialImage;
|
||||
if (!ii) {
|
||||
ii = InitialImage::load (job->fname, job->isRaw, &errorCode);
|
||||
if (errorCode) {
|
||||
ii->decreaseRef ();
|
||||
delete job;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
procparams::ProcParams& params = job->pparams;
|
||||
|
||||
// aquire image from imagesource
|
||||
ImageSource* imgsrc = ii->getImageSource ();
|
||||
ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green);
|
||||
if (params.wb.method=="Camera")
|
||||
currWB = imgsrc->getWB ();
|
||||
else if (params.wb.method=="Auto")
|
||||
currWB = imgsrc->getAutoWB ();
|
||||
|
||||
int tr = TR_NONE;
|
||||
if (params.coarse.rotate==90) tr |= TR_R90;
|
||||
if (params.coarse.rotate==180) tr |= TR_R180;
|
||||
if (params.coarse.rotate==270) tr |= TR_R270;
|
||||
if (params.coarse.hflip) tr |= TR_HFLIP;
|
||||
if (params.coarse.vflip) tr |= TR_VFLIP;
|
||||
|
||||
int fw, fh;
|
||||
imgsrc->getFullSize (fw, fh, tr);
|
||||
|
||||
ImProcFunctions ipf (¶ms, true);
|
||||
|
||||
Image16* baseImg;
|
||||
PreviewProps pp (0, 0, fw, fh, 1);
|
||||
if (fabs(params.resize.scale-1.0)<1e-5) {
|
||||
baseImg = new Image16 (fw, fh);
|
||||
imgsrc->getImage (currWB, tr, baseImg, pp, params.hlrecovery, params.icm);
|
||||
}
|
||||
else {
|
||||
Image16* oorig = new Image16 (fw, fh);
|
||||
imgsrc->getImage (currWB, tr, oorig, pp, params.hlrecovery, params.icm);
|
||||
fw *= params.resize.scale;
|
||||
fh *= params.resize.scale;
|
||||
baseImg = new Image16 (fw, fh);
|
||||
ipf.resize (oorig, baseImg);
|
||||
delete oorig;
|
||||
}
|
||||
if (pl)
|
||||
pl->setProgress (0.25);
|
||||
|
||||
// perform first analysis
|
||||
unsigned int* hist16 = new unsigned int[65536];
|
||||
ipf.firstAnalysis (baseImg, ¶ms, hist16, imgsrc->getGamma());
|
||||
|
||||
// perform transform
|
||||
if (ipf.needsTransform()) {
|
||||
Image16* trImg = new Image16 (fw, fh);
|
||||
ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh);
|
||||
delete baseImg;
|
||||
baseImg = trImg;
|
||||
}
|
||||
|
||||
// update blurmap
|
||||
int** buffer = new int*[fh];
|
||||
for (int i=0; i<fh; i++)
|
||||
buffer[i] = new int[fw];
|
||||
|
||||
SHMap* shmap = NULL;
|
||||
if (params.sh.enabled) {
|
||||
shmap = new SHMap (fw, fh, true);
|
||||
double radius = sqrt (double(fw*fw+fh*fh)) / 2.0;
|
||||
double shradius = radius / 1800.0 * params.sh.radius;
|
||||
shmap->update (baseImg, (unsigned short**)buffer, shradius, ipf.lumimul, params.sh.hq);
|
||||
}
|
||||
// RGB processing
|
||||
//!!!// auto exposure!!!
|
||||
double br = params.toneCurve.expcomp;
|
||||
int bl = params.toneCurve.black;
|
||||
|
||||
if (params.toneCurve.autoexp) {
|
||||
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::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, curve, shmap);
|
||||
|
||||
if (shmap)
|
||||
delete shmap;
|
||||
|
||||
if (pl)
|
||||
pl->setProgress (0.5);
|
||||
|
||||
|
||||
// luminance histogram update
|
||||
memset (hist16, 0, 65536*sizeof(int));
|
||||
for (int i=0; i<fh; i++)
|
||||
for (int j=0; j<fw; j++)
|
||||
hist16[labView->L[i][j]]++;
|
||||
|
||||
// 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);
|
||||
ipf.luminanceCurve (labView, labView, curve, 0, fh);
|
||||
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, curve, 1);
|
||||
ipf.chrominanceCurve (labView, labView, 0, curve, 0, fh);
|
||||
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, curve, 1);
|
||||
ipf.chrominanceCurve (labView, labView, 1, curve, 0, fh);
|
||||
|
||||
ipf.impulsedenoise (labView);
|
||||
ipf.lumadenoise (labView, buffer);
|
||||
ipf.sharpening (labView, (unsigned short**)buffer);
|
||||
|
||||
delete [] curve;
|
||||
delete [] hist16;
|
||||
|
||||
// color processing
|
||||
ipf.colorCurve (labView, labView);
|
||||
ipf.colordenoise (labView, buffer);
|
||||
ipf.dirpyrdenoise (labView);
|
||||
|
||||
// wavelet equalizer
|
||||
ipf.waveletEqualizer (labView, true, true);
|
||||
|
||||
// directional pyramid equalizer
|
||||
ipf.dirpyrequalizer (labView);
|
||||
|
||||
for (int i=0; i<fh; i++)
|
||||
delete [] buffer[i];
|
||||
delete [] buffer;
|
||||
|
||||
if (pl)
|
||||
pl->setProgress (0.75);
|
||||
|
||||
// obtain final image
|
||||
Image16* readyImg;
|
||||
int cx = 0, cy = 0, cw = labView->W, ch = labView->H;
|
||||
if (params.crop.enabled) {
|
||||
cx = params.crop.x;
|
||||
cy = params.crop.y;
|
||||
cw = params.crop.w;
|
||||
ch = params.crop.h;
|
||||
}
|
||||
readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output);
|
||||
|
||||
if (pl)
|
||||
pl->setProgress (1.0);
|
||||
|
||||
readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc);
|
||||
|
||||
ProfileContent pc;
|
||||
if (params.icm.output.compare (0, 6, "No ICM") && params.icm.output!="")
|
||||
pc = iccStore.getContent (params.icm.output);
|
||||
|
||||
readyImg->setOutputProfile (pc.data, pc.length);
|
||||
|
||||
delete baseImg;
|
||||
|
||||
if (!job->initialImage)
|
||||
ii->decreaseRef ();
|
||||
|
||||
delete job;
|
||||
|
||||
if (pl) {
|
||||
pl->setProgress (1.0);
|
||||
pl->setProgressStr ("Ready.");
|
||||
}
|
||||
|
||||
return readyImg;
|
||||
}
|
||||
|
||||
void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl) {
|
||||
|
||||
ProcessingJob* currentJob = job;
|
||||
|
||||
while (currentJob) {
|
||||
int errorCode;
|
||||
IImage16* img = processImage (currentJob, errorCode, bpl);
|
||||
if (errorCode)
|
||||
bpl->error ("Can not load input image.");
|
||||
currentJob = bpl->imageReady (img);
|
||||
}
|
||||
}
|
||||
|
||||
void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl) {
|
||||
|
||||
if (bpl)
|
||||
Glib::Thread::create(sigc::bind(sigc::ptr_fun(batchProcessingThread), job, bpl), 0, true, true, Glib::THREAD_PRIORITY_LOW);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 <rtengine.h>
|
||||
#include <colortemp.h>
|
||||
#include <imagesource.h>
|
||||
#include <improcfun.h>
|
||||
#include <curves.h>
|
||||
#include <iccstore.h>
|
||||
#include <processingjob.h>
|
||||
#include <glibmm.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#undef THREAD_PRIORITY_NORMAL
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* pl) {
|
||||
|
||||
errorCode = 0;
|
||||
|
||||
ProcessingJobImpl* job = (ProcessingJobImpl*) pjob;
|
||||
|
||||
if (pl) {
|
||||
pl->setProgressStr ("Processing...");
|
||||
pl->setProgress (0.0);
|
||||
}
|
||||
|
||||
InitialImage* ii = job->initialImage;
|
||||
if (!ii) {
|
||||
ii = InitialImage::load (job->fname, job->isRaw, &errorCode);
|
||||
if (errorCode) {
|
||||
ii->decreaseRef ();
|
||||
delete job;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
procparams::ProcParams& params = job->pparams;
|
||||
|
||||
// aquire image from imagesource
|
||||
ImageSource* imgsrc = ii->getImageSource ();
|
||||
ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green);
|
||||
if (params.wb.method=="Camera")
|
||||
currWB = imgsrc->getWB ();
|
||||
else if (params.wb.method=="Auto")
|
||||
currWB = imgsrc->getAutoWB ();
|
||||
|
||||
int tr = TR_NONE;
|
||||
if (params.coarse.rotate==90) tr |= TR_R90;
|
||||
if (params.coarse.rotate==180) tr |= TR_R180;
|
||||
if (params.coarse.rotate==270) tr |= TR_R270;
|
||||
if (params.coarse.hflip) tr |= TR_HFLIP;
|
||||
if (params.coarse.vflip) tr |= TR_VFLIP;
|
||||
|
||||
int fw, fh;
|
||||
imgsrc->getFullSize (fw, fh, tr);
|
||||
|
||||
ImProcFunctions ipf (¶ms, true);
|
||||
|
||||
Image16* baseImg;
|
||||
PreviewProps pp (0, 0, fw, fh, 1);
|
||||
if (fabs(params.resize.scale-1.0)<1e-5) {
|
||||
baseImg = new Image16 (fw, fh);
|
||||
imgsrc->getImage (currWB, tr, baseImg, pp, params.hlrecovery, params.icm);
|
||||
}
|
||||
else {
|
||||
Image16* oorig = new Image16 (fw, fh);
|
||||
imgsrc->getImage (currWB, tr, oorig, pp, params.hlrecovery, params.icm);
|
||||
fw *= params.resize.scale;
|
||||
fh *= params.resize.scale;
|
||||
baseImg = new Image16 (fw, fh);
|
||||
ipf.resize (oorig, baseImg);
|
||||
delete oorig;
|
||||
}
|
||||
if (pl)
|
||||
pl->setProgress (0.25);
|
||||
|
||||
// perform first analysis
|
||||
unsigned int* hist16 = new unsigned int[65536];
|
||||
ipf.firstAnalysis (baseImg, ¶ms, hist16, imgsrc->getGamma());
|
||||
|
||||
// perform transform
|
||||
if (ipf.needsTransform()) {
|
||||
Image16* trImg = new Image16 (fw, fh);
|
||||
ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh);
|
||||
delete baseImg;
|
||||
baseImg = trImg;
|
||||
}
|
||||
|
||||
// update blurmap
|
||||
int** buffer = new int*[fh];
|
||||
for (int i=0; i<fh; i++)
|
||||
buffer[i] = new int[fw];
|
||||
|
||||
SHMap* shmap = NULL;
|
||||
if (params.sh.enabled) {
|
||||
shmap = new SHMap (fw, fh, true);
|
||||
double radius = sqrt (double(fw*fw+fh*fh)) / 2.0;
|
||||
double shradius = radius / 1800.0 * params.sh.radius;
|
||||
shmap->update (baseImg, (unsigned short**)buffer, shradius, ipf.lumimul, params.sh.hq);
|
||||
}
|
||||
// RGB processing
|
||||
//!!!// auto exposure!!!
|
||||
double br = params.toneCurve.expcomp;
|
||||
int bl = params.toneCurve.black;
|
||||
|
||||
if (params.toneCurve.autoexp) {
|
||||
unsigned int aehist[65536]; int aehistcompr;
|
||||
imgsrc->getAEHistogram (aehist, aehistcompr);
|
||||
ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, br, bl);
|
||||
}
|
||||
|
||||
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, curve1, curve2, NULL);
|
||||
|
||||
LabImage* labView = new LabImage (baseImg);
|
||||
ipf.rgbProc (baseImg, labView, curve1, curve2, shmap);
|
||||
|
||||
if (shmap)
|
||||
delete shmap;
|
||||
|
||||
if (pl)
|
||||
pl->setProgress (0.5);
|
||||
|
||||
|
||||
// luminance histogram update
|
||||
memset (hist16, 0, 65536*sizeof(int));
|
||||
for (int i=0; i<fh; i++)
|
||||
for (int j=0; j<fw; j++)
|
||||
hist16[labView->L[i][j]]++;
|
||||
|
||||
// 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, curve1, curve2, NULL);
|
||||
ipf.luminanceCurve (labView, labView, curve2, 0, fh);
|
||||
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, curve1, 1);
|
||||
ipf.chrominanceCurve (labView, labView, 0, curve1, 0, fh);
|
||||
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, curve1, 1);
|
||||
ipf.chrominanceCurve (labView, labView, 1, curve1, 0, fh);
|
||||
|
||||
ipf.impulsedenoise (labView);
|
||||
ipf.lumadenoise (labView, buffer);
|
||||
ipf.sharpening (labView, (unsigned short**)buffer);
|
||||
|
||||
delete [] curve1;
|
||||
delete [] curve2;
|
||||
delete [] hist16;
|
||||
|
||||
// color processing
|
||||
ipf.colorCurve (labView, labView);
|
||||
ipf.colordenoise (labView, buffer);
|
||||
ipf.dirpyrdenoise (labView);
|
||||
|
||||
// wavelet equalizer
|
||||
ipf.waveletEqualizer (labView, true, true);
|
||||
|
||||
// directional pyramid equalizer
|
||||
ipf.dirpyrequalizer (labView);
|
||||
|
||||
for (int i=0; i<fh; i++)
|
||||
delete [] buffer[i];
|
||||
delete [] buffer;
|
||||
|
||||
if (pl)
|
||||
pl->setProgress (0.75);
|
||||
|
||||
// obtain final image
|
||||
Image16* readyImg;
|
||||
int cx = 0, cy = 0, cw = labView->W, ch = labView->H;
|
||||
if (params.crop.enabled) {
|
||||
cx = params.crop.x;
|
||||
cy = params.crop.y;
|
||||
cw = params.crop.w;
|
||||
ch = params.crop.h;
|
||||
}
|
||||
readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output);
|
||||
|
||||
if (pl)
|
||||
pl->setProgress (1.0);
|
||||
|
||||
readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc);
|
||||
|
||||
ProfileContent pc;
|
||||
if (params.icm.output.compare (0, 6, "No ICM") && params.icm.output!="")
|
||||
pc = iccStore.getContent (params.icm.output);
|
||||
|
||||
readyImg->setOutputProfile (pc.data, pc.length);
|
||||
|
||||
delete baseImg;
|
||||
|
||||
if (!job->initialImage)
|
||||
ii->decreaseRef ();
|
||||
|
||||
delete job;
|
||||
|
||||
if (pl) {
|
||||
pl->setProgress (1.0);
|
||||
pl->setProgressStr ("Ready.");
|
||||
}
|
||||
|
||||
return readyImg;
|
||||
}
|
||||
|
||||
void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl) {
|
||||
|
||||
ProcessingJob* currentJob = job;
|
||||
|
||||
while (currentJob) {
|
||||
int errorCode;
|
||||
IImage16* img = processImage (currentJob, errorCode, bpl);
|
||||
if (errorCode)
|
||||
bpl->error ("Can not load input image.");
|
||||
currentJob = bpl->imageReady (img);
|
||||
}
|
||||
}
|
||||
|
||||
void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl) {
|
||||
|
||||
if (bpl)
|
||||
Glib::Thread::create(sigc::bind(sigc::ptr_fun(batchProcessingThread), job, bpl), 0, true, true, Glib::THREAD_PRIORITY_LOW);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user