From 5a05b04e0973feb28a5fac9e3abcd5b883fa7608 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Sun, 29 Oct 2017 21:41:19 +0100 Subject: [PATCH] profile-based CA correction applied during 1:1 preview --- rtengine/improcfun.h | 2 +- rtengine/iptransform.cc | 24 +++++++++++++----------- rtengine/lcp.cc | 8 +++++++- rtengine/lcp.h | 4 ++-- rtengine/rtlensfun.cc | 6 +++++- rtengine/rtlensfun.h | 2 +- 6 files changed, 29 insertions(+), 17 deletions(-) diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 3b835a124..699193632 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -58,7 +58,7 @@ class ImProcFunctions TRANSFORM_PREVIEW, TRANSFORM_HIGH_QUALITY, TRANSFORM_HIGH_QUALITY_FULLIMAGE, - TRANSFORM_HIGH_QUALITY_FULLIMAGE_CA + TRANSFORM_HIGH_QUALITY_CA }; void transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH); void transformGeneral(TransformMode mode, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap); diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 5a50fafe9..87ab7b922 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -329,21 +329,23 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, std::unique_ptr tmpimg; if (!needsCA() && scale != 1) { mode = TRANSFORM_PREVIEW; - } else if (!fullImage) { - mode = TRANSFORM_HIGH_QUALITY; } else { - mode = TRANSFORM_HIGH_QUALITY_FULLIMAGE; + if (!fullImage) { + mode = TRANSFORM_HIGH_QUALITY; + } else { + mode = TRANSFORM_HIGH_QUALITY_FULLIMAGE; + } // agriggio: CA correction via the lens profile has to be // performed before all the other transformations (except for the // coarse rotation/flipping). In order to not change the code too // much, I simply introduced a new mode - // TRANSFORM_HIGH_QUALITY_FULLIMAGE_CA, which applies *only* + // TRANSFORM_HIGH_QUALITY_CA, which applies *only* // profile-based CA correction. So, the correction in this case // occurs in two steps, using an intermediate temporary // image. There's room for optimization of course... if (pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable()) { - tmpimg.reset(new Imagefloat(transformed->getWidth(), transformed->getHeight())); - transformGeneral(TRANSFORM_HIGH_QUALITY_FULLIMAGE_CA, original, tmpimg.get(), cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap.get()); + tmpimg.reset(new Imagefloat(original->getWidth(), original->getHeight())); + transformGeneral(TRANSFORM_HIGH_QUALITY_CA, original, tmpimg.get(), 0, 0, 0, 0, fW, fH, fW, fH, pLCPMap.get()); original = tmpimg.get(); } } @@ -750,7 +752,7 @@ void ImProcFunctions::transformGeneral(ImProcFunctions::TransformMode mode, Imag bool enableDistortion = needsDistortion(); switch (mode) { - case ImProcFunctions::TRANSFORM_HIGH_QUALITY_FULLIMAGE_CA: + case ImProcFunctions::TRANSFORM_HIGH_QUALITY_CA: enableLCPDist = false; enablePerspective = false; enableDistortion = false; @@ -763,9 +765,9 @@ void ImProcFunctions::transformGeneral(ImProcFunctions::TransformMode mode, Imag enableLCPCA = false; break; case ImProcFunctions::TRANSFORM_HIGH_QUALITY: - if (enableLCPDist) { + // if (enableLCPDist) { enableLCPCA = false; - } + // } break; case ImProcFunctions::TRANSFORM_PREVIEW: enableLCPCA = false; @@ -834,7 +836,7 @@ void ImProcFunctions::transformGeneral(ImProcFunctions::TransformMode mode, Imag //double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0; double ascale = 1.0; - if (mode != ImProcFunctions::TRANSFORM_HIGH_QUALITY_FULLIMAGE_CA && + if (mode != ImProcFunctions::TRANSFORM_HIGH_QUALITY_CA && params->commonTrans.autofill) { ascale = getTransformAutoFill (oW, oH, pLCPMap); } @@ -912,7 +914,7 @@ void ImProcFunctions::transformGeneral(ImProcFunctions::TransformMode mode, Imag // LCP CA if (enableLCPCA) { - pLCPMap->correctCA (Dx, Dy, c); + pLCPMap->correctCA (Dx, Dy, cx, cy, c); } // Extract integer and fractions of source screen coordinates diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index 3824d2b2f..44a470e17 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -1077,12 +1077,15 @@ void rtengine::LCPMapper::correctDistortion(double &x, double &y, int cx, int cy y -= cy * scale; } -void rtengine::LCPMapper::correctCA(double& x, double& y, int channel) const +void rtengine::LCPMapper::correctCA(double& x, double& y, int cx, int cy, int channel) const { if (!enableCA) { return; } + x += cx; + y += cy; + double xgreen, ygreen; // First calc the green channel like normal distortion @@ -1123,6 +1126,9 @@ void rtengine::LCPMapper::correctCA(double& x, double& y, int channel) const x = (chrom[channel].scale_factor * ( xd * commonSum + xfac * rsqr )) * chrom[channel].fx + chrom[channel].x0; y = (chrom[channel].scale_factor * ( yd * commonSum + yfac * rsqr )) * chrom[channel].fy + chrom[channel].y0; } + + x -= cx; + x -= cy; } SSEFUNCTION void rtengine::LCPMapper::processVignetteLine(int width, int y, float* line) const diff --git a/rtengine/lcp.h b/rtengine/lcp.h index 17eb892c8..b50fd335e 100644 --- a/rtengine/lcp.h +++ b/rtengine/lcp.h @@ -164,7 +164,7 @@ public: virtual ~LensCorrection() {} virtual void correctDistortion(double &x, double &y, int cx, int cy, double scale) const = 0; virtual bool isCACorrectionAvailable() const = 0; - virtual void correctCA(double &x, double &y, int channel) const = 0; + virtual void correctCA(double &x, double &y, int cx, int cy, int channel) const = 0; virtual void processVignetteLine(int width, int y, float *line) const = 0; virtual void processVignetteLine3Channels(int width, int y, float *line) const = 0; }; @@ -192,7 +192,7 @@ public: void correctDistortion(double &x, double &y, int cx, int cy, double scale) const; // MUST be the first stage bool isCACorrectionAvailable() const; - void correctCA(double& x, double& y, int channel) const; + void correctCA(double& x, double& y, int cx, int cy, int channel) const; void processVignetteLine(int width, int y, float* line) const; void processVignetteLine3Channels(int width, int y, float* line) const; diff --git a/rtengine/rtlensfun.cc b/rtengine/rtlensfun.cc index 99315c20d..cc4f6f53c 100644 --- a/rtengine/rtlensfun.cc +++ b/rtengine/rtlensfun.cc @@ -76,7 +76,7 @@ bool LFModifier::isCACorrectionAvailable() const } -void LFModifier::correctCA(double &x, double &y, int channel) const +void LFModifier::correctCA(double &x, double &y, int cx, int cy, int channel) const { assert(channel >= 0 && channel <= 2); @@ -84,6 +84,8 @@ void LFModifier::correctCA(double &x, double &y, int channel) const // lensfun applies it to all the three channels simultaneously. This means // we do the work 3 times, because each time we discard 2 of the 3 // channels. We could consider caching the info to speed this up + x += cx; + y += cy; float pos[6]; if (swap_xy_) { @@ -95,6 +97,8 @@ void LFModifier::correctCA(double &x, double &y, int channel) const if (swap_xy_) { std::swap(x, y); } + x -= cx; + y -= cy; } diff --git a/rtengine/rtlensfun.h b/rtengine/rtlensfun.h index ddc6d885a..60ef461c7 100644 --- a/rtengine/rtlensfun.h +++ b/rtengine/rtlensfun.h @@ -44,7 +44,7 @@ public: void correctDistortion(double &x, double &y, int cx, int cy, double scale) const override; bool isCACorrectionAvailable() const override; - void correctCA(double &x, double &y, int channel) const override; + void correctCA(double &x, double &y, int cx, int cy, int channel) const override; void processVignetteLine(int width, int y, float *line) const override; void processVignetteLine3Channels(int width, int y, float *line) const override;