diff --git a/rtdata/languages/default b/rtdata/languages/default
index 1ca699bf6..7c989d960 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -443,8 +443,10 @@ HISTORY_MSG_205;CAM02 hot/bad pixels
HISTORY_MSG_206;CAT02 - Adapt scene auto
HISTORY_MSG_207;Defringing Hue curve
HISTORY_MSG_208;Blue/Red Equalizer
-HISTORY_MSG_210;Gradient Filter
-HISTORY_MSG_211;Gradient Filter
+HISTORY_MSG_210;Graduated Filter
+HISTORY_MSG_211;Graduated Filter
+HISTORY_MSG_212;Vignette Filter
+HISTORY_MSG_213;Vignette Filter
HISTORY_NEWSNAPSHOTAS;As...
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
@@ -659,6 +661,7 @@ PARTIALPASTE_LENSPROFILE;Lens correction profile
PARTIALPASTE_LUMADENOISE;Luminance noise reduction
PARTIALPASTE_LUMINANCEGROUP;Luminance related settings
PARTIALPASTE_METAICMGROUP;Metadata/Color Management Settings
+PARTIALPASTE_PCVIGNETTE;Vignette Filter
PARTIALPASTE_PERSPECTIVE;Perspective
PARTIALPASTE_PREPROCESS_GREENEQUIL;Green equilibration
PARTIALPASTE_PREPROCESS_HOTDEADPIXFILT;Apply hot/dead pixel filter
@@ -1199,6 +1202,13 @@ TP_LUMADENOISE_LABEL;Luminance Noise Reduction
TP_LUMADENOISE_RADIUS;Radius
TP_NEUTRAL;Neutral
TP_NEUTRAL_TIP;Reset exposure sliders to neutral values.\nApplies to the same controls that Auto Levels applies to, regardless of whether you used Auto Levels or not
+TP_PCVIGNETTE_FEATHER;Feather
+TP_PCVIGNETTE_FEATHER_TOOLTIP;Feathering: 0=corners only, 50=halfway to center, 100=to center
+TP_PCVIGNETTE_LABEL;Vignette Filter
+TP_PCVIGNETTE_ROUNDNESS;Roundness
+TP_PCVIGNETTE_ROUNDNESS_TOOLTIP;Roundness: 0=rectangle, 50=fitted ellipse, 100=circle
+TP_PCVIGNETTE_STRENGTH;Strength
+TP_PCVIGNETTE_STRENGTH_TOOLTIP;Filter strength in stops (reached in corners)
TP_PERSPECTIVE_HORIZONTAL;Horizontal
TP_PERSPECTIVE_LABEL;Perspective
TP_PERSPECTIVE_VERTICAL;Vertical
diff --git a/rtengine/colorclip.h b/rtengine/colorclip.h
index b81c35bc3..0526af83d 100644
--- a/rtengine/colorclip.h
+++ b/rtengine/colorclip.h
@@ -90,6 +90,30 @@ inline double tightestroot (double L, double a, double b, double r1, double r2,
/*******************************************************************************
* FindCubicRoots
+ * --------------
+ *
+ * Copyright (C) 1997-2001 Ken Turkowski.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ------------------------------------------------------------------------
*
* Solve:
* coeff[3] * x^3 + coeff[2] * x^2 + coeff[1] * x + coeff[0] = 0
@@ -97,6 +121,7 @@ inline double tightestroot (double L, double a, double b, double r1, double r2,
* returns:
* 3 - 3 real roots
* 1 - 1 real root (2 complex conjugate)
+ *
*******************************************************************************/
/*long
@@ -111,6 +136,7 @@ FindCubicRoots(const FLOAT coeff[4], FLOAT x[3])
double_t Qcubed = Q * Q * Q;
double_t d = Qcubed - R * R;
+ // Three real roots
if (d >= 0) {
double_t theta = acos(R / sqrt(Qcubed));
double_t sqrtQ = sqrt(Q);
@@ -120,6 +146,7 @@ FindCubicRoots(const FLOAT coeff[4], FLOAT x[3])
return (3);
}
+ // One real root
else {
double_t e = pow(sqrt(-d) + fabs(R), 1. / 3.);
if (R > 0)
diff --git a/rtengine/cubic.cc b/rtengine/cubic.cc
deleted file mode 100644
index 3354f3c9d..000000000
--- a/rtengine/cubic.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright (C) 1997-2001 Ken Turkowski.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include
-
-
-#define FLOAT float
-#define double_t double
-
-/*******************************************************************************
- * FindCubicRoots
- *
- * Solve:
- * coeff[3] * x^3 + coeff[2] * x^2 + coeff[1] * x + coeff[0] = 0
- *
- * returns:
- * 3 - 3 real roots
- * 1 - 1 real root (2 complex conjugate)
- *******************************************************************************/
-
-long
-FindCubicRoots(const FLOAT coeff[4], FLOAT x[3])
-{
- FLOAT a1 = coeff[2] / coeff[3];
- FLOAT a2 = coeff[1] / coeff[3];
- FLOAT a3 = coeff[0] / coeff[3];
-
- double_t Q = (a1 * a1 - 3 * a2) / 9;
- double_t R = (2 * a1 * a1 * a1 - 9 * a1 * a2 + 27 * a3) / 54;
- double_t Qcubed = Q * Q * Q;
- double_t d = Qcubed - R * R;
-
- /* Three real roots */
- if (d >= 0) {
- double_t theta = acos(R / sqrt(Qcubed));
- double_t sqrtQ = sqrt(Q);
- x[0] = -2 * sqrtQ * cos( theta / 3) - a1 / 3;
- x[1] = -2 * sqrtQ * cos((theta + 2 * 3.14159265) / 3) - a1 / 3;
- x[2] = -2 * sqrtQ * cos((theta + 4 * 3.14159265) / 3) - a1 / 3;
- return (3);
- }
-
- /* One real root */
- else {
- double_t e = pow(sqrt(-d) + fabs(R), 1. / 3.);
- if (R > 0)
- e = -e;
- x[0] = (e + Q / e) - a1 / 3.;
- return (1);
- }
-}
diff --git a/rtengine/cubint.cc b/rtengine/cubint.cc
deleted file mode 100644
index a658999dd..000000000
--- a/rtengine/cubint.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * This file is part of RawTherapee.
- *
- * Copyright (c) 2004-2010 Gabor Horvath
- *
- * RawTherapee is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * RawTherapee is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with RawTherapee. If not, see .
- */
-
-inline void interpolateTransformCubic (Imagefloat* src, int xs, int ys, double Dx, double Dy, float *r, float *g, float *b, double mul) {
- const double A=-0.85;
-
- double w[4];
-
- {
- double t1, t2;
- t1 = -A*(Dx-1.0)*Dx;
- t2 = (3.0-2.0*Dx)*Dx*Dx;
- w[3] = t1*Dx;
- w[2] = t1*(Dx-1.0) + t2;
- w[1] = -t1*Dx + 1.0 - t2;
- w[0] = -t1*(Dx-1.0);
- }
-
- double rd, gd, bd;
- double yr[4], yg[4], yb[4];
-
- for (int k=ys, kx=0; kr(k,i) * w[ix];
- gd += src->g(k,i) * w[ix];
- bd += src->b(k,i) * w[ix];
- }
- yr[kx] = rd; yg[kx] = gd; yb[kx] = bd;
- }
-
-
- {
- double t1, t2;
-
- t1 = -A*(Dy-1.0)*Dy;
- t2 = (3.0-2.0*Dy)*Dy*Dy;
- w[3] = t1*Dy;
- w[2] = t1*(Dy-1.0) + t2;
- w[1] = -t1*Dy + 1.0 - t2;
- w[0] = -t1*(Dy-1.0);
- }
-
- rd = gd = bd = 0.0;
- for (int i=0; i<4; i++) {
- rd += yr[i] * w[i];
- gd += yg[i] * w[i];
- bd += yb[i] * w[i];
- }
-
- *r = rd * mul;
- *g = gd * mul;
- *b = bd * mul;
-
-// if (xs==100 && ys==100)
-// printf ("r=%g, g=%g\n", *r, *g);
-}
diff --git a/rtengine/cubintch.cc b/rtengine/cubintch.cc
deleted file mode 100644
index 7bc55e089..000000000
--- a/rtengine/cubintch.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * This file is part of RawTherapee.
- *
- * Copyright (c) 2004-2010 Gabor Horvath
- *
- * RawTherapee is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * RawTherapee is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with RawTherapee. If not, see .
- */
-
-inline void interpolateTransformChannelsCubic (float** src, int xs, int ys, double Dx, double Dy, float *r, double mul) {
- const double A=-0.85;
-
- double w[4];
-
- {
- double t1, t2;
- t1 = -A*(Dx-1.0)*Dx;
- t2 = (3.0-2.0*Dx)*Dx*Dx;
- w[3] = t1*Dx;
- w[2] = t1*(Dx-1.0) + t2;
- w[1] = -t1*Dx + 1.0 - t2;
- w[0] = -t1*(Dx-1.0);
- }
-
- double rd;
- double yr[4];
-
- for (int k=ys, kx=0; kparams;
+ // No need to update todo here, since it has already been changed in ImprocCoordinator::updatePreviewImage,
+ // and Crop::update ask to do ALL anyway
+
// give possibility to the listener to modify crop window (as the full image dimensions are already known at this point)
int wx, wy, ww, wh, ws;
bool overrideWindow = false;
@@ -129,7 +132,7 @@ void Crop::update (int todo) {
transCrop = new Imagefloat (cropw, croph);
if ((todo & M_TRANSFORM) && needstransform)
- parent->ipf.transform (baseCrop, transCrop, cropx/skip, cropy/skip, trafx/skip, trafy/skip, SKIPS(parent->fw,skip), SKIPS(parent->fh,skip),
+ parent->ipf.transform (baseCrop, transCrop, cropx/skip, cropy/skip, trafx/skip, trafy/skip, SKIPS(parent->fw,skip), SKIPS(parent->fh,skip), parent->getFullWidth(), parent->getFullHeight(),
parent->imgsrc->getMetaData()->getFocalLen(), parent->imgsrc->getMetaData()->getFocalLen35mm(),
parent->imgsrc->getMetaData()->getFocusDist(), parent->imgsrc->getRotateDegree(), false);
if (transCrop)
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index f39dedad2..3dfe943d0 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -112,6 +112,9 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
int numofphases = 14;
int readyphase = 0;
+ if (todo==CROP && ipf.needsPCVignetting())
+ todo |= TRANSFORM; // Change about Crop does affect TRANSFORM
+
// Tells to the ImProcFunctions' tools what is the preview scale, which may lead to some simplifications
ipf.setScale (scale);
@@ -238,8 +241,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
readyphase++;
progress ("Rotate / Distortion...",100*readyphase/numofphases);
- bool needstransform = ipf.needsTransform();
// Remove transformation if unneeded
+ bool needstransform = ipf.needsTransform();
if (!needstransform && orig_prev!=oprevi) {
delete oprevi;
oprevi = orig_prev;
@@ -247,7 +250,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
if (needstransform && orig_prev==oprevi)
oprevi = new Imagefloat (pW, pH);
if ((todo & M_TRANSFORM) && needstransform)
- ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, imgsrc->getMetaData()->getFocalLen(),
+ ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, fw, fh, imgsrc->getMetaData()->getFocalLen(),
imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), false);
readyphase++;
@@ -274,7 +277,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
}
progress ("Exposure curve & CIELAB conversion...",100*readyphase/numofphases);
- if ((todo & M_RGBCURVE) || todo==CROP) {
+ if ((todo & M_RGBCURVE) || (todo & M_CROP)) {
if (hListener) oprevi->calcCroppedHistogram(params, scale, histCropped);
// complexCurve also calculated pre-curves histogram dependend on crop
@@ -291,7 +294,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, scale==1 ? 1 : 1);
// if it's just crop we just need the histogram, no image updates
- if ( todo!=CROP ) {
+ if ( todo!=MINUPDATE ) {
ipf.rgbProc (oprevi, oprevl, hltonecurve, shtonecurve, tonecurve, shmap, params.toneCurve.saturation,
rCurve, gCurve, bCurve, customToneCurve1, customToneCurve2, params.toneCurve.expcomp, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh);
}
@@ -316,7 +319,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
butili=false;
ccutili=false;
cclutili=false;
- if ((todo & M_LUMACURVE) || todo==CROP) {
+ if ((todo & M_LUMACURVE) || (todo & M_CROP)) {
CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, lhist16, lhist16Cropped,
lumacurve, histLCurve, scale==1 ? 1 : 16, utili);
}
@@ -329,7 +332,6 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
nprevl->CopyFrom(oprevl);
progress ("Applying Color Boost...",100*readyphase/numofphases);
- int poscc;
ipf.chromiLuminanceCurve (pW,nprevl, nprevl, chroma_acurve, chroma_bcurve, satcurve,lhskcurve, lumacurve, utili, autili, butili, ccutili,cclutili, histCCurve);
ipf.vibrance(nprevl);
@@ -465,7 +467,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
crops[i]->update (todo); // may call ourselves
progress ("Conversion to RGB...",100*readyphase/numofphases);
- if (todo!=CROP) {
+ if (todo!=CROP && todo!=MINUPDATE) {
MyMutex::MyLock prevImgLock(previmg->getMutex());
try
{
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index d9125549b..bc1ad32e2 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -51,9 +51,9 @@ class ImProcFunctions {
void calcVignettingParams(int oW, int oH, const VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul);
- void transformPreview (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, const LCPMapper *pLCPMap);
- void transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH);
- void transformHighQuality (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, const LCPMapper *pLCPMap, bool fullImage);
+ void transformPreview (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap);
+ void transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH);
+ void transformHighQuality (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap, bool fullImage);
void sharpenHaloCtrl (LabImage* lab, float** blurmap, float** base, int W, int H);
void sharpenHaloCtrlcam (CieImage* ncie, float** blurmap, float** base, int W, int H);
@@ -67,7 +67,106 @@ class ImProcFunctions {
bool needsGradient ();
bool needsVignetting ();
bool needsLCP ();
- // static cmsUInt8Number* Mempro = NULL;
+ // static cmsUInt8Number* Mempro = NULL;
+
+ inline void interpolateTransformCubic (Imagefloat* src, int xs, int ys, double Dx, double Dy, float *r, float *g, float *b, double mul) {
+ const double A=-0.85;
+
+ double w[4];
+
+ {
+ double t1, t2;
+ t1 = -A*(Dx-1.0)*Dx;
+ t2 = (3.0-2.0*Dx)*Dx*Dx;
+ w[3] = t1*Dx;
+ w[2] = t1*(Dx-1.0) + t2;
+ w[1] = -t1*Dx + 1.0 - t2;
+ w[0] = -t1*(Dx-1.0);
+ }
+
+ double rd, gd, bd;
+ double yr[4], yg[4], yb[4];
+
+ for (int k=ys, kx=0; kr(k,i) * w[ix];
+ gd += src->g(k,i) * w[ix];
+ bd += src->b(k,i) * w[ix];
+ }
+ yr[kx] = rd; yg[kx] = gd; yb[kx] = bd;
+ }
+
+
+ {
+ double t1, t2;
+
+ t1 = -A*(Dy-1.0)*Dy;
+ t2 = (3.0-2.0*Dy)*Dy*Dy;
+ w[3] = t1*Dy;
+ w[2] = t1*(Dy-1.0) + t2;
+ w[1] = -t1*Dy + 1.0 - t2;
+ w[0] = -t1*(Dy-1.0);
+ }
+
+ rd = gd = bd = 0.0;
+ for (int i=0; i<4; i++) {
+ rd += yr[i] * w[i];
+ gd += yg[i] * w[i];
+ bd += yb[i] * w[i];
+ }
+
+ *r = rd * mul;
+ *g = gd * mul;
+ *b = bd * mul;
+
+ // if (xs==100 && ys==100)
+ // printf ("r=%g, g=%g\n", *r, *g);
+ }
+
+ inline void interpolateTransformChannelsCubic (float** src, int xs, int ys, double Dx, double Dy, float *r, double mul) {
+ const double A=-0.85;
+
+ double w[4];
+
+ {
+ double t1, t2;
+ t1 = -A*(Dx-1.0)*Dx;
+ t2 = (3.0-2.0*Dx)*Dx*Dx;
+ w[3] = t1*Dx;
+ w[2] = t1*(Dx-1.0) + t2;
+ w[1] = -t1*Dx + 1.0 - t2;
+ w[0] = -t1*(Dx-1.0);
+ }
+
+ double rd;
+ double yr[4];
+
+ for (int k=ys, kx=0; kwidth, original->height, params->coarse, rawRotationDeg);
}
- if (!(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP()) && (needsVignetting() || needsGradient()))
- transformLuminanceOnly (original, transformed, cx, cy, oW, oH);
- else if (!needsCA() && scale!=1)
- transformPreview (original, transformed, cx, cy, sx, sy, oW, oH, pLCPMap);
- else
- transformHighQuality (original, transformed, cx, cy, sx, sy, oW, oH, pLCPMap, fullImage);
+ if (!(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP()) && (needsVignetting() || needsPCVignetting() || needsGradient()))
+ transformLuminanceOnly (original, transformed, cx, cy, oW, oH, fW, fH);
+ else if (!needsCA() && scale!=1)
+ transformPreview (original, transformed, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap);
+ else
+ transformHighQuality (original, transformed, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap, fullImage);
if (pLCPMap) delete pLCPMap;
}
@@ -246,7 +246,6 @@ struct grad_params {
float ta, yc, xc;
float ys, ys_inv;
float scale, botmul, topmul;
- float gamma;
float top_edge_0;
int h;
};
@@ -322,7 +321,6 @@ static void calcGradientParams(int oW, int oH, const GradientParams& gradient, s
gp.ys_inv = 0;
gp.ys = 0;
}
- gp.gamma = 1.5; // tested to be "visually pleasing"
}
static float calcGradientFactor(const struct grad_params& gp, int x, int y) {
@@ -338,10 +336,11 @@ static float calcGradientFactor(const struct grad_params& gp, int x, int y) {
if (gp.bright_top) {
val = 1.0 - val;
}
- val = 2 * val - 1.0; // adjust range to -1 to 1
- val = 0.5 * (3 * val - powf(val, 3)); // s-curve
- val = 0.5 * (1.0 + val); // adjust range back to 0 to 1
- val = powf(val, gp.gamma); // apply gamma
+ if (gp.scale < 1.0) {
+ val = pow(sin(val*M_PI/2), 3);
+ } else {
+ val = 1.0 - pow(cos(val*M_PI/2), 3);
+ }
return gp.scale + val * (1.0 - gp.scale);
}
} else {
@@ -354,33 +353,168 @@ static float calcGradientFactor(const struct grad_params& gp, int x, int y) {
return gp.botmul;
} else {
float val = ((float)(gy - top_edge) * gp.ys_inv);
+
if (gp.bright_top) {
val = 1.0 - val;
}
- val = 2 * val - 1.0;
- val = 0.5 * (3 * val - powf(val, 3));
- val = 0.5 * (1.0 + val);
- val = powf(val, gp.gamma);
+ if (gp.scale < 1.0) {
+ val = pow(sin(val*M_PI/2), 3);
+ } else {
+ val = 1.0 - pow(cos(val*M_PI/2), 3);
+ }
return gp.scale + val * (1.0 - gp.scale);
}
}
}
-// Transform vignetting only
-void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH) {
+struct pcv_params {
+ float oe_a, oe_b, oe1_a, oe1_b, oe2_a, oe2_b;
+ float ie_mul, ie1_mul, ie2_mul;
+ float sepmix, feather;
+ int w, h, x1, x2, y1, y2;
+ int sep;
+ bool is_super_ellipse_mode, is_portrait;
+ float scale;
+ float fadeout_mul;
+};
+static void calcPCVignetteParams(int fW, int fH, int oW, int oH, const PCVignetteParams& pcvignette, const CropParams &crop, struct pcv_params& pcv) {
+
+ // ellipse formula: (x/a)^2 + (y/b)^2 = 1
+ double roundness = pcvignette.roundness / 100.0;
+ pcv.feather = pcvignette.feather / 100.0;
+ if (crop.enabled) {
+ pcv.w = (crop.w * oW) / fW;
+ pcv.h = (crop.h * oH) / fH;
+ pcv.x1 = (crop.x * oW) / fW;
+ pcv.y1 = (crop.y * oH) / fH;
+ pcv.x2 = pcv.x1+pcv.w;
+ pcv.y2 = pcv.y1+pcv.h;
+ } else {
+ pcv.x1 = 0, pcv.y1 = 0;
+ pcv.x2 = oW, pcv.y2 = oH;
+ pcv.w = oW;
+ pcv.h = oH;
+ }
+ pcv.fadeout_mul = 1.0 / (0.05 * sqrtf(oW*oW+oH*oH));
+ float short_side = (pcv.w < pcv.h) ? pcv.w : pcv.h;
+ float long_side = (pcv.w > pcv.h) ? pcv.w : pcv.h;
+
+ pcv.sep = 2;
+ pcv.sepmix = 0;
+ pcv.oe_a = sqrt(2.0)*long_side*0.5;
+ pcv.oe_b = pcv.oe_a * short_side / long_side;
+ pcv.ie_mul = 1.0 / sqrt(2.0);
+ pcv.is_super_ellipse_mode = false;
+ pcv.is_portrait = (pcv.w < pcv.h);
+ if (roundness < 0.5) {
+ // make super-ellipse of higher and higher degree
+ pcv.is_super_ellipse_mode = true;
+ float sepf = 2 + 4*powf(1.0 - 2*roundness, 1.3); // gamma 1.3 used to balance the effect in the 0.0...0.5 roundness range
+ pcv.sep = ((int)sepf) & ~0x1;
+ pcv.sepmix = (sepf - pcv.sep) * 0.5; // 0.0 to 1.0
+ pcv.oe1_a = powf(2.0, 1.0/pcv.sep)*long_side*0.5;
+ pcv.oe1_b = pcv.oe1_a * short_side / long_side;
+ pcv.ie1_mul = 1.0 / powf(2.0, 1.0/pcv.sep);
+ pcv.oe2_a = powf(2.0, 1.0/(pcv.sep+2))*long_side*0.5;
+ pcv.oe2_b = pcv.oe2_a * short_side / long_side;
+ pcv.ie2_mul = 1.0 / powf(2.0, 1.0/(pcv.sep+2));
+ }
+ if (roundness > 0.5) {
+ // scale from fitted ellipse towards circle
+ float rad = sqrtf(pcv.w*pcv.w+pcv.h*pcv.h) / 2.0;
+ float diff_a = rad - pcv.oe_a;
+ float diff_b = rad - pcv.oe_b;
+ pcv.oe_a = pcv.oe_a + diff_a * 2*(roundness - 0.5);
+ pcv.oe_b = pcv.oe_b + diff_b * 2*(roundness - 0.5);
+ }
+ pcv.scale = powf(2, -pcvignette.strength);
+ if (pcvignette.strength >= 6.0) {
+ pcv.scale = 0.0;
+ }
+}
+
+static float calcPCVignetteFactor(const struct pcv_params& pcv, int x, int y) {
+
+ float fo = 1.0;
+ if (x < pcv.x1 || x > pcv.x2 || y < pcv.y1 || y > pcv.y2) {
+ /*
+ The initial plan was to have 1.0 directly outside the crop box (ie no fading), but due to
+ rounding/trunction here and there I didn't succeed matching up exactly on the pixel with
+ the crop box. To hide that mismatch I made a fade.
+ */
+ int dist_x = (x < pcv.x1) ? pcv.x1 - x : x - pcv.x2;
+ int dist_y = (y < pcv.y1) ? pcv.y1 - y : y - pcv.y2;
+ if (dist_x < 0) dist_x = 0;
+ if (dist_y < 0) dist_y = 0;
+ fo = sqrtf(dist_x*dist_x+dist_y*dist_y) * pcv.fadeout_mul;
+ if (fo >= 1.0) {
+ return 1.0;
+ }
+ }
+ float val, a, b;
+ if (pcv.is_portrait) {
+ a = fabs((y-pcv.y1)-pcv.h*0.5);
+ b = fabs((x-pcv.x1)-pcv.w*0.5);
+ } else {
+ a = fabs((x-pcv.x1)-pcv.w*0.5);
+ b = fabs((y-pcv.y1)-pcv.h*0.5);
+ }
+ float angle = atan2f(b, a);
+ float dist = sqrtf(a*a+b*b);
+ float dist_oe, dist_ie;
+ if (pcv.is_super_ellipse_mode) {
+ float dist_oe1 = pcv.oe1_a*pcv.oe1_b / powf(powf(pcv.oe1_b*cosf(angle), pcv.sep) + powf(pcv.oe1_a*sinf(angle), pcv.sep), 1.0/pcv.sep);
+ float dist_oe2 = pcv.oe2_a*pcv.oe2_b / powf(powf(pcv.oe2_b*cosf(angle), pcv.sep+2) + powf(pcv.oe2_a*sinf(angle), pcv.sep+2), 1.0/(pcv.sep+2));
+ float dist_ie1 = pcv.ie1_mul * dist_oe1 * (1.0 - pcv.feather);
+ float dist_ie2 = pcv.ie2_mul * dist_oe2 * (1.0 - pcv.feather);
+ dist_oe = dist_oe1 * (1.0 - pcv.sepmix) + dist_oe2 * pcv.sepmix;
+ dist_ie = dist_ie1 * (1.0 - pcv.sepmix) + dist_ie2 * pcv.sepmix;
+ } else {
+ dist_oe = pcv.oe_a*pcv.oe_b / sqrtf(pcv.oe_b*cosf(angle)*pcv.oe_b*cosf(angle) + pcv.oe_a*sinf(angle)*pcv.oe_a*sinf(angle));
+ dist_ie = pcv.ie_mul * dist_oe * (1.0 - pcv.feather);
+ }
+ if (dist <= dist_ie) {
+ return 1.0;
+ }
+
+ if (dist >= dist_oe) {
+ val = pcv.scale;
+ } else {
+ val = (dist - dist_ie) / (dist_oe - dist_ie);
+ if (pcv.scale < 1.0) {
+ val = pow(cos(val*M_PI/2), 4);
+ } else {
+ val = 1 - pow(sin(val*M_PI/2), 4);
+ }
+ val = pcv.scale + val * (1.0 - pcv.scale);
+ }
+ if (fo < 1.0) {
+ val = 1.0 * fo + val * (1.0 - fo);
+ }
+ return val;
+}
+
+void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH) {
const bool applyVignetting = needsVignetting();
const bool applyGradient = needsGradient();
+ const bool applyPCVignetting = needsPCVignetting();
double vig_w2, vig_h2, maxRadius, v, b, mul;
if (applyVignetting) {
calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul);
}
- struct grad_params gp;
- if (applyGradient) {
- calcGradientParams(oW, oH, params->gradient, gp);
- }
+ struct grad_params gp;
+ if (applyGradient) {
+ calcGradientParams(oW, oH, params->gradient, gp);
+ }
+
+ struct pcv_params pcv;
+ if (applyPCVignetting) {
+ //fprintf(stderr, "%d %d | %d %d | %d %d | %d %d [%d %d]\n", fW, fH, oW, oH, transformed->width, transformed->height, cx, cy, params->crop.w, params->crop.h);
+ calcPCVignetteParams(fW, fH, oW, oH, params->pcvignette, params->crop, pcv);
+ }
#pragma omp parallel for if (multiThread)
for (int y=0; yheight; y++) {
@@ -394,7 +528,10 @@ void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat*
}
if (applyGradient) {
factor *= calcGradientFactor(gp, cx+x, cy+y);
- }
+ }
+ if (applyPCVignetting) {
+ factor *= calcPCVignetteFactor(pcv, cx+x, cy+y);
+ }
transformed->r(y,x) = original->r(y,x) * factor;
transformed->g(y,x) = original->g(y,x) * factor;
transformed->b(y,x) = original->b(y,x) * factor;
@@ -403,10 +540,7 @@ void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat*
}
// Transform WITH scaling (opt.) and CA, cubic interpolation
-#include "cubintch.cc"
-#include "cubint.cc"
-
-void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH,
+void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH,
const LCPMapper *pLCPMap, bool fullImage) {
double w2 = (double) oW / 2.0 - 0.5;
@@ -415,10 +549,14 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr
double vig_w2,vig_h2,maxRadius,v,b,mul;
calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul);
- struct grad_params gp;
- if (needsGradient()) {
+ struct grad_params gp;
+ if (needsGradient()) {
calcGradientParams(oW, oH, params->gradient, gp);
}
+ struct pcv_params pcv;
+ if (needsPCVignetting()) {
+ calcPCVignetteParams(fW, fH, oW, oH, params->pcvignette, params->crop, pcv);
+ }
float** chOrig[3];
chOrig[0] = original->r.ptrs;
@@ -504,13 +642,13 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr
}
double r2;
- if (needsVignetting()) {
- double vig_Dx = vig_x_d * cost - vig_y_d * sint;
- double vig_Dy = vig_x_d * sint + vig_y_d * cost;
+ if (needsVignetting()) {
+ double vig_Dx = vig_x_d * cost - vig_y_d * sint;
+ double vig_Dy = vig_x_d * sint + vig_y_d * cost;
r2=sqrt(vig_Dx*vig_Dx + vig_Dy*vig_Dy);
}
- for (int c=0; c < (enableCA ? 3 : 1); c++) {
+ for (int c=0; c < (enableCA ? 3 : 1); c++) {
double Dx = Dxc * (s + chDist[c]);
double Dy = Dyc * (s + chDist[c]);
@@ -520,22 +658,25 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr
// LCP CA
if (enableLCPCA) pLCPMap->correctCA(Dx,Dy,c);
- // Extract integer and fractions of source screen coordinates
- int xc = (int)Dx; Dx -= (double)xc; xc -= sx;
- int yc = (int)Dy; Dy -= (double)yc; yc -= sy;
+ // Extract integer and fractions of source screen coordinates
+ int xc = (int)Dx; Dx -= (double)xc; xc -= sx;
+ int yc = (int)Dy; Dy -= (double)yc; yc -= sy;
- // Convert only valid pixels
- if (yc>=0 && ycheight && xc>=0 && xcwidth) {
+ // Convert only valid pixels
+ if (yc>=0 && ycheight && xc>=0 && xcwidth) {
- // multiplier for vignetting correction
- double vignmul = 1.0;
- if (needsVignetting())
- vignmul /= std::max(v + mul * tanh (b*(maxRadius-s*r2) / maxRadius), 0.001);
- if (needsGradient()) {
- vignmul *= calcGradientFactor(gp, cx+x, cy+y);
- }
+ // multiplier for vignetting correction
+ double vignmul = 1.0;
+ if (needsVignetting())
+ vignmul /= std::max(v + mul * tanh (b*(maxRadius-s*r2) / maxRadius), 0.001);
+ if (needsGradient()) {
+ vignmul *= calcGradientFactor(gp, cx+x, cy+y);
+ }
+ if (needsPCVignetting()) {
+ vignmul *= calcPCVignetteFactor(pcv, cx+x, cy+y);
+ }
- if (yc > 0 && yc < original->height-2 && xc > 0 && xc < original->width-2) {
+ if (yc > 0 && yc < original->height-2 && xc > 0 && xc < original->width-2) {
// all interpolation pixels inside image
if (enableCA)
interpolateTransformChannelsCubic (chOrig[c], xc-1, yc-1, Dx, Dy, &(chTrans[c][y][x]), vignmul);
@@ -543,37 +684,37 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr
interpolateTransformCubic (original, xc-1, yc-1, Dx, Dy, &(transformed->r(y,x)), &(transformed->g(y,x)), &(transformed->b(y,x)), vignmul);
} else {
// edge pixels
- int y1 = LIM(yc, 0, original->height-1);
- int y2 = LIM(yc+1, 0, original->height-1);
- int x1 = LIM(xc, 0, original->width-1);
- int x2 = LIM(xc+1, 0, original->width-1);
+ int y1 = LIM(yc, 0, original->height-1);
+ int y2 = LIM(yc+1, 0, original->height-1);
+ int x1 = LIM(xc, 0, original->width-1);
+ int x2 = LIM(xc+1, 0, original->width-1);
- if (enableCA) {
- chTrans[c][y][x] = vignmul * (chOrig[c][y1][x1]*(1.0-Dx)*(1.0-Dy) + chOrig[c][y1][x2]*Dx*(1.0-Dy) + chOrig[c][y2][x1]*(1.0-Dx)*Dy + chOrig[c][y2][x2]*Dx*Dy);
- } else {
- transformed->r(y,x) = vignmul*(original->r(y1,x1)*(1.0-Dx)*(1.0-Dy) + original->r(y1,x2)*Dx*(1.0-Dy) + original->r(y2,x1)*(1.0-Dx)*Dy + original->r(y2,x2)*Dx*Dy);
- transformed->g(y,x) = vignmul*(original->g(y1,x1)*(1.0-Dx)*(1.0-Dy) + original->g(y1,x2)*Dx*(1.0-Dy) + original->g(y2,x1)*(1.0-Dx)*Dy + original->g(y2,x2)*Dx*Dy);
- transformed->b(y,x) = vignmul*(original->b(y1,x1)*(1.0-Dx)*(1.0-Dy) + original->b(y1,x2)*Dx*(1.0-Dy) + original->b(y2,x1)*(1.0-Dx)*Dy + original->b(y2,x2)*Dx*Dy);
- }
- }
+ if (enableCA) {
+ chTrans[c][y][x] = vignmul * (chOrig[c][y1][x1]*(1.0-Dx)*(1.0-Dy) + chOrig[c][y1][x2]*Dx*(1.0-Dy) + chOrig[c][y2][x1]*(1.0-Dx)*Dy + chOrig[c][y2][x2]*Dx*Dy);
+ } else {
+ transformed->r(y,x) = vignmul*(original->r(y1,x1)*(1.0-Dx)*(1.0-Dy) + original->r(y1,x2)*Dx*(1.0-Dy) + original->r(y2,x1)*(1.0-Dx)*Dy + original->r(y2,x2)*Dx*Dy);
+ transformed->g(y,x) = vignmul*(original->g(y1,x1)*(1.0-Dx)*(1.0-Dy) + original->g(y1,x2)*Dx*(1.0-Dy) + original->g(y2,x1)*(1.0-Dx)*Dy + original->g(y2,x2)*Dx*Dy);
+ transformed->b(y,x) = vignmul*(original->b(y1,x1)*(1.0-Dx)*(1.0-Dy) + original->b(y1,x2)*Dx*(1.0-Dy) + original->b(y2,x1)*(1.0-Dx)*Dy + original->b(y2,x2)*Dx*Dy);
}
- else {
- if (enableCA) {
- // not valid (source pixel x,y not inside source image, etc.)
- chTrans[c][y][x] = 0;
- } else {
- transformed->r(y,x) = 0;
- transformed->g(y,x) = 0;
- transformed->b(y,x) = 0;
- }
- }
- }
+ }
+ }
+ else {
+ if (enableCA) {
+ // not valid (source pixel x,y not inside source image, etc.)
+ chTrans[c][y][x] = 0;
+ } else {
+ transformed->r(y,x) = 0;
+ transformed->g(y,x) = 0;
+ transformed->b(y,x) = 0;
+ }
+ }
+ }
}
}
}
// Transform WITH scaling, WITHOUT CA, simple (and fast) interpolation. Used for preview
-void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, const LCPMapper *pLCPMap) {
+void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap) {
double w2 = (double) oW / 2.0 - 0.5;
double h2 = (double) oH / 2.0 - 0.5;
@@ -581,10 +722,14 @@ void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transf
double vig_w2, vig_h2, maxRadius, v, b, mul;
calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul);
- struct grad_params gp;
- if (needsGradient()) {
- calcGradientParams(oW, oH, params->gradient, gp);
- }
+ struct grad_params gp;
+ if (needsGradient()) {
+ calcGradientParams(oW, oH, params->gradient, gp);
+ }
+ struct pcv_params pcv;
+ if (needsPCVignetting()) {
+ calcPCVignetteParams(fW, fH, oW, oH, params->pcvignette, params->crop, pcv);
+ }
// auxiliary variables for distortion correction
bool needsDist = needsDistortion(); // for performance
@@ -665,11 +810,13 @@ void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transf
if (yc>=0 && ycheight && xc>=0 && xcwidth) {
// multiplier for vignetting correction
- double vignmul = 1.0;
+ double vignmul = 1.0;
if (needsVignetting())
- vignmul /= std::max(v + mul * tanh (b*(maxRadius-s*r2) / maxRadius), 0.001);
- if (needsGradient())
- vignmul *= calcGradientFactor(gp, cx+x, cy+y);
+ vignmul /= std::max(v + mul * tanh (b*(maxRadius-s*r2) / maxRadius), 0.001);
+ if (needsGradient())
+ vignmul *= calcGradientFactor(gp, cx+x, cy+y);
+ if (needsPCVignetting())
+ vignmul *= calcPCVignetteFactor(pcv, cx+x, cy+y);
if (yc < original->height-1 && xc < original->width-1) {
// all interpolation pixels inside image
@@ -739,6 +886,10 @@ bool ImProcFunctions::needsGradient () {
return params->gradient.enabled && fabs(params->gradient.strength) > 1e-15;
}
+bool ImProcFunctions::needsPCVignetting () {
+ return params->pcvignette.enabled && fabs(params->pcvignette.strength) > 1e-15;
+}
+
bool ImProcFunctions::needsVignetting () {
return params->vignetting.amount;
}
@@ -748,7 +899,7 @@ bool ImProcFunctions::needsLCP () {
}
bool ImProcFunctions::needsTransform () {
- return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsVignetting () || needsLCP();
+ return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP();
}
diff --git a/rtengine/procevents.h b/rtengine/procevents.h
index bb3d02ace..2bf679fda 100644
--- a/rtengine/procevents.h
+++ b/rtengine/procevents.h
@@ -234,7 +234,9 @@ enum ProcEvent {
EvWBequalbo=208,
EvGradient=209,
EvGradientEnabled=210,
- NUMOFEVENTS=211
+ EvPCVignette=211,
+ EvPCVignetteEnabled=212,
+ NUMOFEVENTS=213
};
}
#endif
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index e1ae6ff34..03c8c1faa 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -338,6 +338,11 @@ void ProcParams::setDefaults () {
gradient.centerX = 0;
gradient.centerY = 0;
+ pcvignette.enabled = false;
+ pcvignette.strength = 0;
+ pcvignette.feather = 50;
+ pcvignette.roundness = 50;
+
cacorrection.red = 0;
cacorrection.blue = 0;
@@ -838,6 +843,12 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol
if (!pedited || pedited->gradient.centerX) keyFile.set_integer ("Gradient", "CenterX", gradient.centerX);
if (!pedited || pedited->gradient.centerY) keyFile.set_integer ("Gradient", "CenterY", gradient.centerY);
+ // save post-crop vignette
+ if (!pedited || pedited->pcvignette.enabled) keyFile.set_boolean ("PCVignette", "Enabled", pcvignette.enabled);
+ if (!pedited || pedited->pcvignette.strength) keyFile.set_double ("PCVignette", "Strength", pcvignette.strength);
+ if (!pedited || pedited->pcvignette.feather) keyFile.set_integer ("PCVignette", "Feather", pcvignette.feather);
+ if (!pedited || pedited->pcvignette.roundness) keyFile.set_integer ("PCVignette", "Roundness", pcvignette.roundness);
+
// save C/A correction
if (!pedited || pedited->cacorrection.red) keyFile.set_double ("CACorrection", "Red", cacorrection.red);
if (!pedited || pedited->cacorrection.blue) keyFile.set_double ("CACorrection", "Blue", cacorrection.blue);
@@ -1393,6 +1404,13 @@ if (keyFile.has_group ("Gradient")) {
if (keyFile.has_key ("Gradient", "CenterY")) { gradient.centerY = keyFile.get_integer ("Gradient", "CenterY"); if (pedited) pedited->gradient.centerY = true; }
}
+if (keyFile.has_group ("PCVignette")) {
+ if (keyFile.has_key ("PCVignette", "Enabled")) { pcvignette.enabled = keyFile.get_boolean ("PCVignette", "Enabled"); if (pedited) pedited->pcvignette.enabled = true; }
+ if (keyFile.has_key ("PCVignette", "Strength")) { pcvignette.strength = keyFile.get_double ("PCVignette", "Strength");if (pedited) pedited->pcvignette.strength = true; }
+ if (keyFile.has_key ("PCVignette", "Feather")) { pcvignette.feather = keyFile.get_integer ("PCVignette", "Feather"); if (pedited) pedited->pcvignette.feather = true; }
+ if (keyFile.has_key ("PCVignette", "Roundness")) { pcvignette.roundness = keyFile.get_integer ("PCVignette", "Roundness"); if (pedited) pedited->pcvignette.roundness = true; }
+}
+
// load c/a correction
if (keyFile.has_group ("CACorrection")) {
if (keyFile.has_key ("CACorrection", "Red")) { cacorrection.red = keyFile.get_double ("CACorrection", "Red"); if (pedited) pedited->cacorrection.red = true; }
@@ -1734,6 +1752,10 @@ bool ProcParams::operator== (const ProcParams& other) {
&& gradient.strength == other.gradient.strength
&& gradient.centerX == other.gradient.centerX
&& gradient.centerY == other.gradient.centerY
+ && pcvignette.enabled == other.pcvignette.enabled
+ && pcvignette.strength == other.pcvignette.strength
+ && pcvignette.feather == other.pcvignette.feather
+ && pcvignette.roundness == other.pcvignette.roundness
&& cacorrection.red == other.cacorrection.red
&& cacorrection.blue == other.cacorrection.blue
&& vignetting.amount == other.vignetting.amount
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 627cd25c7..2e490c74d 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -590,6 +590,18 @@ class GradientParams {
int centerY;
};
+/**
+ * Parameters of the post-crop vignette filter
+ */
+class PCVignetteParams {
+
+ public:
+ bool enabled;
+ double strength;
+ int feather;
+ int roundness;
+};
+
/**
* Parameters of the vignetting correction
*/
@@ -786,6 +798,7 @@ class ProcParams {
LensProfParams lensProf; ///< Lens correction profile parameters
PerspectiveParams perspective; ///< Perspective correction parameters
GradientParams gradient; ///< Gradient filter parameters
+ PCVignetteParams pcvignette; ///< Post-crop vignette filter parameters
CACorrParams cacorrection; ///< Lens c/a correction parameters
VignettingParams vignetting; ///< Lens vignetting correction parameters
ChannelMixerParams chmixer; ///< Channel mixer parameters
diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc
index b132796e7..278d44c2f 100644
--- a/rtengine/refreshmap.cc
+++ b/rtengine/refreshmap.cc
@@ -230,7 +230,9 @@ DEFRINGE, // EvPFCurve,
WHITEBALANCE, // EvWBequal,
WHITEBALANCE, // EvWBequalbo,
TRANSFORM, // EvGradient
-TRANSFORM // EvGradientEnabled
+TRANSFORM, // EvGradientEnabled
+TRANSFORM, // EvPCVignette
+TRANSFORM // EvPCVignetteEnabled
//LUMINANCECURVE // EvCATsharpcie
diff --git a/rtengine/refreshmap.h b/rtengine/refreshmap.h
index 00bdabada..ba914e77d 100644
--- a/rtengine/refreshmap.h
+++ b/rtengine/refreshmap.h
@@ -24,12 +24,14 @@
// Use M_VOID is you wish to update the proc params without updating the preview at all !
#define M_VOID (1<<15)
// Use M_MINUPDATE if you you wish to update the preview without modifying the image (think about it like a "refreshPreview")
+// Must NOT be used with other event (i.e. will be used for MINUPDATE only)
#define M_MINUPDATE (1<<14)
// Force high quality
#define M_HIGHQUAL (1<<13)
// Elementary functions that can be done to
// the preview image when an event occurs
+#define M_CROP (1<<11)
#define M_PREPROC (1<<10)
#define M_RAW (1<<9)
#define M_INIT (1<<8)
@@ -59,13 +61,14 @@
#define DARKFRAME (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
#define FLATFIELD (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
#define DIRPYRDENOISE (M_COLOR|M_LUMINANCE)
-#define CROP M_MINUPDATE
+#define CROP M_CROP
#define RESIZE M_VOID
#define EXIF M_VOID
#define IPTC M_VOID
#define DIRPYREQUALIZER (M_COLOR|M_LUMINANCE)
#define OUTPUTPROFIL (M_COLOR|M_LUMINANCE)
#define GAMMA (M_COLOR|M_LUMINANCE)
+#define MINUPDATE M_MINUPDATE
#define NONE 0
#define ALLNORAW (M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
index 24d81e1b0..91013fa92 100644
--- a/rtengine/rtthumbnail.cc
+++ b/rtengine/rtthumbnail.cc
@@ -682,7 +682,11 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
// perform transform
if (ipf.needsTransform()) {
Imagefloat* trImg = new Imagefloat (fw, fh);
- ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, focalLen, focalLen35mm, focusDist, 0, true); // Raw rotate degree not detectable here
+ int origFW;
+ int origFH;
+ double tscale;
+ getDimensions(origFW, origFH, tscale);
+ ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, origFW*tscale+0.5, origFH*tscale+0.5, focalLen, focalLen35mm, focusDist, 0, true); // Raw rotate degree not detectable here
delete baseImg;
baseImg = trImg;
}
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index 1c71bf629..dd5125250 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -136,7 +136,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
// perform transform (excepted resizing)
if (ipf.needsTransform()) {
Imagefloat* trImg = new Imagefloat (fw, fh);
- ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(),
+ 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;
diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt
index 55d3372a5..459c52a9b 100644
--- a/rtgui/CMakeLists.txt
+++ b/rtgui/CMakeLists.txt
@@ -10,7 +10,7 @@ set (BASESOURCEFILES
impulsedenoise.cc dirpyrdenoise.cc epd.cc
exifpanel.cc toolpanel.cc lensprofile.cc
sharpening.cc vibrance.cc rgbcurves.cc
- whitebalance.cc vignetting.cc gradient.cc rotate.cc distortion.cc
+ whitebalance.cc vignetting.cc gradient.cc pcvignette.cc rotate.cc distortion.cc
crophandler.cc dirbrowser.cc
curveeditor.cc curveeditorgroup.cc diagonalcurveeditorsubgroup.cc flatcurveeditorsubgroup.cc
filecatalog.cc extprog.cc
diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h
index 37ad71d1c..5a35f176f 100644
--- a/rtgui/addsetids.h
+++ b/rtgui/addsetids.h
@@ -70,8 +70,11 @@
#define ADDSET_GRADIENT_FEATHER 62
#define ADDSET_GRADIENT_STRENGTH 63
#define ADDSET_GRADIENT_CENTER 64
+#define ADDSET_PCVIGNETTE_STRENGTH 65
+#define ADDSET_PCVIGNETTE_FEATHER 66
+#define ADDSET_PCVIGNETTE_ROUNDNESS 67
// When adding items, make sure to update ADDSET_PARAM_NUM
-#define ADDSET_PARAM_NUM 65 // THIS IS USED AS A DELIMITER!!
+#define ADDSET_PARAM_NUM 68 // THIS IS USED AS A DELIMITER!!
#endif
diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc
index 7319baddb..a505e8af1 100644
--- a/rtgui/batchtoolpanelcoord.cc
+++ b/rtgui/batchtoolpanelcoord.cc
@@ -134,6 +134,7 @@ void BatchToolPanelCoordinator::initSession () {
distortion->setAdjusterBehavior (false);
perspective->setAdjusterBehavior (false);
gradient->setAdjusterBehavior (false, false, false, false);
+ pcvignette->setAdjusterBehavior (false, false, false);
cacorrection->setAdjusterBehavior (false);
sharpening->setAdjusterBehavior (false);
sharpenEdge->setAdjusterBehavior (false, false);
@@ -162,6 +163,7 @@ void BatchToolPanelCoordinator::initSession () {
distortion->setAdjusterBehavior (options.baBehav[ADDSET_DIST_AMOUNT]);
perspective->setAdjusterBehavior (options.baBehav[ADDSET_PERSPECTIVE]);
gradient->setAdjusterBehavior (options.baBehav[ADDSET_GRADIENT_DEGREE], options.baBehav[ADDSET_GRADIENT_FEATHER], options.baBehav[ADDSET_GRADIENT_STRENGTH], options.baBehav[ADDSET_GRADIENT_CENTER]);
+ pcvignette->setAdjusterBehavior (options.baBehav[ADDSET_PCVIGNETTE_STRENGTH], options.baBehav[ADDSET_PCVIGNETTE_FEATHER], options.baBehav[ADDSET_PCVIGNETTE_ROUNDNESS]);
cacorrection->setAdjusterBehavior (options.baBehav[ADDSET_CA]);
sharpening->setAdjusterBehavior (options.baBehav[ADDSET_SHARP_AMOUNT]);
sharpenEdge->setAdjusterBehavior (options.baBehav[ADDSET_SHARPENEDGE_AMOUNT],options.baBehav[ADDSET_SHARPENEDGE_PASS]);
@@ -238,6 +240,9 @@ void BatchToolPanelCoordinator::initSession () {
if (options.baBehav[ADDSET_GRADIENT_STRENGTH]) pparams.gradient.strength = 0;
if (options.baBehav[ADDSET_GRADIENT_CENTER]) pparams.gradient.centerX = 0;
if (options.baBehav[ADDSET_GRADIENT_CENTER]) pparams.gradient.centerY = 0;
+ if (options.baBehav[ADDSET_PCVIGNETTE_STRENGTH]) pparams.pcvignette.strength = 0;
+ if (options.baBehav[ADDSET_PCVIGNETTE_FEATHER]) pparams.pcvignette.feather = 0;
+ if (options.baBehav[ADDSET_PCVIGNETTE_ROUNDNESS]) pparams.pcvignette.roundness = 0;
if (options.baBehav[ADDSET_CA]) pparams.cacorrection.red = 0;
if (options.baBehav[ADDSET_CA]) pparams.cacorrection.blue = 0;
if (options.baBehav[ADDSET_VIGN_AMOUNT]) pparams.vignetting.amount = 0;
diff --git a/rtgui/options.cc b/rtgui/options.cc
index 0dd0a2de4..60932f54b 100644
--- a/rtgui/options.cc
+++ b/rtgui/options.cc
@@ -452,10 +452,13 @@ void Options::setDefaults () {
0, // ADDSET_CAT_CHROMA
0, // ADDSET_CAT_CONTRAST
0, // ADDSET_WB_EQUAL
- 0, // ADDSET_GRADIENT_AMOUNT
- 0, // ADDSET_GRADIENT_RADIUS
+ 0, // ADDSET_GRADIENT_DEGREE
+ 0, // ADDSET_GRADIENT_FEATHER
0, // ADDSET_GRADIENT_STRENGTH
0, // ADDSET_GRADIENT_CENTER
+ 0, // ADDSET_PCVIGNETTE_STRENGTH
+ 0, // ADDSET_PCVIGNETTE_FEATHER
+ 0, // ADDSET_PCVIGNETTE_ROUNDNESS
};
baBehav = std::vector (babehav, babehav+ADDSET_PARAM_NUM);
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index 62f5b27b8..e2c8353b2 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -196,6 +196,10 @@ void ParamsEdited::set (bool v) {
gradient.strength = v;
gradient.centerX = v;
gradient.centerY = v;
+ pcvignette.enabled = v;
+ pcvignette.strength = v;
+ pcvignette.feather = v;
+ pcvignette.roundness = v;
cacorrection.red = v;
cacorrection.blue = v;
vignetting.amount = v;
@@ -450,6 +454,10 @@ void ParamsEdited::initFrom (const std::vector
gradient.strength = gradient.strength && p.gradient.strength == other.gradient.strength;
gradient.centerX = gradient.centerX && p.gradient.centerX == other.gradient.centerX;
gradient.centerY = gradient.centerY && p.gradient.centerY == other.gradient.centerY;
+ pcvignette.enabled = pcvignette.enabled && p.pcvignette.enabled == other.pcvignette.enabled;
+ pcvignette.strength = pcvignette.strength && p.pcvignette.strength == other.pcvignette.strength;
+ pcvignette.feather = pcvignette.feather && p.pcvignette.feather == other.pcvignette.feather;
+ pcvignette.roundness = pcvignette.roundness && p.pcvignette.roundness == other.pcvignette.roundness;
cacorrection.red = cacorrection.red && p.cacorrection.red == other.cacorrection.red;
cacorrection.blue = cacorrection.blue && p.cacorrection.blue == other.cacorrection.blue;
vignetting.amount = vignetting.amount && p.vignetting.amount == other.vignetting.amount;
@@ -705,12 +713,16 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
if (perspective.horizontal) toEdit.perspective.horizontal = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.horizontal + mods.perspective.horizontal : mods.perspective.horizontal;
if (perspective.vertical) toEdit.perspective.vertical = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.vertical + mods.perspective.vertical : mods.perspective.vertical;
- if (gradient.enabled) toEdit.gradient.enabled = mods.gradient.enabled;
- if (gradient.degree) toEdit.gradient.degree = dontforceSet && options.baBehav[ADDSET_GRADIENT_DEGREE] ? toEdit.gradient.degree + mods.gradient.degree : mods.gradient.degree;
+ if (gradient.enabled) toEdit.gradient.enabled = mods.gradient.enabled;
+ if (gradient.degree) toEdit.gradient.degree = dontforceSet && options.baBehav[ADDSET_GRADIENT_DEGREE] ? toEdit.gradient.degree + mods.gradient.degree : mods.gradient.degree;
if (gradient.feather) toEdit.gradient.feather = mods.gradient.feather;
if (gradient.strength) toEdit.gradient.strength = mods.gradient.strength;
if (gradient.centerX) toEdit.gradient.centerX = mods.gradient.centerX;
if (gradient.centerY) toEdit.gradient.centerY = mods.gradient.centerY;
+ if (pcvignette.enabled) toEdit.pcvignette.enabled = mods.pcvignette.enabled;
+ if (pcvignette.strength) toEdit.pcvignette.strength = mods.pcvignette.strength;
+ if (pcvignette.feather) toEdit.pcvignette.feather = mods.pcvignette.feather;
+ if (pcvignette.roundness) toEdit.pcvignette.roundness = mods.pcvignette.roundness;
if (cacorrection.red) toEdit.cacorrection.red = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.red + mods.cacorrection.red : mods.cacorrection.red;
if (cacorrection.blue) toEdit.cacorrection.blue = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.blue + mods.cacorrection.blue : mods.cacorrection.blue;
if (vignetting.amount) toEdit.vignetting.amount = dontforceSet && options.baBehav[ADDSET_VIGN_AMOUNT] ? toEdit.vignetting.amount + mods.vignetting.amount : mods.vignetting.amount;
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index d9b7bca78..94f20a41b 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -324,6 +324,15 @@ class GradientParamsEdited {
bool centerY;
};
+class PCVignetteParamsEdited {
+
+ public:
+ bool enabled;
+ bool strength;
+ bool feather;
+ bool roundness;
+};
+
class VignettingParamsEdited {
public:
@@ -462,6 +471,7 @@ class ParamsEdited {
LensProfParamsEdited lensProf;
PerspectiveParamsEdited perspective;
GradientParamsEdited gradient;
+ PCVignetteParamsEdited pcvignette;
CACorrParamsEdited cacorrection;
VignettingParamsEdited vignetting;
ChannelMixerParamsEdited chmixer;
diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc
index cf66e73be..ff3a0b1df 100644
--- a/rtgui/partialpastedlg.cc
+++ b/rtgui/partialpastedlg.cc
@@ -49,6 +49,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) {
hlrec = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_HLRECONSTRUCTION")));
sh = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_SHADOWSHIGHLIGHTS")));
epd = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_EPD")));
+ pcvignette = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PCVIGNETTE")));
gradient = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_GRADIENT")));
labcurve = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_LABCURVE")));
colorappearance= Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_COLORAPP")));
@@ -127,6 +128,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) {
vboxes[0]->pack_start (*hlrec, Gtk::PACK_SHRINK, 2);
vboxes[0]->pack_start (*sh, Gtk::PACK_SHRINK, 2);
vboxes[0]->pack_start (*epd, Gtk::PACK_SHRINK, 2);
+ vboxes[0]->pack_start (*pcvignette, Gtk::PACK_SHRINK, 2);
vboxes[0]->pack_start (*gradient, Gtk::PACK_SHRINK, 2);
vboxes[0]->pack_start (*labcurve, Gtk::PACK_SHRINK, 2);
vboxes[0]->pack_start (*colorappearance, Gtk::PACK_SHRINK, 2);
@@ -248,6 +250,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) {
hlrecConn = hlrec->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
shConn = sh->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
epdConn = epd->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
+ pcvignetteConn = pcvignette->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
gradientConn = gradient->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
labcurveConn = labcurve->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
colorappearanceConn=colorappearance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
@@ -430,6 +433,7 @@ void PartialPasteDlg::basicToggled () {
hlrecConn.block (true);
shConn.block (true);
epdConn.block(true);
+ pcvignetteConn.block (true);
gradientConn.block (true);
labcurveConn.block (true);
colorappearanceConn.block (true);
@@ -441,6 +445,7 @@ void PartialPasteDlg::basicToggled () {
hlrec->set_active (basic->get_active ());
sh->set_active (basic->get_active ());
epd->set_active (basic->get_active ());
+ pcvignette->set_active (basic->get_active ());
gradient->set_active (basic->get_active ());
labcurve->set_active (basic->get_active ());
colorappearance->set_active (basic->get_active ());
@@ -450,6 +455,7 @@ void PartialPasteDlg::basicToggled () {
hlrecConn.block (false);
shConn.block (false);
epdConn.block (false);
+ pcvignetteConn.block (false);
gradientConn.block (false);
labcurveConn.block (false);
colorappearanceConn.block (false);
@@ -604,6 +610,7 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param
if (!hlrec->get_active ()) filterPE.hlrecovery = falsePE.hlrecovery;
if (!sh->get_active ()) filterPE.sh = falsePE.sh;
if (!epd->get_active ()) filterPE.edgePreservingDecompositionUI = falsePE.edgePreservingDecompositionUI;
+ if (!pcvignette->get_active ()) filterPE.pcvignette = falsePE.pcvignette;
if (!gradient->get_active ()) filterPE.gradient = falsePE.gradient;
if (!labcurve->get_active ()) filterPE.labCurve = falsePE.labCurve;
if (!colorappearance->get_active ()) filterPE.colorappearance= falsePE.colorappearance;
diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h
index d100ec881..b56094076 100644
--- a/rtgui/partialpastedlg.h
+++ b/rtgui/partialpastedlg.h
@@ -43,6 +43,7 @@ class PartialPasteDlg : public Gtk::Dialog {
Gtk::CheckButton* hlrec;
Gtk::CheckButton* sh;
Gtk::CheckButton* epd;
+ Gtk::CheckButton* pcvignette;
Gtk::CheckButton* gradient;
Gtk::CheckButton* labcurve;
Gtk::CheckButton* colorappearance;
@@ -110,7 +111,7 @@ class PartialPasteDlg : public Gtk::Dialog {
sigc::connection everythingConn, basicConn, detailConn, colorConn, lensConn, compositionConn, metaicmConn, rawConn;
- sigc::connection wbConn, exposureConn, hlrecConn, shConn, gradientConn, labcurveConn, colorappearanceConn;
+ sigc::connection wbConn, exposureConn, hlrecConn, shConn, pcvignetteConn, gradientConn, labcurveConn, colorappearanceConn;
sigc::connection sharpenConn, gradsharpenConn, microcontrastConn, impdenConn, dirpyrdenConn, waveqConn, defringeConn, epdConn, dirpyreqConn;
sigc::connection vibranceConn, chmixerConn, hsveqConn, rgbcurvesConn;
sigc::connection distortionConn, cacorrConn, vignettingConn, lcpConn;
diff --git a/rtgui/ppversion.h b/rtgui/ppversion.h
index 3b3c9cd06..4797eb9ea 100644
--- a/rtgui/ppversion.h
+++ b/rtgui/ppversion.h
@@ -2,16 +2,23 @@
#define _PPVERSION_
// This number have to be incremented whenever the PP3 file format is modified
-#define PPVERSION 310
+#define PPVERSION 311
#define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified
-/* Log of version changes
- * 307 2013-03-16
- * [Perspective] Horizontal and Vertical changed from int to double
- * added [Directional Pyramid Denoising] Method, Redchro, Bluechro
- * added [RGB Curves] LumaMode
- * 310 2013-09-16
- * Defringing /Threshold - changed calculation, issue 1801
+/*
+ Log of version changes
+
+ 311 2013-11-07
+ [Gradient] new tool (gradient/graduated filter
+ [PCVignette] new tool (vignette filter)
+
+ 310 2013-09-16
+ Defringing /Threshold - changed calculation, issue 1801
+
+ 307 2013-03-16
+ [Perspective] Horizontal and Vertical changed from int to double
+ added [Directional Pyramid Denoising] Method, Redchro, Bluechro
+ added [RGB Curves] LumaMode
*/
#endif
diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc
index f368d6ac9..3c2da4f78 100644
--- a/rtgui/preferences.cc
+++ b/rtgui/preferences.cc
@@ -255,6 +255,12 @@ Gtk::Widget* Preferences::getBatchProcPanel () {
appendBehavList (mi, M("TP_GRADIENT_STRENGTH"), ADDSET_GRADIENT_STRENGTH, false);
appendBehavList (mi, M("TP_GRADIENT_CENTER_X")+", "+M("TP_GRADIENT_CENTER_Y"), ADDSET_GRADIENT_CENTER, false);
+ mi = behModel->append ();
+ mi->set_value (behavColumns.label, M("TP_PCVIGNETTE_LABEL"));
+ appendBehavList (mi, M("TP_PCVIGNETTE_STRENGTH"), ADDSET_PCVIGNETTE_STRENGTH, false);
+ appendBehavList (mi, M("TP_PCVIGNETTE_FEATHER"), ADDSET_PCVIGNETTE_FEATHER, false);
+ appendBehavList (mi, M("TP_PCVIGNETTE_ROUNDNESS"), ADDSET_PCVIGNETTE_ROUNDNESS, false);
+
mi = behModel->append ();
mi->set_value (behavColumns.label, M("TP_CACORRECTION_LABEL"));
appendBehavList (mi, M("TP_CACORRECTION_BLUE")+", "+M("TP_CACORRECTION_RED"), ADDSET_CA, true);
diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc
index 5604bcc56..eea01dd70 100644
--- a/rtgui/toolpanelcoord.cc
+++ b/rtgui/toolpanelcoord.cc
@@ -60,6 +60,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) {
whitebalance = Gtk::manage (new WhiteBalance ());
vignetting = Gtk::manage (new Vignetting ());
gradient = Gtk::manage (new Gradient ());
+ pcvignette = Gtk::manage (new PCVignette ());
perspective = Gtk::manage (new PerspCorrection ());
cacorrection = Gtk::manage (new CACorrection ());
hlrecovery = Gtk::manage (new HLRecovery ());
@@ -90,6 +91,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) {
addPanel (colorPanel, hsvequalizer, M("TP_HSVEQUALIZER_LABEL")); toolPanels.push_back (hsvequalizer);
addPanel (colorPanel, rgbcurves, M("TP_RGBCURVES_LABEL")); toolPanels.push_back (rgbcurves);
addPanel (exposurePanel, edgePreservingDecompositionUI, M("TP_EPD_LABEL")); toolPanels.push_back (edgePreservingDecompositionUI);
+ addPanel (exposurePanel, pcvignette, M("TP_PCVIGNETTE_LABEL")); toolPanels.push_back (pcvignette);
addPanel (exposurePanel, gradient, M("TP_GRADIENT_LABEL")); toolPanels.push_back (gradient);
addPanel (exposurePanel, lcurve, M("TP_LABCURVE_LABEL")); toolPanels.push_back (lcurve);
// addPanel (exposurePanel, edgePreservingDecompositionUI, M("TP_EPD_LABEL")); toolPanels.push_back (edgePreservingDecompositionUI);
diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h
index a46e53721..1c9b71434 100644
--- a/rtgui/toolpanelcoord.h
+++ b/rtgui/toolpanelcoord.h
@@ -52,6 +52,7 @@
#include "rotate.h"
#include "vignetting.h"
#include "gradient.h"
+#include "pcvignette.h"
#include "toolbar.h"
#include "lensgeom.h"
#include "lensgeomlistener.h"
@@ -88,6 +89,7 @@ class ToolPanelCoordinator : public ToolPanelListener,
WhiteBalance* whitebalance;
Vignetting* vignetting;
Gradient* gradient;
+ PCVignette* pcvignette;
LensGeometry* lensgeom;
LensProfilePanel* lensProf;
Rotate* rotate;