profile-based CA correction applied during 1:1 preview
This commit is contained in:
parent
830fd6fdbb
commit
5a05b04e09
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user