diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais
index c8f1c8891..b0fdf3c0d 100644
--- a/rtdata/languages/Francais
+++ b/rtdata/languages/Francais
@@ -853,8 +853,8 @@ PARTIALPASTE_PREPROCESS_HOTPIXFILT;Filtrage des pixels chauds
PARTIALPASTE_PREPROCESS_LINEDENOISE;Filtre de bruit de ligne
PARTIALPASTE_PRSHARPENING;Netteté post-redim.
PARTIALPASTE_RAWCACORR_AUTO;Corr. auto. de l'aberr. chromatique
-PARTIALPASTE_RAWCACORR_CABLUE;Aberr. chromatique bleu
-PARTIALPASTE_RAWCACORR_CARED;Aberr. chromatique rouge
+PARTIALPASTE_RAWCACORR_CAAUTOSTRENGTH;Force aberr. chromatique auto
+PARTIALPASTE_RAWCACORR_CAREDBLUE;Aberr. chromatique rouge et bleu
PARTIALPASTE_RAWEXPOS_BLACK;Niveaux de noir
PARTIALPASTE_RAWEXPOS_LINEAR;Correction du point blanc
PARTIALPASTE_RAWEXPOS_PRESER;Préservation des hautes humières
@@ -864,6 +864,7 @@ PARTIALPASTE_RAW_DCBITERATIONS;Nombre d'itération de DCB
PARTIALPASTE_RAW_DMETHOD;Algorithme de dématriçage
PARTIALPASTE_RAW_FALSECOLOR;Nbr d'itération des fausses couleurs
PARTIALPASTE_RAW_LMMSEITERATIONS;Niveau d'amélioration LMMSE
+PARTIALPASTE_RAW_PIXELSHIFT;PixelShift
PARTIALPASTE_RESIZE;Redimentionnement
PARTIALPASTE_RETINEX;Retinex
PARTIALPASTE_RGBCURVES;Courbes RVB
@@ -1629,7 +1630,7 @@ TP_PRSHARPENING_TOOLTIP;Augmente la netteté de l'image après le redimentionnem
TP_RAWCACORR_AUTO;Correction automatique
TP_RAWCACORR_CABLUE;Bleu
TP_RAWCACORR_CARED;Rouge
-TP_RAWCACORR_CASTR;force
+TP_RAWCACORR_CASTR;Force
TP_RAWEXPOS_BLACKS;Niveaux de noir
TP_RAWEXPOS_BLACK_0;Vert 1 (maître)
TP_RAWEXPOS_BLACK_1;Rouge
diff --git a/rtdata/languages/default b/rtdata/languages/default
index 3fed6e505..44a751725 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -89,6 +89,11 @@ EXPORT_BYPASS_SHARPENEDGE;Bypass Edge Sharpening
EXPORT_BYPASS_SHARPENING;Bypass Sharpening
EXPORT_BYPASS_SHARPENMICRO;Bypass Microcontrast
EXPORT_BYPASS_SH_HQ;Bypass Sharp Mask Shadows/Highlights
+EXPORT_PIPELINE;Processing pipeline
+EXPORT_BYPASS;Processing steps to bypass
+EXPORT_USE_NORMAL_PIPELINE;Standard (bypass some steps, resize at the end)
+EXPORT_USE_FAST_PIPELINE;Dedicated (full processing on resized image)
+EXPORT_USE_FAST_PIPELINE_TIP;Use a dedicated processing pipeline for images in Fast Export mode, that trades speed for quality. Resizing of the image is done as early as possible, instead of doing it at the end like in the normal pipeline. The speedup can be significant, but be prepared to see artifacts and a general degradation of output quality.
EXPORT_FASTEXPORTOPTIONS;Fast Export Options
EXPORT_INSTRUCTIONS;Fast Export options provide overrides to bypass time and resource consuming development settings and to run queue processing using the fast export settings instead. This method is recommended for quicker generation of lower resolution images when speed is a priority or when resized output is desired for one or many images without making modifications to their saved development parameters.
EXPORT_MAXHEIGHT;Maximum height:
@@ -117,7 +122,7 @@ FILEBROWSER_DELETEDLGMSG;Are you sure you want to delete the selected %1
FILEBROWSER_DELETEDLGMSGINCLPROC;Are you sure you want to delete the selected %1 files including a queue-processed version?
FILEBROWSER_EMPTYTRASH;Empty trash
FILEBROWSER_EMPTYTRASHHINT;Permanently delete the files from trash.
-FILEBROWSER_EXEC_CPB;Custom Profile Builder
+FILEBROWSER_RESETDEFAULTPROFILE;Reset to default
FILEBROWSER_EXTPROGMENU;Open with
FILEBROWSER_FLATFIELD;Flat-Field
FILEBROWSER_MOVETODARKFDIR;Move to dark-frames directory
@@ -895,8 +900,8 @@ PARTIALPASTE_PREPROCESS_HOTPIXFILT;Hot pixel filter
PARTIALPASTE_PREPROCESS_LINEDENOISE;Line noise filter
PARTIALPASTE_PRSHARPENING;Post-resize sharpening
PARTIALPASTE_RAWCACORR_AUTO;CA auto-correction
-PARTIALPASTE_RAWCACORR_CABLUE;CA blue
-PARTIALPASTE_RAWCACORR_CARED;CA red
+PARTIALPASTE_RAWCACORR_CAAUTOSTRENGTH;CA auto-correction strength
+PARTIALPASTE_RAWCACORR_CAREDBLUE;CA red & blue
PARTIALPASTE_RAWEXPOS_BLACK;Black levels
PARTIALPASTE_RAWEXPOS_LINEAR;White point correction
PARTIALPASTE_RAWEXPOS_PRESER;Highlight preservation
@@ -907,6 +912,7 @@ PARTIALPASTE_RAW_DMETHOD;Demosaic method
PARTIALPASTE_RAW_FALSECOLOR;False color suppression
PARTIALPASTE_RAW_IMAGENUM;Sub-image
PARTIALPASTE_RAW_LMMSEITERATIONS;LMMSE enhancement steps
+PARTIALPASTE_RAW_PIXELSHIFT;PixelShift
PARTIALPASTE_RESIZE;Resize
PARTIALPASTE_RETINEX;Retinex
PARTIALPASTE_RGBCURVES;RGB curves
diff --git a/rtengine/LUT.h b/rtengine/LUT.h
index d83a431ca..eb22ff7f9 100644
--- a/rtengine/LUT.h
+++ b/rtengine/LUT.h
@@ -579,7 +579,7 @@ public:
numVals = std::min(numVals, passThrough.getSize());
float mult = dest.size - 1;
- for (int i = 0; i < numVals; i++) {
+ for (unsigned int i = 0; i < numVals; i++) {
int hi = (int)(mult * passThrough[i]);
dest[hi] += this->data[i] ;
}
diff --git a/rtengine/color.cc b/rtengine/color.cc
index 5cf1d45b1..b67343b82 100644
--- a/rtengine/color.cc
+++ b/rtengine/color.cc
@@ -1530,18 +1530,8 @@ void Color::interpolateRGBColor (float realL, float iplow, float iphigh, int alg
int toDo, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo)
{
float X1, Y1, Z1, X2, Y2, Z2, X, Y, Z, XL, YL, ZL;
- float L1, L2, LL, a_1, b_1, a_2, b_2, a, b, a_L, b_L;
- float c1, c2, h1, h2, cL, hL;
- float RR, GG, BB;
- float Lr;
- float slc = 0.f;
- float hh = 0.f;
- float ll = 0.f;
- float sh = 0.f;
- bool LCH = false;
+ float L1, L2, LL, a_1 = 0.f, b_1 = 0.f, a_2, b_2, a_L, b_L;
- float ha, hb, hc, ba;
- float c_1, h_1;
// converting color 1 to Lab (image)
Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb);
@@ -1566,19 +1556,16 @@ void Color::interpolateRGBColor (float realL, float iplow, float iphigh, int alg
X2 = x2;
Y2 = y2;
Z2 = z2;
- float c_2, h_2;
if(algm == 1 ) {
Color::XYZ2Lab(X2, Y2, Z2, L2, a_2, b_2);
//Color::Lab2Lch(a_2, b_2, c_2, h_2) ;
}
- float bal, balH, cal, calH, calm;
- bal = balH = balance;
+ float cal, calH, calm;
cal = calH = calm = 1.f - chromat;
float med = 1.f;
float medH = 0.f;
- float medL = (iphigh + iplow) / 2.f;
float calan;
calan = chromat;
@@ -1589,19 +1576,6 @@ void Color::interpolateRGBColor (float realL, float iplow, float iphigh, int alg
if(twoc == 0) { // 2 colours
calan = chromat;
- //calculate new balance in function of (arbitrary) "med".. I hope no error !!
- if (realL > iplow && realL <= med) {
- bal = realL * balance / (iplow - med) - med * balance / (iplow - med);
- } else if (realL <= iplow) {
- bal = realL * balance / iplow;
- }
-
- if (realL > medH && realL <= iphigh) {
- balH = realL * balance / (iphigh - medH) - medH * balance / (iphigh - medH);
- } else if (realL > iphigh) {
- balH = realL * balance * (iphigh - 1.f) - balance * (iphigh - 1.f);
- }
-
//calculate new balance chroma
if (realL > iplow && realL <= med) {
cal = realL * calan / (iplow - med) - med * calan / (iplow - med);
@@ -1616,8 +1590,7 @@ void Color::interpolateRGBColor (float realL, float iplow, float iphigh, int alg
}
}
- float hX = 0.f;
- float hLL, hH, ccL, ccH, llH, aaH, bbH;
+ float aaH, bbH;
if(algm <= 1) {
if(twoc == 0 && metchrom == 3) { // 2 colours only with special "ab"
@@ -1639,8 +1612,6 @@ void Color::interpolateRGBColor (float realL, float iplow, float iphigh, int alg
b_1 = b_1 + (b_2 - b_1) * calby * balance;
}
}
- } else {
- h1 = hX;
}
Color::Lab2XYZ(L1, a_1, b_1, X, Y, Z);
diff --git a/rtengine/curves.cc b/rtengine/curves.cc
index 8f2aa03d3..3096f19f4 100644
--- a/rtengine/curves.cc
+++ b/rtengine/curves.cc
@@ -45,7 +45,7 @@ using namespace std;
namespace rtengine
{
-Curve::Curve () : N(0), ppn(0), x(nullptr), y(nullptr), mc(0.0), mfc(0.0), msc(0.0), mhc(0.0), ypp(nullptr), x1(0.0), y1(0.0), x2(0.0), y2(0.0), x3(0.0), y3(0.0), firstPointIncluded(false), increment(0.0), nbr_points(0), hashSize(1000 /* has to be initialized to the maximum value */) {}
+Curve::Curve () : N(0), ppn(0), x(nullptr), y(nullptr), mc(0.0), mfc(0.0), msc(0.0), mhc(0.0), hashSize(1000 /* has to be initialized to the maximum value */), ypp(nullptr), x1(0.0), y1(0.0), x2(0.0), y2(0.0), x3(0.0), y3(0.0), firstPointIncluded(false), increment(0.0), nbr_points(0) {}
void Curve::AddPolygons ()
{
@@ -104,7 +104,7 @@ void Curve::fillHash()
milestone = 0.;
polyIter = 0;
- for (unsigned int i = 0; i < (hashSize + 1);) {
+ for (unsigned int i = 0; i < hashSize + 1u;) {
while(poly_x[polyIter] < (milestone + increment)) {
++polyIter;
}
@@ -1376,7 +1376,7 @@ void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3],
}
float r, g, b, xx, yy, zz;
- float lr1, lr2;
+ float lr1, lr2 = 0.f;
int upperBound = lut1.getUpperBound();
if (pCurve->isIdentity()) {
@@ -1765,7 +1765,7 @@ float PerceptualToneCurve::get_curve_val(float x, float range[2], float lut[], s
int idx = (int)xm;
- if (idx >= lut_size - 1) {
+ if (idx >= static_cast(lut_size) - 1) {
return lut[lut_size - 1];
}
@@ -1790,7 +1790,7 @@ float PerceptualToneCurve::calculateToneCurveContrastValue() const
const float xd = 0.07;
const float tx[] = { 0.30, 0.35, 0.40, 0.45 }; // we only look in the midtone range
- for (int i = 0; i < sizeof(tx) / sizeof(tx[0]); i++) {
+ for (size_t i = 0; i < sizeof(tx) / sizeof(tx[0]); i++) {
float x0 = tx[i] - xd;
float y0 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x0) * 65535.f] / 65535.f) - k * x0;
float x1 = tx[i] + xd;
@@ -1807,7 +1807,7 @@ float PerceptualToneCurve::calculateToneCurveContrastValue() const
{
const float tx[] = { 0.20, 0.25, 0.50, 0.55 }; // we only look in the midtone range
- for (int i = 0; i < sizeof(tx) / sizeof(tx[0]); i++) {
+ for (size_t i = 0; i < sizeof(tx) / sizeof(tx[0]); i++) {
float x0 = tx[i] - xd;
float y0 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x0) * 65535.f] / 65535.f) - k * x0;
float x1 = tx[i] + xd;
diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc
index c1d2e670a..ec54b9fcf 100644
--- a/rtengine/dcraw.cc
+++ b/rtengine/dcraw.cc
@@ -9492,7 +9492,7 @@ dng_skip:
adobe_coeff (make, model);
if(!strncmp(make, "Samsung", 7) && !strncmp(model, "NX1",3))
adobe_coeff (make, model);
- if(!strncmp(make, "Pentax", 6) && (!strncmp(model, "K10D",4) || !strncmp(model, "K-70",4) || !strncmp(model, "K-1",3)))
+ if((!strncmp(make, "Pentax", 6) && (!strncmp(model, "K10D",4) || !strncmp(model, "K-70",4) || !strncmp(model, "K-1",3))) && filters != 0)
adobe_coeff (make, model);
if(!strncmp(make, "Leica", 5) && !strncmp(model, "Q",1))
adobe_coeff (make, model);
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index 4e944d9fd..7b4862ea0 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -1079,8 +1079,11 @@ void Crop::freeAll ()
namespace {
-bool check_need_larger_crop_for_lcp_distortion(const ProcParams ¶ms)
+bool check_need_larger_crop_for_lcp_distortion(int fw, int fh, int x, int y, int w, int h, const ProcParams ¶ms)
{
+ if (x == 0 && y == 0 && w == fw && h == fh) {
+ return false;
+ }
return (params.lensProf.lcpFile.length() > 0 &&
params.lensProf.useDist);
}
@@ -1134,29 +1137,33 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte
// determine which part of the source image is required to compute the crop rectangle
int orx, ory, orw, orh;
+ orx = bx1;
+ ory = by1;
+ orw = bw;
+ orh = bh;
ProcParams& params = parent->params;
+
parent->ipf.transCoord (parent->fw, parent->fh, bx1, by1, bw, bh, orx, ory, orw, orh);
+
+ if (check_need_larger_crop_for_lcp_distortion(parent->fw, parent->fh, orx, ory, orw, orh, parent->params)) {
+ double dW = double(parent->fw) * 0.15 / skip; // TODO - this is hardcoded ATM!
+ double dH = double(parent->fh) * 0.15 / skip; // this is an estimate of the max
+ // distortion relative to the image
+ // size. BUT IS 15% REALLY ENOUGH?
+ // In fact, is there a better way??
+ orw = min(int(orw + dW), parent->fw);
+ orh = min(int(orh + dH), parent->fh);
+ orx = max(int(orx - dW/2.0), 0);
+ ory = max(int(ory - dH/2.0), 0);
+ }
+
PreviewProps cp (orx, ory, orw, orh, skip);
int orW, orH;
parent->imgsrc->getSize (cp, orW, orH);
- if (check_need_larger_crop_for_lcp_distortion(parent->params)) {
- int fW, fH;
- parent->imgsrc->getFullSize(fW, fH);
- double dW = double(fW) * 0.15; // TODO - this is hardcoded ATM!
- double dH = double(fH) * 0.15; // this is an estimate of the max
- // distortion relative to the image
- // size. BUT IS 15% REALLY ENOUGH?
- // In fact, is there a better way??
- orW = min(int(orW + dW), fW);
- orH = min(int(orH + dH), fH);
- trafx = max(int(orx - dW/2.0), 0);
- trafy = max(int(ory - dH/2.0), 0);
- } else {
- trafx = orx;
- trafy = ory;
- }
+ trafx = orx;
+ trafy = ory;
int cw = skips(bw, skip);
int ch = skips(bh, skip);
diff --git a/rtengine/diagonalcurves.cc b/rtengine/diagonalcurves.cc
index 2178e3dac..9ab17a0f4 100644
--- a/rtengine/diagonalcurves.cc
+++ b/rtengine/diagonalcurves.cc
@@ -241,8 +241,8 @@ void DiagonalCurve::NURBS_set ()
nbr_points = (int)(((double)(ppn + N - 2) * sc_length[i / 3] ) / total_length);
if (nbr_points < 0) {
- for(size_t it = 0; it < sc_x.size(); it += 3) {
- printf("sc_length[%zu/3]=%f \n", it, sc_length[it / 3]);
+ for(unsigned int it = 0; it < sc_x.size(); it += 3) { // used unsigned int instead of size_t to avoid %zu in printf
+ printf("sc_length[%u/3]=%f \n", it, sc_length[it / 3]);
}
printf("NURBS diagonal curve: error detected!\n i=%u nbr_points=%d ppn=%d N=%d sc_length[i/3]=%f total_length=%f", i, nbr_points, ppn, N, sc_length[i / 3], total_length);
diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc
index 0986844f5..744950ba8 100644
--- a/rtengine/pixelshift.cc
+++ b/rtengine/pixelshift.cc
@@ -332,7 +332,7 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA
} else if(bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Off) {
bayerParams.pixelShiftMotion = 0;
bayerParams.pixelShiftAutomatic = false;
- bayerParams.pixelshiftShowMotion = false;
+ bayerParams.pixelShiftShowMotion = false;
}
if((bayerParams.pixelShiftMotion > 0 || bayerParams.pixelShiftAutomatic)) {
@@ -454,11 +454,11 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA
}
const int motion = bayerParams.pixelShiftMotion;
- const bool showMotion = bayerParams.pixelshiftShowMotion;
- const bool showOnlyMask = bayerParams.pixelshiftShowMotionMaskOnly && showMotion;
- const RAWParams::BayerSensor::ePSMotionCorrection gridSize_ = bayerParams.pixelShiftMotionCorrection;
+ const bool showMotion = bayerParams.pixelShiftShowMotion;
+ const bool showOnlyMask = bayerParams.pixelShiftShowMotionMaskOnly && showMotion;
const bool adaptive = bayerParams.pixelShiftAutomatic;
#ifdef PIXELSHIFTDEV
+ const RAWParams::BayerSensor::ePSMotionCorrection gridSize_ = bayerParams.pixelShiftMotionCorrection;
const bool detectMotion = bayerParams.pixelShiftMotion > 0;
float stddevFactorGreen = bayerParams.pixelShiftStddevFactorGreen;
float stddevFactorRed = bayerParams.pixelShiftStddevFactorRed;
@@ -475,25 +475,25 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA
const float redBlueWeight = 0.7f + 1.f;
#endif
float eperIso = bayerParams.pixelShiftEperIso;
- const bool checkNonGreenHorizontal = bayerParams.pixelShiftNonGreenHorizontal;
- const bool checkNonGreenVertical = bayerParams.pixelShiftNonGreenVertical;
const bool checkNonGreenCross = bayerParams.pixelShiftNonGreenCross;
- const bool checkNonGreenAmaze = bayerParams.pixelShiftNonGreenAmaze;
- const bool checkNonGreenCross2 = bayerParams.pixelShiftNonGreenCross2;
const bool checkGreen = bayerParams.pixelShiftGreen;
const float greenWeight = 2.f;
const bool blurMap = bayerParams.pixelShiftBlur;
const float sigma = bayerParams.pixelShiftSigma;
#ifdef PIXELSHIFTDEV
+ const bool checkNonGreenHorizontal = bayerParams.pixelShiftNonGreenHorizontal;
+ const bool checkNonGreenVertical = bayerParams.pixelShiftNonGreenVertical;
+ const bool checkNonGreenAmaze = bayerParams.pixelShiftNonGreenAmaze;
+ const bool checkNonGreenCross2 = bayerParams.pixelShiftNonGreenCross2;
const float threshold = bayerParams.pixelShiftSum + 9.f;
+ const bool experimental0 = bayerParams.pixelShiftExp0;
+ const bool automatic = bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Automatic;
#else
constexpr float threshold = 3.f + 9.f;
#endif
- const bool experimental0 = bayerParams.pixelShiftExp0;
const bool holeFill = bayerParams.pixelShiftHoleFill;
const bool equalBrightness = bayerParams.pixelShiftEqualBright;
const bool smoothTransitions = blurMap && bayerParams.pixelShiftSmoothFactor > 0. && !showOnlyMask;
- const bool automatic = bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Automatic;
const float smoothFactor = 1.0 - bayerParams.pixelShiftSmoothFactor;
static const float nReadK3II[] = { 3.4f, // ISO 100
@@ -606,8 +606,10 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA
}
+#ifdef PIXELSHIFTDEV
const bool skip = (gridSize_ == RAWParams::BayerSensor::ePSMotionCorrection::Grid1x2);
int gridSize = 1;
+
bool nOf3x3 = false;
switch (gridSize_) {
@@ -632,6 +634,9 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA
gridSize = 1;
nOf3x3 = true;
}
+#else
+ const bool nOf3x3 = true;
+#endif
if(adaptive && blurMap && nOf3x3 && smoothFactor == 0.f && !showMotion) {
if(plistener) {
@@ -707,9 +712,10 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA
// If the values of two corresponding green pixels differ my more then motionThreshold %, the pixel will be treated as a badGreen pixel
const float motionThreshold = 1.f - (motion / 100.f);
// For shades of green motion indicators
+#ifdef PIXELSHIFTDEV
const float blendFactor = ((adaptive || motion == 0.f) ? 1.f : 1.f / (1.f - motionThreshold));
-
- unsigned int offsX = 0, offsY = 0;
+#endif
+ int offsX = 0, offsY = 0;
if(!bayerParams.pixelShiftMedian || !adaptive) {
// We have to adjust the offsets for the selected subframe we use for areas with motion
@@ -860,9 +866,11 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA
#endif
for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) {
+#ifdef PIXELSHIFTDEV
float *greenDest = green[i + offsY];
float *redDest = red[i + offsY];
float *blueDest = blue[i + offsY];
+#endif
int j = winx + border - offsX;
#ifdef PIXELSHIFTDEV
diff --git a/rtengine/processingjob.cc b/rtengine/processingjob.cc
index 612edc2a2..a377e3963 100644
--- a/rtengine/processingjob.cc
+++ b/rtengine/processingjob.cc
@@ -21,16 +21,16 @@
namespace rtengine
{
-ProcessingJob* ProcessingJob::create (const Glib::ustring& fname, bool isRaw, const procparams::ProcParams& pparams)
+ProcessingJob* ProcessingJob::create (const Glib::ustring& fname, bool isRaw, const procparams::ProcParams& pparams, bool fast)
{
- return new ProcessingJobImpl (fname, isRaw, pparams);
+ return new ProcessingJobImpl (fname, isRaw, pparams, fast);
}
-ProcessingJob* ProcessingJob::create (InitialImage* initialImage, const procparams::ProcParams& pparams)
+ProcessingJob* ProcessingJob::create (InitialImage* initialImage, const procparams::ProcParams& pparams, bool fast)
{
- return new ProcessingJobImpl (initialImage, pparams);
+ return new ProcessingJobImpl (initialImage, pparams, fast);
}
void ProcessingJob::destroy (ProcessingJob* job)
diff --git a/rtengine/processingjob.h b/rtengine/processingjob.h
index 2de426a31..c7f49192e 100644
--- a/rtengine/processingjob.h
+++ b/rtengine/processingjob.h
@@ -32,12 +32,13 @@ public:
bool isRaw;
InitialImage* initialImage;
procparams::ProcParams pparams;
+ bool fast;
- ProcessingJobImpl (const Glib::ustring& fn, bool iR, const procparams::ProcParams& pp)
- : fname(fn), isRaw(iR), initialImage(nullptr), pparams(pp) {}
+ ProcessingJobImpl (const Glib::ustring& fn, bool iR, const procparams::ProcParams& pp, bool ff)
+ : fname(fn), isRaw(iR), initialImage(nullptr), pparams(pp), fast(ff) {}
- ProcessingJobImpl (InitialImage* iImage, const procparams::ProcParams& pp)
- : fname(""), isRaw(true), initialImage(iImage), pparams(pp)
+ ProcessingJobImpl (InitialImage* iImage, const procparams::ProcParams& pp, bool ff)
+ : fname(""), isRaw(true), initialImage(iImage), pparams(pp), fast(ff)
{
iImage->increaseRef();
}
@@ -48,6 +49,8 @@ public:
initialImage->decreaseRef();
}
}
+
+ bool fastPipeline() const { return fast; }
};
}
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 9da09998d..35d690eb4 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -945,8 +945,8 @@ void RAWParams::setDefaults()
deadPixelFilter = false;
hotdeadpix_thresh = 100;
bayersensor.setPixelShiftDefaults();
- bayersensor.pixelshiftShowMotion = false;
- bayersensor.pixelshiftShowMotionMaskOnly = false;
+ bayersensor.pixelShiftShowMotion = false;
+ bayersensor.pixelShiftShowMotionMaskOnly = false;
}
@@ -1168,8 +1168,8 @@ void ProcParams::setDefaults ()
epd.enabled = false;
epd.strength = 0.5;
epd.gamma = 1.0;
- epd.edgeStopping = 1.4;
- epd.scale = 0.3;
+ epd.edgeStopping = 0.5;
+ epd.scale = 0.1;
epd.reweightingIterates = 0;
sh.enabled = false;
@@ -3451,12 +3451,12 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b
keyFile.set_double ("RAW Bayer", "PixelShiftRedBlueWeight", raw.bayersensor.pixelShiftRedBlueWeight );
}
- if (!pedited || pedited->raw.bayersensor.pixelshiftShowMotion) {
- keyFile.set_boolean ("RAW Bayer", "PixelShiftShowMotion", raw.bayersensor.pixelshiftShowMotion );
+ if (!pedited || pedited->raw.bayersensor.pixelShiftShowMotion) {
+ keyFile.set_boolean ("RAW Bayer", "PixelShiftShowMotion", raw.bayersensor.pixelShiftShowMotion );
}
- if (!pedited || pedited->raw.bayersensor.pixelshiftShowMotionMaskOnly) {
- keyFile.set_boolean ("RAW Bayer", "PixelShiftShowMotionMaskOnly", raw.bayersensor.pixelshiftShowMotionMaskOnly );
+ if (!pedited || pedited->raw.bayersensor.pixelShiftShowMotionMaskOnly) {
+ keyFile.set_boolean ("RAW Bayer", "PixelShiftShowMotionMaskOnly", raw.bayersensor.pixelShiftShowMotionMaskOnly );
}
if (!pedited || pedited->raw.bayersensor.pixelShiftAutomatic) {
@@ -7680,18 +7680,18 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited)
}
if (keyFile.has_key ("RAW Bayer", "PixelShiftShowMotion")) {
- raw.bayersensor.pixelshiftShowMotion = keyFile.get_boolean("RAW Bayer", "PixelShiftShowMotion");
+ raw.bayersensor.pixelShiftShowMotion = keyFile.get_boolean("RAW Bayer", "PixelShiftShowMotion");
if (pedited) {
- pedited->raw.bayersensor.pixelshiftShowMotion = true;
+ pedited->raw.bayersensor.pixelShiftShowMotion = true;
}
}
if (keyFile.has_key ("RAW Bayer", "PixelShiftShowMotionMaskOnly")) {
- raw.bayersensor.pixelshiftShowMotionMaskOnly = keyFile.get_boolean("RAW Bayer", "PixelShiftShowMotionMaskOnly");
+ raw.bayersensor.pixelShiftShowMotionMaskOnly = keyFile.get_boolean("RAW Bayer", "PixelShiftShowMotionMaskOnly");
if (pedited) {
- pedited->raw.bayersensor.pixelshiftShowMotionMaskOnly = true;
+ pedited->raw.bayersensor.pixelShiftShowMotionMaskOnly = true;
}
}
@@ -8264,8 +8264,8 @@ bool ProcParams::operator== (const ProcParams& other)
&& raw.bayersensor.pixelShiftSigma == other.raw.bayersensor.pixelShiftSigma
&& raw.bayersensor.pixelShiftSum == other.raw.bayersensor.pixelShiftSum
&& raw.bayersensor.pixelShiftRedBlueWeight == other.raw.bayersensor.pixelShiftRedBlueWeight
- && raw.bayersensor.pixelshiftShowMotion == other.raw.bayersensor.pixelshiftShowMotion
- && raw.bayersensor.pixelshiftShowMotionMaskOnly == other.raw.bayersensor.pixelshiftShowMotionMaskOnly
+ && raw.bayersensor.pixelShiftShowMotion == other.raw.bayersensor.pixelShiftShowMotion
+ && raw.bayersensor.pixelShiftShowMotionMaskOnly == other.raw.bayersensor.pixelShiftShowMotionMaskOnly
&& raw.bayersensor.pixelShiftAutomatic == other.raw.bayersensor.pixelShiftAutomatic
&& raw.bayersensor.pixelShiftNonGreenHorizontal == other.raw.bayersensor.pixelShiftNonGreenHorizontal
&& raw.bayersensor.pixelShiftNonGreenVertical == other.raw.bayersensor.pixelShiftNonGreenVertical
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index c83856870..a2c2bf5a4 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -1221,8 +1221,8 @@ public:
double pixelShiftSigma;
double pixelShiftSum;
double pixelShiftRedBlueWeight;
- bool pixelshiftShowMotion;
- bool pixelshiftShowMotionMaskOnly;
+ bool pixelShiftShowMotion;
+ bool pixelShiftShowMotionMaskOnly;
bool pixelShiftAutomatic;
bool pixelShiftNonGreenHorizontal;
bool pixelShiftNonGreenVertical;
diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc
index 2cd1abf5f..f3252b06b 100644
--- a/rtengine/rawimage.cc
+++ b/rtengine/rawimage.cc
@@ -25,9 +25,9 @@ RawImage::RawImage( const Glib::ustring &name )
: data(nullptr)
, prefilters(0)
, filename(name)
+ , rotate_deg(0)
, profile_data(nullptr)
, allocation(nullptr)
- , rotate_deg(0)
{
memset(maximum_c4, 0, sizeof(maximum_c4));
RT_matrix_from_constant = 0;
@@ -84,9 +84,9 @@ eSensorType RawImage::getSensorType()
*/
void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblack_, bool forceAutoWB)
{
- unsigned row, col, x, y, c, sum[8];
- unsigned W = this->get_width();
- unsigned H = this->get_height();
+ unsigned sum[8], c;
+ unsigned W = this->get_width();
+ unsigned H = this->get_height();
float val;
double dsum[8], dmin, dmax;
@@ -118,7 +118,7 @@ void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblac
dsum[FC(1, 0) + 4] += (int)(((W + 1) / 2) * (H / 2));
dsum[FC(1, 1) + 4] += (int)((W / 2) * (H / 2));
- #pragma omp parallel private(val,row,col,x,y)
+ #pragma omp parallel private(val)
{
double dsumthr[8];
memset(dsumthr, 0, sizeof dsumthr);
@@ -135,15 +135,15 @@ void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblac
float *tempdata = data[0];
#pragma omp for nowait
- for (row = 0; row < H; row += 8) {
- int ymax = row + 8 < H ? row + 8 : H;
+ for (size_t row = 0; row < H; row += 8) {
+ size_t ymax = row + 8 < H ? row + 8 : H;
- for (col = 0; col < W ; col += 8) {
- int xmax = col + 8 < W ? col + 8 : W;
+ for (size_t col = 0; col < W ; col += 8) {
+ size_t xmax = col + 8 < W ? col + 8 : W;
memset(sum, 0, sizeof sum);
- for (y = row; y < ymax; y++)
- for (x = col; x < xmax; x++) {
+ for (size_t y = row; y < ymax; y++)
+ for (size_t x = col; x < xmax; x++) {
int c = FC(y, x);
val = tempdata[y * W + x];
@@ -204,13 +204,13 @@ skip_block2:
#pragma omp for nowait
- for (int row = 0; row < H; row += 8)
- for (int col = 0; col < W ; col += 8)
+ for (size_t row = 0; row < H; row += 8)
+ for (size_t col = 0; col < W ; col += 8)
{
memset(sum, 0, sizeof sum);
- for (int y = row; y < row + 8 && y < H; y++)
- for (int x = col; x < col + 8 && x < W; x++) {
+ for (size_t y = row; y < row + 8 && y < H; y++)
+ for (size_t x = col; x < col + 8 && x < W; x++) {
int c = XTRANSFC(y, x);
float val = data[y][x];
@@ -248,12 +248,12 @@ skip_block3:
pre_mul_[c] = 1;
}
} else {
- for (row = 0; row < H; row += 8)
- for (col = 0; col < W ; col += 8) {
+ for (size_t row = 0; row < H; row += 8)
+ for (size_t col = 0; col < W ; col += 8) {
memset(sum, 0, sizeof sum);
- for (y = row; y < row + 8 && y < H; y++)
- for (x = col; x < col + 8 && x < W; x++)
+ for (size_t y = row; y < row + 8 && y < H; y++)
+ for (size_t x = col; x < col + 8 && x < W; x++)
for (int c = 0; c < 3; c++) {
if (this->isBayer()) {
c = FC(y, x);
@@ -294,8 +294,8 @@ skip_block:
} else {
memset(sum, 0, sizeof sum);
- for (row = 0; row < 8; row++)
- for (col = 0; col < 8; col++) {
+ for (size_t row = 0; row < 8; row++)
+ for (size_t col = 0; col < 8; col++) {
int c = FC(row, col);
if ((val = white[row][col] - cblack_[c]) > 0) {
@@ -604,7 +604,7 @@ int RawImage::loadRaw (bool loadData, unsigned int imageNum, bool closeFile, Pro
if(tiff_bps > 0 && maximum_c4[i] > 0 && !isFoveon()) {
unsigned compare = ((uint64_t)1 << tiff_bps) - 1; // use uint64_t to avoid overflow if tiff_bps == 32
- while(maximum_c4[i] > compare) {
+ while(static_cast(maximum_c4[i]) > compare) {
maximum_c4[i] >>= 1;
}
}
@@ -632,7 +632,7 @@ int RawImage::loadRaw (bool loadData, unsigned int imageNum, bool closeFile, Pro
}
for (int c = 0; c < 4; c++) {
- if (cblack[c] < black_c4[c]) {
+ if (static_cast(cblack[c]) < black_c4[c]) {
cblack[c] = black_c4[c];
}
}
@@ -1074,7 +1074,7 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is
char name[strlen(make) + strlen(model) + 32];
sprintf(name, "%s %s", make, model);
- for (int i = 0; i < sizeof table / sizeof(table[0]); i++) {
+ for (size_t i = 0; i < sizeof table / sizeof(table[0]); i++) {
if (strcasecmp(name, table[i].prefix) == 0) {
*black_level = table[i].black_level;
*white_level = table[i].white_level;
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index df14ddcb2..4aaacd4b0 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -543,17 +543,17 @@ void RawImageSource::transformRect (PreviewProps pp, int tran, int &ssx1, int &s
int ppx = pp_x, ppy = pp_y;
if (tran & TR_HFLIP) {
- ppx = sw - pp_x - pp_width;
+ ppx = max(sw - pp_x - pp_width, 0);
}
if (tran & TR_VFLIP) {
- ppy = sh - pp_y - pp_height;
+ ppy = max(sh - pp_y - pp_height, 0);
}
int sx1 = ppx; // assuming it's >=0
int sy1 = ppy; // assuming it's >=0
- int sx2 = max(ppx + pp_width, w - 1);
- int sy2 = max(ppy + pp_height, h - 1);
+ int sx2 = min(ppx + pp_width, w - 1);
+ int sy2 = min(ppy + pp_height, h - 1);
if ((tran & TR_ROT) == TR_R180) {
sx1 = max(w - ppx - pp_width, 0);
diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h
index 729363d35..6ab12c026 100644
--- a/rtengine/rtengine.h
+++ b/rtengine/rtengine.h
@@ -471,6 +471,7 @@ class ProcessingJob
{
public:
+ virtual ~ProcessingJob() {}
/** Creates a processing job from a file name. This function always succeeds. It only stores the data into the ProcessingJob class, it does not load
* the image thus it returns immediately.
@@ -478,7 +479,7 @@ public:
* @param isRaw shall be true if it is a raw file
* @param pparams is a struct containing the processing parameters
* @return an object containing the data above. It can be passed to the functions that do the actual image processing. */
- static ProcessingJob* create (const Glib::ustring& fname, bool isRaw, const procparams::ProcParams& pparams);
+ static ProcessingJob* create (const Glib::ustring& fname, bool isRaw, const procparams::ProcParams& pparams, bool fast=false);
/** Creates a processing job from a file name. This function always succeeds. It only stores the data into the ProcessingJob class, it does not load
* the image thus it returns immediately. This function increases the reference count of the initialImage. If you decide not the process the image you
@@ -487,12 +488,14 @@ public:
* @param initialImage is a loaded and pre-processed initial image
* @param pparams is a struct containing the processing parameters
* @return an object containing the data above. It can be passed to the functions that do the actual image processing. */
- static ProcessingJob* create (InitialImage* initialImage, const procparams::ProcParams& pparams);
+ static ProcessingJob* create (InitialImage* initialImage, const procparams::ProcParams& pparams, bool fast=false);
/** Cancels and destroys a processing job. The reference count of the corresponding initialImage (if any) is decreased. After the call of this function the ProcessingJob instance
* gets invalid, you must not use it any more. Dont call this function while the job is being processed.
* @param job is the job to destroy */
static void destroy (ProcessingJob* job);
+
+ virtual bool fastPipeline() const = 0;
};
/** This function performs all the image processinf steps corresponding to the given ProcessingJob. It returns when it is ready, so it can be slow.
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index ec0b31b3f..c49535a3c 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -35,642 +35,707 @@ namespace rtengine
{
extern const Settings* settings;
-IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* pl, bool tunnelMetaData, bool flush)
+namespace {
+
+template
+void adjust_radius(const T &default_param, double scale_factor, T ¶m)
{
+ const double delta = (param - default_param) * scale_factor;
+ param = default_param + delta;
+}
+
- errorCode = 0;
-
- ProcessingJobImpl* job = static_cast(pjob);
-
- if (pl) {
- pl->setProgressStr ("PROGRESSBAR_PROCESSING");
- pl->setProgress (0.0);
+class ImageProcessor {
+public:
+ ImageProcessor(ProcessingJob* pjob, int& errorCode,
+ ProgressListener* pl, bool tunnelMetaData, bool flush):
+ job(static_cast(pjob)),
+ errorCode(errorCode),
+ pl(pl),
+ tunnelMetaData(tunnelMetaData),
+ flush(flush),
+ // internal state
+ ii(nullptr),
+ imgsrc(nullptr),
+ fw(-1),
+ fh(-1),
+ pp(0, 0, 0, 0, 0)
+ {
}
- InitialImage* ii = job->initialImage;
+ Image16 *operator()()
+ {
+ if (!job->fast) {
+ return normal_pipeline();
+ } else {
+ return fast_pipeline();
+ }
+ }
- if (!ii) {
- ii = InitialImage::load (job->fname, job->isRaw, &errorCode);
-
- if (errorCode) {
- delete job;
+private:
+ Image16 *normal_pipeline()
+ {
+ if (!stage_init()) {
return nullptr;
}
+ stage_denoise();
+ stage_transform();
+ return stage_finish();
}
- procparams::ProcParams& params = job->pparams;
+ Image16 *fast_pipeline()
+ {
+ if (!job->pparams.resize.enabled) {
+ return normal_pipeline();
+ }
- // acquire image from imagesource
- ImageSource* imgsrc = ii->getImageSource ();
+ pl = nullptr;
+
+ if (!stage_init()) {
+ return nullptr;
+ }
+ stage_transform();
+ stage_early_resize();
+ stage_denoise();
+ return stage_finish();
+ }
- int tr = getCoarseBitMask(params.coarse);
- int fw, fh;
- imgsrc->getFullSize (fw, fh, tr);
+ bool stage_init()
+ {
+ errorCode = 0;
- // check the crop params
- if (params.crop.x > fw || params.crop.y > fh) {
- // the crop is completely out of the image, so we disable the crop
- params.crop.enabled = false;
- // and we set the values to the defaults
- params.crop.x = 0;
- params.crop.y = 0;
- params.crop.w = fw;
- params.crop.h = fh;
- } else {
- if (params.crop.x < 0) {
+ if (pl) {
+ pl->setProgressStr ("PROGRESSBAR_PROCESSING");
+ pl->setProgress (0.0);
+ }
+
+ ii = job->initialImage;
+
+ if (!ii) {
+ ii = InitialImage::load (job->fname, job->isRaw, &errorCode);
+
+ if (errorCode) {
+ delete job;
+ return false; //return nullptr;
+ }
+ }
+
+ procparams::ProcParams& params = job->pparams;
+
+ // acquire image from imagesource
+ imgsrc = ii->getImageSource ();
+
+ tr = getCoarseBitMask(params.coarse);
+ imgsrc->getFullSize (fw, fh, tr);
+
+ // check the crop params
+ if (params.crop.x > fw || params.crop.y > fh) {
+ // the crop is completely out of the image, so we disable the crop
+ params.crop.enabled = false;
+ // and we set the values to the defaults
params.crop.x = 0;
- }
-
- if (params.crop.y < 0) {
params.crop.y = 0;
- }
+ params.crop.w = fw;
+ params.crop.h = fh;
+ } else {
+ if (params.crop.x < 0) {
+ params.crop.x = 0;
+ }
- if ((params.crop.x + params.crop.w) > fw) {
- // crop overflow in the width dimension ; we trim it
- params.crop.w = fw - params.crop.x;
- }
+ if (params.crop.y < 0) {
+ params.crop.y = 0;
+ }
- if ((params.crop.y + params.crop.h) > fh) {
- // crop overflow in the height dimension ; we trim it
- params.crop.h = fh - params.crop.y;
+ if ((params.crop.x + params.crop.w) > fw) {
+ // crop overflow in the width dimension ; we trim it
+ params.crop.w = fw - params.crop.x;
+ }
+
+ if ((params.crop.y + params.crop.h) > fh) {
+ // crop overflow in the height dimension ; we trim it
+ params.crop.h = fh - params.crop.y;
+ }
}
- }
// MyTime t1,t2;
// t1.set();
- ImProcFunctions ipf (¶ms, true);
+ ImProcFunctions ipf (¶ms, true);
- PreviewProps pp (0, 0, fw, fh, 1);
+ pp = PreviewProps(0, 0, fw, fh, 1);
imgsrc->setCurrentFrame(params.raw.bayersensor.imageNum);
- imgsrc->preprocess( params.raw, params.lensProf, params.coarse, params.dirpyrDenoise.enabled);
+ imgsrc->preprocess( params.raw, params.lensProf, params.coarse, params.dirpyrDenoise.enabled);
- if (params.toneCurve.autoexp) {// this enabled HLRecovery
- LUTu histRedRaw(256), histGreenRaw(256), histBlueRaw(256);
- imgsrc->getRAWHistogram(histRedRaw, histGreenRaw, histBlueRaw);
+ if (params.toneCurve.autoexp) {// this enabled HLRecovery
+ LUTu histRedRaw(256), histGreenRaw(256), histBlueRaw(256);
+ imgsrc->getRAWHistogram(histRedRaw, histGreenRaw, histBlueRaw);
- if (ToneCurveParams::HLReconstructionNecessary(histRedRaw, histGreenRaw, histBlueRaw) && !params.toneCurve.hrenabled) {
- params.toneCurve.hrenabled = true;
- // WARNING: Highlight Reconstruction is being forced 'on', should we force a method here too?
+ if (ToneCurveParams::HLReconstructionNecessary(histRedRaw, histGreenRaw, histBlueRaw) && !params.toneCurve.hrenabled) {
+ params.toneCurve.hrenabled = true;
+ // WARNING: Highlight Reconstruction is being forced 'on', should we force a method here too?
+ }
}
- }
- if (pl) {
- pl->setProgress (0.20);
- }
+ if (pl) {
+ pl->setProgress (0.20);
+ }
- imgsrc->demosaic( params.raw);
+ imgsrc->demosaic( params.raw);
- if (pl) {
- pl->setProgress (0.30);
- }
+ if (pl) {
+ pl->setProgress (0.30);
+ }
- if(params.retinex.enabled) { //enabled Retinex
- LUTf cdcurve (65536, 0);
- LUTf mapcurve (65536, 0);
- LUTu dummy;
- RetinextransmissionCurve dehatransmissionCurve;
- RetinexgaintransmissionCurve dehagaintransmissionCurve;
- bool dehacontlutili = false;
- bool mapcontlutili = false;
- bool useHsl = false;
+ if(params.retinex.enabled) { //enabled Retinex
+ LUTf cdcurve (65536, 0);
+ LUTf mapcurve (65536, 0);
+ LUTu dummy;
+ RetinextransmissionCurve dehatransmissionCurve;
+ RetinexgaintransmissionCurve dehagaintransmissionCurve;
+ bool dehacontlutili = false;
+ bool mapcontlutili = false;
+ bool useHsl = false;
// multi_array2D conversionBuffer(1, 1);
- multi_array2D conversionBuffer(1, 1);
- imgsrc->retinexPrepareBuffers(params.icm, params.retinex, conversionBuffer, dummy);
- imgsrc->retinexPrepareCurves(params.retinex, cdcurve, mapcurve, dehatransmissionCurve, dehagaintransmissionCurve, dehacontlutili, mapcontlutili, useHsl, dummy, dummy );
- float minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax;
- imgsrc->retinex( params.icm, params.retinex, params.toneCurve, cdcurve, mapcurve, dehatransmissionCurve, dehagaintransmissionCurve, conversionBuffer, dehacontlutili, mapcontlutili, useHsl, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax, dummy);
- }
-
- if (pl) {
- pl->setProgress (0.40);
- }
-
- imgsrc->HLRecovery_Global( params.toneCurve );
-
-
- if (pl) {
- pl->setProgress (0.45);
- }
-
- // set the color temperature
- ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method);
-
- if (params.wb.method == "Camera") {
- currWB = imgsrc->getWB ();
- } else if (params.wb.method == "Auto") {
- double rm, gm, bm;
- imgsrc->getAutoWBMultipliers(rm, gm, bm);
- currWB.update(rm, gm, bm, params.wb.equal, params.wb.tempBias);
- }
-
- NoiseCurve noiseLCurve;
- NoiseCurve noiseCCurve;
- Imagefloat *calclum = nullptr ;
- params.dirpyrDenoise.getCurves(noiseLCurve, noiseCCurve);
- float autoNR = (float) settings->nrauto;//
- float autoNRmax = (float) settings->nrautomax;//
- int tilesize;
- int overlap;
-
- if(settings->leveldnti == 0) {
- tilesize = 1024;
- overlap = 128;
- }
-
- if(settings->leveldnti == 1) {
- tilesize = 768;
- overlap = 96;
- }
-
- // const int tilesize = 768;
- // const int overlap = 96;
- int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip;
- ipf.Tile_calc (tilesize, overlap, 2, fw, fh, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip);
- int nbtl = numtiles_W * numtiles_H;
-
- if((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) {
- nbtl = 9;
- }
-
- float *ch_M = new float [nbtl];//allocate memory
- float *max_r = new float [nbtl];
- float *max_b = new float [nbtl];
- float *min_b = new float [9];
- float *min_r = new float [9];
- float *lumL = new float [nbtl];
- float *chromC = new float [nbtl];
- float *ry = new float [nbtl];
- float *sk = new float [nbtl];
- float *pcsk = new float [nbtl];
-
- // printf("expert=%d\n",settings->leveldnautsimpl);
- if(settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "PON") {
- MyTime t1pone, t2pone;
- t1pone.set();
- int crW, crH;
-
- if(settings->leveldnv == 0) {
- crW = 100;
- crH = 100;
+ multi_array2D conversionBuffer(1, 1);
+ imgsrc->retinexPrepareBuffers(params.icm, params.retinex, conversionBuffer, dummy);
+ imgsrc->retinexPrepareCurves(params.retinex, cdcurve, mapcurve, dehatransmissionCurve, dehagaintransmissionCurve, dehacontlutili, mapcontlutili, useHsl, dummy, dummy );
+ float minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax;
+ imgsrc->retinex( params.icm, params.retinex, params.toneCurve, cdcurve, mapcurve, dehatransmissionCurve, dehagaintransmissionCurve, conversionBuffer, dehacontlutili, mapcontlutili, useHsl, minCD, maxCD, mini, maxi, Tmean, Tsigma, Tmin, Tmax, dummy);
}
- if(settings->leveldnv == 1) {
- crW = 250;
- crH = 250;
+ if (pl) {
+ pl->setProgress (0.40);
}
- if(settings->leveldnv == 2) {
- crW = int(tileWskip / 2);
- crH = int(tileHskip / 2);
+ imgsrc->HLRecovery_Global( params.toneCurve );
+
+
+ if (pl) {
+ pl->setProgress (0.45);
}
- // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(1.15f*(tileWskip/2));}//adapted to scale of preview
- if(settings->leveldnv == 3) {
- crW = tileWskip - 10;
- crH = tileHskip - 10;
+ // set the color temperature
+ currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method);
+
+ if (params.wb.method == "Camera") {
+ currWB = imgsrc->getWB ();
+ } else if (params.wb.method == "Auto") {
+ double rm, gm, bm;
+ imgsrc->getAutoWBMultipliers(rm, gm, bm);
+ currWB.update(rm, gm, bm, params.wb.equal, params.wb.tempBias);
}
- float lowdenoise = 1.f;
- int levaut = settings->leveldnaut;
+ calclum = nullptr ;
+ params.dirpyrDenoise.getCurves(noiseLCurve, noiseCCurve);
+ autoNR = (float) settings->nrauto;//
+ autoNRmax = (float) settings->nrautomax;//
- if(levaut == 1) { //Standard
- lowdenoise = 0.7f;
+ if(settings->leveldnti == 0) {
+ tilesize = 1024;
+ overlap = 128;
}
- // int crW=tileWskip-10;//crop noise width
- // int crH=tileHskip-10;//crop noise height
+ if(settings->leveldnti == 1) {
+ tilesize = 768;
+ overlap = 96;
+ }
+
+ // const int tilesize = 768;
+ // const int overlap = 96;
+ int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip;
+ ipf.Tile_calc (tilesize, overlap, 2, fw, fh, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip);
+ int nbtl = numtiles_W * numtiles_H;
+
+ if((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) {
+ nbtl = 9;
+ }
+
+ ch_M = new float [nbtl];//allocate memory
+ max_r = new float [nbtl];
+ max_b = new float [nbtl];
+ min_b = new float [9];
+ min_r = new float [9];
+ lumL = new float [nbtl];
+ chromC = new float [nbtl];
+ ry = new float [nbtl];
+ sk = new float [nbtl];
+ pcsk = new float [nbtl];
+
+ // printf("expert=%d\n",settings->leveldnautsimpl);
+ if(settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "PON") {
+ MyTime t1pone, t2pone;
+ t1pone.set();
+ int crW, crH;
+
+ if(settings->leveldnv == 0) {
+ crW = 100;
+ crH = 100;
+ }
+
+ if(settings->leveldnv == 1) {
+ crW = 250;
+ crH = 250;
+ }
+
+ if(settings->leveldnv == 2) {
+ crW = int(tileWskip / 2);
+ crH = int(tileHskip / 2);
+ }
+
+ // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(1.15f*(tileWskip/2));}//adapted to scale of preview
+ if(settings->leveldnv == 3) {
+ crW = tileWskip - 10;
+ crH = tileHskip - 10;
+ }
+
+ float lowdenoise = 1.f;
+ int levaut = settings->leveldnaut;
+
+ if(levaut == 1) { //Standard
+ lowdenoise = 0.7f;
+ }
+
+ // int crW=tileWskip-10;//crop noise width
+ // int crH=tileHskip-10;//crop noise height
// Imagefloat *origCropPart;//init auto noise
// origCropPart = new Imagefloat (crW, crH);//allocate memory
- if (params.dirpyrDenoise.enabled) {//evaluate Noise
- LUTf gamcurve(65536, 0);
- float gam, gamthresh, gamslope;
- ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope);
- #pragma omp parallel
- {
- Imagefloat *origCropPart;//init auto noise
- origCropPart = new Imagefloat (crW, crH);//allocate memory
- Imagefloat *provicalc = new Imagefloat ((crW + 1) / 2, (crH + 1) / 2); //for denoise curves
- int skipP = 1;
- #pragma omp for schedule(dynamic) collapse(2) nowait
+ if (params.dirpyrDenoise.enabled) {//evaluate Noise
+ LUTf gamcurve(65536, 0);
+ float gam, gamthresh, gamslope;
+ ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope);
+#pragma omp parallel
+ {
+ Imagefloat *origCropPart;//init auto noise
+ origCropPart = new Imagefloat (crW, crH);//allocate memory
+ Imagefloat *provicalc = new Imagefloat ((crW + 1) / 2, (crH + 1) / 2); //for denoise curves
+ int skipP = 1;
+#pragma omp for schedule(dynamic) collapse(2) nowait
- for(int wcr = 0; wcr < numtiles_W; wcr++) {
- for(int hcr = 0; hcr < numtiles_H; hcr++) {
- int beg_tileW = wcr * tileWskip + tileWskip / 2.f - crW / 2.f;
- int beg_tileH = hcr * tileHskip + tileHskip / 2.f - crH / 2.f;
- PreviewProps ppP (beg_tileW , beg_tileH, crW, crH, skipP);
- imgsrc->getImage (currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw );
+ for(int wcr = 0; wcr < numtiles_W; wcr++) {
+ for(int hcr = 0; hcr < numtiles_H; hcr++) {
+ int beg_tileW = wcr * tileWskip + tileWskip / 2.f - crW / 2.f;
+ int beg_tileH = hcr * tileHskip + tileHskip / 2.f - crH / 2.f;
+ PreviewProps ppP (beg_tileW , beg_tileH, crW, crH, skipP);
+ imgsrc->getImage (currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw );
+ //baseImg->getStdImage(currWB, tr, origCropPart, ppP, true, params.toneCurve);
- // we only need image reduced to 1/4 here
- for(int ii = 0; ii < crH; ii += 2) {
- for(int jj = 0; jj < crW; jj += 2) {
- provicalc->r(ii >> 1, jj >> 1) = origCropPart->r(ii, jj);
- provicalc->g(ii >> 1, jj >> 1) = origCropPart->g(ii, jj);
- provicalc->b(ii >> 1, jj >> 1) = origCropPart->b(ii, jj);
+ // we only need image reduced to 1/4 here
+ for(int ii = 0; ii < crH; ii += 2) {
+ for(int jj = 0; jj < crW; jj += 2) {
+ provicalc->r(ii >> 1, jj >> 1) = origCropPart->r(ii, jj);
+ provicalc->g(ii >> 1, jj >> 1) = origCropPart->g(ii, jj);
+ provicalc->b(ii >> 1, jj >> 1) = origCropPart->b(ii, jj);
+ }
}
- }
- imgsrc->convertColorSpace(provicalc, params.icm, currWB);//for denoise luminance curve
- float maxr = 0.f;
- float maxb = 0.f;
- float pondcorrec = 1.0f;
- float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc;
- int Nb;
- chaut = 0.f;
- redaut = 0.f;
- blueaut = 0.f;
- maxredaut = 0.f;
- maxblueaut = 0.f;
- chromina = 0.f;
- sigma = 0.f;
- ipf.RGB_denoise_info(origCropPart, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, imgsrc->getDirPyrDenoiseExpComp(), chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc);
- float multip = 1.f;
- float adjustr = 1.f;
+ imgsrc->convertColorSpace(provicalc, params.icm, currWB);//for denoise luminance curve
+ float maxr = 0.f;
+ float maxb = 0.f;
+ float pondcorrec = 1.0f;
+ float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc;
+ int Nb;
+ chaut = 0.f;
+ redaut = 0.f;
+ blueaut = 0.f;
+ maxredaut = 0.f;
+ maxblueaut = 0.f;
+ chromina = 0.f;
+ sigma = 0.f;
+ ipf.RGB_denoise_info(origCropPart, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, imgsrc->getDirPyrDenoiseExpComp(), chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc);
+ float multip = 1.f;
+ float adjustr = 1.f;
- if (params.icm.working == "ProPhoto") {
- adjustr = 1.f; //
- } else if (params.icm.working == "Adobe RGB") {
- adjustr = 1.f / 1.3f;
- } else if (params.icm.working == "sRGB") {
- adjustr = 1.f / 1.3f;
- } else if (params.icm.working == "WideGamut") {
- adjustr = 1.f / 1.1f;
- } else if (params.icm.working == "Rec2020") {
- adjustr = 1.f / 1.1f;
- } else if (params.icm.working == "Beta RGB") {
- adjustr = 1.f / 1.2f;
- } else if (params.icm.working == "BestRGB") {
- adjustr = 1.f / 1.2f;
- } else if (params.icm.working == "BruceRGB") {
- adjustr = 1.f / 1.2f;
- }
-
- if(!imgsrc->isRAW()) {
- multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good fot gamma=1
- }
-
- float maxmax = max(maxredaut, maxblueaut);
- float delta;
- int mode = 2;
- int lissage = settings->leveldnliss;
- ipf.calcautodn_info (chaut, delta, Nb, levaut, maxmax, lumema, chromina, mode, lissage, redyel, skinc, nsknc);
-
- // printf("PROCESS cha=%f red=%f bl=%f redM=%f bluM=%f chrom=%f sigm=%f lum=%f sigL=%f\n",chaut,redaut,blueaut, maxredaut, maxblueaut, chromina, sigma, lumema, sigma_L);
- if(maxredaut > maxblueaut) {
- maxr = (delta) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f);
-
- if(minblueaut <= minredaut && minblueaut < chaut) {
- maxb = (-chaut + minblueaut) / (autoNRmax * multip * adjustr * lowdenoise);
+ if (params.icm.working == "ProPhoto") {
+ adjustr = 1.f; //
+ } else if (params.icm.working == "Adobe RGB") {
+ adjustr = 1.f / 1.3f;
+ } else if (params.icm.working == "sRGB") {
+ adjustr = 1.f / 1.3f;
+ } else if (params.icm.working == "WideGamut") {
+ adjustr = 1.f / 1.1f;
+ } else if (params.icm.working == "Rec2020") {
+ adjustr = 1.f / 1.1f;
+ } else if (params.icm.working == "Beta RGB") {
+ adjustr = 1.f / 1.2f;
+ } else if (params.icm.working == "BestRGB") {
+ adjustr = 1.f / 1.2f;
+ } else if (params.icm.working == "BruceRGB") {
+ adjustr = 1.f / 1.2f;
}
+
+ if(!imgsrc->isRAW()) {
+ multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good fot gamma=1
+ }
+
+ float maxmax = max(maxredaut, maxblueaut);
+ float delta;
+ int mode = 2;
+ int lissage = settings->leveldnliss;
+ ipf.calcautodn_info (chaut, delta, Nb, levaut, maxmax, lumema, chromina, mode, lissage, redyel, skinc, nsknc);
+
+ // printf("PROCESS cha=%f red=%f bl=%f redM=%f bluM=%f chrom=%f sigm=%f lum=%f sigL=%f\n",chaut,redaut,blueaut, maxredaut, maxblueaut, chromina, sigma, lumema, sigma_L);
+ if(maxredaut > maxblueaut) {
+ maxr = (delta) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f);
+
+ if(minblueaut <= minredaut && minblueaut < chaut) {
+ maxb = (-chaut + minblueaut) / (autoNRmax * multip * adjustr * lowdenoise);
+ }
+ } else {
+ maxb = (delta) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f);
+
+ if(minredaut <= minblueaut && minredaut < chaut) {
+ maxr = (-chaut + minredaut) / (autoNRmax * multip * adjustr * lowdenoise);
+ }
+ }//maxb mxr - empirical evaluation red / blue
+
+ ch_M[hcr * numtiles_W + wcr] = pondcorrec * chaut / (autoNR * multip * adjustr * lowdenoise);
+ max_r[hcr * numtiles_W + wcr] = pondcorrec * maxr;
+ max_b[hcr * numtiles_W + wcr] = pondcorrec * maxb;
+ lumL[hcr * numtiles_W + wcr] = lumema;
+ chromC[hcr * numtiles_W + wcr] = chromina;
+ ry[hcr * numtiles_W + wcr] = redyel;
+ sk[hcr * numtiles_W + wcr] = skinc;
+ pcsk[hcr * numtiles_W + wcr] = nsknc;
+
+ }
+ }
+
+ delete provicalc;
+ delete origCropPart;
+ }
+
+ int liss = settings->leveldnliss; //smooth result around mean
+
+ if(liss == 2 || liss == 3) {
+ // I smooth only mean and not delta (max)
+ float nchm = 0.f;
+ float koef = 0.4f; //between 0.1 to 0.9
+
+ if(liss == 3) {
+ koef = 0.0f; //quasi auto for mean Ch
+ }
+
+ for(int wcr = 0; wcr < numtiles_W; wcr++) {
+ for(int hcr = 0; hcr < numtiles_H; hcr++) {
+ nchm += ch_M[hcr * numtiles_W + wcr];
+ }
+ }
+
+ nchm /= (numtiles_H * numtiles_W);
+
+ for(int wcr = 0; wcr < numtiles_W; wcr++) {
+ for(int hcr = 0; hcr < numtiles_H; hcr++) {
+ ch_M[hcr * numtiles_W + wcr] = nchm + (ch_M[hcr * numtiles_W + wcr] - nchm) * koef;
+ }
+ }
+ }
+
+ if(liss == 3) { //same as auto but with much cells
+ float MaxR = 0.f;
+ float MaxB = 0.f;
+ float MaxRMoy = 0.f;
+ float MaxBMoy = 0.f;
+
+ for(int k = 0; k < nbtl; k++) {
+ MaxBMoy += max_b[k];
+ MaxRMoy += max_r[k];
+
+ if(max_r[k] > MaxR) {
+ MaxR = max_r[k];
+ }
+
+ if(max_b[k] > MaxB) {
+ MaxB = max_b[k];
+ }
+
+ }
+
+ MaxBMoy /= nbtl;
+ MaxRMoy /= nbtl;
+
+ for(int k = 0; k < nbtl; k++) {
+ if(MaxR > MaxB) {
+ max_r[k] = MaxRMoy + (MaxR - MaxRMoy) * 0.66f; //#std Dev
+ //max_b[k]=MinB;
+ max_b[k] = MaxBMoy + (MaxB - MaxBMoy) * 0.66f;
+
} else {
- maxb = (delta) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f);
+ max_b[k] = MaxBMoy + (MaxB - MaxBMoy) * 0.66f;
+ //max_r[k]=MinR;
+ max_r[k] = MaxRMoy + (MaxR - MaxRMoy) * 0.66f;
- if(minredaut <= minblueaut && minredaut < chaut) {
- maxr = (-chaut + minredaut) / (autoNRmax * multip * adjustr * lowdenoise);
+ }
+ }
+ }
+
+ if (settings->verbose) {
+ t2pone.set();
+ printf("Info denoise ponderated performed in %d usec:\n", t2pone.etime(t1pone));
+ }
+
+ }
+ }
+
+
+ if((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) {
+ MyTime t1aue, t2aue;
+ t1aue.set();
+ int crW, crH;
+
+ if(settings->leveldnv == 0) {
+ crW = 100;
+ crH = 100;
+ }
+
+ if(settings->leveldnv == 1) {
+ crW = 250;
+ crH = 250;
+ }
+
+ if(settings->leveldnv == 2) {
+ crW = int(tileWskip / 2);
+ crH = int(tileHskip / 2);
+ }
+
+ // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(1.15f*(tileWskip/2));}//adapted to scale of preview
+ if(settings->leveldnv == 3) {
+ crW = tileWskip - 10;
+ crH = tileHskip - 10;
+ }
+
+ float lowdenoise = 1.f;
+ int levaut = settings->leveldnaut;
+
+ if(levaut == 1) { //Standard
+ lowdenoise = 0.7f;
+ }
+
+ if (params.dirpyrDenoise.enabled) {//evaluate Noise
+ LUTf gamcurve(65536, 0);
+ float gam, gamthresh, gamslope;
+ ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope);
+ int Nb[9];
+ int coordW[3];//coordonate of part of image to mesure noise
+ int coordH[3];
+ int begW = 50;
+ int begH = 50;
+ coordW[0] = begW;
+ coordW[1] = fw / 2 - crW / 2;
+ coordW[2] = fw - crW - begW;
+ coordH[0] = begH;
+ coordH[1] = fh / 2 - crH / 2;
+ coordH[2] = fh - crH - begH;
+#pragma omp parallel
+ {
+ Imagefloat *origCropPart;//init auto noise
+ origCropPart = new Imagefloat (crW, crH);//allocate memory
+ Imagefloat *provicalc = new Imagefloat ((crW + 1) / 2, (crH + 1) / 2); //for denoise curves
+
+#pragma omp for schedule(dynamic) collapse(2) nowait
+
+ for(int wcr = 0; wcr <= 2; wcr++) {
+ for(int hcr = 0; hcr <= 2; hcr++) {
+ PreviewProps ppP (coordW[wcr] , coordH[hcr], crW, crH, 1);
+ imgsrc->getImage (currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw);
+ //baseImg->getStdImage(currWB, tr, origCropPart, ppP, true, params.toneCurve);
+
+
+ // we only need image reduced to 1/4 here
+ for(int ii = 0; ii < crH; ii += 2) {
+ for(int jj = 0; jj < crW; jj += 2) {
+ provicalc->r(ii >> 1, jj >> 1) = origCropPart->r(ii, jj);
+ provicalc->g(ii >> 1, jj >> 1) = origCropPart->g(ii, jj);
+ provicalc->b(ii >> 1, jj >> 1) = origCropPart->b(ii, jj);
+ }
}
- }//maxb mxr - empirical evaluation red / blue
-
- ch_M[hcr * numtiles_W + wcr] = pondcorrec * chaut / (autoNR * multip * adjustr * lowdenoise);
- max_r[hcr * numtiles_W + wcr] = pondcorrec * maxr;
- max_b[hcr * numtiles_W + wcr] = pondcorrec * maxb;
- lumL[hcr * numtiles_W + wcr] = lumema;
- chromC[hcr * numtiles_W + wcr] = chromina;
- ry[hcr * numtiles_W + wcr] = redyel;
- sk[hcr * numtiles_W + wcr] = skinc;
- pcsk[hcr * numtiles_W + wcr] = nsknc;
+ imgsrc->convertColorSpace(provicalc, params.icm, currWB);//for denoise luminance curve
+ int nb = 0;
+ float chaut = 0.f, redaut = 0.f, blueaut = 0.f, maxredaut = 0.f, maxblueaut = 0.f, minredaut = 0.f, minblueaut = 0.f, chromina = 0.f, sigma = 0.f, lumema = 0.f, sigma_L = 0.f, redyel = 0.f, skinc = 0.f, nsknc = 0.f;
+ ipf.RGB_denoise_info(origCropPart, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, imgsrc->getDirPyrDenoiseExpComp(), chaut, nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc);
+ Nb[hcr * 3 + wcr] = nb;
+ ch_M[hcr * 3 + wcr] = chaut;
+ max_r[hcr * 3 + wcr] = maxredaut;
+ max_b[hcr * 3 + wcr] = maxblueaut;
+ min_r[hcr * 3 + wcr] = minredaut;
+ min_b[hcr * 3 + wcr] = minblueaut;
+ lumL[hcr * 3 + wcr] = lumema;
+ chromC[hcr * 3 + wcr] = chromina;
+ ry[hcr * 3 + wcr] = redyel;
+ sk[hcr * 3 + wcr] = skinc;
+ pcsk[hcr * 3 + wcr] = nsknc;
+ }
}
+
+ delete provicalc;
+ delete origCropPart;
}
-
- delete provicalc;
- delete origCropPart;
- }
-
- int liss = settings->leveldnliss; //smooth result around mean
-
- if(liss == 2 || liss == 3) {
- // I smooth only mean and not delta (max)
- float nchm = 0.f;
- float koef = 0.4f; //between 0.1 to 0.9
-
- if(liss == 3) {
- koef = 0.0f; //quasi auto for mean Ch
- }
-
- for(int wcr = 0; wcr < numtiles_W; wcr++) {
- for(int hcr = 0; hcr < numtiles_H; hcr++) {
- nchm += ch_M[hcr * numtiles_W + wcr];
- }
- }
-
- nchm /= (numtiles_H * numtiles_W);
-
- for(int wcr = 0; wcr < numtiles_W; wcr++) {
- for(int hcr = 0; hcr < numtiles_H; hcr++) {
- ch_M[hcr * numtiles_W + wcr] = nchm + (ch_M[hcr * numtiles_W + wcr] - nchm) * koef;
- }
- }
- }
-
- if(liss == 3) { //same as auto but with much cells
+ float chM = 0.f;
float MaxR = 0.f;
float MaxB = 0.f;
+ float MinR = 100000000.f;
+ float MinB = 100000000.f;
+ float maxr = 0.f;
+ float maxb = 0.f;
+ float multip = 1.f;
+ float adjustr = 1.f;
+ float Max_R[9] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
+ float Max_B[9] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
+ float Min_R[9];
+ float Min_B[9];
float MaxRMoy = 0.f;
float MaxBMoy = 0.f;
+ float MinRMoy = 0.f;
+ float MinBMoy = 0.f;
- for(int k = 0; k < nbtl; k++) {
- MaxBMoy += max_b[k];
- MaxRMoy += max_r[k];
-
- if(max_r[k] > MaxR) {
- MaxR = max_r[k];
- }
-
- if(max_b[k] > MaxB) {
- MaxB = max_b[k];
- }
-
+ if (params.icm.working == "ProPhoto") {
+ adjustr = 1.f;
+ } else if (params.icm.working == "Adobe RGB") {
+ adjustr = 1.f / 1.3f;
+ } else if (params.icm.working == "sRGB") {
+ adjustr = 1.f / 1.3f;
+ } else if (params.icm.working == "WideGamut") {
+ adjustr = 1.f / 1.1f;
+ } else if (params.icm.working == "Rec2020") {
+ adjustr = 1.f / 1.1f;
+ } else if (params.icm.working == "Beta RGB") {
+ adjustr = 1.f / 1.2f;
+ } else if (params.icm.working == "BestRGB") {
+ adjustr = 1.f / 1.2f;
+ } else if (params.icm.working == "BruceRGB") {
+ adjustr = 1.f / 1.2f;
}
- MaxBMoy /= nbtl;
- MaxRMoy /= nbtl;
+ if(!imgsrc->isRAW()) {
+ multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good fot gamma=1
+ }
- for(int k = 0; k < nbtl; k++) {
- if(MaxR > MaxB) {
- max_r[k] = MaxRMoy + (MaxR - MaxRMoy) * 0.66f; //#std Dev
- //max_b[k]=MinB;
- max_b[k] = MaxBMoy + (MaxB - MaxBMoy) * 0.66f;
+ float delta[9];
+ int mode = 1;
+ int lissage = settings->leveldnliss;
+ for(int k = 0; k < 9; k++) {
+ float maxmax = max(max_r[k], max_b[k]);
+ ipf.calcautodn_info (ch_M[k], delta[k], Nb[k], levaut, maxmax, lumL[k], chromC[k], mode, lissage, ry[k], sk[k], pcsk[k] );
+ // printf("ch_M=%f delta=%f\n",ch_M[k], delta[k]);
+ }
+
+ for(int k = 0; k < 9; k++) {
+ if(max_r[k] > max_b[k]) {
+ //printf("R delta=%f koef=%f\n",delta[k],autoNRmax*multip*adjustr*lowdenoise);
+ Max_R[k] = (delta[k]) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f);
+ Min_B[k] = -(ch_M[k] - min_b[k]) / (autoNRmax * multip * adjustr * lowdenoise);
+ Max_B[k] = 0.f;
+ Min_R[k] = 0.f;
} else {
- max_b[k] = MaxBMoy + (MaxB - MaxBMoy) * 0.66f;
- //max_r[k]=MinR;
- max_r[k] = MaxRMoy + (MaxR - MaxRMoy) * 0.66f;
-
- }
- }
- }
-
- if (settings->verbose) {
- t2pone.set();
- printf("Info denoise ponderated performed in %d usec:\n", t2pone.etime(t1pone));
- }
-
- }
- }
-
-
- if((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) {
- MyTime t1aue, t2aue;
- t1aue.set();
- int crW, crH;
-
- if(settings->leveldnv == 0) {
- crW = 100;
- crH = 100;
- }
-
- if(settings->leveldnv == 1) {
- crW = 250;
- crH = 250;
- }
-
- if(settings->leveldnv == 2) {
- crW = int(tileWskip / 2);
- crH = int(tileHskip / 2);
- }
-
- // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(1.15f*(tileWskip/2));}//adapted to scale of preview
- if(settings->leveldnv == 3) {
- crW = tileWskip - 10;
- crH = tileHskip - 10;
- }
-
- float lowdenoise = 1.f;
- int levaut = settings->leveldnaut;
-
- if(levaut == 1) { //Standard
- lowdenoise = 0.7f;
- }
-
- if (params.dirpyrDenoise.enabled) {//evaluate Noise
- LUTf gamcurve(65536, 0);
- float gam, gamthresh, gamslope;
- ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope);
- int Nb[9];
- int coordW[3];//coordonate of part of image to mesure noise
- int coordH[3];
- int begW = 50;
- int begH = 50;
- coordW[0] = begW;
- coordW[1] = fw / 2 - crW / 2;
- coordW[2] = fw - crW - begW;
- coordH[0] = begH;
- coordH[1] = fh / 2 - crH / 2;
- coordH[2] = fh - crH - begH;
- #pragma omp parallel
- {
- Imagefloat *origCropPart;//init auto noise
- origCropPart = new Imagefloat (crW, crH);//allocate memory
- Imagefloat *provicalc = new Imagefloat ((crW + 1) / 2, (crH + 1) / 2); //for denoise curves
-
- #pragma omp for schedule(dynamic) collapse(2) nowait
-
- for(int wcr = 0; wcr <= 2; wcr++) {
- for(int hcr = 0; hcr <= 2; hcr++) {
- PreviewProps ppP (coordW[wcr] , coordH[hcr], crW, crH, 1);
- imgsrc->getImage (currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw);
-
- // we only need image reduced to 1/4 here
- for(int ii = 0; ii < crH; ii += 2) {
- for(int jj = 0; jj < crW; jj += 2) {
- provicalc->r(ii >> 1, jj >> 1) = origCropPart->r(ii, jj);
- provicalc->g(ii >> 1, jj >> 1) = origCropPart->g(ii, jj);
- provicalc->b(ii >> 1, jj >> 1) = origCropPart->b(ii, jj);
- }
- }
-
- imgsrc->convertColorSpace(provicalc, params.icm, currWB);//for denoise luminance curve
- int nb = 0;
- float chaut = 0.f, redaut = 0.f, blueaut = 0.f, maxredaut = 0.f, maxblueaut = 0.f, minredaut = 0.f, minblueaut = 0.f, chromina = 0.f, sigma = 0.f, lumema = 0.f, sigma_L = 0.f, redyel = 0.f, skinc = 0.f, nsknc = 0.f;
- ipf.RGB_denoise_info(origCropPart, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, imgsrc->getDirPyrDenoiseExpComp(), chaut, nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc);
- Nb[hcr * 3 + wcr] = nb;
- ch_M[hcr * 3 + wcr] = chaut;
- max_r[hcr * 3 + wcr] = maxredaut;
- max_b[hcr * 3 + wcr] = maxblueaut;
- min_r[hcr * 3 + wcr] = minredaut;
- min_b[hcr * 3 + wcr] = minblueaut;
- lumL[hcr * 3 + wcr] = lumema;
- chromC[hcr * 3 + wcr] = chromina;
- ry[hcr * 3 + wcr] = redyel;
- sk[hcr * 3 + wcr] = skinc;
- pcsk[hcr * 3 + wcr] = nsknc;
+ //printf("B delta=%f koef=%f\n",delta[k],autoNRmax*multip*adjustr*lowdenoise);
+ Max_B[k] = (delta[k]) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f);
+ Min_R[k] = - (ch_M[k] - min_r[k]) / (autoNRmax * multip * adjustr * lowdenoise);
+ Min_B[k] = 0.f;
+ Max_R[k] = 0.f;
}
}
- delete provicalc;
- delete origCropPart;
- }
- float chM = 0.f;
- float MaxR = 0.f;
- float MaxB = 0.f;
- float MinR = 100000000.f;
- float MinB = 100000000.f;
- float maxr = 0.f;
- float maxb = 0.f;
- float multip = 1.f;
- float adjustr = 1.f;
- float Max_R[9] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
- float Max_B[9] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
- float Min_R[9];
- float Min_B[9];
- float MaxRMoy = 0.f;
- float MaxBMoy = 0.f;
- float MinRMoy = 0.f;
- float MinBMoy = 0.f;
+ for(int k = 0; k < 9; k++) {
+ // printf("ch_M= %f Max_R=%f Max_B=%f min_r=%f min_b=%f\n",ch_M[k],Max_R[k], Max_B[k],Min_R[k], Min_B[k]);
+ chM += ch_M[k];
+ MaxBMoy += Max_B[k];
+ MaxRMoy += Max_R[k];
+ MinRMoy += Min_R[k];
+ MinBMoy += Min_B[k];
- if (params.icm.working == "ProPhoto") {
- adjustr = 1.f;
- } else if (params.icm.working == "Adobe RGB") {
- adjustr = 1.f / 1.3f;
- } else if (params.icm.working == "sRGB") {
- adjustr = 1.f / 1.3f;
- } else if (params.icm.working == "WideGamut") {
- adjustr = 1.f / 1.1f;
- } else if (params.icm.working == "Rec2020") {
- adjustr = 1.f / 1.1f;
- } else if (params.icm.working == "Beta RGB") {
- adjustr = 1.f / 1.2f;
- } else if (params.icm.working == "BestRGB") {
- adjustr = 1.f / 1.2f;
- } else if (params.icm.working == "BruceRGB") {
- adjustr = 1.f / 1.2f;
- }
+ if(Max_R[k] > MaxR) {
+ MaxR = Max_R[k];
+ }
- if(!imgsrc->isRAW()) {
- multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good fot gamma=1
- }
+ if(Max_B[k] > MaxB) {
+ MaxB = Max_B[k];
+ }
- float delta[9];
- int mode = 1;
- int lissage = settings->leveldnliss;
+ if(Min_R[k] < MinR) {
+ MinR = Min_R[k];
+ }
- for(int k = 0; k < 9; k++) {
- float maxmax = max(max_r[k], max_b[k]);
- ipf.calcautodn_info (ch_M[k], delta[k], Nb[k], levaut, maxmax, lumL[k], chromC[k], mode, lissage, ry[k], sk[k], pcsk[k] );
- // printf("ch_M=%f delta=%f\n",ch_M[k], delta[k]);
- }
+ if(Min_B[k] < MinB) {
+ MinB = Min_B[k];
+ }
+
+ }
+
+ chM /= 9;
+ MaxBMoy /= 9;
+ MaxRMoy /= 9;
+ MinBMoy /= 9;
+ MinRMoy /= 9;
+
+ if(MaxR > MaxB) {
+ maxr = MaxRMoy + (MaxR - MaxRMoy) * 0.66f; //#std Dev
+ // maxb=MinB;
+ maxb = MinBMoy + (MinB - MinBMoy) * 0.66f;
- for(int k = 0; k < 9; k++) {
- if(max_r[k] > max_b[k]) {
- //printf("R delta=%f koef=%f\n",delta[k],autoNRmax*multip*adjustr*lowdenoise);
- Max_R[k] = (delta[k]) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f);
- Min_B[k] = -(ch_M[k] - min_b[k]) / (autoNRmax * multip * adjustr * lowdenoise);
- Max_B[k] = 0.f;
- Min_R[k] = 0.f;
} else {
- //printf("B delta=%f koef=%f\n",delta[k],autoNRmax*multip*adjustr*lowdenoise);
- Max_B[k] = (delta[k]) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f);
- Min_R[k] = - (ch_M[k] - min_r[k]) / (autoNRmax * multip * adjustr * lowdenoise);
- Min_B[k] = 0.f;
- Max_R[k] = 0.f;
+ maxb = MaxBMoy + (MaxB - MaxBMoy) * 0.66f;
+ // maxr=MinR;
+ maxr = MinRMoy + (MinR - MinRMoy) * 0.66f;
+
}
- }
-
- for(int k = 0; k < 9; k++) {
- // printf("ch_M= %f Max_R=%f Max_B=%f min_r=%f min_b=%f\n",ch_M[k],Max_R[k], Max_B[k],Min_R[k], Min_B[k]);
- chM += ch_M[k];
- MaxBMoy += Max_B[k];
- MaxRMoy += Max_R[k];
- MinRMoy += Min_R[k];
- MinBMoy += Min_B[k];
-
- if(Max_R[k] > MaxR) {
- MaxR = Max_R[k];
- }
-
- if(Max_B[k] > MaxB) {
- MaxB = Max_B[k];
- }
-
- if(Min_R[k] < MinR) {
- MinR = Min_R[k];
- }
-
- if(Min_B[k] < MinB) {
- MinB = Min_B[k];
- }
-
- }
-
- chM /= 9;
- MaxBMoy /= 9;
- MaxRMoy /= 9;
- MinBMoy /= 9;
- MinRMoy /= 9;
-
- if(MaxR > MaxB) {
- maxr = MaxRMoy + (MaxR - MaxRMoy) * 0.66f; //#std Dev
- // maxb=MinB;
- maxb = MinBMoy + (MinB - MinBMoy) * 0.66f;
-
- } else {
- maxb = MaxBMoy + (MaxB - MaxBMoy) * 0.66f;
- // maxr=MinR;
- maxr = MinRMoy + (MinR - MinRMoy) * 0.66f;
-
- }
// printf("SIMPL cha=%f red=%f bl=%f \n",chM,maxr,maxb);
- params.dirpyrDenoise.chroma = chM / (autoNR * multip * adjustr);
- params.dirpyrDenoise.redchro = maxr;
- params.dirpyrDenoise.bluechro = maxb;
+ params.dirpyrDenoise.chroma = chM / (autoNR * multip * adjustr);
+ params.dirpyrDenoise.redchro = maxr;
+ params.dirpyrDenoise.bluechro = maxb;
+ }
+
+ if (settings->verbose) {
+ t2aue.set();
+ printf("Info denoise auto performed in %d usec:\n", t2aue.etime(t1aue));
+ }
+
+ //end evaluate noise
}
- if (settings->verbose) {
- t2aue.set();
- printf("Info denoise auto performed in %d usec:\n", t2aue.etime(t1aue));
+ baseImg = new Imagefloat (fw, fh);
+ imgsrc->getImage (currWB, tr, baseImg, pp, params.toneCurve, params.icm, params.raw);
+
+ if (pl) {
+ pl->setProgress (0.50);
}
- //end evaluate noise
- }
-
-
-
-
-
- Imagefloat* baseImg = new Imagefloat (fw, fh);
- imgsrc->getImage (currWB, tr, baseImg, pp, params.toneCurve, params.icm, params.raw);
-
- if (pl) {
- pl->setProgress (0.50);
- }
-
// LUTf Noisecurve (65536,0);
//!!!// auto exposure!!!
- double expcomp = params.toneCurve.expcomp;
- int bright = params.toneCurve.brightness;
- int contr = params.toneCurve.contrast;
- int black = params.toneCurve.black;
- int hlcompr = params.toneCurve.hlcompr;
- int hlcomprthresh = params.toneCurve.hlcomprthresh;
+ expcomp = params.toneCurve.expcomp;
+ bright = params.toneCurve.brightness;
+ contr = params.toneCurve.contrast;
+ black = params.toneCurve.black;
+ hlcompr = params.toneCurve.hlcompr;
+ hlcomprthresh = params.toneCurve.hlcomprthresh;
- if (params.toneCurve.autoexp) {
- LUTu aehist;
- int aehistcompr;
- imgsrc->getAutoExpHistogram (aehist, aehistcompr);
- ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, expcomp, bright, contr, black, hlcompr, hlcomprthresh);
+
+ if (params.toneCurve.autoexp) {
+ LUTu aehist;
+ int aehistcompr;
+ imgsrc->getAutoExpHistogram (aehist, aehistcompr);
+ ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, expcomp, bright, contr, black, hlcompr, hlcomprthresh);
+ }
+
+ // at this stage, we can flush the raw data to free up quite an important amount of memory
+ // commented out because it makes the application crash when batch processing...
+ // TODO: find a better place to flush rawData and rawRGB
+ if(flush) {
+ imgsrc->flushRawData();
+ imgsrc->flushRGB();
+ }
+
+ return true;
}
- // at this stage, we can flush the raw data to free up quite an important amount of memory
- // commented out because it makes the application crash when batch processing...
- // TODO: find a better place to flush rawData and rawRGB
- if(flush) {
- imgsrc->flushRawData();
- imgsrc->flushRGB();
- }
-
- // perform luma/chroma denoise
+ void stage_denoise()
+ {
+ procparams::ProcParams& params = job->pparams;
+ ImProcFunctions ipf (¶ms, true);
+
+ // perform luma/chroma denoise
// CieImage *cieView;
// NoisCurve noiseLCurve;
// bool lldenoiseutili=false;
@@ -678,604 +743,781 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
// params.dirpyrDenoise.getCurves(noiseLCurve, lldenoiseutili);
// if (params.dirpyrDenoise.enabled && lldenoiseutili) {
- DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise; // make a copy because we cheat here
+ DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise; // make a copy because we cheat here
- if(denoiseParams.Lmethod == "CUR") {
- if(noiseLCurve) {
- denoiseParams.luma = 0.5f;
- } else {
- denoiseParams.luma = 0.0f;
+ if(denoiseParams.Lmethod == "CUR") {
+ if(noiseLCurve) {
+ denoiseParams.luma = 0.5f;
+ } else {
+ denoiseParams.luma = 0.0f;
+ }
+ } else if(denoiseParams.Lmethod == "SLI") {
+ noiseLCurve.Reset();
}
- } else if(denoiseParams.Lmethod == "SLI") {
- noiseLCurve.Reset();
+
+ if (denoiseParams.enabled && (noiseLCurve || noiseCCurve )) {
+ // we only need image reduced to 1/4 here
+ calclum = new Imagefloat ((fw + 1) / 2, (fh + 1) / 2); //for luminance denoise curve
+#pragma omp parallel for
+
+ for(int ii = 0; ii < fh; ii += 2) {
+ for(int jj = 0; jj < fw; jj += 2) {
+ calclum->r(ii >> 1, jj >> 1) = baseImg->r(ii, jj);
+ calclum->g(ii >> 1, jj >> 1) = baseImg->g(ii, jj);
+ calclum->b(ii >> 1, jj >> 1) = baseImg->b(ii, jj);
+ }
+ }
+
+ imgsrc->convertColorSpace(calclum, params.icm, currWB);
+ }
+
+ if (denoiseParams.enabled) {
+ // CurveFactory::denoiseLL(lldenoiseutili, denoiseParams.lcurve, Noisecurve,1);
+ //denoiseParams.getCurves(noiseLCurve);
+// ipf.RGB_denoise(baseImg, baseImg, calclum, imgsrc->isRAW(), denoiseParams, params.defringe, imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, lldenoiseutili);
+ float chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi;
+ int kall = 2;
+ ipf.RGB_denoise(kall, baseImg, baseImg, calclum, ch_M, max_r, max_b, imgsrc->isRAW(), denoiseParams, imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, noiseCCurve, chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi);
+
+ }
+
+// delete calclum;
+ delete [] ch_M;
+ delete [] max_r;
+ delete [] max_b;
+ delete [] min_r;
+ delete [] min_b;
+ delete [] lumL;
+ delete [] chromC;
+ delete [] ry;
+ delete [] sk;
+ delete [] pcsk;
}
- if (denoiseParams.enabled && (noiseLCurve || noiseCCurve )) {
- // we only need image reduced to 1/4 here
- calclum = new Imagefloat ((fw + 1) / 2, (fh + 1) / 2); //for luminance denoise curve
- #pragma omp parallel for
+ void stage_transform()
+ {
+ procparams::ProcParams& params = job->pparams;
+ ImProcFunctions ipf (¶ms, true);
- for(int ii = 0; ii < fh; ii += 2) {
- for(int jj = 0; jj < fw; jj += 2) {
- calclum->r(ii >> 1, jj >> 1) = baseImg->r(ii, jj);
- calclum->g(ii >> 1, jj >> 1) = baseImg->g(ii, jj);
- calclum->b(ii >> 1, jj >> 1) = baseImg->b(ii, jj);
+ imgsrc->convertColorSpace(baseImg, params.icm, currWB);
+
+ // perform first analysis
+ hist16 (65536);
+
+ ipf.firstAnalysis (baseImg, params, hist16);
+
+ // perform transform (excepted resizing)
+ if (ipf.needsTransform()) {
+ Imagefloat* trImg = new Imagefloat (fw, fh);
+ ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, fw, fh, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(),
+ imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), true);
+ delete baseImg;
+ baseImg = trImg;
+ }
+ }
+
+ Image16 *stage_finish()
+ {
+ procparams::ProcParams& params = job->pparams;
+ ImProcFunctions ipf (¶ms, true);
+
+ if (params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) {
+ const int W = baseImg->getWidth();
+ const int H = baseImg->getHeight();
+ LabImage labcbdl(W, H);
+ ipf.rgb2lab(*baseImg, labcbdl, params.icm.working);
+ ipf.dirpyrequalizer (&labcbdl, 1);
+ ipf.lab2rgb(labcbdl, *baseImg, params.icm.working);
+ }
+
+ // update blurmap
+ SHMap* shmap = nullptr;
+
+ if (params.sh.enabled) {
+ shmap = new SHMap (fw, fh, true);
+ double radius = sqrt (double(fw * fw + fh * fh)) / 2.0;
+ double shradius = params.sh.radius;
+
+ if (!params.sh.hq) {
+ shradius *= radius / 1800.0;
+ }
+
+ shmap->update (baseImg, shradius, ipf.lumimul, params.sh.hq, 1);
+ }
+
+ // RGB processing
+
+ curve1(65536);
+ curve2(65536);
+ curve(65536, 0);
+ satcurve(65536, 0);
+ lhskcurve(65536, 0);
+ lumacurve(32770, 0); // lumacurve[32768] and lumacurve[32769] will be set to 32768 and 32769 later to allow linear interpolation
+ clcurve(65536, 0);
+ wavclCurve(65536, 0);
+
+ //if(params.blackwhite.enabled) params.toneCurve.hrenabled=false;
+
+ CurveFactory::complexCurve (expcomp, black / 65535.0, hlcompr, hlcomprthresh, params.toneCurve.shcompr, bright, contr,
+ params.toneCurve.curveMode, params.toneCurve.curve, params.toneCurve.curveMode2, params.toneCurve.curve2,
+ hist16, curve1, curve2, curve, dummy, customToneCurve1, customToneCurve2 );
+
+ CurveFactory::RGBCurve (params.rgbCurves.rcurve, rCurve, 1);
+ CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, 1);
+ CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, 1);
+
+ bool opautili = false;
+
+ if(params.colorToning.enabled) {
+ TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params.icm.working);
+ double wp[3][3] = {
+ {wprof[0][0], wprof[0][1], wprof[0][2]},
+ {wprof[1][0], wprof[1][1], wprof[1][2]},
+ {wprof[2][0], wprof[2][1], wprof[2][2]}
+ };
+ TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params.icm.working);
+ double wip[3][3] = {
+ {wiprof[0][0], wiprof[0][1], wiprof[0][2]},
+ {wiprof[1][0], wiprof[1][1], wiprof[1][2]},
+ {wiprof[2][0], wiprof[2][1], wiprof[2][2]}
+ };
+ params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip, opautili);
+ clToningcurve (65536, 0);
+ CurveFactory::curveToning(params.colorToning.clcurve, clToningcurve, 1);
+ cl2Toningcurve (65536, 0);
+ CurveFactory::curveToning(params.colorToning.cl2curve, cl2Toningcurve, 1);
+ }
+
+ labView = new LabImage (fw, fh);
+
+ if(params.blackwhite.enabled) {
+ CurveFactory::curveBW (params.blackwhite.beforeCurve, params.blackwhite.afterCurve, hist16, dummy, customToneCurvebw1, customToneCurvebw2, 1);
+ }
+
+ double rrm, ggm, bbm;
+ float autor, autog, autob;
+ float satLimit = float(params.colorToning.satProtectionThreshold) / 100.f * 0.7f + 0.3f;
+ float satLimitOpacity = 1.f - (float(params.colorToning.saturatedOpacity) / 100.f);
+
+ if(params.colorToning.enabled && params.colorToning.autosat) { //for colortoning evaluation of saturation settings
+ float moyS = 0.f;
+ float eqty = 0.f;
+ ipf.moyeqt (baseImg, moyS, eqty);//return image : mean saturation and standard dev of saturation
+ float satp = ((moyS + 1.5f * eqty) - 0.3f) / 0.7f; //1.5 sigma ==> 93% pixels with high saturation -0.3 / 0.7 convert to Hombre scale
+
+ if(satp >= 0.92f) {
+ satp = 0.92f; //avoid values too high (out of gamut)
+ }
+
+ if(satp <= 0.15f) {
+ satp = 0.15f; //avoid too low values
+ }
+
+ satLimit = 100.f * satp;
+
+ satLimitOpacity = 100.f * (moyS - 0.85f * eqty); //-0.85 sigma==>20% pixels with low saturation
+ }
+
+ autor = -9000.f; // This will ask to compute the "auto" values for the B&W tool (have to be inferior to -5000)
+ DCPProfile::ApplyState as;
+ DCPProfile *dcpProf = imgsrc->getDCP(params.icm, currWB, as);
+
+ LUTu histToneCurve;
+
+ ipf.rgbProc (baseImg, labView, nullptr, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf, as, histToneCurve);
+
+ if (settings->verbose) {
+ printf("Output image / Auto B&W coefs: R=%.2f G=%.2f B=%.2f\n", autor, autog, autob);
+ }
+
+ // if clut was used and size of clut cache == 1 we free the memory used by the clutstore (default clut cache size = 1 for 32 bit OS)
+ if ( params.filmSimulation.enabled && !params.filmSimulation.clutFilename.empty() && options.clutCacheSize == 1) {
+ CLUTStore::getInstance().clearCache();
+ }
+
+ // freeing up some memory
+ customToneCurve1.Reset();
+ customToneCurve2.Reset();
+ ctColorCurve.Reset();
+ ctOpacityCurve.Reset();
+ noiseLCurve.Reset();
+ noiseCCurve.Reset();
+ customToneCurvebw1.Reset();
+ customToneCurvebw2.Reset();
+
+ // Freeing baseImg because not used anymore
+ delete baseImg;
+ baseImg = nullptr;
+
+ if (shmap) {
+ delete shmap;
+ }
+
+ shmap = nullptr;
+
+ if (pl) {
+ pl->setProgress (0.55);
+ }
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ // start tile processing...???
+
+
+ if(params.labCurve.contrast != 0) { //only use hist16 for contrast
+ hist16.clear();
+
+#ifdef _OPENMP
+#pragma omp parallel
+#endif
+ {
+ LUTu hist16thr (hist16.getSize()); // one temporary lookup table per thread
+ hist16thr.clear();
+#ifdef _OPENMP
+#pragma omp for schedule(static) nowait
+#endif
+
+ for (int i = 0; i < fh; i++)
+ for (int j = 0; j < fw; j++) {
+ hist16thr[(int)((labView->L[i][j]))]++;
+ }
+
+#pragma omp critical
+ {
+ hist16 += hist16thr;
+ }
}
}
- imgsrc->convertColorSpace(calclum, params.icm, currWB);
- }
+ bool utili;
+ CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, hist16, lumacurve, dummy, 1, utili);
- if (denoiseParams.enabled) {
- // CurveFactory::denoiseLL(lldenoiseutili, denoiseParams.lcurve, Noisecurve,1);
- //denoiseParams.getCurves(noiseLCurve);
-// ipf.RGB_denoise(baseImg, baseImg, calclum, imgsrc->isRAW(), denoiseParams, params.defringe, imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, lldenoiseutili);
- float chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi;
- int kall = 2;
- ipf.RGB_denoise(kall, baseImg, baseImg, calclum, ch_M, max_r, max_b, imgsrc->isRAW(), denoiseParams, imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, noiseCCurve, chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi);
+ bool clcutili;
+ CurveFactory::curveCL(clcutili, params.labCurve.clcurve, clcurve, 1);
- }
+ bool ccutili, cclutili;
+ CurveFactory::complexsgnCurve (autili, butili, ccutili, cclutili, params.labCurve.acurve, params.labCurve.bcurve, params.labCurve.cccurve,
+ params.labCurve.lccurve, curve1, curve2, satcurve, lhskcurve, 1);
-// delete calclum;
- delete [] ch_M;
- delete [] max_r;
- delete [] max_b;
- delete [] min_r;
- delete [] min_b;
- delete [] lumL;
- delete [] chromC;
- delete [] ry;
- delete [] sk;
- delete [] pcsk;
+ ipf.chromiLuminanceCurve (nullptr, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy);
- imgsrc->convertColorSpace(baseImg, params.icm, currWB);
-
- // perform first analysis
- LUTu hist16 (65536);
-
- ipf.firstAnalysis (baseImg, params, hist16);
-
- // perform transform (excepted resizing)
- if (ipf.needsTransform()) {
- Imagefloat* trImg = new Imagefloat (fw, fh);
- ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, fw, fh, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(),
- imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), true);
- delete baseImg;
- baseImg = trImg;
- }
-
-
- if (params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) {
- const int W = baseImg->getWidth();
- const int H = baseImg->getHeight();
- LabImage labcbdl(W, H);
- ipf.rgb2lab(*baseImg, labcbdl, params.icm.working);
- ipf.dirpyrequalizer (&labcbdl, 1);
- ipf.lab2rgb(labcbdl, *baseImg, params.icm.working);
- }
-
- // update blurmap
- SHMap* shmap = nullptr;
-
- if (params.sh.enabled) {
- shmap = new SHMap (fw, fh, true);
- double radius = sqrt (double(fw * fw + fh * fh)) / 2.0;
- double shradius = params.sh.radius;
-
- if (!params.sh.hq) {
- shradius *= radius / 1800.0;
+ if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) {
+ ipf.EPDToneMap(labView, 5, 1);
}
- shmap->update (baseImg, shradius, ipf.lumimul, params.sh.hq, 1);
+
+ ipf.vibrance(labView);
+
+ if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) {
+ ipf.impulsedenoise (labView);
+ }
+
+ // for all treatments Defringe, Sharpening, Contrast detail ,Microcontrast they are activated if "CIECAM" function are disabled
+
+ if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) {
+ ipf.defringe (labView);
+ }
+
+ if (params.sharpenEdge.enabled) {
+ ipf.MLsharpen(labView);
+ }
+
+ if (params.sharpenMicro.enabled) {
+ if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) {
+ ipf.MLmicrocontrast (labView); //!params.colorappearance.sharpcie
+ }
+ }
+
+ if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) && params.sharpening.enabled) {
+
+ float **buffer = new float*[fh];
+
+ for (int i = 0; i < fh; i++) {
+ buffer[i] = new float[fw];
+ }
+
+ ipf.sharpening (labView, (float**)buffer, params.sharpening);
+
+ for (int i = 0; i < fh; i++) {
+ delete [] buffer[i];
+ }
+
+ delete [] buffer;
+ }
+
+ WaveletParams WaveParams = params.wavelet;
+ WavCurve wavCLVCurve;
+ WavOpacityCurveRG waOpacityCurveRG;
+ WavOpacityCurveBY waOpacityCurveBY;
+ WavOpacityCurveW waOpacityCurveW;
+ WavOpacityCurveWL waOpacityCurveWL;
+
+ params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL );
+
+
+ // directional pyramid wavelet
+ if(params.dirpyrequalizer.cbdlMethod == "aft") {
+ if((params.colorappearance.enabled && !settings->autocielab) || !params.colorappearance.enabled) {
+ ipf.dirpyrequalizer (labView, 1); //TODO: this is the luminance tonecurve, not the RGB one
+ }
+ }
+
+ bool wavcontlutili = false;
+
+ CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve,/* hist16C, dummy,*/ 1);
+
+ if(params.wavelet.enabled) {
+ ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, wavcontlutili, 1);
+ }
+
+ wavCLVCurve.Reset();
+
+ //Colorappearance and tone-mapping associated
+
+ int f_w = 1, f_h = 1;
+ int begh = 0, endh = fh;
+
+ if(params.colorappearance.tonecie || params.colorappearance.enabled) {
+ f_w = fw;
+ f_h = fh;
+ }
+
+ CieImage *cieView = new CieImage (f_w, (f_h));
+ begh = 0;
+ endh = fh;
+ CurveFactory::curveLightBrightColor (
+ params.colorappearance.curve,
+ params.colorappearance.curve2,
+ params.colorappearance.curve3,
+ hist16, dummy,
+ dummy, dummy,
+ customColCurve1,
+ customColCurve2,
+ customColCurve3,
+ 1);
+
+ if(params.colorappearance.enabled) {
+ double adap;
+ float fnum = imgsrc->getMetaData()->getFNumber ();// F number
+ float fiso = imgsrc->getMetaData()->getISOSpeed () ;// ISO
+ float fspeed = imgsrc->getMetaData()->getShutterSpeed () ;//speed
+ float fcomp = imgsrc->getMetaData()->getExpComp ();//compensation + -
+
+ if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) {
+ adap = 2000.;
+ }//if no exif data or wrong
+ else {
+ float E_V = fcomp + log2 ((fnum * fnum) / fspeed / (fiso / 100.f));
+ E_V += params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV
+ E_V += log2(params.raw.expos);// exposure raw white point ; log2 ==> linear to EV
+ adap = powf(2.f, E_V - 3.f); //cd / m2
+ }
+
+ LUTf CAMBrightCurveJ;
+ LUTf CAMBrightCurveQ;
+ float CAMMean = NAN;
+
+ if (params.sharpening.enabled) {
+ if(settings->ciecamfloat) {
+ float d;
+ ipf.ciecam_02float (cieView, float(adap), begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, d, 1, 1);
+ } else {
+ double dd;
+ ipf.ciecam_02 (cieView, adap, begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, dd, 1, 1);
+ }
+ } else {
+ if(settings->ciecamfloat) {
+ float d;
+ ipf.ciecam_02float (cieView, float(adap), begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, d, 1, 1);
+ } else {
+ double dd;
+ ipf.ciecam_02 (cieView, adap, begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, dd, 1, 1);
+ }
+ }
+ }
+
+ delete cieView;
+ cieView = nullptr;
+
+
+
+
+ // end tile processing...???
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ if (pl) {
+ pl->setProgress (0.60);
+ }
+
+ int imw, imh;
+ double tmpScale = ipf.resizeScale(¶ms, fw, fh, imw, imh);
+ bool labResize = params.resize.enabled && params.resize.method != "Nearest" && tmpScale != 1.0;
+ LabImage *tmplab;
+
+ // crop and convert to rgb16
+ 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;
+
+ if(labResize) { // crop lab data
+ tmplab = new LabImage(cw, ch);
+
+ for(int row = 0; row < ch; row++) {
+ for(int col = 0; col < cw; col++) {
+ tmplab->L[row][col] = labView->L[row + cy][col + cx];
+ tmplab->a[row][col] = labView->a[row + cy][col + cx];
+ tmplab->b[row][col] = labView->b[row + cy][col + cx];
+ }
+ }
+
+ delete labView;
+ labView = tmplab;
+ cx = 0;
+ cy = 0;
+ }
+ }
+
+ if (labResize) { // resize lab data
+ // resize image
+ tmplab = new LabImage(imw, imh);
+ ipf.Lanczos (labView, tmplab, tmpScale);
+ delete labView;
+ labView = tmplab;
+ cw = labView->W;
+ ch = labView->H;
+
+ if(params.prsharpening.enabled) {
+ for(int i = 0; i < ch; i++)
+ for(int j = 0; j < cw; j++) {
+ labView->L[i][j] = labView->L[i][j] < 0.f ? 0.f : labView->L[i][j];
+ }
+
+ float **buffer = new float*[ch];
+
+ for (int i = 0; i < ch; i++) {
+ buffer[i] = new float[cw];
+ }
+
+ ipf.sharpening (labView, (float**)buffer, params.prsharpening);
+
+ for (int i = 0; i < ch; i++) {
+ delete [] buffer[i];
+ }
+
+ delete [] buffer;
+ }
+ }
+
+ Image16* readyImg = nullptr;
+ cmsHPROFILE jprof = nullptr;
+ bool customGamma = false;
+ bool useLCMS = false;
+ bool bwonly = params.blackwhite.enabled && !params.colorToning.enabled && !autili && !butili ;
+
+ if(params.icm.gamma != "default" || params.icm.freegamma) { // if select gamma output between BT709, sRGB, linear, low, high, 2.2 , 1.8
+
+ GammaValues ga;
+ // if(params.blackwhite.enabled) params.toneCurve.hrenabled=false;
+ readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm, bwonly, &ga);
+ customGamma = true;
+
+ //or selected Free gamma
+ useLCMS = false;
+
+ if ((jprof = ICCStore::getInstance()->createCustomGammaOutputProfile (params.icm, ga)) == nullptr) {
+ useLCMS = true;
+ }
+
+ } else {
+ // if Default gamma mode: we use the profile selected in the "Output profile" combobox;
+ // gamma come from the selected profile, otherwise it comes from "Free gamma" tool
+
+ readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm, bwonly);
+
+ if (settings->verbose) {
+ printf("Output profile_: \"%s\"\n", params.icm.output.c_str());
+ }
+ }
+
+ delete labView;
+ labView = nullptr;
+
+
+
+ if(bwonly) { //force BW r=g=b
+ if (settings->verbose) {
+ printf("Force BW\n");
+ }
+
+ for (int ccw = 0; ccw < cw; ccw++) {
+ for (int cch = 0; cch < ch; cch++) {
+ readyImg->r(cch, ccw) = readyImg->g(cch, ccw);
+ readyImg->b(cch, ccw) = readyImg->g(cch, ccw);
+ }
+ }
+ }
+
+ if (pl) {
+ pl->setProgress (0.70);
+ }
+
+ if (tmpScale != 1.0 && params.resize.method == "Nearest") { // resize rgb data (gamma applied)
+ Image16* tempImage = new Image16 (imw, imh);
+ ipf.resize (readyImg, tempImage, tmpScale);
+ delete readyImg;
+ readyImg = tempImage;
+ }
+
+ if (tunnelMetaData) {
+ readyImg->setMetadata (ii->getMetaData()->getExifData ());
+ } else {
+ readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc);
+ }
+
+
+ // Setting the output curve to readyImg
+ if (customGamma) {
+ if (!useLCMS) {
+ // use corrected sRGB profile in order to apply a good TRC if present, otherwise use LCMS2 profile generated by lab2rgb16 w/ gamma
+ ProfileContent pc(jprof);
+ readyImg->setOutputProfile(pc.getData().c_str(), pc.getData().size());
+ }
+ } else {
+ // use the selected output profile if present, otherwise use LCMS2 profile generate by lab2rgb16 w/ gamma
+
+ if (params.icm.output != "" && params.icm.output != ColorManagementParams::NoICMString) {
+
+ // if ICCStore::getInstance()->getProfile send back an object, then ICCStore::getInstance()->getContent will do too
+ cmsHPROFILE jprof = ICCStore::getInstance()->getProfile(params.icm.output); //get outProfile
+
+ if (jprof == nullptr) {
+ if (settings->verbose) {
+ printf("\"%s\" ICC output profile not found!\n - use LCMS2 substitution\n", params.icm.output.c_str());
+ }
+ } else {
+ if (settings->verbose) {
+ printf("Using \"%s\" output profile\n", params.icm.output.c_str());
+ }
+
+ ProfileContent pc = ICCStore::getInstance()->getContent (params.icm.output);
+ readyImg->setOutputProfile(pc.getData().c_str(), pc.getData().size());
+ }
+ } else {
+ // No ICM
+ readyImg->setOutputProfile (nullptr, 0);
+ }
+ }
+
+// t2.set();
+// if( settings->verbose )
+// printf("Total:- %d usec\n", t2.etime(t1));
+
+ if (!job->initialImage) {
+ ii->decreaseRef ();
+ }
+
+ delete job;
+
+ if (pl) {
+ pl->setProgress (0.75);
+ }
+
+ /* curve1.reset();curve2.reset();
+ curve.reset();
+ satcurve.reset();
+ lhskcurve.reset();
+
+ rCurve.reset();
+ gCurve.reset();
+ bCurve.reset();
+ hist16.reset();
+ hist16C.reset();
+ */
+ return readyImg;
}
- // RGB processing
+ void stage_early_resize()
+ {
+ procparams::ProcParams& params = job->pparams;
+ ImProcFunctions ipf (¶ms, true);
+
+ int imw, imh;
+ double scale_factor = ipf.resizeScale(¶ms, fw, fh, imw, imh);
- LUTf curve1 (65536);
- LUTf curve2 (65536);
- LUTf curve (65536, 0);
- LUTf satcurve (65536, 0);
- LUTf lhskcurve (65536, 0);
- LUTf lumacurve(32770, 0); // lumacurve[32768] and lumacurve[32769] will be set to 32768 and 32769 later to allow linear interpolation
- LUTf clcurve (65536, 0);
+ std::unique_ptr tmplab(new LabImage(fw, fh));
+ ipf.rgb2lab(*baseImg, *tmplab, params.icm.working);
+
+ if (params.crop.enabled) {
+ int cx = params.crop.x;
+ int cy = params.crop.y;
+ int cw = params.crop.w;
+ int ch = params.crop.h;
+
+ std::unique_ptr cropped(new LabImage(cw, ch));
+
+ for(int row = 0; row < ch; row++) {
+ for(int col = 0; col < cw; col++) {
+ cropped->L[row][col] = tmplab->L[row + cy][col + cx];
+ cropped->a[row][col] = tmplab->a[row + cy][col + cx];
+ cropped->b[row][col] = tmplab->b[row + cy][col + cx];
+ }
+ }
+
+ tmplab = std::move(cropped);
+ }
+
+ assert(params.resize.enabled);
+
+ // resize image
+ {
+ std::unique_ptr resized(new LabImage(imw, imh));
+ ipf.Lanczos(tmplab.get(), resized.get(), scale_factor);
+ tmplab = std::move(resized);
+ }
+
+ adjust_procparams(scale_factor);
+
+ fw = imw;
+ fh = imh;
+
+ delete baseImg;
+ baseImg = new Imagefloat(fw, fh);
+ ipf.lab2rgb(*tmplab, *baseImg, params.icm.working);
+ }
+
+ void adjust_procparams(double scale_factor)
+ {
+ procparams::ProcParams ¶ms = job->pparams;
+ procparams::ProcParams defaultparams;
+
+ params.resize.enabled = false;
+ params.crop.enabled = false;
+
+ if (params.prsharpening.enabled) {
+ params.sharpening = params.prsharpening;
+ } else {
+ adjust_radius(defaultparams.sharpening.radius, scale_factor,
+ params.sharpening.radius);
+ }
+ params.impulseDenoise.thresh *= scale_factor;
+ if (scale_factor < 0.5) {
+ params.impulseDenoise.enabled = false;
+ }
+ params.wavelet.strength *= scale_factor;
+ params.dirpyrDenoise.luma *= scale_factor;
+ //params.dirpyrDenoise.smethod = "shal";
+ for (auto &p : params.dirpyrDenoise.lcurve) {
+ p *= scale_factor;
+ }
+
+ params.epd.scale *= scale_factor;
+ //params.epd.edgeStopping *= scale_factor;
+
+ const double dirpyreq_scale = min(scale_factor * 1.5, 1.0);
+ for (int i = 0; i < 6; ++i) {
+ adjust_radius(defaultparams.dirpyrequalizer.mult[i], dirpyreq_scale,
+ params.dirpyrequalizer.mult[i]);
+ }
+
+ adjust_radius(defaultparams.defringe.radius, scale_factor,
+ params.defringe.radius);
+ adjust_radius(defaultparams.sh.radius, scale_factor, params.sh.radius);
+
+ if (params.raw.xtranssensor.method ==
+ procparams::RAWParams::XTransSensor::methodstring[
+ procparams::RAWParams::XTransSensor::threePass]) {
+ params.raw.xtranssensor.method =
+ procparams::RAWParams::XTransSensor::methodstring[
+ procparams::RAWParams::XTransSensor::onePass];
+ }
+ }
+
+private:
+ ProcessingJobImpl* job;
+ int& errorCode;
+ ProgressListener* pl;
+ bool tunnelMetaData;
+ bool flush;
+
+ // internal state
+ InitialImage *ii;
+ ImageSource *imgsrc;
+ int fw;
+ int fh;
+
+ int tr;
+ PreviewProps pp;
+
+ NoiseCurve noiseLCurve;
+ NoiseCurve noiseCCurve;
+ Imagefloat *calclum;
+ float autoNR;
+ float autoNRmax;
+ int tilesize;
+ int overlap;
+
+ float *ch_M;
+ float *max_r;
+ float *max_b;
+ float *min_b;
+ float *min_r;
+ float *lumL;
+ float *chromC;
+ float *ry;
+ float *sk;
+ float *pcsk;
+
+ double expcomp;
+ int bright;
+ int contr;
+ int black;
+ int hlcompr;
+ int hlcomprthresh;
+
+ ColorTemp currWB;
+ Imagefloat *baseImg;
+ LabImage* labView;
+
+ LUTu hist16;
+
+ LUTf curve1;
+ LUTf curve2;
+ LUTf curve;
+ LUTf satcurve;
+ LUTf lhskcurve;
+ LUTf lumacurve;
+ LUTf clcurve;
LUTf clToningcurve;
LUTf cl2Toningcurve;
- LUTf wavclCurve (65536, 0);
+ LUTf wavclCurve;
LUTf rCurve;
LUTf gCurve;
LUTf bCurve;
LUTu dummy;
-
+
ToneCurve customToneCurve1, customToneCurve2;
ColorGradientCurve ctColorCurve;
OpacityCurve ctOpacityCurve;
ColorAppearance customColCurve1, customColCurve2, customColCurve3 ;
ToneCurve customToneCurvebw1;
ToneCurve customToneCurvebw2;
- //if(params.blackwhite.enabled) params.toneCurve.hrenabled=false;
- CurveFactory::complexCurve (expcomp, black / 65535.0, hlcompr, hlcomprthresh, params.toneCurve.shcompr, bright, contr,
- params.toneCurve.curveMode, params.toneCurve.curve, params.toneCurve.curveMode2, params.toneCurve.curve2,
- hist16, curve1, curve2, curve, dummy, customToneCurve1, customToneCurve2 );
+ bool autili, butili;
+};
- CurveFactory::RGBCurve (params.rgbCurves.rcurve, rCurve, 1);
- CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, 1);
- CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, 1);
+} // namespace
- bool opautili = false;
- if(params.colorToning.enabled) {
- TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params.icm.working);
- double wp[3][3] = {
- {wprof[0][0], wprof[0][1], wprof[0][2]},
- {wprof[1][0], wprof[1][1], wprof[1][2]},
- {wprof[2][0], wprof[2][1], wprof[2][2]}
- };
- TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params.icm.working);
- double wip[3][3] = {
- {wiprof[0][0], wiprof[0][1], wiprof[0][2]},
- {wiprof[1][0], wiprof[1][1], wiprof[1][2]},
- {wiprof[2][0], wiprof[2][1], wiprof[2][2]}
- };
- params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip, opautili);
- clToningcurve (65536, 0);
- CurveFactory::curveToning(params.colorToning.clcurve, clToningcurve, 1);
- cl2Toningcurve (65536, 0);
- CurveFactory::curveToning(params.colorToning.cl2curve, cl2Toningcurve, 1);
- }
-
- LabImage* labView = new LabImage (fw, fh);
-
- if(params.blackwhite.enabled) {
- CurveFactory::curveBW (params.blackwhite.beforeCurve, params.blackwhite.afterCurve, hist16, dummy, customToneCurvebw1, customToneCurvebw2, 1);
- }
-
- double rrm, ggm, bbm;
- float autor, autog, autob;
- float satLimit = float(params.colorToning.satProtectionThreshold) / 100.f * 0.7f + 0.3f;
- float satLimitOpacity = 1.f - (float(params.colorToning.saturatedOpacity) / 100.f);
-
- if(params.colorToning.enabled && params.colorToning.autosat) { //for colortoning evaluation of saturation settings
- float moyS = 0.f;
- float eqty = 0.f;
- ipf.moyeqt (baseImg, moyS, eqty);//return image : mean saturation and standard dev of saturation
- float satp = ((moyS + 1.5f * eqty) - 0.3f) / 0.7f; //1.5 sigma ==> 93% pixels with high saturation -0.3 / 0.7 convert to Hombre scale
-
- if(satp >= 0.92f) {
- satp = 0.92f; //avoid values too high (out of gamut)
- }
-
- if(satp <= 0.15f) {
- satp = 0.15f; //avoid too low values
- }
-
- satLimit = 100.f * satp;
-
- satLimitOpacity = 100.f * (moyS - 0.85f * eqty); //-0.85 sigma==>20% pixels with low saturation
- }
-
- autor = -9000.f; // This will ask to compute the "auto" values for the B&W tool (have to be inferior to -5000)
- DCPProfile::ApplyState as;
- DCPProfile *dcpProf = imgsrc->getDCP(params.icm, currWB, as);
-
- LUTu histToneCurve;
-
- ipf.rgbProc (baseImg, labView, nullptr, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf, as, histToneCurve);
-
- if (settings->verbose) {
- printf("Output image / Auto B&W coefs: R=%.2f G=%.2f B=%.2f\n", autor, autog, autob);
- }
-
- // if clut was used and size of clut cache == 1 we free the memory used by the clutstore (default clut cache size = 1 for 32 bit OS)
- if ( params.filmSimulation.enabled && !params.filmSimulation.clutFilename.empty() && options.clutCacheSize == 1) {
- CLUTStore::getInstance().clearCache();
- }
-
- // freeing up some memory
- customToneCurve1.Reset();
- customToneCurve2.Reset();
- ctColorCurve.Reset();
- ctOpacityCurve.Reset();
- noiseLCurve.Reset();
- noiseCCurve.Reset();
- customToneCurvebw1.Reset();
- customToneCurvebw2.Reset();
-
- // Freeing baseImg because not used anymore
- delete baseImg;
- baseImg = nullptr;
-
- if (shmap) {
- delete shmap;
- }
-
- shmap = nullptr;
-
- if (pl) {
- pl->setProgress (0.55);
- }
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- // start tile processing...???
-
-
- if(params.labCurve.contrast != 0) { //only use hist16 for contrast
- hist16.clear();
-
-#ifdef _OPENMP
- #pragma omp parallel
-#endif
- {
- LUTu hist16thr (hist16.getSize()); // one temporary lookup table per thread
- hist16thr.clear();
-#ifdef _OPENMP
- #pragma omp for schedule(static) nowait
-#endif
-
- for (int i = 0; i < fh; i++)
- for (int j = 0; j < fw; j++) {
- hist16thr[(int)((labView->L[i][j]))]++;
- }
-
- #pragma omp critical
- {
- hist16 += hist16thr;
- }
- }
- }
-
- bool utili;
- CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, hist16, lumacurve, dummy, 1, utili);
-
- bool clcutili;
- CurveFactory::curveCL(clcutili, params.labCurve.clcurve, clcurve, 1);
-
- bool autili, butili, ccutili, cclutili;
- CurveFactory::complexsgnCurve (autili, butili, ccutili, cclutili, params.labCurve.acurve, params.labCurve.bcurve, params.labCurve.cccurve,
- params.labCurve.lccurve, curve1, curve2, satcurve, lhskcurve, 1);
-
- ipf.chromiLuminanceCurve (nullptr, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy);
-
- if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) {
- ipf.EPDToneMap(labView, 5, 1);
- }
-
-
- ipf.vibrance(labView);
-
- if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) {
- ipf.impulsedenoise (labView);
- }
-
- // for all treatments Defringe, Sharpening, Contrast detail ,Microcontrast they are activated if "CIECAM" function are disabled
-
- if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) {
- ipf.defringe (labView);
- }
-
- if (params.sharpenEdge.enabled) {
- ipf.MLsharpen(labView);
- }
-
- if (params.sharpenMicro.enabled) {
- if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) {
- ipf.MLmicrocontrast (labView); //!params.colorappearance.sharpcie
- }
- }
-
- if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) && params.sharpening.enabled) {
-
- float **buffer = new float*[fh];
-
- for (int i = 0; i < fh; i++) {
- buffer[i] = new float[fw];
- }
-
- ipf.sharpening (labView, (float**)buffer, params.sharpening);
-
- for (int i = 0; i < fh; i++) {
- delete [] buffer[i];
- }
-
- delete [] buffer;
- }
-
- WaveletParams WaveParams = params.wavelet;
- WavCurve wavCLVCurve;
- WavOpacityCurveRG waOpacityCurveRG;
- WavOpacityCurveBY waOpacityCurveBY;
- WavOpacityCurveW waOpacityCurveW;
- WavOpacityCurveWL waOpacityCurveWL;
-
- params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL );
-
-
- // directional pyramid wavelet
- if(params.dirpyrequalizer.cbdlMethod == "aft") {
- if((params.colorappearance.enabled && !settings->autocielab) || !params.colorappearance.enabled) {
- ipf.dirpyrequalizer (labView, 1); //TODO: this is the luminance tonecurve, not the RGB one
- }
- }
-
- bool wavcontlutili = false;
-
- CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve,/* hist16C, dummy,*/ 1);
-
- if(params.wavelet.enabled) {
- ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, wavcontlutili, 1);
- }
-
- wavCLVCurve.Reset();
-
- //Colorappearance and tone-mapping associated
-
- int f_w = 1, f_h = 1;
- int begh = 0, endh = fh;
-
- if(params.colorappearance.tonecie || params.colorappearance.enabled) {
- f_w = fw;
- f_h = fh;
- }
-
- CieImage *cieView = new CieImage (f_w, (f_h));
- begh = 0;
- endh = fh;
- CurveFactory::curveLightBrightColor (
- params.colorappearance.curve,
- params.colorappearance.curve2,
- params.colorappearance.curve3,
- hist16, dummy,
- dummy, dummy,
- customColCurve1,
- customColCurve2,
- customColCurve3,
- 1);
-
- if(params.colorappearance.enabled) {
- double adap;
- float fnum = imgsrc->getMetaData()->getFNumber ();// F number
- float fiso = imgsrc->getMetaData()->getISOSpeed () ;// ISO
- float fspeed = imgsrc->getMetaData()->getShutterSpeed () ;//speed
- float fcomp = imgsrc->getMetaData()->getExpComp ();//compensation + -
-
- if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) {
- adap = 2000.;
- }//if no exif data or wrong
- else {
- float E_V = fcomp + log2 ((fnum * fnum) / fspeed / (fiso / 100.f));
- E_V += params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV
- E_V += log2(params.raw.expos);// exposure raw white point ; log2 ==> linear to EV
- adap = powf(2.f, E_V - 3.f); //cd / m2
- }
-
- LUTf CAMBrightCurveJ;
- LUTf CAMBrightCurveQ;
- float CAMMean = NAN;
-
- if (params.sharpening.enabled) {
- if(settings->ciecamfloat) {
- float d;
- ipf.ciecam_02float (cieView, float(adap), begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, d, 1, 1);
- } else {
- double dd;
- ipf.ciecam_02 (cieView, adap, begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, dd, 1, 1);
- }
- } else {
- if(settings->ciecamfloat) {
- float d;
- ipf.ciecam_02float (cieView, float(adap), begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, d, 1, 1);
- } else {
- double dd;
- ipf.ciecam_02 (cieView, adap, begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, dd, 1, 1);
- }
- }
- }
-
- delete cieView;
- cieView = nullptr;
-
-
-
-
- // end tile processing...???
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- if (pl) {
- pl->setProgress (0.60);
- }
-
- int imw, imh;
- double tmpScale = ipf.resizeScale(¶ms, fw, fh, imw, imh);
- bool labResize = params.resize.enabled && params.resize.method != "Nearest" && tmpScale != 1.0;
- LabImage *tmplab;
-
- // crop and convert to rgb16
- 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;
-
- if(labResize) { // crop lab data
- tmplab = new LabImage(cw, ch);
-
- for(int row = 0; row < ch; row++) {
- for(int col = 0; col < cw; col++) {
- tmplab->L[row][col] = labView->L[row + cy][col + cx];
- tmplab->a[row][col] = labView->a[row + cy][col + cx];
- tmplab->b[row][col] = labView->b[row + cy][col + cx];
- }
- }
-
- delete labView;
- labView = tmplab;
- cx = 0;
- cy = 0;
- }
- }
-
- if (labResize) { // resize lab data
- // resize image
- tmplab = new LabImage(imw, imh);
- ipf.Lanczos (labView, tmplab, tmpScale);
- delete labView;
- labView = tmplab;
- cw = labView->W;
- ch = labView->H;
-
- if(params.prsharpening.enabled) {
- for(int i = 0; i < ch; i++)
- for(int j = 0; j < cw; j++) {
- labView->L[i][j] = labView->L[i][j] < 0.f ? 0.f : labView->L[i][j];
- }
-
- float **buffer = new float*[ch];
-
- for (int i = 0; i < ch; i++) {
- buffer[i] = new float[cw];
- }
-
- ipf.sharpening (labView, (float**)buffer, params.prsharpening);
-
- for (int i = 0; i < ch; i++) {
- delete [] buffer[i];
- }
-
- delete [] buffer;
- }
- }
-
- Image16* readyImg = nullptr;
- cmsHPROFILE jprof = nullptr;
- bool customGamma = false;
- bool useLCMS = false;
- bool bwonly = params.blackwhite.enabled && !params.colorToning.enabled && !autili && !butili ;
-
- if(params.icm.gamma != "default" || params.icm.freegamma) { // if select gamma output between BT709, sRGB, linear, low, high, 2.2 , 1.8
-
- GammaValues ga;
- // if(params.blackwhite.enabled) params.toneCurve.hrenabled=false;
- readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm, bwonly, &ga);
- customGamma = true;
-
- //or selected Free gamma
- useLCMS = false;
-
- if ((jprof = ICCStore::getInstance()->createCustomGammaOutputProfile (params.icm, ga)) == nullptr) {
- useLCMS = true;
- }
-
- } else {
- // if Default gamma mode: we use the profile selected in the "Output profile" combobox;
- // gamma come from the selected profile, otherwise it comes from "Free gamma" tool
-
- readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm, bwonly);
-
- if (settings->verbose) {
- printf("Output profile_: \"%s\"\n", params.icm.output.c_str());
- }
- }
-
- delete labView;
- labView = nullptr;
-
-
-
- if(bwonly) { //force BW r=g=b
- if (settings->verbose) {
- printf("Force BW\n");
- }
-
- for (int ccw = 0; ccw < cw; ccw++) {
- for (int cch = 0; cch < ch; cch++) {
- readyImg->r(cch, ccw) = readyImg->g(cch, ccw);
- readyImg->b(cch, ccw) = readyImg->g(cch, ccw);
- }
- }
- }
-
- if (pl) {
- pl->setProgress (0.70);
- }
-
- if (tmpScale != 1.0 && params.resize.method == "Nearest") { // resize rgb data (gamma applied)
- Image16* tempImage = new Image16 (imw, imh);
- ipf.resize (readyImg, tempImage, tmpScale);
- delete readyImg;
- readyImg = tempImage;
- }
-
- if (tunnelMetaData) {
- readyImg->setMetadata (ii->getMetaData()->getExifData ());
- } else {
- readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc);
- }
-
-
- // Setting the output curve to readyImg
- if (customGamma) {
- if (!useLCMS) {
- // use corrected sRGB profile in order to apply a good TRC if present, otherwise use LCMS2 profile generated by lab2rgb16 w/ gamma
- ProfileContent pc(jprof);
- readyImg->setOutputProfile(pc.getData().c_str(), pc.getData().size());
- }
- } else {
- // use the selected output profile if present, otherwise use LCMS2 profile generate by lab2rgb16 w/ gamma
-
- if (params.icm.output != "" && params.icm.output != ColorManagementParams::NoICMString) {
-
- // if ICCStore::getInstance()->getProfile send back an object, then ICCStore::getInstance()->getContent will do too
- cmsHPROFILE jprof = ICCStore::getInstance()->getProfile(params.icm.output); //get outProfile
-
- if (jprof == nullptr) {
- if (settings->verbose) {
- printf("\"%s\" ICC output profile not found!\n - use LCMS2 substitution\n", params.icm.output.c_str());
- }
- } else {
- if (settings->verbose) {
- printf("Using \"%s\" output profile\n", params.icm.output.c_str());
- }
-
- ProfileContent pc = ICCStore::getInstance()->getContent (params.icm.output);
- readyImg->setOutputProfile(pc.getData().c_str(), pc.getData().size());
- }
- } else {
- // No ICM
- readyImg->setOutputProfile (nullptr, 0);
- }
- }
-
-// t2.set();
-// if( settings->verbose )
-// printf("Total:- %d usec\n", t2.etime(t1));
-
- if (!job->initialImage) {
- ii->decreaseRef ();
- }
-
- delete job;
-
- if (pl) {
- pl->setProgress (0.75);
- }
-
- /* curve1.reset();curve2.reset();
- curve.reset();
- satcurve.reset();
- lhskcurve.reset();
-
- rCurve.reset();
- gCurve.reset();
- bCurve.reset();
- hist16.reset();
- hist16C.reset();
- */
- return readyImg;
+IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* pl, bool tunnelMetaData, bool flush)
+{
+ ImageProcessor proc(pjob, errorCode, pl, tunnelMetaData, flush);
+ return proc();
}
void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl, bool tunnelMetaData)
diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc
index fc5636b1a..763e1e441 100644
--- a/rtgui/batchqueue.cc
+++ b/rtgui/batchqueue.cc
@@ -34,6 +34,7 @@
#include "guiutils.h"
#include "rtimage.h"
#include
+
using namespace std;
using namespace rtengine;
@@ -227,7 +228,7 @@ bool BatchQueue::saveBatchQueue ()
// The column's header is mandatory (the first line will be skipped when loaded)
file << "input image full path|param file full path|output image full path|file format|jpeg quality|jpeg subsampling|"
- << "png bit depth|png compression|tiff bit depth|uncompressed tiff|save output params|force format options|"
+ << "png bit depth|png compression|tiff bit depth|uncompressed tiff|save output params|force format options|fast export|"
<< std::endl;
// method is already running with entryLock, so no need to lock again
@@ -242,6 +243,7 @@ bool BatchQueue::saveBatchQueue ()
<< saveFormat.pngBits << '|' << saveFormat.pngCompression << '|'
<< saveFormat.tiffBits << '|' << saveFormat.tiffUncompressed << '|'
<< saveFormat.saveParams << '|' << entry->forceFormatOpts << '|'
+ << entry->job->fastPipeline() << '|'
<< std::endl;
}
}
@@ -308,6 +310,7 @@ bool BatchQueue::loadBatchQueue ()
const auto tiffUncompressed = nextIntOr (options.saveFormat.tiffUncompressed);
const auto saveParams = nextIntOr (options.saveFormat.saveParams);
const auto forceFormatOpts = nextIntOr (options.forceFormatOpts);
+ const auto fast = nextIntOr(false);
rtengine::procparams::ProcParams pparams;
@@ -319,7 +322,7 @@ bool BatchQueue::loadBatchQueue ()
if (!thumb)
continue;
- auto job = rtengine::ProcessingJob::create (source, thumb->getType () == FT_Raw, pparams);
+ auto job = rtengine::ProcessingJob::create (source, thumb->getType () == FT_Raw, pparams, fast);
auto prevh = getMaxThumbnailHeight ();
auto prevw = prevh;
diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc
index ba7cfa8e8..bc2809971 100644
--- a/rtgui/bayerprocess.cc
+++ b/rtgui/bayerprocess.cc
@@ -357,11 +357,11 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params
dcbIterations->setValue (pp->raw.bayersensor.dcb_iterations);
dcbEnhance->setValue (pp->raw.bayersensor.dcb_enhance);
- pixelShiftShowMotion->setValue (pp->raw.bayersensor.pixelshiftShowMotion);
+ pixelShiftShowMotion->setValue (pp->raw.bayersensor.pixelShiftShowMotion);
if (!batchMode) {
- pixelShiftShowMotionMaskOnly->set_sensitive (pp->raw.bayersensor.pixelshiftShowMotion);
+ pixelShiftShowMotionMaskOnly->set_sensitive (pp->raw.bayersensor.pixelShiftShowMotion);
}
- pixelShiftShowMotionMaskOnly->setValue (pp->raw.bayersensor.pixelshiftShowMotionMaskOnly);
+ pixelShiftShowMotionMaskOnly->setValue (pp->raw.bayersensor.pixelShiftShowMotionMaskOnly);
pixelShiftHoleFill->setValue (pp->raw.bayersensor.pixelShiftHoleFill);
pixelShiftMedian->setValue (pp->raw.bayersensor.pixelShiftMedian);
pixelShiftGreen->setValue (pp->raw.bayersensor.pixelShiftGreen);
@@ -412,8 +412,8 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params
ccSteps->setEditedState (pedited->raw.bayersensor.ccSteps ? Edited : UnEdited);
dcbIterations->setEditedState ( pedited->raw.bayersensor.dcbIterations ? Edited : UnEdited);
dcbEnhance->setEdited (pedited->raw.bayersensor.dcbEnhance);
- pixelShiftShowMotion->setEdited (pedited->raw.bayersensor.pixelshiftShowMotion);
- pixelShiftShowMotionMaskOnly->setEdited (pedited->raw.bayersensor.pixelshiftShowMotionMaskOnly);
+ pixelShiftShowMotion->setEdited (pedited->raw.bayersensor.pixelShiftShowMotion);
+ pixelShiftShowMotionMaskOnly->setEdited (pedited->raw.bayersensor.pixelShiftShowMotionMaskOnly);
pixelShiftHoleFill->setEdited (pedited->raw.bayersensor.pixelShiftHoleFill);
pixelShiftMedian->setEdited(pedited->raw.bayersensor.pixelShiftMedian);
pixelShiftGreen->setEdited (pedited->raw.bayersensor.pixelShiftGreen);
@@ -515,8 +515,8 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe
pp->raw.bayersensor.pixelShiftMotionCorrectionMethod = (RAWParams::BayerSensor::ePSMotionCorrectionMethod)pixelShiftMotionMethod->get_active_row_number();
pp->raw.bayersensor.pixelShiftEperIso = pixelShiftEperIso->getValue();
pp->raw.bayersensor.pixelShiftSigma = pixelShiftSigma->getValue();
- pp->raw.bayersensor.pixelshiftShowMotion = pixelShiftShowMotion->getLastActive ();
- pp->raw.bayersensor.pixelshiftShowMotionMaskOnly = pixelShiftShowMotionMaskOnly->getLastActive ();
+ pp->raw.bayersensor.pixelShiftShowMotion = pixelShiftShowMotion->getLastActive ();
+ pp->raw.bayersensor.pixelShiftShowMotionMaskOnly = pixelShiftShowMotionMaskOnly->getLastActive ();
pp->raw.bayersensor.pixelShiftHoleFill = pixelShiftHoleFill->getLastActive ();
pp->raw.bayersensor.pixelShiftMedian = pixelShiftMedian->getLastActive ();
pp->raw.bayersensor.pixelShiftGreen = pixelShiftGreen->getLastActive ();
@@ -566,8 +566,8 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe
pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod = pixelShiftMotionMethod->get_active_text() != M("GENERAL_UNCHANGED");
pedited->raw.bayersensor.pixelShiftEperIso = pixelShiftEperIso->getEditedState ();
pedited->raw.bayersensor.pixelShiftSigma = pixelShiftSigma->getEditedState ();
- pedited->raw.bayersensor.pixelshiftShowMotion = !pixelShiftShowMotion->get_inconsistent();
- pedited->raw.bayersensor.pixelshiftShowMotionMaskOnly = !pixelShiftShowMotionMaskOnly->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftShowMotion = !pixelShiftShowMotion->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftShowMotionMaskOnly = !pixelShiftShowMotionMaskOnly->get_inconsistent();
pedited->raw.bayersensor.pixelShiftHoleFill = !pixelShiftHoleFill->get_inconsistent();
pedited->raw.bayersensor.pixelShiftMedian = !pixelShiftMedian->get_inconsistent();
pedited->raw.bayersensor.pixelShiftGreen = !pixelShiftGreen->get_inconsistent();
diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc
index bd673e5c3..1fe86c2ca 100644
--- a/rtgui/dirpyrdenoise.cc
+++ b/rtgui/dirpyrdenoise.cc
@@ -26,7 +26,7 @@ using namespace rtengine;
using namespace rtengine::procparams;
extern Options options;
-DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP_DIRPYRDENOISE_LABEL"), true, true), lastenhance(false)
+DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP_DIRPYRDENOISE_LABEL"), true, true), lastenhance(false), lastmedian(false), lastautochroma(false)
{
std::vector milestones;
CurveListener::setMulti(true);
diff --git a/rtgui/epd.cc b/rtgui/epd.cc
index 15f15f607..d7848aee0 100644
--- a/rtgui/epd.cc
+++ b/rtgui/epd.cc
@@ -30,8 +30,8 @@ EdgePreservingDecompositionUI::EdgePreservingDecompositionUI () : FoldableToolPa
strength = Gtk::manage(new Adjuster (M("TP_EPD_STRENGTH"), -1.0, 2.0, 0.01, 0.5));
gamma = Gtk::manage(new Adjuster (M("TP_EPD_GAMMA"), 0.8, 1.5, 0.01, 1.));
- edgeStopping = Gtk::manage(new Adjuster (M("TP_EPD_EDGESTOPPING"), 0.1, 4.0, 0.01, 1.4));
- scale = Gtk::manage(new Adjuster (M("TP_EPD_SCALE"), 0.1, 10.0, 0.01, 0.3));
+ edgeStopping = Gtk::manage(new Adjuster (M("TP_EPD_EDGESTOPPING"), 0.1, 4.0, 0.01, 0.5));
+ scale = Gtk::manage(new Adjuster (M("TP_EPD_SCALE"), 0.1, 10.0, 0.01, 0.1));
reweightingIterates = Gtk::manage(new Adjuster (M("TP_EPD_REWEIGHTINGITERATES"), 0, 9, 1, 0));
strength->setAdjusterListener(this);
diff --git a/rtgui/exportpanel.cc b/rtgui/exportpanel.cc
index 3f7be7ab4..72cf30fdd 100644
--- a/rtgui/exportpanel.cc
+++ b/rtgui/exportpanel.cc
@@ -38,7 +38,12 @@ ExportPanel::ExportPanel () : listener (nullptr)
labExportTitle->set_alignment(Gtk::ALIGN_START);
pack_start(*labExportTitle, Gtk::PACK_SHRINK, 4);
+ Gtk::RadioButton::Group pipeline_group;
+ use_fast_pipeline = Gtk::manage ( new Gtk::RadioButton (pipeline_group, M("EXPORT_USE_FAST_PIPELINE")));
+ use_normal_pipeline = Gtk::manage ( new Gtk::RadioButton (pipeline_group, M("EXPORT_USE_NORMAL_PIPELINE")));
+ bypass_box = Gtk::manage(new Gtk::VBox());
bypass_ALL = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_ALL")));
+ use_fast_pipeline->set_tooltip_text(M("EXPORT_USE_FAST_PIPELINE_TIP"));
bypass_sharpening = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_SHARPENING")));
bypass_sharpenEdge = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_SHARPENEDGE")));
bypass_sharpenMicro = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_SHARPENMICRO")));
@@ -96,18 +101,28 @@ ExportPanel::ExportPanel () : listener (nullptr)
// ----------------------------------------------------------------
// start global packing
- pack_start(*bypass_ALL , Gtk::PACK_SHRINK, 4);
- pack_start(*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 4);
- pack_start(*bypass_sharpening , Gtk::PACK_SHRINK, 4);
- pack_start(*bypass_sharpenEdge , Gtk::PACK_SHRINK, 4);
- pack_start(*bypass_sharpenMicro , Gtk::PACK_SHRINK, 4);
+ Gtk::HBox* lblbox = Gtk::manage (new Gtk::HBox ());
+ lblbox->pack_start (*Gtk::manage (new Gtk::Label (M("EXPORT_PIPELINE"))), Gtk::PACK_SHRINK, 4);
+ pack_start (*lblbox, Gtk::PACK_SHRINK, 4);
+ pack_start(*use_fast_pipeline , Gtk::PACK_SHRINK, 4);
+ pack_start(*use_normal_pipeline , Gtk::PACK_SHRINK, 4);
+
+ bypass_box->pack_start(*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 4);
+ lblbox = Gtk::manage (new Gtk::HBox ());
+ lblbox->pack_start (*Gtk::manage (new Gtk::Label (M("EXPORT_BYPASS"))), Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start (*lblbox, Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_ALL , Gtk::PACK_SHRINK, 4);
+ // bypass_box->pack_start(*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_sharpening , Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_sharpenEdge , Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_sharpenMicro , Gtk::PACK_SHRINK, 4);
//pack_start(*bypass_lumaDenoise , Gtk::PACK_SHRINK, 4);
//pack_start(*bypass_colorDenoise , Gtk::PACK_SHRINK, 4);
- pack_start(*bypass_defringe , Gtk::PACK_SHRINK, 4);
- pack_start(*bypass_dirpyrDenoise, Gtk::PACK_SHRINK, 4);
- pack_start(*bypass_sh_hq , Gtk::PACK_SHRINK, 4);
- pack_start(*bypass_dirpyrequalizer , Gtk::PACK_SHRINK, 4);
- pack_start(*bypass_wavelet , Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_defringe , Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_dirpyrDenoise, Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_sh_hq , Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_dirpyrequalizer , Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_wavelet , Gtk::PACK_SHRINK, 4);
bayerFrameVBox->pack_start(*hb_raw_bayer_method, Gtk::PACK_SHRINK, 4);
//bayerFrameVBox->pack_start(*bypass_raw_all_enhance , Gtk::PACK_SHRINK, 4);
@@ -121,12 +136,14 @@ ExportPanel::ExportPanel () : listener (nullptr)
xtransFrameVBox->pack_start(*hb_raw_xtrans_method, Gtk::PACK_SHRINK, 4);
xtransFrame->add(*xtransFrameVBox);
- pack_start(*bypass_raw_ccSteps , Gtk::PACK_SHRINK, 4);
- pack_start(*bypass_raw_ca , Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_raw_ccSteps , Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_raw_ca , Gtk::PACK_SHRINK, 4);
- pack_start(*bypass_raw_df , Gtk::PACK_SHRINK, 4);
- pack_start(*bypass_raw_ff , Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_raw_df , Gtk::PACK_SHRINK, 4);
+ bypass_box->pack_start(*bypass_raw_ff , Gtk::PACK_SHRINK, 4);
+ pack_start(*bypass_box, Gtk::PACK_SHRINK);
+
pack_start (*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 2);
// Resize options
@@ -176,6 +193,7 @@ ExportPanel::ExportPanel () : listener (nullptr)
pack_start(*vboxpe, Gtk::PACK_SHRINK, 0);
+ use_fast_pipeline->signal_toggled().connect(sigc::mem_fun(*this, &ExportPanel::use_fast_pipeline_toggled));
btnFastExport->signal_clicked().connect( sigc::mem_fun(*this, &ExportPanel::FastExportPressed) );
//btnExportLoadSettings->signal_clicked().connect( sigc::mem_fun(*this, &ExportPanel::LoadSettings) );
//btnExportSaveSettings->signal_clicked().connect( sigc::mem_fun(*this, &ExportPanel::SaveSettings) );
@@ -224,40 +242,48 @@ void ExportPanel::FastExportPressed ()
void ExportPanel::SaveSettingsAsDefault()
{
+ bool changed = false;
+#define FE_OPT_STORE_(n, v) \
+ do { \
+ if (n != v) { \
+ n = v; \
+ changed = true; \
+ } \
+ } while (false)
// Save fast export settings to options
- options.fastexport_bypass_sharpening = bypass_sharpening->get_active ();
- options.fastexport_bypass_sharpenEdge = bypass_sharpenEdge->get_active ();
- options.fastexport_bypass_sharpenMicro = bypass_sharpenMicro->get_active ();
+ FE_OPT_STORE_(options.fastexport_bypass_sharpening, bypass_sharpening->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_sharpenEdge, bypass_sharpenEdge->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_sharpenMicro, bypass_sharpenMicro->get_active ());
//options.fastexport_bypass_lumaDenoise = bypass_lumaDenoise->get_active ();
//options.fastexport_bypass_colorDenoise = bypass_colorDenoise->get_active ();
- options.fastexport_bypass_defringe = bypass_defringe->get_active ();
- options.fastexport_bypass_dirpyrDenoise = bypass_dirpyrDenoise->get_active ();
- options.fastexport_bypass_sh_hq = bypass_sh_hq->get_active ();
- options.fastexport_bypass_dirpyrequalizer = bypass_dirpyrequalizer->get_active ();
- options.fastexport_bypass_wavelet = bypass_wavelet->get_active ();
+ FE_OPT_STORE_(options.fastexport_bypass_defringe, bypass_defringe->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_dirpyrDenoise, bypass_dirpyrDenoise->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_sh_hq, bypass_sh_hq->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_dirpyrequalizer, bypass_dirpyrequalizer->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_wavelet, bypass_wavelet->get_active ());
//options.fastexport_bypass_raw_bayer_all_enhance = bypass_raw_all_enhance->get_active ();
- options.fastexport_bypass_raw_bayer_dcb_iterations = bypass_raw_bayer_dcb_iterations->get_active ();
- options.fastexport_bypass_raw_bayer_dcb_enhance = bypass_raw_bayer_dcb_enhance->get_active ();
- options.fastexport_bypass_raw_bayer_lmmse_iterations = bypass_raw_bayer_lmmse_iterations->get_active();
- options.fastexport_bypass_raw_bayer_linenoise = bypass_raw_bayer_linenoise->get_active ();
- options.fastexport_bypass_raw_bayer_greenthresh = bypass_raw_bayer_greenthresh->get_active ();
- options.fastexport_bypass_raw_ccSteps = bypass_raw_ccSteps->get_active ();
- options.fastexport_bypass_raw_ca = bypass_raw_ca->get_active ();
- options.fastexport_bypass_raw_df = bypass_raw_df->get_active ();
- options.fastexport_bypass_raw_ff = bypass_raw_ff->get_active ();
+ FE_OPT_STORE_(options.fastexport_bypass_raw_bayer_dcb_iterations, bypass_raw_bayer_dcb_iterations->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_raw_bayer_dcb_enhance, bypass_raw_bayer_dcb_enhance->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_raw_bayer_lmmse_iterations, bypass_raw_bayer_lmmse_iterations->get_active());
+ FE_OPT_STORE_(options.fastexport_bypass_raw_bayer_linenoise, bypass_raw_bayer_linenoise->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_raw_bayer_greenthresh, bypass_raw_bayer_greenthresh->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_raw_ccSteps, bypass_raw_ccSteps->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_raw_ca, bypass_raw_ca->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_raw_df, bypass_raw_df->get_active ());
+ FE_OPT_STORE_(options.fastexport_bypass_raw_ff, bypass_raw_ff->get_active ());
//saving Bayer demosaic_method
int currentRow = raw_bayer_method->get_active_row_number();
if( currentRow >= 0 && currentRow < procparams::RAWParams::BayerSensor::numMethods) {
- options.fastexport_raw_bayer_method = procparams::RAWParams::BayerSensor::methodstring[currentRow];
+ FE_OPT_STORE_(options.fastexport_raw_bayer_method, procparams::RAWParams::BayerSensor::methodstring[currentRow]);
}
//saving X-Trans demosaic_method
currentRow = raw_xtrans_method->get_active_row_number();
if( currentRow >= 0 && currentRow < procparams::RAWParams::XTransSensor::numMethods) {
- options.fastexport_raw_xtrans_method = procparams::RAWParams::XTransSensor::methodstring[currentRow];
+ FE_OPT_STORE_(options.fastexport_raw_xtrans_method, procparams::RAWParams::XTransSensor::methodstring[currentRow]);
}
// options.fastexport_icm_input = icm_input ;
@@ -269,9 +295,16 @@ void ExportPanel::SaveSettingsAsDefault()
// options.fastexport_resize_appliesTo = resize_appliesTo;
// options.fastexport_resize_dataspec = resize_dataspec ;
- options.fastexport_resize_method = "Lanczos";
- options.fastexport_resize_width = MaxWidth->get_value_as_int ();
- options.fastexport_resize_height = MaxHeight->get_value_as_int ();
+ FE_OPT_STORE_(options.fastexport_resize_method, "Lanczos");
+ FE_OPT_STORE_(options.fastexport_resize_width, MaxWidth->get_value_as_int ());
+ FE_OPT_STORE_(options.fastexport_resize_height, MaxHeight->get_value_as_int ());
+
+ FE_OPT_STORE_(options.fastexport_use_fast_pipeline, use_fast_pipeline->get_active());
+#undef FE_OPT_STORE_
+
+ if (changed) {
+ Options::save();
+ }
}
void ExportPanel::LoadDefaultSettings()
@@ -327,6 +360,13 @@ void ExportPanel::LoadDefaultSettings()
MaxWidth->set_value(options.fastexport_resize_width);
MaxHeight->set_value(options.fastexport_resize_height);
+
+ if (options.fastexport_use_fast_pipeline) {
+ use_fast_pipeline->set_active(true);
+ bypass_box->set_sensitive(false);
+ } else {
+ use_normal_pipeline->set_active(true);
+ }
}
void ExportPanel::LoadSettings()
@@ -408,6 +448,11 @@ void ExportPanel::bypassALL_Toggled()
bypass_raw_ffConn.block (false);
}
+void ExportPanel::use_fast_pipeline_toggled()
+{
+ bypass_box->set_sensitive(!use_fast_pipeline->get_active());
+}
+
/*
fastexport_bypass_sharpening
fastexport_bypass_sharpenEdge
diff --git a/rtgui/exportpanel.h b/rtgui/exportpanel.h
index 840a4638d..db4431ca5 100644
--- a/rtgui/exportpanel.h
+++ b/rtgui/exportpanel.h
@@ -36,7 +36,10 @@ class ExportPanel : public Gtk::VBox
protected:
+ Gtk::VBox *bypass_box;
//Gtk::CheckButton* enabled;
+ Gtk::RadioButton* use_fast_pipeline;
+ Gtk::RadioButton* use_normal_pipeline;
Gtk::CheckButton* bypass_ALL;
Gtk::CheckButton* bypass_sharpenEdge;
Gtk::CheckButton* bypass_sharpenMicro;
@@ -105,6 +108,7 @@ protected:
ExportPanelListener* listener;
void bypassALL_Toggled();
+ void use_fast_pipeline_toggled();
void SaveSettingsAsDefault();
void LoadDefaultSettings();
void LoadSettings();
diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc
index 5081962a1..ed4c1e628 100644
--- a/rtgui/filebrowser.cc
+++ b/rtgui/filebrowser.cc
@@ -340,7 +340,7 @@ FileBrowser::FileBrowser ()
p++;
submenuProfileOperations->attach (*Gtk::manage(applypartprof = new Gtk::MenuItem (M("FILEBROWSER_APPLYPROFILE_PARTIAL"))), 0, 1, p, p + 1);
p++;
- submenuProfileOperations->attach (*Gtk::manage(execcustprof = new Gtk::MenuItem (M("FILEBROWSER_EXEC_CPB"))), 0, 1, p, p + 1);
+ submenuProfileOperations->attach (*Gtk::manage(resetdefaultprof = new Gtk::MenuItem (M("FILEBROWSER_RESETDEFAULTPROFILE"))), 0, 1, p, p + 1);
p++;
submenuProfileOperations->attach (*Gtk::manage(clearprof = new Gtk::MenuItem (M("FILEBROWSER_CLEARPROFILE"))), 0, 1, p, p + 1);
p++;
@@ -358,7 +358,7 @@ FileBrowser::FileBrowser ()
p++;
pmenu->attach (*Gtk::manage(applypartprof = new Gtk::MenuItem (M("FILEBROWSER_APPLYPROFILE_PARTIAL"))), 0, 1, p, p + 1);
p++;
- pmenu->attach (*Gtk::manage(execcustprof = new Gtk::MenuItem (M("FILEBROWSER_EXEC_CPB"))), 0, 1, p, p + 1);
+ pmenu->attach (*Gtk::manage(resetdefaultprof = new Gtk::MenuItem (M("FILEBROWSER_RESETDEFAULTPROFILE"))), 0, 1, p, p + 1);
p++;
pmenu->attach (*Gtk::manage(clearprof = new Gtk::MenuItem (M("FILEBROWSER_CLEARPROFILE"))), 0, 1, p, p + 1);
p++;
@@ -389,6 +389,7 @@ FileBrowser::FileBrowser ()
untrash->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_Delete, Gdk::SHIFT_MASK, Gtk::ACCEL_VISIBLE);
open->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_Return, (Gdk::ModifierType)0, Gtk::ACCEL_VISIBLE);
develop->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_B, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
+ developfast->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_B, Gdk::CONTROL_MASK | Gdk::SHIFT_MASK, Gtk::ACCEL_VISIBLE);
copyprof->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_C, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
pasteprof->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_V, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
partpasteprof->add_accelerator ("activate", pmenu->get_accel_group(), GDK_KEY_V, Gdk::CONTROL_MASK | Gdk::SHIFT_MASK, Gtk::ACCEL_VISIBLE);
@@ -427,7 +428,7 @@ FileBrowser::FileBrowser ()
partpasteprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), partpasteprof));
applyprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), applyprof));
applypartprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), applypartprof));
- execcustprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), execcustprof));
+ resetdefaultprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), resetdefaultprof));
clearprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), clearprof));
cachemenu->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), cachemenu));
@@ -767,6 +768,12 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m)
else if (m == develop) {
tbl->developRequested (mselected, false);
} else if (m == developfast) {
+ if (exportPanel) {
+ // force saving export panel settings
+ exportPanel->setExportPanelListener(nullptr);
+ exportPanel->FastExportPressed();
+ exportPanel->setExportPanelListener(this);
+ }
tbl->developRequested (mselected, true);
}
@@ -960,7 +967,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m)
}
queue_draw ();
- } else if (m == execcustprof) {
+ } else if (m == resetdefaultprof) {
if (!mselected.empty() && bppcl) {
bppcl->beginBatchPParamsChange(mselected.size());
}
@@ -1139,9 +1146,12 @@ bool FileBrowser::keyPressed (GdkEventKey* event)
} else if (event->keyval == GDK_KEY_Delete && shift) {
menuItemActivated (untrash);
return true;
- } else if ((event->keyval == GDK_KEY_B || event->keyval == GDK_KEY_b) && ctrl) {
+ } else if ((event->keyval == GDK_KEY_B || event->keyval == GDK_KEY_b) && ctrl && !shift) {
menuItemActivated (develop);
return true;
+ } else if ((event->keyval == GDK_KEY_B || event->keyval == GDK_KEY_b) && ctrl && shift) {
+ menuItemActivated (developfast);
+ return true;
} else if ((event->keyval == GDK_KEY_A || event->keyval == GDK_KEY_a) && ctrl) {
menuItemActivated (selall);
return true;
diff --git a/rtgui/filebrowser.h b/rtgui/filebrowser.h
index ac6055696..faede2d8c 100644
--- a/rtgui/filebrowser.h
+++ b/rtgui/filebrowser.h
@@ -111,7 +111,7 @@ protected:
Gtk::MenuItem* partpasteprof;
Gtk::MenuItem* applyprof;
Gtk::MenuItem* applypartprof;
- Gtk::MenuItem* execcustprof;
+ Gtk::MenuItem* resetdefaultprof;
Gtk::MenuItem* clearprof;
Gtk::MenuItem* cachemenu;
Gtk::MenuItem* clearFromCache;
diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc
index 47466216e..395552cf2 100644
--- a/rtgui/filecatalog.cc
+++ b/rtgui/filecatalog.cc
@@ -1097,99 +1097,108 @@ void FileCatalog::developRequested (std::vector tbe, bool fas
// and also those which effect is not pronounced after reducing the image size
// TODO!!! could expose selections below via preferences
if (fastmode) {
- if (options.fastexport_bypass_sharpening ) {
- params.sharpening.enabled = false;
+ if (!options.fastexport_use_fast_pipeline) {
+ if (options.fastexport_bypass_sharpening) {
+ params.sharpening.enabled = false;
+ }
+
+ if (options.fastexport_bypass_sharpenEdge) {
+ params.sharpenEdge.enabled = false;
+ }
+
+ if (options.fastexport_bypass_sharpenMicro) {
+ params.sharpenMicro.enabled = false;
+ }
+
+ //if (options.fastexport_bypass_lumaDenoise) params.lumaDenoise.enabled = false;
+ //if (options.fastexport_bypass_colorDenoise) params.colorDenoise.enabled = false;
+ if (options.fastexport_bypass_defringe) {
+ params.defringe.enabled = false;
+ }
+
+ if (options.fastexport_bypass_dirpyrDenoise) {
+ params.dirpyrDenoise.enabled = false;
+ }
+
+ if (options.fastexport_bypass_sh_hq) {
+ params.sh.hq = false;
+ }
+
+ if (options.fastexport_bypass_dirpyrequalizer) {
+ params.dirpyrequalizer.enabled = false;
+ }
+
+ if (options.fastexport_bypass_wavelet) {
+ params.wavelet.enabled = false;
+ }
+
+ //if (options.fastexport_bypass_raw_bayer_all_enhance) params.raw.bayersensor.all_enhance = false;
+ if (options.fastexport_bypass_raw_bayer_dcb_iterations) {
+ params.raw.bayersensor.dcb_iterations = 0;
+ }
+
+ if (options.fastexport_bypass_raw_bayer_dcb_enhance) {
+ params.raw.bayersensor.dcb_enhance = false;
+ }
+
+ if (options.fastexport_bypass_raw_bayer_lmmse_iterations) {
+ params.raw.bayersensor.lmmse_iterations = 0;
+ }
+
+ if (options.fastexport_bypass_raw_bayer_linenoise) {
+ params.raw.bayersensor.linenoise = 0;
+ }
+
+ if (options.fastexport_bypass_raw_bayer_greenthresh) {
+ params.raw.bayersensor.greenthresh = 0;
+ }
+
+ if (options.fastexport_bypass_raw_ccSteps) {
+ params.raw.bayersensor.ccSteps = params.raw.xtranssensor.ccSteps = 0;
+ }
+
+ if (options.fastexport_bypass_raw_ca) {
+ params.raw.ca_autocorrect = false;
+ params.raw.cared = 0;
+ params.raw.cablue = 0;
+ }
+
+ if (options.fastexport_bypass_raw_df) {
+ params.raw.df_autoselect = false;
+ params.raw.dark_frame = "";
+ }
+
+ if (options.fastexport_bypass_raw_ff) {
+ params.raw.ff_AutoSelect = false;
+ params.raw.ff_file = "";
+ }
+
+ params.raw.bayersensor.method = options.fastexport_raw_bayer_method;
+ params.raw.xtranssensor.method = options.fastexport_raw_xtrans_method;
+ params.icm.input = options.fastexport_icm_input;
+ params.icm.working = options.fastexport_icm_working;
+ params.icm.output = options.fastexport_icm_output;
+ params.icm.outputIntent = options.fastexport_icm_outputIntent;
+ params.icm.outputBPC = options.fastexport_icm_outputBPC;
+ params.icm.gamma = options.fastexport_icm_gamma;
}
- if (options.fastexport_bypass_sharpenEdge ) {
- params.sharpenEdge.enabled = false;
+ if (params.resize.enabled) {
+ params.resize.width = rtengine::min(params.resize.width, options.fastexport_resize_width);
+ params.resize.height = rtengine::min(params.resize.height, options.fastexport_resize_height);
+ } else {
+ params.resize.width = options.fastexport_resize_width;
+ params.resize.height = options.fastexport_resize_height;
}
-
- if (options.fastexport_bypass_sharpenMicro ) {
- params.sharpenMicro.enabled = false;
- }
-
- //if (options.fastexport_bypass_lumaDenoise ) params.lumaDenoise.enabled = false;
- //if (options.fastexport_bypass_colorDenoise ) params.colorDenoise.enabled = false;
- if (options.fastexport_bypass_defringe ) {
- params.defringe.enabled = false;
- }
-
- if (options.fastexport_bypass_dirpyrDenoise ) {
- params.dirpyrDenoise.enabled = false;
- }
-
- if (options.fastexport_bypass_sh_hq ) {
- params.sh.hq = false;
- }
-
- if (options.fastexport_bypass_dirpyrequalizer ) {
- params.dirpyrequalizer.enabled = false;
- }
-
- if (options.fastexport_bypass_wavelet ) {
- params.wavelet.enabled = false;
- }
-
- //if (options.fastexport_bypass_raw_bayer_all_enhance ) params.raw.bayersensor.all_enhance = false;
- if (options.fastexport_bypass_raw_bayer_dcb_iterations ) {
- params.raw.bayersensor.dcb_iterations = 0;
- }
-
- if (options.fastexport_bypass_raw_bayer_dcb_enhance ) {
- params.raw.bayersensor.dcb_enhance = false;
- }
-
- if (options.fastexport_bypass_raw_bayer_lmmse_iterations) {
- params.raw.bayersensor.lmmse_iterations = 0;
- }
-
- if (options.fastexport_bypass_raw_bayer_linenoise ) {
- params.raw.bayersensor.linenoise = 0;
- }
-
- if (options.fastexport_bypass_raw_bayer_greenthresh ) {
- params.raw.bayersensor.greenthresh = 0;
- }
-
- if (options.fastexport_bypass_raw_ccSteps ) {
- params.raw.bayersensor.ccSteps = params.raw.xtranssensor.ccSteps = 0;
- }
-
- if (options.fastexport_bypass_raw_ca ) {
- params.raw.ca_autocorrect = false;
- params.raw.cared = 0;
- params.raw.cablue = 0;
- }
-
- if (options.fastexport_bypass_raw_df ) {
- params.raw.df_autoselect = false;
- params.raw.dark_frame = "";
- }
-
- if (options.fastexport_bypass_raw_ff ) {
- params.raw.ff_AutoSelect = false;
- params.raw.ff_file = "";
- }
-
- params.raw.bayersensor.method = options.fastexport_raw_bayer_method ;
- params.raw.xtranssensor.method = options.fastexport_raw_xtrans_method;
- params.icm.input = options.fastexport_icm_input ;
- params.icm.working = options.fastexport_icm_working ;
- params.icm.output = options.fastexport_icm_output ;
- params.icm.outputIntent = options.fastexport_icm_outputIntent ;
- params.icm.outputBPC = options.fastexport_icm_outputBPC ;
- params.icm.gamma = options.fastexport_icm_gamma ;
- params.resize.enabled = options.fastexport_resize_enabled ;
- params.resize.scale = options.fastexport_resize_scale ;
- params.resize.appliesTo = options.fastexport_resize_appliesTo ;
- params.resize.method = options.fastexport_resize_method ;
- params.resize.dataspec = options.fastexport_resize_dataspec ;
- params.resize.width = options.fastexport_resize_width ;
- params.resize.height = options.fastexport_resize_height ;
+
+ params.resize.enabled = options.fastexport_resize_enabled;
+ params.resize.scale = options.fastexport_resize_scale;
+ params.resize.appliesTo = options.fastexport_resize_appliesTo;
+ params.resize.method = options.fastexport_resize_method;
+ params.resize.dataspec = options.fastexport_resize_dataspec;
}
- rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (fbe->filename, th->getType() == FT_Raw, params);
+ rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (fbe->filename, th->getType() == FT_Raw, params, fastmode && options.fastexport_use_fast_pipeline);
int pw;
int ph = BatchQueue::calcMaxThumbnailHeight();
diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc
index 71c54e2b5..2f4526cad 100644
--- a/rtgui/lensprofile.cc
+++ b/rtgui/lensprofile.cc
@@ -26,7 +26,7 @@
using namespace rtengine;
using namespace rtengine::procparams;
-LensProfilePanel::LensProfilePanel () : FoldableToolPanel(this, "lensprof", M("TP_LENSPROFILE_LABEL"))
+LensProfilePanel::LensProfilePanel () : FoldableToolPanel(this, "lensprof", M("TP_LENSPROFILE_LABEL")), isRaw(true)
{
hbLCPFile = Gtk::manage(new Gtk::HBox());
diff --git a/rtgui/main-cli.cc b/rtgui/main-cli.cc
index d9a481e7e..3a601e18e 100644
--- a/rtgui/main-cli.cc
+++ b/rtgui/main-cli.cc
@@ -81,6 +81,8 @@ Glib::ustring fname_to_utf8 (const char* fname)
#endif
}
+bool fast_export = false;
+
}
/* Process line command options
@@ -407,6 +409,10 @@ int processLineParams( int argc, char **argv )
compression = -1;
break;
+ case 'f':
+ fast_export = true;
+ break;
+
case 'c': // MUST be last option
while (iArg + 1 < argc) {
iArg++;
@@ -491,7 +497,7 @@ int processLineParams( int argc, char **argv )
std::cout << std::endl;
#endif
std::cout << "Options:" << std::endl;
- std::cout << " " << Glib::path_get_basename(argv[0]) << " [-o