diff --git a/rtengine/cubint.cc b/rtengine/cubint.cc index d730c6299..85f3d3ef6 100644 --- a/rtengine/cubint.cc +++ b/rtengine/cubint.cc @@ -17,7 +17,6 @@ * along with RawTherapee. If not, see . */ -// currently not in use any more 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; diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index ba4af940f..a03167cc5 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -263,6 +263,8 @@ void ImProcFunctions::transformVignetteOnly (Imagefloat* original, Imagefloat* t // 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, const LCPMapper *pLCPMap, bool fullImage) { @@ -313,9 +315,10 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, fullImage ? pLCPMap : NULL) : 1.0; // smaller crop images are a problem, so only when processing fully - bool enableLCPCA = pLCPMap && params->lensProf.useCA && fullImage; + bool enableLCPCA = pLCPMap && params->lensProf.useCA && fullImage && pLCPMap->enableCA; bool enableLCPDist = pLCPMap && params->lensProf.useDist && fullImage; if (enableLCPCA) enableLCPDist=false; + bool enableCA = enableLCPCA || needsCA(); // main cycle #pragma omp parallel for if (multiThread) @@ -361,7 +364,7 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr r2=sqrt(vig_Dx*vig_Dx + vig_Dy*vig_Dy); } - for (int c=0; c<3; c++) { + for (int c=0; c < (enableCA ? 3 : 1); c++) { double Dx = Dxc * (s + chDist[c]); double Dy = Dyc * (s + chDist[c]); @@ -385,19 +388,36 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr 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); + else + 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); + + 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 + } + 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; + } + } } } } diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index 5cc0b78dd..df7e413df 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -144,6 +144,8 @@ LCPMapper::LCPMapper(LCPProfile* pProf, float focalLength, float focalLength35mm pProf->calcParams(2, focalLength, focusDist, aperture, &chrom[0], &chrom[1], &chrom[2]); for (int i=0;i<3;i++) chrom[i].prepareParams(fullWidth, fullHeight, focalLength, focalLength35mm, pProf->sensorFormatFactor, swapXY, mirrorX, mirrorY); } + + enableCA = !vignette && focusDist>0; } void LCPMapper::correctDistortion(double& x, double& y) const { @@ -164,6 +166,8 @@ void LCPMapper::correctDistortion(double& x, double& y) const { } void LCPMapper::correctCA(double& x, double& y, int channel) const { + if (!enableCA) return; + double rsqr, xgreen, ygreen; // First calc the green channel like normal distortion diff --git a/rtengine/lcp.h b/rtengine/lcp.h index 90061124c..4986094dc 100644 --- a/rtengine/lcp.h +++ b/rtengine/lcp.h @@ -114,6 +114,8 @@ namespace rtengine { LCPModelCommon chrom[3]; // in order RedGreen/Green/BlueGreen public: + bool enableCA; // is the mapper capable if CA correction? + // precalculates the mapper. LCPMapper(LCPProfile* pProf, float focalLength, float focalLength35mm, float focusDist, float aperture, bool vignette, bool useCADistP, int fullWidth, int fullHeight, const CoarseTransformParams& coarse, int rawRotationDeg);