diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index ffce66ed9..4e944d9fd 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -1076,6 +1076,17 @@ void Crop::freeAll () cropAllocated = false; } + +namespace { + +bool check_need_larger_crop_for_lcp_distortion(const ProcParams ¶ms) +{ + return (params.lensProf.lcpFile.length() > 0 && + params.lensProf.useDist); +} + +} // namespace + /** @brief Handles crop's image buffer reallocation and trigger sizeChanged of SizeListener[s] * If the scale changes, this method will free all buffers and reallocate ones of the new size. * It will then tell to the SizeListener that size has changed (sizeChanged) @@ -1130,6 +1141,23 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte int orW, orH; parent->imgsrc->getSize (cp, orW, orH); + if (check_need_larger_crop_for_lcp_distortion(parent->params)) { + int fW, fH; + parent->imgsrc->getFullSize(fW, fH); + double dW = double(fW) * 0.15; // TODO - this is hardcoded ATM! + double dH = double(fH) * 0.15; // this is an estimate of the max + // distortion relative to the image + // size. BUT IS 15% REALLY ENOUGH? + // In fact, is there a better way?? + orW = min(int(orW + dW), fW); + orH = min(int(orH + dH), fH); + trafx = max(int(orx - dW/2.0), 0); + trafy = max(int(ory - dH/2.0), 0); + } else { + trafx = orx; + trafy = ory; + } + int cw = skips(bw, skip); int ch = skips(bh, skip); @@ -1226,8 +1254,6 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte cropx = bx1; cropy = by1; - trafx = orx; - trafy = ory; if (settings->verbose) { printf ("setsizes ends\n"); diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 34aab1c7b..abbb5d77d 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -83,6 +83,19 @@ float normn(float a, float b, int n) return pow_F(pown(a, n) + pown(b, n), 1.f / n); } } + +void correct_distortion(const rtengine::LCPMapper *lcp, double &x, double &y, + int cx, int cy) +{ + assert(lcp); + + x += cx; + y += cy; + lcp->correctDistortion(x, y); + x -= cx; + y -= cy; +} + } namespace rtengine @@ -142,7 +155,7 @@ bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, double x_d = src[i].x, y_d = src[i].y; if (pLCPMap && params->lensProf.useDist) { - pLCPMap->correctDistortion(x_d, y_d); // must be first transform + correct_distortion(pLCPMap, x_d, y_d, 0, 0); } y_d = ascale * (y_d - h2); @@ -297,8 +310,12 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, if (needsLCP()) { // don't check focal length to allow distortion correction for lenses without chip LCPProfile *pLCPProf = lcpStore->getProfile(params->lensProf.lcpFile); - if (pLCPProf) pLCPMap = new LCPMapper(pLCPProf, focalLen, focalLen35mm, focusDist, 0, false, params->lensProf.useDist, - original->getWidth(), original->getHeight(), params->coarse, rawRotationDeg); + if (pLCPProf) { + pLCPMap = new LCPMapper(pLCPProf, focalLen, focalLen35mm, + focusDist, 0, false, + params->lensProf.useDist, + oW, oH, params->coarse, rawRotationDeg); + } } if (!(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP()) && (needsVignetting() || needsPCVignetting() || needsGradient())) { @@ -705,7 +722,6 @@ void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat* 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; double h2 = (double) oH / 2.0 - 0.5; @@ -762,11 +778,11 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr oH * tan(hpalpha) * sqrt(SQR(4 * maxRadius) + SQR(oH * tan(hpalpha)))) / (SQR(maxRadius) * 8))); double hpcospt = (hpdeg >= 0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); - double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, fullImage ? pLCPMap : nullptr) : 1.0; + double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, true /*fullImage*/ ? pLCPMap : nullptr) : 1.0; // smaller crop images are a problem, so only when processing fully bool enableLCPCA = pLCPMap && params->lensProf.useCA && fullImage && pLCPMap->enableCA; - bool enableLCPDist = pLCPMap && params->lensProf.useDist && fullImage; + bool enableLCPDist = pLCPMap && params->lensProf.useDist; // && fullImage; if (enableLCPCA) { enableLCPDist = false; @@ -783,7 +799,7 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr double x_d = x, y_d = y; if (enableLCPDist) { - pLCPMap->correctDistortion(x_d, y_d); // must be first transform + correct_distortion(pLCPMap, x_d, y_d, cx, cy); // must be first transform } x_d = ascale * (x_d + cx - w2); // centering x coord & scale @@ -960,7 +976,7 @@ void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transf double x_d = x, y_d = y; if (pLCPMap && params->lensProf.useDist) { - pLCPMap->correctDistortion(x_d, y_d); // must be first transform + correct_distortion(pLCPMap, x_d, y_d, cx, cy); // must be first transform } y_d = ascale * (y_d + cy - h2); // centering y coord & scale