diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 96ca16a84..0a3df7d5c 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -1212,10 +1212,6 @@ TP_RAW_DMETHOD;Methode TP_RAW_FALSECOLOR;Falschfarbenunterdrückung\nStufen TP_RAW_LABEL;Farbinterpolation TP_RESIZE_APPLIESTO;Gilt für: -TP_RESIZE_BICUBICSF;Bikubisch (weicher) -TP_RESIZE_BICUBICSH;Bikubisch (schärfer) -TP_RESIZE_BICUBIC;Bikubisch -TP_RESIZE_BILINEAR;Bilinear TP_RESIZE_CROPPEDAREA;Ausschnitt TP_RESIZE_FITBOX;Begrenzungsrahmen TP_RESIZE_FULLIMAGE;Ganzes Bild diff --git a/rtdata/languages/default b/rtdata/languages/default index 55af5aafd..5bdfeb34c 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1533,10 +1533,6 @@ TP_RAW_SENSOR_BAYER_LABEL;Sensor with Bayer Matrix TP_RAW_SENSOR_XTRANS_DMETHOD_TOOLTIP;3-pass gives best results (recommended for low ISO images).\n1-pass is almost undistinguishable from 3-pass for high ISO images and is faster. TP_RAW_SENSOR_XTRANS_LABEL;Sensor with X-Trans Matrix TP_RESIZE_APPLIESTO;Applies to: -TP_RESIZE_BICUBICSF;Bicubic (softer) -TP_RESIZE_BICUBICSH;Bicubic (sharper) -TP_RESIZE_BICUBIC;Bicubic -TP_RESIZE_BILINEAR;Bilinear TP_RESIZE_CROPPEDAREA;Cropped Area TP_RESIZE_FITBOX;Bounding Box TP_RESIZE_FULLIMAGE;Full Image diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 6d14fe2c5..0af3ae0b2 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -319,7 +319,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { imgsrc->convertColorSpace(orig_prev, params.icm, currWB, params.raw); - ipf.firstAnalysis (orig_prev, ¶ms, vhist16, imgsrc->getGamma()); + ipf.firstAnalysis (orig_prev, ¶ms, vhist16); } readyphase++; diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 3e45b869b..387f26dc1 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -170,7 +170,7 @@ void ImProcFunctions::CAT02 (Imagefloat* baseImg, const ProcParams* params) } } */ -void ImProcFunctions::firstAnalysis (Imagefloat* original, const ProcParams* params, LUTu & histogram, double gamma) { +void ImProcFunctions::firstAnalysis (Imagefloat* original, const ProcParams* params, LUTu & histogram) { // set up monitor transform Glib::ustring wprofile = params->icm.working; diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 94c1cea7a..66fa5d159 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -218,7 +218,7 @@ class ImProcFunctions { bool needsTransform (); bool needsPCVignetting (); - void firstAnalysis (Imagefloat* working, const ProcParams* params, LUTu & vhist16, double gamma); + void firstAnalysis (Imagefloat* working, const ProcParams* params, LUTu & vhist16); void rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1,const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob); @@ -253,7 +253,8 @@ class ImProcFunctions { float resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh); void lab2monitorRgb (LabImage* lab, Image8* image); void resize (Image16* src, Image16* dst, float dScale); - // void Lanczoslab (LabImage* src, LabImage* dst, float scale); + void Lanczos (const LabImage* src, LabImage* dst, float scale); +// void Lanczos (const Image16* src, Image16* dst, float scale); void deconvsharpening (LabImage* lab, float** buffer); void deconvsharpeningcam (CieImage* ncie, float** buffer); diff --git a/rtengine/ipresize.cc b/rtengine/ipresize.cc index b3ad7785f..ff82a4377 100644 --- a/rtengine/ipresize.cc +++ b/rtengine/ipresize.cc @@ -19,9 +19,6 @@ #include "improcfun.h" #include "rt_math.h" -#ifdef _OPENMP -#include -#endif #include "sleef.c" #include "opthelper.h" //#define PROFILE @@ -44,8 +41,10 @@ static inline float Lanc(float x, float a) } } -static void Lanczos(const Image16* src, Image16* dst, float scale) +/* This Function is not used anymore +void ImProcFunctions::Lanczos(const Image16* src, Image16* dst, float scale) { + const float delta = 1.0f / scale; const float a = 3.0f; const float sc = min(scale, 1.0f); @@ -168,37 +167,29 @@ static void Lanczos(const Image16* src, Image16* dst, float scale) delete[] lb; } } +*/ -// this function is implemented for future use and not tested yet -SSEFUNCTION static void Lanczos(const LabImage* src, LabImage* dst, float scale) +SSEFUNCTION void ImProcFunctions::Lanczos(const LabImage* src, LabImage* dst, float scale) { const float delta = 1.0f / scale; const float a = 3.0f; const float sc = min(scale, 1.0f); const int support = static_cast(2.0f * a / sc) + 1; -#pragma omp parallel -{ - // storage for precomputed parameters for horisontal interpolation + // storage for precomputed parameters for horizontal interpolation float * wwh = new float[support * dst->W]; int * jj0 = new int[dst->W]; int * jj1 = new int[dst->W]; - - // temporal storage for vertically-interpolated row of pixels - float * lL = new float[src->W]; - float * la = new float[src->W]; - float * lb = new float[src->W]; - // Phase 1: precompute coefficients for horisontal interpolation - + // Phase 1: precompute coefficients for horizontal interpolation for (int j = 0; j < dst->W; j++) { - + // x coord of the center of pixel on src image float x0 = (static_cast(j) + 0.5f) * delta - 0.5f; - // weights for interpolation in horisontal direction + // weights for interpolation in horizontal direction float * w = wwh + j * support; - + // sum of weights used for normalization float ws = 0.0f; @@ -212,28 +203,38 @@ SSEFUNCTION static void Lanczos(const LabImage* src, LabImage* dst, float scale) w[k] = Lanc(z, a); ws += w[k]; } - + // normalize weights for (int k = 0; k < support; k++) { w[k] /= ws; } } + +#ifdef _OPENMP +#pragma omp parallel +#endif +{ + // temporal storage for vertically-interpolated row of pixels + float * lL = new float[src->W]; + float * la = new float[src->W]; + float * lb = new float[src->W]; + // weights for interpolation in y direction + float w[support] ALIGNED64; + // Phase 2: do actual interpolation +#ifdef _OPENMP #pragma omp for +#endif for (int i = 0; i < dst->H; i++) { - // y coord of the center of pixel on src image float y0 = (static_cast(i) + 0.5f) * delta - 0.5f; - - // weights for interpolation in y direction - float w[support]; - + // sum of weights used for normalization - float ws= 0.0f; + float ws = 0.0f; int ii0 = max(0, static_cast(floorf(y0 - a / sc)) + 1); int ii1 = min(src->H, static_cast(floorf(y0 + a / sc)) + 1); - + // calculate weights for vertical interpolation for (int ii = ii0; ii < ii1; ii++) { int k = ii - ii0; @@ -246,91 +247,74 @@ SSEFUNCTION static void Lanczos(const LabImage* src, LabImage* dst, float scale) for (int k = 0; k < support; k++) { w[k] /= ws; } - + // Do vertical interpolation. Store results. -#ifdef __SSE299__ // actually disabled. To enable replace __SSE299__ by __SSE2__ - __m128 Lv,av,bv,wkv; +#ifdef __SSE2__ int j; + __m128 Lv,av,bv,wkv; for (j = 0; j < src->W-3; j+=4) { Lv = _mm_setzero_ps(); av = _mm_setzero_ps(); bv = _mm_setzero_ps(); - + for (int ii = ii0; ii < ii1; ii++) { int k = ii - ii0; - wkv = LVFU(w[k]); + wkv = _mm_set1_ps(w[k]); Lv += wkv * LVFU(src->L[ii][j]); av += wkv * LVFU(src->a[ii][j]); bv += wkv * LVFU(src->b[ii][j]); } - - _mm_storeu_ps(&lL[j],Lv); - _mm_storeu_ps(&la[j],av); - _mm_storeu_ps(&lb[j],bv); - } - for (; j < src->W; j++) { - - float L = 0.0f, a = 0.0f, b = 0.0f; - - for (int ii = ii0; ii < ii1; ii++) { - int k = ii - ii0; - - L += w[k] * src->L[ii][j]; - a += w[k] * src->a[ii][j]; - b += w[k] * src->b[ii][j]; - } - - lL[j] = L; - la[j] = a; - lb[j] = b; - } + STVF(lL[j],Lv); + STVF(la[j],av); + STVF(lb[j],bv); + } #else - for (int j = 0; j < src->W; j++) { - + int j=0; +#endif + for (; j < src->W; j++) { float L = 0.0f, a = 0.0f, b = 0.0f; for (int ii = ii0; ii < ii1; ii++) { int k = ii - ii0; - + L += w[k] * src->L[ii][j]; a += w[k] * src->a[ii][j]; b += w[k] * src->b[ii][j]; } - + lL[j] = L; la[j] = a; lb[j] = b; } -#endif + // Do horizontal interpolation for(int j = 0; j < dst->W; j++) { float * wh = wwh + support * j; - + float L = 0.0f, a = 0.0f, b = 0.0f; - + for (int jj = jj0[j]; jj < jj1[j]; jj++) { int k = jj - jj0[j]; - + L += wh[k] * lL[jj]; a += wh[k] * la[jj]; b += wh[k] * lb[jj]; } - + dst->L[i][j] = L; dst->a[i][j] = a; dst->b[i][j] = b; } } - - delete[] wwh; + delete[] lL; + delete[] la; + delete[] lb; +} delete[] jj0; delete[] jj1; - delete[] lL; - delete[] la; - delete[] lb; -} + delete[] wwh; } float ImProcFunctions::resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh) { @@ -397,13 +381,30 @@ void ImProcFunctions::resize (Image16* src, Image16* dst, float dScale) { #ifdef PROFILE time_t t1 = clock(); #endif - + // Nearest neighbour algorithm +#ifdef _OPENMP +#pragma omp parallel for if (multiThread) +#endif + for (int i=0; iheight; i++) { + int sy = i/dScale; + sy = LIM(sy, 0, src->height-1); + for (int j=0; jwidth; j++) { + int sx = j/dScale; + sx = LIM(sx, 0, src->width-1); + dst->r(i,j) = src->r(sy,sx); + dst->g(i,j) = src->g(sy,sx); + dst->b(i,j) = src->b(sy,sx); + } + } +/* not used anymore if(params->resize.method == "Lanczos" || params->resize.method == "Downscale (Better)" || params->resize.method == "Downscale (Faster)" ) { Lanczos(src, dst, dScale); + } else { } + else if (params->resize.method.substr(0,7)=="Bicubic") { float Av = -0.5f; if (params->resize.method=="Bicubic (Sharper)") @@ -505,7 +506,7 @@ void ImProcFunctions::resize (Image16* src, Image16* dst, float dScale) { } } } - +*/ #ifdef PROFILE time_t t2 = clock(); std::cout << "Resize: " << params->resize.method << ": " diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 8f178ee73..86fb0a63e 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -826,7 +826,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei LUTu hist16C (65536); double gamma = isRaw ? Color::sRGBGamma : 0; // usually in ImageSource, but we don't have that here - ipf.firstAnalysis (baseImg, ¶ms, hist16, gamma); + ipf.firstAnalysis (baseImg, ¶ms, hist16); // perform transform if (ipf.needsTransform()) { diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 1c843f8b5..186d470bf 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -571,7 +571,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p LUTu hist16 (65536); LUTu hist16C (65536); - ipf.firstAnalysis (baseImg, ¶ms, hist16, imgsrc->getGamma()); + ipf.firstAnalysis (baseImg, ¶ms, hist16); // perform transform (excepted resizing) if (ipf.needsTransform()) { @@ -853,6 +853,11 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p if (pl) pl->setProgress (0.60); + int imw, imh; + double tmpScale = ipf.resizeScale(¶ms, fw, fh, imw, imh); + bool labResize = params.resize.enabled && params.resize.method != "Nearest" && tmpScale != 1.0; + LabImage *tmplab; + // crop and convert to rgb16 int cx = 0, cy = 0, cw = labView->W, ch = labView->H; if (params.crop.enabled) { @@ -860,13 +865,36 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p cy = params.crop.y; cw = params.crop.w; ch = params.crop.h; + if(labResize) { // crop lab data + tmplab = new LabImage(cw,ch); + for(int row = 0;rowL[row][col] = labView->L[row+cy][col+cx]; + tmplab->a[row][col] = labView->a[row+cy][col+cx]; + tmplab->b[row][col] = labView->b[row+cy][col+cx]; + } + } + delete labView; + labView = tmplab; + cx = 0; + cy = 0; + } + } + + if (labResize) { // resize lab data + // resize image + tmplab = new LabImage(imw,imh); + ipf.Lanczos (labView, tmplab, tmpScale); + delete labView; + labView = tmplab; + cw = labView->W; + ch = labView->H; } Image16* readyImg = NULL; cmsHPROFILE jprof = NULL; bool customGamma = false; bool useLCMS = false; - if(params.icm.gamma != "default" || params.icm.freegamma) { // if select gamma output between BT709, sRGB, linear, low, high, 2.2 , 1.8 cmsMLU *DescriptionMLU, *CopyrightMLU, *DmndMLU, *DmddMLU;// for modification TAG @@ -1045,17 +1073,13 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p } if (pl) pl->setProgress (0.70); - int imw, imh; - double tmpScale = ipf.resizeScale(¶ms, fw, fh, imw, imh); - if (tmpScale != 1.0) { - // resize image + if (tmpScale != 1.0 && params.resize.method == "Nearest") { // resize rgb data (gamma applied) Image16* tempImage = new Image16 (imw, imh); ipf.resize (readyImg, tempImage, tmpScale); delete readyImg; readyImg = tempImage; } - if (tunnelMetaData) readyImg->setMetadata (ii->getMetaData()->getExifData ()); else diff --git a/rtgui/resize.cc b/rtgui/resize.cc index e5faca43b..5f02def95 100644 --- a/rtgui/resize.cc +++ b/rtgui/resize.cc @@ -42,12 +42,8 @@ Resize::Resize () : FoldableToolPanel(this, "resize", M("TP_RESIZE_LABEL"), fals combos->attach (*appliesTo, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); method = Gtk::manage (new MyComboBoxText ()); - method->append_text (M("TP_RESIZE_NEAREST")); - method->append_text (M("TP_RESIZE_BILINEAR")); - method->append_text (M("TP_RESIZE_BICUBIC")); - method->append_text (M("TP_RESIZE_BICUBICSF")); - method->append_text (M("TP_RESIZE_BICUBICSH")); method->append_text (M("TP_RESIZE_LANCZOS")); + method->append_text (M("TP_RESIZE_NEAREST")); method->set_active (0); label = Gtk::manage (new Gtk::Label (M("TP_RESIZE_METHOD"))); @@ -142,24 +138,12 @@ void Resize::read (const ProcParams* pp, const ParamsEdited* pedited) { else if (pp->resize.appliesTo == "Full image") appliesTo->set_active (1); - method->set_active (2); - if (pp->resize.method == "Nearest") + if (pp->resize.method == "Lanczos") method->set_active (0); - else if (pp->resize.method == "Bilinear") + else if (pp->resize.method == "Nearest") method->set_active (1); - else if (pp->resize.method == "Bicubic") - method->set_active (2); - else if (pp->resize.method == "Bicubic (Softer)") - method->set_active (3); - else if (pp->resize.method == "Bicubic (Sharper)") - method->set_active (4); - else if (pp->resize.method == "Lanczos") - method->set_active (5); - else if (pp->resize.method == "Downscale (Better)" || - pp->resize.method == "Downscale (Faster)") - { - method->set_active (5); - } + else + method->set_active (0); wDirty = false; hDirty = false; @@ -171,7 +155,7 @@ void Resize::read (const ProcParams* pp, const ParamsEdited* pedited) { if (!pedited->resize.appliesTo) appliesTo->set_active (2); if (!pedited->resize.method) - method->set_active (8); + method->set_active (3); if (!pedited->resize.dataspec) spec->set_active (4); set_inconsistent (multiImage && !pedited->resize.enabled); @@ -196,19 +180,11 @@ void Resize::write (ProcParams* pp, ParamsEdited* pedited) { else if (appliesTo->get_active_row_number() == 1) pp->resize.appliesTo = "Full image"; - pp->resize.method = "Bicubic"; + pp->resize.method = "Lanczos"; if (method->get_active_row_number() == 0) - pp->resize.method = "Nearest"; - else if (method->get_active_row_number() == 1) - pp->resize.method = "Bilinear"; - else if (method->get_active_row_number() == 2) - pp->resize.method = "Bicubic"; - else if (method->get_active_row_number() == 3) - pp->resize.method = "Bicubic (Softer)"; - else if (method->get_active_row_number() == 4) - pp->resize.method = "Bicubic (Sharper)"; - else if (method->get_active_row_number() == 5) pp->resize.method = "Lanczos"; + else if (method->get_active_row_number() == 1) + pp->resize.method = "Nearest"; pp->resize.dataspec = dataSpec; pp->resize.width = w->get_value_as_int (); @@ -220,7 +196,7 @@ void Resize::write (ProcParams* pp, ParamsEdited* pedited) { pedited->resize.enabled = !get_inconsistent(); pedited->resize.dataspec = dataSpec != 4; pedited->resize.appliesTo = appliesTo->get_active_row_number() != 2; - pedited->resize.method = method->get_active_row_number() != 8; + pedited->resize.method = method->get_active_row_number() != 3; if (pedited->resize.dataspec) { pedited->resize.scale = scale->getEditedState (); pedited->resize.width = wDirty;