merge with dev

This commit is contained in:
Desmis 2020-01-13 08:33:45 +01:00
commit ba7a61c391
20 changed files with 489 additions and 159 deletions

View File

@ -787,6 +787,7 @@ HISTORY_MSG_SH_COLORSPACE;S/H - Colorspace
HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light
HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength
HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor
HISTORY_MSG_TRANS_Method;Geometry - Method
HISTORY_MSG_WAVCLARI;Clarity
HISTORY_MSG_WAVUSHAMET;Clarity method
HISTORY_MSG_WAVMERGEL;Merge L
@ -1786,6 +1787,8 @@ TP_LABCURVE_RSTPRO_TOOLTIP;Works on the Chromaticity slider and the CC curve.
TP_LENSGEOM_AUTOCROP;Auto-Crop
TP_LENSGEOM_FILL;Auto-fill
TP_LENSGEOM_LABEL;Lens / Geometry
TP_LENSGEOM_LIN;Linear
TP_LENSGEOM_LOG;Logarithmic
TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected
TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file
TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected

View File

@ -131,6 +131,11 @@ inline void gauss3x3div (float** RESTRICT src, float** RESTRICT dst, float** RES
const float c00 = kernel[1][1];
for (int i = 1; i < tileSize - 1; i++) {
#if defined(__clang__)
#pragma clang loop vectorize(assume_safety)
#elif defined(__GNUC__)
#pragma GCC ivdep
#endif
for (int j = 1; j < tileSize - 1; j++) {
const float val = c11 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) +
c10 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) +
@ -151,6 +156,11 @@ inline void gauss5x5div (float** RESTRICT src, float** RESTRICT dst, float** RES
for (int i = 2; i < tileSize - 2; ++i) {
// I tried hand written SSE code but gcc vectorizes better
#if defined(__clang__)
#pragma clang loop vectorize(assume_safety)
#elif defined(__GNUC__)
#pragma GCC ivdep
#endif
for (int j = 2; j < tileSize - 2; ++j) {
const float val = c21 * ((src[i - 2][j - 1] + src[i - 2][j + 1]) + (src[i - 1][j - 2] + src[i - 1][j + 2]) + (src[i + 1][j - 2] + src[i + 1][j + 2]) + (src[i + 2][j - 1] + src[i + 2][j + 1])) +
c20 * (src[i - 2][j] + src[i][j - 2] + src[i][j + 2] + src[i + 2][j]) +
@ -177,6 +187,11 @@ inline void gauss7x7div(float** RESTRICT src, float** RESTRICT dst, float** REST
for (int i = 3; i < tileSize - 3; ++i) {
// I tried hand written SSE code but gcc vectorizes better
#if defined(__clang__)
#pragma clang loop vectorize(assume_safety)
#elif defined(__GNUC__)
#pragma GCC ivdep
#endif
for (int j = 3; j < tileSize - 3; ++j) {
const float val = c31 * ((src[i - 3][j - 1] + src[i - 3][j + 1]) + (src[i - 1][j - 3] + src[i - 1][j + 3]) + (src[i + 1][j - 3] + src[i + 1][j + 3]) + (src[i + 3][j - 1] + src[i + 3][j + 1])) +
c30 * (src[i - 3][j] + src[i][j - 3] + src[i][j + 3] + src[i + 3][j]) +
@ -199,6 +214,11 @@ inline void gauss3x3mult(float** RESTRICT src, float** RESTRICT dst, const int t
const float c00 = kernel[1][1];
for (int i = 1; i < tileSize - 1; i++) {
#if defined(__clang__)
#pragma clang loop vectorize(assume_safety)
#elif defined(__GNUC__)
#pragma GCC ivdep
#endif
for (int j = 1; j < tileSize - 1; j++) {
const float val = c11 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) +
c10 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) +
@ -220,6 +240,11 @@ inline void gauss5x5mult (float** RESTRICT src, float** RESTRICT dst, const int
for (int i = 2; i < tileSize - 2; ++i) {
// I tried hand written SSE code but gcc vectorizes better
#if defined(__clang__)
#pragma clang loop vectorize(assume_safety)
#elif defined(__GNUC__)
#pragma GCC ivdep
#endif
for (int j = 2; j < tileSize - 2; ++j) {
const float val = c21 * ((src[i - 2][j - 1] + src[i - 2][j + 1]) + (src[i - 1][j - 2] + src[i - 1][j + 2]) + (src[i + 1][j - 2] + src[i + 1][j + 2]) + (src[i + 2][j - 1] + src[i + 2][j + 1])) +
c20 * (src[i - 2][j] + src[i][j - 2] + src[i][j + 2] + src[i + 2][j]) +
@ -246,6 +271,11 @@ inline void gauss7x7mult(float** RESTRICT src, float** RESTRICT dst, const int t
for (int i = 3; i < tileSize - 3; ++i) {
// I tried hand written SSE code but gcc vectorizes better
#if defined(__clang__)
#pragma clang loop vectorize(assume_safety)
#elif defined(__GNUC__)
#pragma GCC ivdep
#endif
for (int j = 3; j < tileSize - 3; ++j) {
const float val = c31 * ((src[i - 3][j - 1] + src[i - 3][j + 1]) + (src[i - 1][j - 3] + src[i - 1][j + 3]) + (src[i + 1][j - 3] + src[i + 1][j + 3]) + (src[i + 3][j - 1] + src[i + 3][j + 1])) +
c30 * (src[i - 3][j] + src[i][j - 3] + src[i][j + 3] + src[i + 3][j]) +
@ -495,28 +525,25 @@ float calcRadiusXtrans(const float * const *rawData, int W, int H, float lowerLi
bool checkForStop(float** tmpIThr, float** iterCheck, int fullTileSize, int border)
{
bool stopped = false;
for (int ii = border; !stopped && ii < fullTileSize - border; ++ii) {
for (int ii = border; ii < fullTileSize - border; ++ii) {
#ifdef __SSE2__
for (int jj = border; jj < fullTileSize - border; jj += 4) {
if (_mm_movemask_ps((vfloat)vmaskf_lt(LVFU(tmpIThr[ii][jj]), LVFU(iterCheck[ii - border][jj - border])))) {
stopped = true;
break;
if (UNLIKELY(_mm_movemask_ps((vfloat)vmaskf_lt(LVFU(tmpIThr[ii][jj]), LVFU(iterCheck[ii - border][jj - border]))))) {
return true;
}
}
#else
for (int jj = border; jj < fullTileSize - border; ++jj) {
if (tmpIThr[ii][jj] < iterCheck[ii - border][jj - border]) {
stopped = true;
break;
return true;
}
}
#endif
}
return stopped;
return false;
}
void CaptureDeconvSharpening (float ** clipmask, float** luminance, float** oldLuminance, const float * const * blend, int W, int H, double sigma, double sigmaCornerOffset, int iterations, bool checkIterStop, rtengine::ProgressListener* plistener, double startVal, double endVal)
void CaptureDeconvSharpening (float** luminance, const float* const * oldLuminance, const float * const * blend, int W, int H, double sigma, double sigmaCornerOffset, int iterations, bool checkIterStop, rtengine::ProgressListener* plistener, double startVal, double endVal)
{
BENCHFUN
const bool is5x5 = (sigma <= 0.84 && sigmaCornerOffset == 0.0);
@ -541,6 +568,7 @@ BENCHFUN
double progress = startVal;
const double progressStep = (endVal - startVal) * rtengine::SQR(tileSize) / (W * H);
constexpr float minBlend = 0.01f;
#ifdef _OPENMP
@ -567,14 +595,14 @@ BENCHFUN
if (checkIterStop) {
for (int k = 0, ii = endOfCol ? H - fullTileSize + border : i; k < tileSize; ++k, ++ii) {
for (int l = 0, jj = endOfRow ? W - fullTileSize + border : j; l < tileSize; ++l, ++jj) {
iterCheck[k][l] = oldLuminance[ii][jj] * clipmask[ii][jj] * 0.5f;
maxVal = std::max(maxVal, clipmask[ii][jj]);
iterCheck[k][l] = oldLuminance[ii][jj] * blend[ii][jj] * 0.5f;
maxVal = std::max(maxVal, blend[ii][jj]);
}
}
} else {
for (int k = 0, ii = endOfCol ? H - fullTileSize + border : i; k < tileSize; ++k, ++ii) {
for (int l = 0, jj = endOfRow ? W - fullTileSize + border : j; l < tileSize; ++l, ++jj) {
maxVal = std::max(maxVal, clipmask[ii][jj]);
maxVal = std::max(maxVal, blend[ii][jj]);
}
}
}
@ -593,14 +621,14 @@ BENCHFUN
if (checkIterStop) {
for (int ii = 0; ii < tileSize; ++ii) {
for (int jj = 0; jj < tileSize; ++jj) {
iterCheck[ii][jj] = oldLuminance[i + ii][j + jj] * clipmask[i + ii][j + jj] * 0.5f;
maxVal = std::max(maxVal, clipmask[i + ii][j + jj]);
iterCheck[ii][jj] = oldLuminance[i + ii][j + jj] * blend[i + ii][j + jj] * 0.5f;
maxVal = std::max(maxVal, blend[i + ii][j + jj]);
}
}
} else {
for (int ii = 0; ii < tileSize; ++ii) {
for (int jj = 0; jj < tileSize; ++jj) {
maxVal = std::max(maxVal, clipmask[i + ii][j + jj]);
maxVal = std::max(maxVal, blend[i + ii][j + jj]);
}
}
}
@ -615,23 +643,22 @@ BENCHFUN
}
}
}
bool stopped = false;
if (is3x3) {
for (int k = 0; k < iterations && !stopped; ++k) {
for (int k = 0; k < iterations; ++k) {
// apply 3x3 gaussian blur and divide luminance by result of gaussian blur
gauss3x3div(tmpIThr, tmpThr, lumThr, fullTileSize, kernel3);
gauss3x3mult(tmpThr, tmpIThr, fullTileSize, kernel3);
if (checkIterStop) {
stopped = checkForStop(tmpIThr, iterCheck, fullTileSize, border);
if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) {
break;
}
}
} else if (is5x5) {
for (int k = 0; k < iterations && !stopped; ++k) {
for (int k = 0; k < iterations; ++k) {
// apply 5x5 gaussian blur and divide luminance by result of gaussian blur
gauss5x5div(tmpIThr, tmpThr, lumThr, fullTileSize, kernel5);
gauss5x5mult(tmpThr, tmpIThr, fullTileSize, kernel5);
if (checkIterStop) {
stopped = checkForStop(tmpIThr, iterCheck, fullTileSize, border);
if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) {
break;
}
}
} else {
@ -642,34 +669,34 @@ BENCHFUN
if (sigmaTile > 0.84) { // have to use 7x7 kernel
float lkernel7[7][7];
compute7x7kernel(static_cast<float>(sigma) + distanceFactor * distance, lkernel7);
for (int k = 0; k < iterations && !stopped; ++k) {
for (int k = 0; k < iterations; ++k) {
// apply 7x7 gaussian blur and divide luminance by result of gaussian blur
gauss7x7div(tmpIThr, tmpThr, lumThr, fullTileSize, lkernel7);
gauss7x7mult(tmpThr, tmpIThr, fullTileSize, lkernel7);
if (checkIterStop) {
stopped = checkForStop(tmpIThr, iterCheck, fullTileSize, border);
if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) {
break;
}
}
} else { // can use 5x5 kernel
float lkernel7[5][5];
compute5x5kernel(static_cast<float>(sigma) + distanceFactor * distance, lkernel7);
for (int k = 0; k < iterations && !stopped; ++k) {
float lkernel5[5][5];
compute5x5kernel(static_cast<float>(sigma) + distanceFactor * distance, lkernel5);
for (int k = 0; k < iterations; ++k) {
// apply 7x7 gaussian blur and divide luminance by result of gaussian blur
gauss5x5div(tmpIThr, tmpThr, lumThr, fullTileSize, lkernel7);
gauss5x5mult(tmpThr, tmpIThr, fullTileSize, lkernel7);
if (checkIterStop) {
stopped = checkForStop(tmpIThr, iterCheck, fullTileSize, border);
gauss5x5div(tmpIThr, tmpThr, lumThr, fullTileSize, lkernel5);
gauss5x5mult(tmpThr, tmpIThr, fullTileSize, lkernel5);
if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) {
break;
}
}
}
}
} else {
for (int k = 0; k < iterations && !stopped; ++k) {
for (int k = 0; k < iterations; ++k) {
// apply 7x7 gaussian blur and divide luminance by result of gaussian blur
gauss7x7div(tmpIThr, tmpThr, lumThr, fullTileSize, kernel7);
gauss7x7mult(tmpThr, tmpIThr, fullTileSize, kernel7);
if (checkIterStop) {
stopped = checkForStop(tmpIThr, iterCheck, fullTileSize, border);
if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) {
break;
}
}
}
@ -689,12 +716,12 @@ BENCHFUN
}
}
if (plistener) {
if (++progresscounter % 16 == 0) {
if (++progresscounter % 32 == 0) {
#ifdef _OPENMP
#pragma omp critical(csprogress)
#endif
{
progress += 16.0 * progressStep;
progress += 32.0 * progressStep;
progress = rtengine::min(progress, endVal);
plistener->setProgress(progress);
}
@ -721,6 +748,7 @@ void RawImageSource::captureSharpening(const procparams::CaptureSharpeningParams
plistener->setProgress(0.0);
}
BENCHFUN
constexpr float xyz_rgb[3][3] = { // XYZ from RGB
{ 0.412453, 0.357580, 0.180423 },
{ 0.212671, 0.715160, 0.072169 },
@ -799,8 +827,7 @@ BENCHFUN
plistener->setProgress(0.1);
}
array2D<float>& blend = red; // red will be overridden anyway => we can use its buffer to store the blend mask
buildBlendMask(L, blend, W, H, contrast, sharpeningParams.autoContrast, clipMask);
buildBlendMask(L, clipMask, W, H, contrast, sharpeningParams.autoContrast, clipMask);
if (plistener) {
plistener->setProgress(0.2);
}
@ -810,7 +837,7 @@ BENCHFUN
#endif
for (int i = 0; i < H; ++i) {
for (int j = 0; j < W; ++j) {
red[i][j] = green[i][j] = blue[i][j] = blend[i][j] * 16384.f;
red[i][j] = green[i][j] = blue[i][j] = clipMask[i][j] * 16384.f;
}
}
if (plistener) {
@ -847,18 +874,18 @@ BENCHFUN
if (plistener) {
plistener->setProgress(0.1);
}
// calculate contrast based blend factors to reduce sharpening in regions with low contrast
array2D<float>& blend = clipMask; // we can share blend and clipMask buffer here
buildBlendMask(L, blend, W, H, contrast, sharpeningParams.autoContrast, clipMask);
buildBlendMask(L, clipMask, W, H, contrast, sharpeningParams.autoContrast, clipMask);
if (plistener) {
plistener->setProgress(0.2);
}
conrastThreshold = contrast * 100.f;
CaptureDeconvSharpening(clipMask, YNew, YOld, blend, W, H, radius, sharpeningParams.deconvradiusOffset, sharpeningParams.deconviter, sharpeningParams.deconvitercheck, plistener, 0.2, 0.9);
CaptureDeconvSharpening(YNew, YOld, clipMask, W, H, radius, sharpeningParams.deconvradiusOffset, sharpeningParams.deconviter, sharpeningParams.deconvitercheck, plistener, 0.2, 0.9);
if (plistener) {
plistener->setProgress(0.9);
}
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 16)
#endif
@ -866,7 +893,7 @@ BENCHFUN
int j = 0;
#ifdef __SSE2__
for (; j < W - 3; j += 4) {
const vfloat factor = vmaxf(LVFU(YNew[i][j]), ZEROV) / vmaxf(LVFU(YOld[i][j]), F2V(0.00001f));
const vfloat factor = LVFU(YNew[i][j]) / vmaxf(LVFU(YOld[i][j]), F2V(0.00001f));
STVFU(red[i][j], LVFU(redVals[i][j]) * factor);
STVFU(green[i][j], LVFU(greenVals[i][j]) * factor);
STVFU(blue[i][j], LVFU(blueVals[i][j]) * factor);
@ -874,7 +901,7 @@ BENCHFUN
#endif
for (; j < W; ++j) {
const float factor = std::max(YNew[i][j], 0.f) / std::max(YOld[i][j], 0.00001f);
const float factor = YNew[i][j] / std::max(YOld[i][j], 0.00001f);
red[i][j] = redVals[i][j] * factor;
green[i][j] = greenVals[i][j] * factor;
blue[i][j] = blueVals[i][j] * factor;

View File

@ -174,8 +174,6 @@ void Crop::update(int todo)
int widIm = parent->fw;//full image
int heiIm = parent->fh;
bool needstransform = parent->ipf.needsTransform();
if (todo & (M_INIT | M_LINDENOISE | M_HDR)) {
MyMutex::MyLock lock(parent->minit); // Also used in improccoord
@ -767,6 +765,7 @@ void Crop::update(int todo)
}
}
const bool needstransform = parent->ipf.needsTransform(skips(parent->fw, skip), skips(parent->fh, skip), parent->imgsrc->getRotateDegree(), parent->imgsrc->getMetaData());
// transform
if (needstransform || ((todo & (M_TRANSFORM | M_RGBCURVE)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled)) {
if (!transCrop) {
@ -785,10 +784,7 @@ void Crop::update(int todo)
baseCrop = transCrop;
}
} else {
if (transCrop) {
delete transCrop;
}
transCrop = nullptr;
}
@ -1338,6 +1334,7 @@ bool Crop::setCropSizes(int rcx, int rcy, int rcw, int rch, int skip, bool inter
parent->ipf.transCoord(parent->fw, parent->fh, bx1, by1, bw, bh, orx, ory, orw, orh);
if (parent->ipf.needsTransform(skips(parent->fw, skip), skips(parent->fh, skip), parent->imgsrc->getRotateDegree(), parent->imgsrc->getMetaData())) {
if (check_need_larger_crop_for_lcp_distortion(parent->fw, parent->fh, orx, ory, orw, orh, *parent->params)) {
// TODO - this is an estimate of the max distortion relative to the image size. ATM it is hardcoded to be 15%, which seems enough. If not, need to revise
int dW = int (double (parent->fw) * 0.15 / (2 * skip));
@ -1372,7 +1369,7 @@ bool Crop::setCropSizes(int rcx, int rcy, int rcw, int rch, int skip, bool inter
orw = min(x2 - x1, parent->fw - orx);
orh = min(y2 - y1, parent->fh - ory);
}
}
leftBorder = skips(rqx1 - bx1, skip);
upperBorder = skips(rqy1 - by1, skip);

View File

@ -106,7 +106,18 @@ void guidedFilter(const array2D<float> &guide, const array2D<float> &src, array2
const auto f_subsample =
[multithread](array2D<float> &d, const array2D<float> &s) -> void
{
if (d.width() == s.width() && d.height() == s.height()) {
#ifdef _OPENMP
#pragma omp parallel for if (multithread)
#endif
for (int y = 0; y < s.height(); ++y) {
for (int x = 0; x < s.width(); ++x) {
d[y][x] = s[y][x];
}
}
} else {
rescaleBilinear(s, d, multithread);
}
};
const auto f_mean =

View File

@ -551,7 +551,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
oprevi = orig_prev;
// Remove transformation if unneeded
bool needstransform = ipf.needsTransform();
bool needstransform = ipf.needsTransform(fw, fh, imgsrc->getRotateDegree(), imgsrc->getMetaData());
if ((needstransform || ((todo & (M_TRANSFORM | M_RGBCURVE)) && params->dirpyrequalizer.cbdlMethod == "bef" && params->dirpyrequalizer.enabled && !params->colorappearance.enabled))) {
assert(oprevi);
@ -1565,7 +1565,7 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a
imgsrc->getImage(currWB, tr, im, pp, ppar.toneCurve, ppar.raw);
ImProcFunctions ipf(&ppar, true);
if (ipf.needsTransform()) {
if (ipf.needsTransform(fW, fH, imgsrc->getRotateDegree(), imgsrc->getMetaData())) {
Imagefloat* trImg = new Imagefloat(fW, fH);
ipf.transform(im, trImg, 0, 0, 0, 0, fW, fH, fW, fH,
imgsrc->getMetaData(), imgsrc->getRotateDegree(), true);

View File

@ -84,8 +84,8 @@ class ImProcFunctions
void calcVignettingParams(int oW, int oH, const procparams::VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul);
void transformLuminanceOnly(Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH);
void transformGeneral(bool highQuality, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap);
void transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap);
void transformGeneral(bool highQuality, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap, bool useOriginalBuffer);
void transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap, bool useOriginalBuffer);
bool needsCA() const;
bool needsDistortion() const;
@ -119,7 +119,7 @@ public:
}
void setScale(double iscale);
bool needsTransform() const;
bool needsTransform(int oW, int oH, int rawRotationDeg, const FramesMetaData *metadata) const;
bool needsPCVignetting() const;
void firstAnalysis(const Imagefloat* const working, const procparams::ProcParams &params, LUTu & vhist16);
@ -156,7 +156,7 @@ public:
// void colorCurve (LabImage* lold, LabImage* lnew);
void sharpening(LabImage* lab, const procparams::SharpeningParams &sharpenParam, bool showMask = false);
void sharpeningcam(CieImage* ncie, float** buffer, bool showMask = false);
void transform(Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, int rawRotationDeg, bool fullImage);
void transform(Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, int rawRotationDeg, bool fullImage, bool useOriginalBuffer = false);
float resizeScale(const procparams::ProcParams* params, int fw, int fh, int &imw, int &imh);
void lab2monitorRgb(LabImage* lab, Image8* image);
void resize(Imagefloat* src, Imagefloat* dst, float dScale);

View File

@ -86,6 +86,29 @@ float normn (float a, float b, int n)
}
}
void logEncode(rtengine::Imagefloat *src, rtengine::Imagefloat *dest, bool multiThread) {
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 16) if(multiThread)
#endif
for (int y = 0; y < src->getHeight(); ++y) {
int x = 0;
#ifdef __SSE2__
for (; x < src->getWidth() - 3; x += 4) {
STVFU(dest->r(y, x), xlogf1(LVFU(src->r(y, x))));
STVFU(dest->g(y, x), xlogf1(LVFU(src->g(y, x))));
STVFU(dest->b(y, x), xlogf1(LVFU(src->b(y, x))));
}
#endif
for (; x < src->getWidth(); ++x) {
dest->r(y, x) = xlogf1(src->r(y, x));
dest->g(y, x) = xlogf1(src->g(y, x));
dest->b(y, x) = xlogf1(src->b(y, x));
}
}
}
#ifdef __SSE2__
inline void interpolateTransformCubic(rtengine::Imagefloat* src, int xs, int ys, float Dx, float Dy, float &r, float &g, float &b, float mul)
{
@ -111,6 +134,33 @@ inline void interpolateTransformCubic(rtengine::Imagefloat* src, int xs, int ys,
g = vhadd(weight * gv);
b = vhadd(weight * bv);
}
inline void interpolateTransformCubicLog(rtengine::Imagefloat* src, int xs, int ys, float Dx, float Dy, float &r, float &g, float &b, float mul)
{
constexpr float A = -0.85f;
// Vertical
const float t1Vert = A * (Dy - Dy * Dy);
const float t2Vert = (3.f - 2.f * Dy) * Dy * Dy;
const vfloat w3Vert = F2V(t1Vert * Dy);
const vfloat w2Vert = F2V(t1Vert * Dy - t1Vert + t2Vert);
const vfloat w1Vert = F2V(1.f - (t1Vert * Dy) - t2Vert);
const vfloat w0Vert = F2V(t1Vert - (t1Vert * Dy));
const vfloat rv = (w0Vert * LVFU(src->r(ys, xs)) + w1Vert * LVFU(src->r(ys + 1, xs))) + (w2Vert * LVFU(src->r(ys + 2, xs)) + w3Vert * LVFU(src->r(ys + 3, xs)));
const vfloat gv = (w0Vert * LVFU(src->g(ys, xs)) + w1Vert * LVFU(src->g(ys + 1, xs))) + (w2Vert * LVFU(src->g(ys + 2, xs)) + w3Vert * LVFU(src->g(ys + 3, xs)));
const vfloat bv = (w0Vert * LVFU(src->b(ys, xs)) + w1Vert * LVFU(src->b(ys + 1, xs))) + (w2Vert * LVFU(src->b(ys + 2, xs)) + w3Vert * LVFU(src->b(ys + 3, xs)));
// Horizontal
const float t1Hor = A * (Dx - Dx * Dx);
const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx;
const vfloat weight = _mm_set_ps(t1Hor * Dx, t1Hor * Dx - t1Hor + t2Hor, 1.f - (t1Hor * Dx) - t2Hor, t1Hor - (t1Hor * Dx));
const vfloat tempv = _mm_setr_ps(vhadd(weight * rv), vhadd(weight * gv), vhadd(weight * bv), 0.f);
const vfloat resultv = xexpf(tempv);
r = mul * resultv[0];
g = mul * resultv[1];
b = mul * resultv[2];
}
#else
inline void interpolateTransformCubic(rtengine::Imagefloat* src, int xs, int ys, float Dx, float Dy, float &r, float &g, float &b, float mul)
{
@ -143,6 +193,38 @@ inline void interpolateTransformCubic(rtengine::Imagefloat* src, int xs, int ys,
g = mul * (gv[0] * w0Hor + gv[1] * w1Hor + gv[2] * w2Hor + gv[3] * w3Hor);
b = mul * (bv[0] * w0Hor + bv[1] * w1Hor + bv[2] * w2Hor + bv[3] * w3Hor);
}
inline void interpolateTransformCubicLog(rtengine::Imagefloat* src, int xs, int ys, float Dx, float Dy, float &r, float &g, float &b, float mul)
{
constexpr float A = -0.85f;
// Vertical
const float t1Vert = A * (Dy - Dy * Dy);
const float t2Vert = (3.f - 2.f * Dy) * Dy * Dy;
const float w3Vert = t1Vert * Dy;
const float w2Vert = t1Vert * Dy - t1Vert + t2Vert;
const float w1Vert = 1.f - (t1Vert * Dy) - t2Vert;
const float w0Vert = t1Vert - (t1Vert * Dy);
float rv[4], gv[4], bv[4];
for (int i = 0; i < 4; ++i) {
rv[i] = w0Vert * src->r(ys, xs + i) + w1Vert * src->r(ys + 1, xs + i) + w2Vert * src->r(ys + 2, xs + i) + w3Vert * src->r(ys + 3, xs + i);
gv[i] = w0Vert * src->g(ys, xs + i) + w1Vert * src->g(ys + 1, xs + i) + w2Vert * src->g(ys + 2, xs + i) + w3Vert * src->g(ys + 3, xs + i);
bv[i] = w0Vert * src->b(ys, xs + i) + w1Vert * src->b(ys + 1, xs + i) + w2Vert * src->b(ys + 2, xs + i) + w3Vert * src->b(ys + 3, xs + i);
}
// Horizontal
const float t1Hor = A * (Dx - Dx * Dx);
const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx;
const float w3Hor = t1Hor * Dx;
const float w2Hor = t1Hor * Dx - t1Hor + t2Hor;
const float w1Hor = 1.f - (t1Hor * Dx) - t2Hor;
const float w0Hor = t1Hor - (t1Hor * Dx);
r = mul * xexpf(rv[0] * w0Hor + rv[1] * w1Hor + rv[2] * w2Hor + rv[3] * w3Hor);
g = mul * xexpf(gv[0] * w0Hor + gv[1] * w1Hor + gv[2] * w2Hor + gv[3] * w3Hor);
b = mul * xexpf(bv[0] * w0Hor + bv[1] * w1Hor + bv[2] * w2Hor + bv[3] * w3Hor);
}
#endif
#ifdef __SSE2__
inline void interpolateTransformChannelsCubic(const float* const* src, int xs, int ys, float Dx, float Dy, float& dest, float mul)
@ -165,6 +247,27 @@ inline void interpolateTransformChannelsCubic(const float* const* src, int xs, i
const vfloat weight = _mm_set_ps(t1Hor * Dx, t1Hor * Dx - t1Hor + t2Hor, 1.f - (t1Hor * Dx) - t2Hor, t1Hor - (t1Hor * Dx));
dest = mul * vhadd(weight * cv);
}
inline void interpolateTransformChannelsCubicLog(const float* const* src, int xs, int ys, float Dx, float Dy, float& dest, float mul)
{
constexpr float A = -0.85f;
// Vertical
const float t1Vert = A * (Dy - Dy * Dy);
const float t2Vert = (3.f - 2.f * Dy) * Dy * Dy;
const vfloat w3Vert = F2V(t1Vert * Dy);
const vfloat w2Vert = F2V(t1Vert * Dy - t1Vert + t2Vert);
const vfloat w1Vert = F2V(1.f - (t1Vert * Dy) - t2Vert);
const vfloat w0Vert = F2V(t1Vert - (t1Vert * Dy));
const vfloat cv = (w0Vert * LVFU(src[ys][xs]) + w1Vert * LVFU(src[ys + 1][xs])) + (w2Vert * LVFU(src[ys + 2][xs]) + w3Vert * LVFU(src[ys + 3][xs]));
// Horizontal
const float t1Hor = A * (Dx - Dx * Dx);
const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx;
const vfloat weight = _mm_set_ps(t1Hor * Dx, t1Hor * Dx - t1Hor + t2Hor, 1.f - (t1Hor * Dx) - t2Hor, t1Hor - (t1Hor * Dx));
dest = mul * xexpf(vhadd(weight * cv));
}
#else
inline void interpolateTransformChannelsCubic(const float* const* src, int xs, int ys, float Dx, float Dy, float& dest, float mul)
{
@ -193,6 +296,34 @@ inline void interpolateTransformChannelsCubic(const float* const* src, int xs, i
dest = mul * (cv[0] * w0Hor + cv[1] * w1Hor + cv[2] * w2Hor + cv[3] * w3Hor);
}
inline void interpolateTransformChannelsCubicLog(const float* const* src, int xs, int ys, float Dx, float Dy, float& dest, float mul)
{
constexpr float A = -0.85f;
// Vertical
const float t1Vert = A * (Dy - Dy * Dy);
const float t2Vert = (3.f - 2.f * Dy) * Dy * Dy;
const float w3Vert = t1Vert * Dy;
const float w2Vert = t1Vert * Dy - t1Vert + t2Vert;
const float w1Vert = 1.f - (t1Vert * Dy) - t2Vert;
const float w0Vert = t1Vert - (t1Vert * Dy);
float cv[4];
for (int i = 0; i < 4; ++i) {
cv[i] = w0Vert * src[ys][xs + i] + w1Vert * src[ys + 1][xs + i] + w2Vert * src[ys + 2][xs + i] + w3Vert * src[ys + 3][xs + i];
}
// Horizontal
const float t1Hor = A * (Dx - Dx * Dx);
const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx;
const float w3Hor = t1Hor * Dx;
const float w2Hor = t1Hor * Dx - t1Hor + t2Hor;
const float w1Hor = 1.f - (t1Hor * Dx) - t2Hor;
const float w0Hor = t1Hor - (t1Hor * Dx);
dest = mul * xexpf(cv[0] * w0Hor + cv[1] * w1Hor + cv[2] * w2Hor + cv[3] * w3Hor);
}
#endif
}
@ -405,7 +536,7 @@ bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int&
void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH,
const FramesMetaData *metadata,
int rawRotationDeg, bool fullImage)
int rawRotationDeg, bool fullImage, bool useOriginalBuffer)
{
double focalLen = metadata->getFocalLen();
double focalLen35mm = metadata->getFocalLen35mm();
@ -453,10 +584,10 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed,
dest = tmpimg.get();
}
}
transformGeneral(highQuality, original, dest, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap.get());
transformGeneral(highQuality, original, dest, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap.get(), useOriginalBuffer);
if (highQuality && dest != transformed) {
transformLCPCAOnly(dest, transformed, cx, cy, pLCPMap.get());
transformLCPCAOnly(dest, transformed, cx, cy, pLCPMap.get(), useOriginalBuffer);
}
}
}
@ -845,8 +976,9 @@ void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat*
}
void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap)
void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap, bool useOriginalBuffer)
{
// set up stuff, depending on the mode we are
const bool enableLCPDist = pLCPMap && params->lensProf.useDist;
const bool enableCA = highQuality && needsCA();
@ -874,11 +1006,6 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I
calcPCVignetteParams(fW, fH, oW, oH, params->pcvignette, params->crop, pcv);
}
const std::array<const float* const*, 3> chOrig = {
original->r.ptrs,
original->g.ptrs,
original->b.ptrs
};
const std::array<float* const*, 3> chTrans = {
transformed->r.ptrs,
transformed->g.ptrs,
@ -922,9 +1049,27 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I
const double ascale = params->commonTrans.autofill ? getTransformAutoFill(oW, oH, pLCPMap) : 1.0;
const bool darkening = (params->vignetting.amount <= 0.0);
const bool useLog = params->commonTrans.method == "log" && highQuality;
const double centerFactorx = cx - w2;
const double centerFactory = cy - h2;
std::unique_ptr<Imagefloat> tempLog;
if (useLog) {
if (!useOriginalBuffer) {
tempLog.reset(new Imagefloat(original->getWidth(), original->getHeight()));
logEncode(original, tempLog.get(), multiThread);
original = tempLog.get();
} else {
logEncode(original, original, multiThread);
}
}
const std::array<const float* const*, 3> chOrig = {
original->r.ptrs,
original->g.ptrs,
original->b.ptrs
};
// main cycle
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 16) if(multiThread)
@ -1011,15 +1156,23 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I
if (yc > 0 && yc < original->getHeight() - 2 && xc > 0 && xc < original->getWidth() - 2) {
// all interpolation pixels inside image
if (enableCA) {
interpolateTransformChannelsCubic(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], vignmul);
} else if (!highQuality) {
if (!highQuality) {
transformed->r(y, x) = vignmul * (original->r(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r(yc, xc + 1) * Dx * (1.0 - Dy) + original->r(yc + 1, xc) * (1.0 - Dx) * Dy + original->r(yc + 1, xc + 1) * Dx * Dy);
transformed->g(y, x) = vignmul * (original->g(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g(yc, xc + 1) * Dx * (1.0 - Dy) + original->g(yc + 1, xc) * (1.0 - Dx) * Dy + original->g(yc + 1, xc + 1) * Dx * Dy);
transformed->b(y, x) = vignmul * (original->b(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b(yc, xc + 1) * Dx * (1.0 - Dy) + original->b(yc + 1, xc) * (1.0 - Dx) * Dy + original->b(yc + 1, xc + 1) * Dx * Dy);
} else if (!useLog) {
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 {
if (enableCA) {
interpolateTransformChannelsCubicLog(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], vignmul);
} else {
interpolateTransformCubicLog(original, xc - 1, yc - 1, Dx, Dy, transformed->r(y, x), transformed->g(y, x), transformed->b(y, x), vignmul);
}
}
} else {
// edge pixels
const int y1 = LIM(yc, 0, original->getHeight() - 1);
@ -1027,6 +1180,15 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I
const int x1 = LIM(xc, 0, original->getWidth() - 1);
const int x2 = LIM(xc + 1, 0, original->getWidth() - 1);
if (useLog) {
if (enableCA) {
chTrans[c][y][x] = vignmul * xexpf(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 * xexpf(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 * xexpf(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 * xexpf(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 {
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 {
@ -1035,6 +1197,7 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I
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 {
if (enableCA) {
// not valid (source pixel x,y not inside source image, etc.)
@ -1051,19 +1214,24 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I
}
void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap)
void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap, bool useOriginalBuffer)
{
assert(pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable());
const bool useLog = params->commonTrans.method == "log";
float** chOrig[3];
chOrig[0] = original->r.ptrs;
chOrig[1] = original->g.ptrs;
chOrig[2] = original->b.ptrs;
float** chTrans[3] = {transformed->r.ptrs, transformed->g.ptrs, transformed->b.ptrs};
float** chTrans[3];
chTrans[0] = transformed->r.ptrs;
chTrans[1] = transformed->g.ptrs;
chTrans[2] = transformed->b.ptrs;
std::unique_ptr<Imagefloat> tempLog;
if (useLog) {
if (!useOriginalBuffer) {
tempLog.reset(new Imagefloat(original->getWidth(), original->getHeight()));
logEncode(original, tempLog.get(), multiThread);
original = tempLog.get();
} else {
logEncode(original, original, multiThread);
}
}
float** chOrig[3] = {original->r.ptrs, original->g.ptrs, original->b.ptrs};
#ifdef _OPENMP
#pragma omp parallel for if (multiThread)
@ -1089,15 +1257,22 @@ void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *trans
// multiplier for vignetting correction
if (yc > 0 && yc < original->getHeight() - 2 && xc > 0 && xc < original->getWidth() - 2) {
// all interpolation pixels inside image
if (!useLog) {
interpolateTransformChannelsCubic(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], 1.0);
} else {
interpolateTransformChannelsCubicLog(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], 1.0);
}
} else {
// edge pixels
int y1 = LIM (yc, 0, original->getHeight() - 1);
int y2 = LIM (yc + 1, 0, original->getHeight() - 1);
int x1 = LIM (xc, 0, original->getWidth() - 1);
int x2 = LIM (xc + 1, 0, original->getWidth() - 1);
if (!useLog) {
chTrans[c][y][x] = (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 {
chTrans[c][y][x] = xexpf(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 {
// not valid (source pixel x,y not inside source image, etc.)
@ -1178,9 +1353,14 @@ bool ImProcFunctions::needsLensfun() const
return params->lensProf.useLensfun();
}
bool ImProcFunctions::needsTransform () const
bool ImProcFunctions::needsTransform (int oW, int oH, int rawRotationDeg, const FramesMetaData *metadata) const
{
return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP() || needsLensfun();
bool needsLf = needsLensfun();
if (needsLf) {
std::unique_ptr<const LensCorrection> pLCPMap = LFDatabase::getInstance()->findModifier(params->lensProf, metadata, oW, oH, params->coarse, rawRotationDeg);
needsLf = pLCPMap.get();
}
return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP() || needsLf;
}

View File

@ -1732,13 +1732,14 @@ bool CoarseTransformParams::operator !=(const CoarseTransformParams& other) cons
}
CommonTransformParams::CommonTransformParams() :
method("log"),
autofill(true)
{
}
bool CommonTransformParams::operator ==(const CommonTransformParams& other) const
{
return autofill == other.autofill;
return method == other.method && autofill == other.autofill;
}
bool CommonTransformParams::operator !=(const CommonTransformParams& other) const
@ -3344,6 +3345,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->coarse.vflip, "Coarse Transformation", "VerticalFlip", coarse.vflip, keyFile);
// Common properties for transformations
saveToKeyfile(!pedited || pedited->commonTrans.method, "Common Properties for Transformations", "Method", commonTrans.method, keyFile);
saveToKeyfile(!pedited || pedited->commonTrans.autofill, "Common Properties for Transformations", "AutoFill", commonTrans.autofill, keyFile);
// Rotation
@ -4393,6 +4395,11 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
}
if (keyFile.has_group("Common Properties for Transformations")) {
if (keyFile.has_key("Common Properties for Transformations", "Method")) {
assignFromKeyfile(keyFile, "Common Properties for Transformations", "Method", pedited, commonTrans.method, pedited->commonTrans.method);
} else {
commonTrans.method = "lin";
}
assignFromKeyfile(keyFile, "Common Properties for Transformations", "AutoFill", pedited, commonTrans.autofill, pedited->commonTrans.autofill);
}

View File

@ -837,6 +837,7 @@ struct CoarseTransformParams {
* Common transformation parameters
*/
struct CommonTransformParams {
Glib::ustring method;
bool autofill;
CommonTransformParams();

View File

@ -1247,12 +1247,12 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
ipf.ToneMapFattal02(baseImg);
// perform transform
if (ipf.needsTransform()) {
Imagefloat* trImg = new Imagefloat (fw, fh);
int origFW;
int origFH;
double tscale = 0.0;
getDimensions (origFW, origFH, tscale);
if (ipf.needsTransform(origFW * tscale + 0.5, origFH * tscale + 0.5, 0, metadata)) {
Imagefloat* trImg = new Imagefloat (fw, fh);
ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, origFW * tscale + 0.5, origFH * tscale + 0.5, metadata, 0, true); // Raw rotate degree not detectable here
delete baseImg;
baseImg = trImg;

View File

@ -880,7 +880,7 @@ private:
ipf.ToneMapFattal02(baseImg);
// perform transform (excepted resizing)
if (ipf.needsTransform()) {
if (ipf.needsTransform(fw, fh, imgsrc->getRotateDegree(), imgsrc->getMetaData())) {
Imagefloat* trImg = nullptr;
if (ipf.needsLuminanceOnly()) {
@ -890,7 +890,7 @@ private:
}
ipf.transform(baseImg, trImg, 0, 0, 0, 0, fw, fh, fw, fh,
imgsrc->getMetaData(), imgsrc->getRotateDegree(), true);
imgsrc->getMetaData(), imgsrc->getRotateDegree(), true, true);
if (trImg != baseImg) {
delete baseImg;

View File

@ -532,7 +532,7 @@ __inline double xlog(double d) {
x = x * t + 0.693147180559945286226764 * e;
if (xisinf(d)) x = rtengine::RT_INFINITY;
if (xispinf(d)) x = rtengine::RT_INFINITY;
if (d < 0) x = rtengine::RT_NAN;
if (d == 0) x = -rtengine::RT_INFINITY;
@ -864,7 +864,7 @@ __inline double xlog10(double a) {
double2 d = mul_dd(logk(a), dd(0.43429448190325176116, 6.6494347733425473126e-17));
double x = d.x + d.y;
if (xisinf(a)) x = rtengine::RT_INFINITY;
if (xispinf(a)) x = rtengine::RT_INFINITY;
if (a < 0) x = rtengine::RT_NAN;
if (a == 0) x = -rtengine::RT_INFINITY;
@ -875,7 +875,7 @@ __inline double xlog1p(double a) {
double2 d = logk2(add2_ss(a, 1));
double x = d.x + d.y;
if (xisinf(a)) x = rtengine::RT_INFINITY;
if (xispinf(a)) x = rtengine::RT_INFINITY;
if (a < -1) x = rtengine::RT_NAN;
if (a == -1) x = -rtengine::RT_INFINITY;
@ -894,6 +894,15 @@ __inline double xlog1p(double a) {
#define R_LN2f 1.442695040888963407359924681001892137426645954152985934135449406931f
#ifdef __SSE2__
__inline int xrintf(float x) {
return _mm_cvt_ss2si(_mm_set_ss(x));
}
#else
__inline int xrintf(float x) {
return x + (x < 0 ? -0.5f : 0.5f);
}
#endif
__inline int32_t floatToRawIntBits(float d) {
union {
float f;
@ -980,7 +989,7 @@ __inline float xsinf(float d) {
int q;
float u, s;
q = rint(d * rtengine::RT_1_PI_F);
q = xrintf(d * rtengine::RT_1_PI_F);
d = mlaf(q, -PI4_Af*4, d);
d = mlaf(q, -PI4_Bf*4, d);
@ -1009,7 +1018,7 @@ __inline float xcosf(float d) {
int q;
float u, s;
q = 1 + 2*rint(d * rtengine::RT_1_PI_F - 0.5f);
q = 1 + 2*xrintf(d * rtengine::RT_1_PI_F - 0.5f);
d = mlaf(q, -PI4_Af*2, d);
d = mlaf(q, -PI4_Bf*2, d);
@ -1041,7 +1050,7 @@ __inline float2 xsincosf(float d) {
float u, s, t;
float2 r;
q = rint(d * rtengine::RT_2_PI_F);
q = xrintf(d * rtengine::RT_2_PI_F);
s = d;
@ -1083,7 +1092,7 @@ __inline float xtanf(float d) {
int q;
float u, s, x;
q = rint(d * (float)(2 * rtengine::RT_1_PI));
q = xrintf(d * (float)(2 * rtengine::RT_1_PI));
x = d;
@ -1199,17 +1208,41 @@ __inline float xlogf(float d) {
x = x * t + 0.693147180559945286226764f * e;
if (xisinff(d)) x = rtengine::RT_INFINITY_F;
if (xispinff(d)) x = rtengine::RT_INFINITY_F;
if (d < 0) x = rtengine::RT_NAN_F;
if (d == 0) x = -rtengine::RT_INFINITY_F;
return x;
}
__inline float xlogf1(float d) { // does xlogf(vmaxf(d, 1.f)) but faster
float x, x2, t, m;
int e;
e = ilogbp1f(d * 0.7071f);
m = ldexpkf(d, -e);
x = (m-1.0f) / (m+1.0f);
x2 = x * x;
t = 0.2371599674224853515625f;
t = mlaf(t, x2, 0.285279005765914916992188f);
t = mlaf(t, x2, 0.400005519390106201171875f);
t = mlaf(t, x2, 0.666666567325592041015625f);
t = mlaf(t, x2, 2.0f);
x = x * t + 0.693147180559945286226764f * e;
if (xispinff(d)) x = rtengine::RT_INFINITY_F;
if (d <= 1.f) x = 0;
return x;
}
__inline float xexpf(float d) {
if(d<=-104.0f) return 0.0f;
int q = rint(d * R_LN2f);
int q = xrintf(d * R_LN2f);
float s, u;
s = mlaf(q, -L2Uf, d);

View File

@ -1253,6 +1253,30 @@ static INLINE vfloat xlogf(vfloat d) {
return x;
}
static INLINE vfloat xlogf1(vfloat d) { // does xlogf(vmaxf(d, 1.f)) but faster
vfloat x, x2, t, m;
vint2 e;
e = vilogbp1f(vmulf(d, vcast_vf_f(0.7071f)));
m = vldexpf(d, vsubi2(vcast_vi2_i(0), e));
x = vdivf(vaddf(vcast_vf_f(-1.0f), m), vaddf(vcast_vf_f(1.0f), m));
x2 = vmulf(x, x);
t = vcast_vf_f(0.2371599674224853515625f);
t = vmlaf(t, x2, vcast_vf_f(0.285279005765914916992188f));
t = vmlaf(t, x2, vcast_vf_f(0.400005519390106201171875f));
t = vmlaf(t, x2, vcast_vf_f(0.666666567325592041015625f));
t = vmlaf(t, x2, vcast_vf_f(2.0f));
x = vaddf(vmulf(x, t), vmulf(vcast_vf_f(0.693147180559945286226764f), vcast_vf_vi2(e)));
x = vself(vmaskf_ispinf(d), vcast_vf_f(INFINITYf), x);
x = vselfnotzero(vmaskf_le(d, vcast_vf_f(1.f)), x);
return x;
}
static INLINE vfloat xlogf0(vfloat d) {
vfloat x, x2, t, m;
vint2 e;

View File

@ -69,12 +69,13 @@ void EdgePreservingDecompositionUI::read(const ProcParams *pp, const ParamsEdite
setEnabled(pp->epd.enabled);
strength->set_sensitive (true);
gamma->set_sensitive (true);
/*
if(pp->wavelet.enabled) {
if(pp->wavelet.tmrs == 0) {
if(pp->wavelet.tmrs == 0 || pp->wavelet.TMmethod == "cont") {
strength->set_sensitive (true);
gamma->set_sensitive (true);
} else {
} else if(pp->wavelet.tmrs != 0 && pp->wavelet.TMmethod == "tm") {
strength->set_sensitive (false);
gamma->set_sensitive (false);
}
@ -98,12 +99,13 @@ void EdgePreservingDecompositionUI::write(ProcParams *pp, ParamsEdited *pedited)
pp->epd.reweightingIterates = reweightingIterates->getValue();
pp->epd.enabled = getEnabled();
strength->set_sensitive (true);
gamma->set_sensitive (true);
/*
if(pp->wavelet.enabled) {
if(pp->wavelet.tmrs == 0) {
if(pp->wavelet.tmrs == 0 || pp->wavelet.TMmethod == "cont") {
strength->set_sensitive (true);
gamma->set_sensitive (true);
} else {
} else if(pp->wavelet.tmrs != 0 && pp->wavelet.TMmethod == "tm") {
strength->set_sensitive (false);
gamma->set_sensitive (false);
}

View File

@ -14,7 +14,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/
#include "filterpanel.h"
#include "multilangmgr.h"
@ -107,8 +107,8 @@ FilterPanel::FilterPanel () : listener (nullptr)
scamera->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
scamera->set_size_request(-1, 80);
scamera->add(*camera);
cvb->pack_start (*scamera, Gtk::PACK_SHRINK, 0);
pack_start (*cvb, Gtk::PACK_SHRINK, 4);
cvb->pack_start (*scamera, Gtk::PACK_EXPAND_WIDGET, 0);
pack_start (*cvb, Gtk::PACK_EXPAND_WIDGET, 4);
enaLens = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_LENS") + ":"));
Gtk::VBox* lvb = Gtk::manage(new Gtk::VBox ());
@ -119,8 +119,8 @@ FilterPanel::FilterPanel () : listener (nullptr)
slens->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
slens->set_size_request(-1, 80);
slens->add(*lens);
lvb->pack_start (*slens, Gtk::PACK_SHRINK, 0);
pack_start (*lvb, Gtk::PACK_SHRINK, 4);
lvb->pack_start (*slens, Gtk::PACK_EXPAND_WIDGET, 0);
pack_start (*lvb, Gtk::PACK_EXPAND_WIDGET, 4);
enaFiletype = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_FILETYPE") + ":"));
Gtk::VBox* ftvb = Gtk::manage(new Gtk::VBox ());
@ -131,8 +131,8 @@ FilterPanel::FilterPanel () : listener (nullptr)
sfiletype->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
sfiletype->set_size_request(-1, 80);
sfiletype->add(*filetype);
ftvb->pack_start (*sfiletype, Gtk::PACK_SHRINK, 0);
pack_start (*ftvb, Gtk::PACK_SHRINK, 4);
ftvb->pack_start (*sfiletype, Gtk::PACK_EXPAND_WIDGET, 0);
pack_start (*ftvb, Gtk::PACK_EXPAND_WIDGET, 4);
// add panel ending
Gtk::VBox* vboxpe = Gtk::manage (new Gtk::VBox ());

View File

@ -17,6 +17,8 @@
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
*/
#include "lensgeom.h"
#include "eventmapper.h"
#include "guiutils.h"
#include "rtimage.h"
@ -28,6 +30,18 @@ using namespace rtengine::procparams;
LensGeometry::LensGeometry () : FoldableToolPanel(this, "lensgeom", M("TP_LENSGEOM_LABEL")), rlistener(nullptr), lastFill(false)
{
auto m = ProcEventMapper::getInstance();
EvTransMethod = m->newEvent(TRANSFORM, "HISTORY_MSG_TRANS_METHOD");
Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ());
hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") + ": ")), Gtk::PACK_SHRINK, 4);
method = Gtk::manage (new MyComboBoxText ());
method->append(M("TP_LENSGEOM_LOG"));
method->append(M("TP_LENSGEOM_LIN"));
method->set_active(0);
hb1->pack_end (*method, Gtk::PACK_EXPAND_WIDGET, 4);
pack_start( *hb1, Gtk::PACK_SHRINK, 4);
fill = Gtk::manage (new Gtk::CheckButton (M("TP_LENSGEOM_FILL")));
pack_start (*fill);
@ -39,6 +53,7 @@ LensGeometry::LensGeometry () : FoldableToolPanel(this, "lensgeom", M("TP_LENSGE
packBox = Gtk::manage (new ToolParamBlock ());
pack_start (*packBox);
method->connect(method->signal_changed().connect(sigc::mem_fun(*this, &LensGeometry::methodChanged)));
autoCrop->signal_pressed().connect(sigc::mem_fun(*this, &LensGeometry::autoCropPressed));
fillConn = fill->signal_toggled().connect(sigc::mem_fun(*this, &LensGeometry::fillPressed));
@ -55,8 +70,14 @@ void LensGeometry::read (const ProcParams* pp, const ParamsEdited* pedited)
{
disableListener ();
method->block (true);
method->set_active(pp->commonTrans.method == "log" ? 0 : 1);
if (pedited) {
if(!pedited->commonTrans.method) {
method->set_active_text(M("GENERAL_UNCHANGED"));
}
fill->set_inconsistent (!pedited->commonTrans.autofill);
}
@ -67,15 +88,20 @@ void LensGeometry::read (const ProcParams* pp, const ParamsEdited* pedited)
lastFill = pp->commonTrans.autofill;
method->block (false);
enableListener ();
}
void LensGeometry::write (ProcParams* pp, ParamsEdited* pedited)
{
int currentRow = method->get_active_row_number();
if( currentRow >= 0 && method->get_active_text() != M("GENERAL_UNCHANGED")) {
pp->commonTrans.method = currentRow == 0 ? "log" : "lin";
}
pp->commonTrans.autofill = fill->get_active ();
if (pedited) {
pedited->commonTrans.method = method->get_active_text() != M("GENERAL_UNCHANGED");
pedited->commonTrans.autofill = !fill->get_inconsistent();
}
}
@ -115,6 +141,14 @@ void LensGeometry::fillPressed ()
}
}
void LensGeometry::methodChanged ()
{
if (listener && method->get_active_row_number() >= 0) {
listener->panelChanged(EvTransMethod, method->get_active_text());
}
}
void LensGeometry::setBatchMode (bool batchMode)
{

View File

@ -29,6 +29,7 @@ class LensGeometry final :
{
protected:
MyComboBoxText* method;
Gtk::Button* autoCrop;
LensGeomListener* rlistener;
Gtk::CheckButton* fill;
@ -36,6 +37,7 @@ protected:
sigc::connection fillConn;
ToolParamBlock* packBox;
rtengine::ProcEvent EvTransMethod;
public:
LensGeometry ();
@ -50,6 +52,7 @@ public:
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override;
void setBatchMode (bool batchMode) override;
void methodChanged();
void fillPressed ();
void autoCropPressed ();
void setLensGeomListener (LensGeomListener* l)

View File

@ -586,6 +586,9 @@ void LensProfilePanel::onCorrModeChanged(const Gtk::RadioButton* rbChanged)
LensProfilePanel::LFDbHelper::LFDbHelper()
{
lensfunCameraModel = Gtk::TreeStore::create(lensfunModelCam);
lensfunLensModel = Gtk::TreeStore::create(lensfunModelLens);
#ifdef _OPENMP
#pragma omp parallel sections if (!settings->verbose)
#endif
@ -594,14 +597,12 @@ LensProfilePanel::LFDbHelper::LFDbHelper()
#pragma omp section
#endif
{
lensfunCameraModel = Gtk::TreeStore::create(lensfunModelCam);
fillLensfunCameras();
}
#ifdef _OPENMP
#pragma omp section
#endif
{
lensfunLensModel = Gtk::TreeStore::create(lensfunModelLens);
fillLensfunLenses();
}
}

View File

@ -321,6 +321,7 @@ void ParamsEdited::set(bool v)
coarse.rotate = v;
coarse.hflip = v;
coarse.vflip = v;
commonTrans.method = v;
commonTrans.autofill = v;
rotate.degree = v;
distortion.amount = v;
@ -915,6 +916,7 @@ void ParamsEdited::initFrom(const std::vector<rtengine::procparams::ProcParams>&
coarse.rotate = coarse.rotate && p.coarse.rotate == other.coarse.rotate;
coarse.hflip = coarse.hflip && p.coarse.hflip == other.coarse.hflip;
coarse.vflip = coarse.vflip && p.coarse.vflip == other.coarse.vflip;
commonTrans.method = commonTrans.method && p.commonTrans.method == other.commonTrans.method;
commonTrans.autofill = commonTrans.autofill && p.commonTrans.autofill == other.commonTrans.autofill;
rotate.degree = rotate.degree && p.rotate.degree == other.rotate.degree;
distortion.amount = distortion.amount && p.distortion.amount == other.distortion.amount;
@ -2287,6 +2289,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.coarse.vflip = mods.coarse.vflip;
}
if (commonTrans.method) {
toEdit.commonTrans.method = mods.commonTrans.method;
}
if (commonTrans.autofill) {
toEdit.commonTrans.autofill = mods.commonTrans.autofill;
}

View File

@ -365,6 +365,7 @@ struct CoarseTransformParamsEdited {
};
struct CommonTransformParamsEdited {
bool method;
bool autofill;
};