profile-based CA correction applied during 1:1 preview

This commit is contained in:
Alberto Griggio 2017-10-29 21:41:19 +01:00
parent 830fd6fdbb
commit 5a05b04e09
6 changed files with 29 additions and 17 deletions

View File

@ -58,7 +58,7 @@ class ImProcFunctions
TRANSFORM_PREVIEW, TRANSFORM_PREVIEW,
TRANSFORM_HIGH_QUALITY, TRANSFORM_HIGH_QUALITY,
TRANSFORM_HIGH_QUALITY_FULLIMAGE, 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 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); 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);

View File

@ -329,21 +329,23 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed,
std::unique_ptr<Imagefloat> tmpimg; std::unique_ptr<Imagefloat> tmpimg;
if (!needsCA() && scale != 1) { if (!needsCA() && scale != 1) {
mode = TRANSFORM_PREVIEW; mode = TRANSFORM_PREVIEW;
} else if (!fullImage) {
mode = TRANSFORM_HIGH_QUALITY;
} else { } 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 // agriggio: CA correction via the lens profile has to be
// performed before all the other transformations (except for the // performed before all the other transformations (except for the
// coarse rotation/flipping). In order to not change the code too // coarse rotation/flipping). In order to not change the code too
// much, I simply introduced a new mode // 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 // profile-based CA correction. So, the correction in this case
// occurs in two steps, using an intermediate temporary // occurs in two steps, using an intermediate temporary
// image. There's room for optimization of course... // image. There's room for optimization of course...
if (pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable()) { if (pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable()) {
tmpimg.reset(new Imagefloat(transformed->getWidth(), transformed->getHeight())); tmpimg.reset(new Imagefloat(original->getWidth(), original->getHeight()));
transformGeneral(TRANSFORM_HIGH_QUALITY_FULLIMAGE_CA, original, tmpimg.get(), cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap.get()); transformGeneral(TRANSFORM_HIGH_QUALITY_CA, original, tmpimg.get(), 0, 0, 0, 0, fW, fH, fW, fH, pLCPMap.get());
original = tmpimg.get(); original = tmpimg.get();
} }
} }
@ -750,7 +752,7 @@ void ImProcFunctions::transformGeneral(ImProcFunctions::TransformMode mode, Imag
bool enableDistortion = needsDistortion(); bool enableDistortion = needsDistortion();
switch (mode) { switch (mode) {
case ImProcFunctions::TRANSFORM_HIGH_QUALITY_FULLIMAGE_CA: case ImProcFunctions::TRANSFORM_HIGH_QUALITY_CA:
enableLCPDist = false; enableLCPDist = false;
enablePerspective = false; enablePerspective = false;
enableDistortion = false; enableDistortion = false;
@ -763,9 +765,9 @@ void ImProcFunctions::transformGeneral(ImProcFunctions::TransformMode mode, Imag
enableLCPCA = false; enableLCPCA = false;
break; break;
case ImProcFunctions::TRANSFORM_HIGH_QUALITY: case ImProcFunctions::TRANSFORM_HIGH_QUALITY:
if (enableLCPDist) { // if (enableLCPDist) {
enableLCPCA = false; enableLCPCA = false;
} // }
break; break;
case ImProcFunctions::TRANSFORM_PREVIEW: case ImProcFunctions::TRANSFORM_PREVIEW:
enableLCPCA = false; 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 = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0;
double ascale = 1.0; double ascale = 1.0;
if (mode != ImProcFunctions::TRANSFORM_HIGH_QUALITY_FULLIMAGE_CA && if (mode != ImProcFunctions::TRANSFORM_HIGH_QUALITY_CA &&
params->commonTrans.autofill) { params->commonTrans.autofill) {
ascale = getTransformAutoFill (oW, oH, pLCPMap); ascale = getTransformAutoFill (oW, oH, pLCPMap);
} }
@ -912,7 +914,7 @@ void ImProcFunctions::transformGeneral(ImProcFunctions::TransformMode mode, Imag
// LCP CA // LCP CA
if (enableLCPCA) { if (enableLCPCA) {
pLCPMap->correctCA (Dx, Dy, c); pLCPMap->correctCA (Dx, Dy, cx, cy, c);
} }
// Extract integer and fractions of source screen coordinates // Extract integer and fractions of source screen coordinates

View File

@ -1077,12 +1077,15 @@ void rtengine::LCPMapper::correctDistortion(double &x, double &y, int cx, int cy
y -= cy * scale; 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) { if (!enableCA) {
return; return;
} }
x += cx;
y += cy;
double xgreen, ygreen; double xgreen, ygreen;
// First calc the green channel like normal distortion // 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; 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; 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 SSEFUNCTION void rtengine::LCPMapper::processVignetteLine(int width, int y, float* line) const

View File

@ -164,7 +164,7 @@ public:
virtual ~LensCorrection() {} virtual ~LensCorrection() {}
virtual void correctDistortion(double &x, double &y, int cx, int cy, double scale) const = 0; virtual void correctDistortion(double &x, double &y, int cx, int cy, double scale) const = 0;
virtual bool isCACorrectionAvailable() 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 processVignetteLine(int width, int y, float *line) const = 0;
virtual void processVignetteLine3Channels(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 void correctDistortion(double &x, double &y, int cx, int cy, double scale) const; // MUST be the first stage
bool isCACorrectionAvailable() const; 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 processVignetteLine(int width, int y, float* line) const;
void processVignetteLine3Channels(int width, int y, float* line) const; void processVignetteLine3Channels(int width, int y, float* line) const;

View File

@ -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); 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 // 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 // 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 // channels. We could consider caching the info to speed this up
x += cx;
y += cy;
float pos[6]; float pos[6];
if (swap_xy_) { if (swap_xy_) {
@ -95,6 +97,8 @@ void LFModifier::correctCA(double &x, double &y, int channel) const
if (swap_xy_) { if (swap_xy_) {
std::swap(x, y); std::swap(x, y);
} }
x -= cx;
y -= cy;
} }

View File

@ -44,7 +44,7 @@ public:
void correctDistortion(double &x, double &y, int cx, int cy, double scale) const override; void correctDistortion(double &x, double &y, int cx, int cy, double scale) const override;
bool isCACorrectionAvailable() 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 processVignetteLine(int width, int y, float *line) const override;
void processVignetteLine3Channels(int width, int y, float *line) const override; void processVignetteLine3Channels(int width, int y, float *line) const override;