diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 5d6695bad..724fcdddf 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -160,7 +160,9 @@ HISTORY_MSG_105;Defringing aktiv HISTORY_MSG_106;Defringing Radius HISTORY_MSG_107;Defringing Schwellenwert HISTORY_MSG_108;Lichter-Kompression Schwellenwert +HISTORY_MSG_109;Größenänderung Begrenzungsrahmen HISTORY_MSG_10;Schatten-Kompression +HISTORY_MSG_110;Größenänderung gilt für HISTORY_MSG_11;Tonwertkurve HISTORY_MSG_12;Automatische Belichtung HISTORY_MSG_13;Belichtungsbeschneidung @@ -719,12 +721,16 @@ TP_PREPROCESS_DARKFRAME;Dunkelbild TP_PREPROCESS_DFAUTOSELECT;Automatische Auswahl TP_RAWPANEL_DEMOSAICING;Demosaic TP_RAWPANEL_PREPROCESSING;Vorverarbeitung +TP_RESIZE_APPLIESTO;Gilt für: TP_RESIZE_BICUBIC;Bikubisch TP_RESIZE_BICUBICSF;Bikubisch (Weicher) TP_RESIZE_BICUBICSH;Bikubisch (Schärfer) TP_RESIZE_BILINEAR;Bilinear +TP_RESIZE_CROPPEDAREA;Ausschnitt TP_RESIZE_DOWNSCALEB;Verkleinern (besser) TP_RESIZE_DOWNSCALEF;Verkleinern (schneller) +TP_RESIZE_FITBOX;Begrenzungsrahmen +TP_RESIZE_FULLIMAGE;Ganzes Bild TP_RESIZE_FULLSIZE;Volle Bildgröße: TP_RESIZE_H;H: TP_RESIZE_HEIGHT;Höhe diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 68d8921b7..9db9e45e6 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -150,7 +150,12 @@ HISTORY_MSG_105;Corr. aberr. chromatique HISTORY_MSG_106;Corr. a.c. - Rayon HISTORY_MSG_107;Corr. a.c. - Seuil HISTORY_MSG_108;Seuil de compr. des hautes lumières +HISTORY_MSG_109;Redim. - boîte englobante HISTORY_MSG_10;Compression des ombres +HISTORY_MSG_110;Redim. s'applique à +HISTORY_MSG_111;Éviter l'écrêtage couleur +HISTORY_MSG_112;Limiteur de saturation +HISTORY_MSG_113;Limite de saturation HISTORY_MSG_11;Courbe tonale HISTORY_MSG_12;Exposition auto HISTORY_MSG_13;Rognage de l'exposition @@ -688,10 +693,13 @@ TP_ICM_SAVEREFERENCE;Utiliser l'image comme profil de référence TP_ICM_WORKINGPROFILE;Profil de Travail TP_IMPULSEDENOISE_LABEL;Réduction du bruit d'impulsion TP_IMPULSEDENOISE_THRESH;Seuil +TP_LABCURVE_AVOIDCOLORCLIP;Éviter l'écrêtage couleur TP_LABCURVE_BRIGHTNESS;Luminosité TP_LABCURVE_CONTRAST;Contraste TP_LABCURVE_CURVEEDITOR;Courbe de luminance +TP_LABCURVE_ENABLESATLIMITER;Activer le limiteur de saturation TP_LABCURVE_LABEL;Courbes Lab +TP_LABCURVE_SATLIMIT;Limite de saturation TP_LABCURVE_SATURATION;Saturation TP_LENSGEOM_AUTOCROP;Recadrage auto TP_LENSGEOM_FILL;Remplir @@ -706,12 +714,16 @@ TP_PREPROCESS_DARKFRAME;Trame noire TP_PREPROCESS_DFAUTOSELECT;Sélection automatique TP_RAWPANEL_DEMOSAICING;Dématriçage TP_RAWPANEL_PREPROCESSING;Traitement pre-dématriçage +TP_RESIZE_APPLIESTO;S'applique à: TP_RESIZE_BICUBIC;Bicubique TP_RESIZE_BICUBICSF;Bicubique (Plus doux) TP_RESIZE_BICUBICSH;Bicubique (Plus net) TP_RESIZE_BILINEAR;Bilinéaire +TP_RESIZE_CROPPEDAREA;La zone recadrée TP_RESIZE_DOWNSCALEB;Diminuer (Meilleur) TP_RESIZE_DOWNSCALEF;Diminuer (Plus rapide) +TP_RESIZE_FITBOX;Boîte englobante +TP_RESIZE_FULLIMAGE;L'image entière TP_RESIZE_FULLSIZE;Dimensions finales de l'image: TP_RESIZE_H;H: TP_RESIZE_HEIGHT;Hauteur @@ -777,13 +789,3 @@ ZOOMPANEL_ZOOM100;Zoom à 100% 1 ZOOMPANEL_ZOOMFITSCREEN;Ajuster à la fenêtre F ZOOMPANEL_ZOOMIN;Zoom + ZOOMPANEL_ZOOMOUT;Zoom - - - -!!!!!!!!!!!!!!!!!!!!!!!!! -! Untranslated keys follow; remove the ! prefix after an entry is translated. -!!!!!!!!!!!!!!!!!!!!!!!!! - - -!TP_LABCURVE_AVOIDCOLORCLIP;Avoid color clipping -!TP_LABCURVE_ENABLESATLIMITER;Enable saturation limiter -!TP_LABCURVE_SATLIMIT;Saturation limit diff --git a/rtdata/languages/default b/rtdata/languages/default index 1e88749ca..d7d432f83 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -150,7 +150,12 @@ HISTORY_MSG_105;Defringing HISTORY_MSG_106;Defringing Radius HISTORY_MSG_107;Defringing Threshold HISTORY_MSG_108;Highlight Compr. Threshold +HISTORY_MSG_109;Resize bounding box HISTORY_MSG_10;Shadow Compression +HISTORY_MSG_110;Resizing applies to +HISTORY_MSG_111;Avoid Color Clipping +HISTORY_MSG_112;Saturation Limiter +HISTORY_MSG_113;Saturation Limit HISTORY_MSG_11;Tone Curve HISTORY_MSG_12;Auto Exposure HISTORY_MSG_13;Exposure Clipping @@ -709,12 +714,16 @@ TP_PREPROCESS_DARKFRAME;Dark frame TP_PREPROCESS_DFAUTOSELECT;Auto selection TP_RAWPANEL_DEMOSAICING;Demosaicing TP_RAWPANEL_PREPROCESSING;Preprocessing +TP_RESIZE_APPLIESTO;Applies to: TP_RESIZE_BICUBIC;Bicubic TP_RESIZE_BICUBICSF;Bicubic (Softer) TP_RESIZE_BICUBICSH;Bicubic (Sharper) TP_RESIZE_BILINEAR;Bilinear +TP_RESIZE_CROPPEDAREA;Cropped area TP_RESIZE_DOWNSCALEB;Downscale (Better) TP_RESIZE_DOWNSCALEF;Downscale (Faster) +TP_RESIZE_FITBOX;Bounding box +TP_RESIZE_FULLIMAGE;Full image TP_RESIZE_FULLSIZE;Full Image Size: TP_RESIZE_H;H: TP_RESIZE_HEIGHT;Height diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 555aeed81..083ffab05 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -65,13 +65,6 @@ void Crop::update (int todo, bool internal) { ProcParams& params = parent->params; cropMutex.lock (); - if (!params.resize.enabled) - params.resize.scale = 1.0; - else if (params.resize.dataspec==1) - params.resize.scale = (double)params.resize.width / (params.coarse.rotate==90 || params.coarse.rotate==270 ? parent->fh : parent->fw); - else if (params.resize.dataspec==2) - params.resize.scale = (double)params.resize.height / (params.coarse.rotate==90 || params.coarse.rotate==270 ? parent->fw : parent->fh); - parent->ipf.setScale (skip); // give possibility to the listener to modify crop window (as the full image dimensions are already known at this point) @@ -98,10 +91,7 @@ void Crop::update (int todo, bool internal) { if( regenHighDetail ) parent->updatePreviewImage (ALL,this); // We have just set skip to 1 - if (resizeCrop) - baseCrop = resizeCrop; - else - baseCrop = origCrop; + baseCrop = origCrop; bool needstransform = parent->ipf.needsTransform(); @@ -119,29 +109,6 @@ void Crop::update (int todo, bool internal) { PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip); parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.hlrecovery, params.icm, params.raw ); - if (fabs(params.resize.scale-1.0)<1e-7) { - if (resizeCrop) { - delete resizeCrop; - resizeCrop = NULL; - } - baseCrop = origCrop; - } - else { - int rcw = trafw*params.resize.scale; - int rch = trafh*params.resize.scale; - if (!needstransform) { - rcw = cropw; - rch = croph; - } - if (resizeCrop && (resizeCrop->width!=rcw || resizeCrop->height!=rch)) { - delete resizeCrop; - resizeCrop = NULL; - } - if (!resizeCrop) - resizeCrop = new Image16 (rcw, rch); - parent->ipf.resize (origCrop, resizeCrop); - baseCrop = resizeCrop; - } parent->minit.unlock (); } @@ -153,7 +120,7 @@ void Crop::update (int todo, bool internal) { if (needstransform && !transCrop) transCrop = new Image16 (cropw, croph); if ((todo & M_TRANSFORM) && needstransform) - parent->ipf.transform (baseCrop, transCrop, cropx/skip, cropy/skip, trafx*params.resize.scale/skip, trafy*params.resize.scale/skip, SKIPS(parent->fw,skip), SKIPS(parent->fh,skip)); + parent->ipf.transform (baseCrop, transCrop, cropx/skip, cropy/skip, trafx/skip, trafy/skip, SKIPS(parent->fw,skip), SKIPS(parent->fh,skip)); if (transCrop) baseCrop = transCrop; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 2f93c627b..eca2db1c6 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -112,13 +112,6 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { int numofphases = 10; int readyphase = 0; - if (!params.resize.enabled) - params.resize.scale = 1.0; - else if (params.resize.dataspec==1) - params.resize.scale = (double)params.resize.width / (params.coarse.rotate==90 || params.coarse.rotate==270 ? fh : fw); - else if (params.resize.dataspec==2) - params.resize.scale = (double)params.resize.height / (params.coarse.rotate==90 || params.coarse.rotate==270 ? fw : fh); - ipf.setScale (scale); bool highDetailNeeded=false; @@ -304,7 +297,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { if (!resultValid) { resultValid = true; if (imageListener) - imageListener->setImage (previmg, scale*params.resize.scale, params.crop); + imageListener->setImage (previmg, scale, params.crop); } if (imageListener) imageListener->imageReady (params.crop); @@ -395,22 +388,8 @@ if (settings->verbose) printf ("setscale before lock\n"); scale = prevscale; resultValid = false; - if (!params.resize.enabled) { - fullw = fw; - fullh = fh; - } - else if (params.resize.dataspec==0) { - fullw = fw*params.resize.scale; - fullh = fh*params.resize.scale; - } - else if (params.resize.dataspec==1) { - fullw = params.resize.width; - fullh = (double)fh*params.resize.width/(params.coarse.rotate==90 || params.coarse.rotate==270 ? fh : fw); - } - else if (params.resize.dataspec==2) { - fullw = (double)fw*params.resize.height/(params.coarse.rotate==90 || params.coarse.rotate==270 ? fw : fh); - fullh = params.resize.height; - } + fullw = fw; + fullh = fh; if (settings->verbose) printf ("setscale ends\n"); if (sizeListeners.size()>0) for (int i=0; i &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef = -1); - void getAutoExp (unsigned int* histogram, int histcompr, double expcomp, double clip, double& br, int& bl); - double getTransformAutoFill (int oW, int oH); - - void rgb2hsv (int r, int g, int b, float &h, float &s, float &v); - void hsv2rgb (float h, float s, float v, int &r, int &g, int &b); + void dirpyrLab_denoise(LabImage * src, LabImage * dst, int luma, int chroma, float gamma );//Emil's directional pyramid denoise + void dirpyr (LabImage* data_fine, LabImage* data_coarse, int level, int * rangefn_L, int * rangefn_ab, int pitch, int scale, const int luma, int chroma ); + void idirpyr (LabImage* data_coarse, LabImage* data_fine, int level, float * nrwt_l, float * nrwt_ab, int pitch, int scale, const int luma, int chroma ); + + void dirpyrLab_equalizer (LabImage * src, LabImage * dst, const double * mult );//Emil's directional pyramid equalizer + void dirpyr_eq (LabImage* data_coarse, LabImage* data_fine, int * rangefn, int level, int pitch, int scale, const double * mult ); + void idirpyr_eq (LabImage* data_coarse, LabImage* data_fine, int *** buffer, int * irangefn, int level, int pitch, int scale, const double * mult ); + + void dirpyr_equalizer (unsigned short ** src, unsigned short ** dst, int srcwidth, int srcheight, const double * mult );//Emil's directional pyramid equalizer + void dirpyr_channel (unsigned short ** data_fine, unsigned short ** data_coarse, int width, int height, int * rangefn, int level, int scale, const double * mult ); + void idirpyr_eq_channel (unsigned short ** data_coarse, unsigned short ** data_fine, int ** buffer, int width, int height, int level, const double * mult ); + + void defringe (LabImage* lab); + void PF_correct_RT (LabImage * src, LabImage * dst, double radius, int thresh, bool edges); + + Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile); + Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile); + + bool transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1); + bool transCoord (int W, int H, std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef = -1); + void getAutoExp (unsigned int* histogram, int histcompr, double expcomp, double clip, double& br, int& bl); + double getTransformAutoFill (int oW, int oH); + + void rgb2hsv (int r, int g, int b, float &h, float &s, float &v); + void hsv2rgb (float h, float s, float v, int &r, int &g, int &b); }; } #endif diff --git a/rtengine/ipresize.cc b/rtengine/ipresize.cc index d48030ed9..4871288f6 100644 --- a/rtengine/ipresize.cc +++ b/rtengine/ipresize.cc @@ -170,12 +170,12 @@ void Lanczos(const Image16* src, Image16* dst, double scale) delete[] lb; } -void ImProcFunctions::resize (Image16* src, Image16* dst) { +void ImProcFunctions::resize (Image16* src, Image16* dst, double dScale) { //time_t t1 = clock(); if(params->resize.method == "Lanczos") { - Lanczos(src, dst, params->resize.scale); + Lanczos(src, dst, dScale); } else if(params->resize.method == "Downscale (Better)") { // small-scale algorithm by Ilia @@ -187,8 +187,8 @@ void ImProcFunctions::resize (Image16* src, Image16* dst) { // this algorithm is much slower on small factors than others, because it uses all pixels of the SOURCE image // Ilia Popov ilia_popov@rambler.ru 2010 - double delta = 1.0 / params->resize.scale; - double k = params->resize.scale * params->resize.scale; + double delta = 1.0 / dScale; + double k = dScale * dScale; #pragma omp parallel for if (multiThread) for(int i = 0; i < dst->height; i++) { @@ -266,7 +266,7 @@ void ImProcFunctions::resize (Image16* src, Image16* dst) { // for weights at all // Ilia Popov ilia_popov@rambler.ru 5.04.2010 - double delta = 1.0 / params->resize.scale; + double delta = 1.0 / dScale; int p = (int) delta; @@ -339,7 +339,7 @@ void ImProcFunctions::resize (Image16* src, Image16* dst) { #pragma omp parallel for if (multiThread) for (int i=0; iheight; i++) { double wx[4], wy[4]; - double Dy = i / params->resize.scale; + double Dy = i / dScale; int yc = (int) Dy; Dy -= (double)yc; int ys = yc - 1; // smallest y-index used for interpolation // compute vertical weights @@ -350,7 +350,7 @@ void ImProcFunctions::resize (Image16* src, Image16* dst) { wy[1] = -t1y*Dy + 1.0 - t2y; wy[0] = -t1y*(Dy-1.0); for (int j=0; jwidth; j++) { - double Dx = j / params->resize.scale; + double Dx = j / dScale; int xc = (int) Dx; Dx -= (double)xc; int xs = xc - 1; // smallest x-index used for interpolation if (ys >= 0 && ys height-3 && xs >= 0 && xs <= src->width-3) { @@ -395,16 +395,16 @@ void ImProcFunctions::resize (Image16* src, Image16* dst) { else if (params->resize.method=="Bilinear") { #pragma omp parallel for if (multiThread) for (int i=0; iheight; i++) { - int sy = i/params->resize.scale; + int sy = i/dScale; sy = CLIPTO(sy, 0, src->height-1); - double dy = i/params->resize.scale - sy; + double dy = i/dScale - sy; int ny = sy+1; if (ny>=src->height) ny = sy; for (int j=0; jwidth; j++) { - int sx = j/params->resize.scale; + int sx = j/dScale; sx = CLIPTO(sx, 0, src->width-1); - double dx = j/params->resize.scale - sx; + double dx = j/dScale - sx; int nx = sx+1; if (nx>=src->width) nx = sx; @@ -417,10 +417,10 @@ void ImProcFunctions::resize (Image16* src, Image16* dst) { else { #pragma omp parallel for if (multiThread) for (int i=0; iheight; i++) { - int sy = i/params->resize.scale; + int sy = i/dScale; sy = CLIPTO(sy, 0, src->height-1); for (int j=0; jwidth; j++) { - int sx = j/params->resize.scale; + int sx = j/dScale; sx = CLIPTO(sx, 0, src->width-1); dst->r[i][j] = src->r[sy][sx]; dst->g[i][j] = src->g[sy][sx]; diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 682738f16..37e7e271e 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -38,6 +38,7 @@ namespace rtengine { #define CLIP(a) ((a)>0?((a)(b)?((a)<(c)?(a):(c)):(b)) #define CLIPTOC(a,b,c,d) ((a)>=(b)?((a)<=(c)?(a):(d=true,(c))):(d=true,(b))) +#define RT_PI 3.141592653589 bool ImProcFunctions::transCoord (int W, int H, std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef) { @@ -50,23 +51,6 @@ bool ImProcFunctions::transCoord (int W, int H, std::vector &src, std:: if (!needsCA() && !needsDistortion() && !needsRotation() && !needsPerspective()) { if (clipresize) { - // Apply resizing - if (fabs(params->resize.scale-1.0)>=1e-7) { - for (int i=0; iresize.scale, src[i].y / params->resize.scale)); - green.push_back (Coord2D (src[i].x / params->resize.scale, src[i].y / params->resize.scale)); - blue.push_back (Coord2D (src[i].x / params->resize.scale, src[i].y / params->resize.scale)); - } - for (int i=0; i &src, std:: return clipped; } - double oW = W*params->resize.scale; - double oH = H*params->resize.scale; + double oW = W; + double oH = H; double w2 = (double) oW / 2.0 - 0.5; double h2 = (double) oH / 2.0 - 0.5; double a = params->distortion.amount; - double cost = cos(params->rotate.degree * 3.14/180.0); - double sint = sin(params->rotate.degree * 3.14/180.0); + double cost = cos(params->rotate.degree * RT_PI/180.0); + double sint = sin(params->rotate.degree * RT_PI/180.0); double maxRadius = sqrt( (double)( oW*oW + oH*oH ) ) / 2; double vpdeg = params->perspective.vertical / 100.0 * 45.0; - double vpalpha = (90.0 - vpdeg) / 180.0 * 3.14; - double vpteta = fabs(vpalpha-3.14/2)<1e-3 ? 0.0 : acos ((vpdeg>0 ? 1.0 : -1.0) * sqrt((-oW*oW*tan(vpalpha)*tan(vpalpha) + (vpdeg>0 ? 1.0 : -1.0) * oW*tan(vpalpha)*sqrt(16*maxRadius*maxRadius+oW*oW*tan(vpalpha)*tan(vpalpha)))/(maxRadius*maxRadius*8))); + double vpalpha = (90.0 - vpdeg) / 180.0 * RT_PI; + double vpteta = fabs(vpalpha-RT_PI/2)<1e-3 ? 0.0 : acos ((vpdeg>0 ? 1.0 : -1.0) * sqrt((-oW*oW*tan(vpalpha)*tan(vpalpha) + (vpdeg>0 ? 1.0 : -1.0) * oW*tan(vpalpha)*sqrt(16*maxRadius*maxRadius+oW*oW*tan(vpalpha)*tan(vpalpha)))/(maxRadius*maxRadius*8))); double vpcospt = (vpdeg>=0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); double hpdeg = params->perspective.horizontal / 100.0 * 45.0; - double hpalpha = (90.0 - hpdeg) / 180.0 * 3.14; - double hpteta = fabs(hpalpha-3.14/2)<1e-3 ? 0.0 : acos ((hpdeg>0 ? 1.0 : -1.0) * sqrt((-oH*oH*tan(hpalpha)*tan(hpalpha) + (hpdeg>0 ? 1.0 : -1.0) * oH*tan(hpalpha)*sqrt(16*maxRadius*maxRadius+oH*oH*tan(hpalpha)*tan(hpalpha)))/(maxRadius*maxRadius*8))); + double hpalpha = (90.0 - hpdeg) / 180.0 * RT_PI; + double hpteta = fabs(hpalpha-RT_PI/2)<1e-3 ? 0.0 : acos ((hpdeg>0 ? 1.0 : -1.0) * sqrt((-oH*oH*tan(hpalpha)*tan(hpalpha) + (hpdeg>0 ? 1.0 : -1.0) * oH*tan(hpalpha)*sqrt(16*maxRadius*maxRadius+oH*oH*tan(hpalpha)*tan(hpalpha)))/(maxRadius*maxRadius*8))); double hpcospt = (hpdeg>=0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); double ascale = ascaleDef>0 ? ascaleDef : (params->commonTrans.autofill ? getTransformAutoFill (oW, oH) : 1.0); @@ -118,16 +102,6 @@ bool ImProcFunctions::transCoord (int W, int H, std::vector &src, std:: } if (clipresize) { - if (fabs(params->resize.scale-1.0)>=1e-7) { - for (int i=0; iresize.scale; - red[i].y /= params->resize.scale; - green[i].x /= params->resize.scale; - green[i].y /= params->resize.scale; - blue[i].x /= params->resize.scale; - blue[i].y /= params->resize.scale; - } - } for (int i=0; idistortion.amount; // auxiliary variables for rotation - double cost = cos(params->rotate.degree * 3.14/180.0); - double sint = sin(params->rotate.degree * 3.14/180.0); + double cost = cos(params->rotate.degree * RT_PI/180.0); + double sint = sin(params->rotate.degree * RT_PI/180.0); bool dovign = params->vignetting.amount != 0; // auxiliary variables for vertical perspective correction double vpdeg = params->perspective.vertical / 100.0 * 45.0; - double vpalpha = (90.0 - vpdeg) / 180.0 * 3.14; - double vpteta = fabs(vpalpha-3.14/2)<1e-3 ? 0.0 : acos ((vpdeg>0 ? 1.0 : -1.0) * sqrt((-oW*oW*tan(vpalpha)*tan(vpalpha) + (vpdeg>0 ? 1.0 : -1.0) * oW*tan(vpalpha)*sqrt(16*maxRadius*maxRadius+oW*oW*tan(vpalpha)*tan(vpalpha)))/(maxRadius*maxRadius*8))); + double vpalpha = (90.0 - vpdeg) / 180.0 * RT_PI; + double vpteta = fabs(vpalpha-RT_PI/2)<1e-3 ? 0.0 : acos ((vpdeg>0 ? 1.0 : -1.0) * sqrt((-oW*oW*tan(vpalpha)*tan(vpalpha) + (vpdeg>0 ? 1.0 : -1.0) * oW*tan(vpalpha)*sqrt(16*maxRadius*maxRadius+oW*oW*tan(vpalpha)*tan(vpalpha)))/(maxRadius*maxRadius*8))); double vpcospt = (vpdeg>=0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); // auxiliary variables for horizontal perspective correction double hpdeg = params->perspective.horizontal / 100.0 * 45.0; - double hpalpha = (90.0 - hpdeg) / 180.0 * 3.14; - double hpteta = fabs(hpalpha-3.14/2)<1e-3 ? 0.0 : acos ((hpdeg>0 ? 1.0 : -1.0) * sqrt((-oH*oH*tan(hpalpha)*tan(hpalpha) + (hpdeg>0 ? 1.0 : -1.0) * oH*tan(hpalpha)*sqrt(16*maxRadius*maxRadius+oH*oH*tan(hpalpha)*tan(hpalpha)))/(maxRadius*maxRadius*8))); + double hpalpha = (90.0 - hpdeg) / 180.0 * RT_PI; + double hpteta = fabs(hpalpha-RT_PI/2)<1e-3 ? 0.0 : acos ((hpdeg>0 ? 1.0 : -1.0) * sqrt((-oH*oH*tan(hpalpha)*tan(hpalpha) + (hpdeg>0 ? 1.0 : -1.0) * oH*tan(hpalpha)*sqrt(16*maxRadius*maxRadius+oH*oH*tan(hpalpha)*tan(hpalpha)))/(maxRadius*maxRadius*8))); double hpcospt = (hpdeg>=0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH) : 1.0; @@ -410,21 +384,21 @@ void ImProcFunctions::transformSep (Image16* original, Image16* transformed, int double a = params->distortion.amount; // auxiliary variables for rotation - double cost = cos(params->rotate.degree * 3.14/180.0); - double sint = sin(params->rotate.degree * 3.14/180.0); + double cost = cos(params->rotate.degree * RT_PI/180.0); + double sint = sin(params->rotate.degree * RT_PI/180.0); bool dovign = params->vignetting.amount != 0; // auxiliary variables for vertical perspective correction double vpdeg = params->perspective.vertical / 100.0 * 45.0; - double vpalpha = (90.0 - vpdeg) / 180.0 * 3.14; - double vpteta = fabs(vpalpha-3.14/2)<1e-3 ? 0.0 : acos ((vpdeg>0 ? 1.0 : -1.0) * sqrt((-oW*oW*tan(vpalpha)*tan(vpalpha) + (vpdeg>0 ? 1.0 : -1.0) * oW*tan(vpalpha)*sqrt(16*maxRadius*maxRadius+oW*oW*tan(vpalpha)*tan(vpalpha)))/(maxRadius*maxRadius*8))); + double vpalpha = (90.0 - vpdeg) / 180.0 * RT_PI; + double vpteta = fabs(vpalpha-RT_PI/2)<1e-3 ? 0.0 : acos ((vpdeg>0 ? 1.0 : -1.0) * sqrt((-oW*oW*tan(vpalpha)*tan(vpalpha) + (vpdeg>0 ? 1.0 : -1.0) * oW*tan(vpalpha)*sqrt(16*maxRadius*maxRadius+oW*oW*tan(vpalpha)*tan(vpalpha)))/(maxRadius*maxRadius*8))); double vpcospt = (vpdeg>=0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); // auxiliary variables for horizontal perspective correction double hpdeg = params->perspective.horizontal / 100.0 * 45.0; - double hpalpha = (90.0 - hpdeg) / 180.0 * 3.14; - double hpteta = fabs(hpalpha-3.14/2)<1e-3 ? 0.0 : acos ((hpdeg>0 ? 1.0 : -1.0) * sqrt((-oH*oH*tan(hpalpha)*tan(hpalpha) + (hpdeg>0 ? 1.0 : -1.0) * oH*tan(hpalpha)*sqrt(16*maxRadius*maxRadius+oH*oH*tan(hpalpha)*tan(hpalpha)))/(maxRadius*maxRadius*8))); + double hpalpha = (90.0 - hpdeg) / 180.0 * RT_PI; + double hpteta = fabs(hpalpha-RT_PI/2)<1e-3 ? 0.0 : acos ((hpdeg>0 ? 1.0 : -1.0) * sqrt((-oH*oH*tan(hpalpha)*tan(hpalpha) + (hpdeg>0 ? 1.0 : -1.0) * oH*tan(hpalpha)*sqrt(16*maxRadius*maxRadius+oH*oH*tan(hpalpha)*tan(hpalpha)))/(maxRadius*maxRadius*8))); double hpcospt = (hpdeg>=0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH) : 1.0; @@ -515,21 +489,21 @@ void ImProcFunctions::simpltransform (Image16* original, Image16* transformed, i double a = params->distortion.amount; // auxiliary variables for rotation - double cost = cos(params->rotate.degree * 3.14/180.0); - double sint = sin(params->rotate.degree * 3.14/180.0); + double cost = cos(params->rotate.degree * RT_PI/180.0); + double sint = sin(params->rotate.degree * RT_PI/180.0); bool dovign = params->vignetting.amount != 0; // auxiliary variables for vertical perspective correction double vpdeg = params->perspective.vertical / 100.0 * 45.0; - double vpalpha = (90 - vpdeg) / 180.0 * 3.14; - double vpteta = fabs(vpalpha-3.14/2)<1e-3 ? 0.0 : acos ((vpdeg>0 ? 1.0 : -1.0) * sqrt((-oW*oW*tan(vpalpha)*tan(vpalpha) + (vpdeg>0 ? 1.0 : -1.0) * oW*tan(vpalpha)*sqrt(16*maxRadius*maxRadius+oW*oW*tan(vpalpha)*tan(vpalpha)))/(maxRadius*maxRadius*8))); + double vpalpha = (90 - vpdeg) / 180.0 * RT_PI; + double vpteta = fabs(vpalpha-RT_PI/2)<1e-3 ? 0.0 : acos ((vpdeg>0 ? 1.0 : -1.0) * sqrt((-oW*oW*tan(vpalpha)*tan(vpalpha) + (vpdeg>0 ? 1.0 : -1.0) * oW*tan(vpalpha)*sqrt(16*maxRadius*maxRadius+oW*oW*tan(vpalpha)*tan(vpalpha)))/(maxRadius*maxRadius*8))); double vpcospt = (vpdeg>=0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); // auxiliary variables for horizontal perspective correction double hpdeg = params->perspective.horizontal / 100.0 * 45.0; - double hpalpha = (90 - hpdeg) / 180.0 * 3.14; - double hpteta = fabs(hpalpha-3.14/2)<1e-3 ? 0.0 : acos ((hpdeg>0 ? 1.0 : -1.0) * sqrt((-oH*oH*tan(hpalpha)*tan(hpalpha) + (hpdeg>0 ? 1.0 : -1.0) * oH*tan(hpalpha)*sqrt(16*maxRadius*maxRadius+oH*oH*tan(hpalpha)*tan(hpalpha)))/(maxRadius*maxRadius*8))); + double hpalpha = (90 - hpdeg) / 180.0 * RT_PI; + double hpteta = fabs(hpalpha-RT_PI/2)<1e-3 ? 0.0 : acos ((hpdeg>0 ? 1.0 : -1.0) * sqrt((-oH*oH*tan(hpalpha)*tan(hpalpha) + (hpdeg>0 ? 1.0 : -1.0) * oH*tan(hpalpha)*sqrt(16*maxRadius*maxRadius+oH*oH*tan(hpalpha)*tan(hpalpha)))/(maxRadius*maxRadius*8))); double hpcospt = (hpdeg>=0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH) : 1.0; diff --git a/rtengine/jdatasrc.c b/rtengine/jdatasrc.c index 3553558d7..7fd4bdd9c 100644 --- a/rtengine/jdatasrc.c +++ b/rtengine/jdatasrc.c @@ -1,6 +1,3 @@ -#ifndef WIN32 -#define jboolean boolean -#endif #include #include #include @@ -41,7 +38,7 @@ typedef struct { FILE * infile; /* source stream */ JOCTET * buffer; /* start of buffer */ - jboolean start_of_file; /* have we gotten any data yet? */ + boolean start_of_file; /* have we gotten any data yet? */ } my_source_mgr; typedef my_source_mgr * my_src_ptr; @@ -100,7 +97,7 @@ my_init_source (j_decompress_ptr cinfo) * the front of the buffer rather than discarding it. */ -METHODDEF(jboolean) +METHODDEF(boolean) my_fill_input_buffer (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; @@ -331,7 +328,7 @@ format_message (j_common_ptr cinfo, char * buffer) const char * msgtext = NULL; const char * msgptr; char ch; - jboolean isstring; + boolean isstring; /* Look up message string in proper table */ if (msg_code > 0 && msg_code <= err->last_jpeg_message) { diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 026db24da..92966304f 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -130,11 +130,12 @@ enum ProcEvent { EvDefringeRadius=105, EvDefringeThreshold=106, EvHLComprThreshold=107, - EvLAvoidClip=108, - EvLSatLimiter=109, - EvLSatLimit=110, - - NUMOFEVENTS=111 + EvResizeBoundingBox=108, + EvResizeAppliesTo=109, + EvLAvoidClip=110, + EvLSatLimiter=111, + EvLSatLimit=112, + NUMOFEVENTS=113 }; } #endif diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index aedb1e22b..e92517d1d 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -175,6 +175,7 @@ void ProcParams::setDefaults () { resize.enabled = false; resize.scale = 1.0; + resize.appliesTo = "Cropped area"; resize.method = "Bicubic"; resize.dataspec = 0; resize.width = 800; @@ -382,6 +383,7 @@ int ProcParams::save (Glib::ustring fname) const { keyFile.set_boolean ("Resize", "Enabled",resize.enabled); keyFile.set_double ("Resize", "Scale", resize.scale); + keyFile.set_string ("Resize", "AppliesTo", resize.appliesTo); keyFile.set_string ("Resize", "Method", resize.method); keyFile.set_integer ("Resize", "DataSpecified", resize.dataspec); keyFile.set_integer ("Resize", "Width", resize.width); @@ -698,6 +700,7 @@ if (keyFile.has_group ("HLRecovery")) { if (keyFile.has_group ("Resize")) { if (keyFile.has_key ("Resize", "Enabled")) resize.enabled = keyFile.get_boolean ("Resize", "Enabled"); if (keyFile.has_key ("Resize", "Scale")) resize.scale = keyFile.get_double ("Resize", "Scale"); + if (keyFile.has_key ("Resize", "AppliesTo")) resize.appliesTo = keyFile.get_string ("Resize", "AppliesTo"); if (keyFile.has_key ("Resize", "Method")) resize.method = keyFile.get_string ("Resize", "Method"); if (keyFile.has_key ("Resize", "DataSpecified")) resize.dataspec = keyFile.get_integer ("Resize", "DataSpecified"); if (keyFile.has_key ("Resize", "Width")) resize.width = keyFile.get_integer ("Resize", "Width"); @@ -953,6 +956,7 @@ bool ProcParams::operator== (const ProcParams& other) { && hlrecovery.enabled == other.hlrecovery.enabled && hlrecovery.method == other.hlrecovery.method && resize.scale == other.resize.scale + && resize.appliesTo == other.resize.appliesTo && resize.method == other.resize.method && resize.dataspec == other.resize.dataspec && resize.width == other.resize.width diff --git a/rtengine/procparams.h b/rtengine/procparams.h index f414ffa33..2a4c962da 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -310,6 +310,7 @@ class ResizeParams { public: bool enabled; double scale; + Glib::ustring appliesTo; Glib::ustring method; int dataspec; int width; @@ -415,38 +416,38 @@ class RAWParams { class ProcParams { public: - ToneCurveParams toneCurve; ///< Tone curve parameters - LCurveParams labCurve; ///< CIELAB luminance curve parameters - SharpeningParams sharpening; ///< Sharpening parameters - ColorBoostParams colorBoost; ///< Color boost parameters - WBParams wb; ///< White balance parameters - ColorShiftParams colorShift; ///< Color shift parameters - LumaDenoiseParams lumaDenoise; ///< Luminance denoising parameters - ColorDenoiseParams colorDenoise; ///< Color denoising parameters - DefringeParams defringe; ///< Defringing parameters - ImpulseDenoiseParams impulseDenoise; ///< Impulse denoising parameters - DirPyrDenoiseParams dirpyrDenoise; ///< Directional Pyramid denoising parameters - SHParams sh; ///< Shadow/highlight enhancement parameters - CropParams crop; ///< Crop parameters - CoarseTransformParams coarse; ///< Coarse transformation (90, 180, 270 deg rotation, h/v flipping) parameters - CommonTransformParams commonTrans; ///< Common transformation parameters (autofill) - RotateParams rotate; ///< Rotation parameters - DistortionParams distortion; ///< Lens distortion correction parameters - PerspectiveParams perspective; ///< Perspective correction parameters - CACorrParams cacorrection; ///< Lens c/a correction parameters - VignettingParams vignetting; ///< Lens vignetting correction parameters - ChannelMixerParams chmixer; ///< Channel mixer parameters - HRecParams hlrecovery; ///< Highlight recovery parameters - ResizeParams resize; ///< Resize parameters - ColorManagementParams icm; ///< profiles/color spaces used during the image processing - EqualizerParams equalizer; ///< wavelet equalizer parameters - RAWParams raw; ///< RAW parameters before demosaicing - DirPyrEqualizerParams dirpyrequalizer; ///< directional pyramid equalizer parameters - HSVEqualizerParams hsvequalizer; ///< hsv equalizer parameters - std::vector exif; ///< List of modifications appplied on the exif tags of the input image - std::vector iptc; ///< The IPTC tags and values to be saved to the output image - int version; ///< Version of the file from which the parameters have been read - + ToneCurveParams toneCurve; ///< Tone curve parameters + LCurveParams labCurve; ///< CIELAB luminance curve parameters + SharpeningParams sharpening; ///< Sharpening parameters + ColorBoostParams colorBoost; ///< Color boost parameters + WBParams wb; ///< White balance parameters + ColorShiftParams colorShift; ///< Color shift parameters + LumaDenoiseParams lumaDenoise; ///< Luminance denoising parameters + ColorDenoiseParams colorDenoise; ///< Color denoising parameters + DefringeParams defringe; ///< Defringing parameters + ImpulseDenoiseParams impulseDenoise; ///< Impulse denoising parameters + DirPyrDenoiseParams dirpyrDenoise; ///< Directional Pyramid denoising parameters + SHParams sh; ///< Shadow/highlight enhancement parameters + CropParams crop; ///< Crop parameters + CoarseTransformParams coarse; ///< Coarse transformation (90, 180, 270 deg rotation, h/v flipping) parameters + CommonTransformParams commonTrans; ///< Common transformation parameters (autofill) + RotateParams rotate; ///< Rotation parameters + DistortionParams distortion; ///< Lens distortion correction parameters + PerspectiveParams perspective; ///< Perspective correction parameters + CACorrParams cacorrection; ///< Lens c/a correction parameters + VignettingParams vignetting; ///< Lens vignetting correction parameters + ChannelMixerParams chmixer; ///< Channel mixer parameters + HRecParams hlrecovery; ///< Highlight recovery parameters + ResizeParams resize; ///< Resize parameters + ColorManagementParams icm; ///< profiles/color spaces used during the image processing + EqualizerParams equalizer; ///< wavelet equalizer parameters + RAWParams raw; ///< RAW parameters before demosaicing + DirPyrEqualizerParams dirpyrequalizer; ///< directional pyramid equalizer parameters + HSVEqualizerParams hsvequalizer; ///< hsv equalizer parameters + std::vector exif; ///< List of modifications appplied on the exif tags of the input image + std::vector iptc; ///< The IPTC tags and values to be saved to the output image + int version; ///< Version of the file from which the parameters have been read + /** * The constructor only sets the hand-wired defaults. */ diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 23d86c553..9f7b34614 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -93,14 +93,14 @@ ALL, // EvOProfile, ALL, // EvIProfile, TRANSFORM, // EvVignetting, RGBCURVE, // EvChMixer, -ALL, // EvResizeScale, -ALL, // EvResizeMethod, +RESIZE, // EvResizeScale, +RESIZE, // EvResizeMethod, EXIF, // EvExif, IPTC, // EvIPTC -ALL, // EvResizeSpec, -ALL, // EvResizeWidth -ALL, // EvResizeHeight -ALL, // EvResizeEnabled +RESIZE, // EvResizeSpec, +RESIZE, // EvResizeWidth +RESIZE, // EvResizeHeight +RESIZE, // EvResizeEnabled ALL, // EvProfileChangeNotification RETINEX, // EvShrHighQuality TRANSFORM, // EvPerspCorr @@ -128,6 +128,8 @@ DEFRINGE, // EvDefringeEnabled, DEFRINGE, // EvDefringeRadius, DEFRINGE, // EvDefringeThreshold, RGBCURVE, // EvHLComprThreshold, +RESIZE, // EvResizeBoundingBox +RESIZE, // EvResizeAppliesTo LUMINANCECURVE, // EvCBAvoidClip, LUMINANCECURVE, // EvCBSatLimiter, LUMINANCECURVE, // EvCBSatLimit, diff --git a/rtengine/refreshmap.h b/rtengine/refreshmap.h index 7d1ac12f4..489913c7b 100644 --- a/rtengine/refreshmap.h +++ b/rtengine/refreshmap.h @@ -59,6 +59,7 @@ #define COLORDENOISE M_COLOR #define DIRPYRDENOISE (M_COLOR|M_LUMINANCE) #define CROP M_MINUPDATE +#define RESIZE M_VOID #define EXIF M_VOID #define IPTC M_VOID #define EQUALIZER (M_COLOR|M_LUMINANCE) diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 185686685..17b7a5537 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -157,7 +157,7 @@ namespace rtengine { /** With this member function the staged processor notifies the listener that it allocated a new * image to store the end result of the processing. It can be used in a shared manner. * @param img is a pointer to the image - * @param scale describes the current scaling applied compared to the 100% size (preview scale + resize scale) + * @param scale describes the current scaling applied compared to the 100% size (preview scale) * @param cp holds the coordinates of the current crop rectangle */ virtual void setImage (IImage8* img, double scale, procparams::CropParams cp) {} /** With this member function the staged processor notifies the listener that the image passed as parameter diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 14f5d56db..4b3e7fbf5 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -741,14 +741,6 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei else myscale = scale * thumbImg->height / fh; - if (params.resize.enabled) { - if (params.resize.dataspec==0) - myscale *= params.resize.scale; - else if (params.resize.dataspec==1) - myscale *= (double)params.resize.width / (params.coarse.rotate==90 || params.coarse.rotate==270 ? thumbImg->height : thumbImg->width) / scale; - else if (params.resize.dataspec==2) - myscale *= (double)params.resize.height / (params.coarse.rotate==90 || params.coarse.rotate==270 ? thumbImg->width : thumbImg->height) / scale; - } myscale = 1.0 / myscale; /* // apply crop @@ -780,6 +772,7 @@ int Thumbnail::getImageWidth (const procparams::ProcParams& params, int rheight) void Thumbnail::getFinalSize (const rtengine::procparams::ProcParams& params, int& fullw, int& fullh) { + // WARNING: When downscaled, the ratio have loosed a lot of precision, so we can't get back the exact initial dimensions double fw = thumbImg->width*scale; double fh = thumbImg->height*scale; @@ -791,17 +784,9 @@ void Thumbnail::getFinalSize (const rtengine::procparams::ProcParams& params, in fullw = fw; fullh = fh; } - else if (params.resize.dataspec==0) { - fullw = fw*params.resize.scale; - fullh = fh*params.resize.scale; - } - else if (params.resize.dataspec==1) { - fullw = params.resize.width; - fullh = (double)fh*params.resize.width/(params.coarse.rotate==90 || params.coarse.rotate==270 ? fh : fw); - } - else if (params.resize.dataspec==2) { - fullw = (double)fw*params.resize.height/(params.coarse.rotate==90 || params.coarse.rotate==270 ? fw : fh); - fullh = params.resize.height; + else { + fullw = (int)((double)fw+0.5); + fullh = (int)((double)fh+0.5); } } diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 5454685ff..b6bf1abdd 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -51,7 +51,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p } } procparams::ProcParams& params = job->pparams; - + // aquire image from imagesource ImageSource* imgsrc = ii->getImageSource (); ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green); @@ -70,25 +70,35 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p int fw, fh; imgsrc->getFullSize (fw, fh, tr); + // check the crop params + if (params.crop.x > fw || params.crop.y > fh) { + // the crop is completely out of the image, so we disable the crop + params.crop.enabled = false; + // and we set the values to the defaults + params.crop.x = 0; + params.crop.y = 0; + params.crop.w = fw; + params.crop.h = fh; + } + else { + if ((params.crop.x + params.crop.w) > fw) { + // crop overflow in the width dimension ; we trim it + params.crop.w = fw-params.crop.x; + } + if ((params.crop.y + params.crop.h) > fh) { + // crop overflow in the height dimension ; we trim it + params.crop.h = fh-params.crop.y; + } + } + ImProcFunctions ipf (¶ms, true); Image16* baseImg; PreviewProps pp (0, 0, fw, fh, 1); imgsrc->preprocess( params.raw ); imgsrc->demosaic( params.raw ); - if (fabs(params.resize.scale-1.0)<1e-5) { - baseImg = new Image16 (fw, fh); - imgsrc->getImage (currWB, tr, baseImg, pp, params.hlrecovery, params.icm, params.raw); - } - else { - Image16* oorig = new Image16 (fw, fh); - imgsrc->getImage (currWB, tr, oorig, pp, params.hlrecovery, params.icm, params.raw); - fw *= params.resize.scale; - fh *= params.resize.scale; - baseImg = new Image16 (fw, fh); - ipf.resize (oorig, baseImg); - delete oorig; - } + baseImg = new Image16 (fw, fh); + imgsrc->getImage (currWB, tr, baseImg, pp, params.hlrecovery, params.icm, params.raw); if (pl) pl->setProgress (0.25); @@ -96,7 +106,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p unsigned int* hist16 = new unsigned int[65536]; ipf.firstAnalysis (baseImg, ¶ms, hist16, imgsrc->getGamma()); - // perform transform + // perform transform (excepted resizing) if (ipf.needsTransform()) { Image16* trImg = new Image16 (fw, fh); ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh); @@ -183,9 +193,9 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p delete [] buffer; if (pl) - pl->setProgress (0.75); + pl->setProgress (0.70); - // obtain final image + // crop and convert to rgb16 Image16* readyImg; int cx = 0, cy = 0, cw = labView->W, ch = labView->H; if (params.crop.enabled) { @@ -199,11 +209,77 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p // we can now safely delete labView delete labView; - if (pl) - pl->setProgress (1.0); + if (pl) + pl->setProgress (0.85); + + // get the resize parameters + int refw, refh; + double tmpScale; + + if (params.resize.enabled) { + + if (params.crop.enabled && params.resize.appliesTo == "Cropped area") { + // the resize values applies to the crop dimensions + refw = cw; + refh = ch; + } + else { + // the resize values applies to the image dimensions + // if a crop exists, it will be resized to the calculated scale + refw = fw; + refh = fh; + } + + switch(params.resize.dataspec) { + case (1): + // Width + tmpScale = (double)params.resize.width/(double)refw; + break; + case (2): + // Height + tmpScale = (double)params.resize.height/(double)refh; + break; + case (3): + // FitBox + if ((double)refw/(double)refh > (double)params.resize.width/(double)params.resize.height) { + tmpScale = (double)params.resize.width/(double)refw; + } + else { + tmpScale = (double)params.resize.height/(double)refh; + } + break; + default: + // Scale + tmpScale = params.resize.scale; + break; + } + + // resize image + if (fabs(tmpScale-1.0)>1e-5) + { + int imw, imh; + if (params.crop.enabled && params.resize.appliesTo == "Full image") { + imw = cw; + imh = ch; + } + else { + imw = refw; + imh = refh; + } + imw = (int)( (double)imw * tmpScale + 0.5 ); + imh = (int)( (double)imh * tmpScale + 0.5 ); + Image16* tempImage = new Image16 (imw, imh); + ipf.resize (readyImg, tempImage, tmpScale); + delete readyImg; + readyImg = tempImage; + } + } readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); + if (pl) + pl->setProgress (1.0); + ProfileContent pc; if (params.icm.output.compare (0, 6, "No ICM") && params.icm.output!="") pc = iccStore->getContent (params.icm.output); diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index fc6bb1f45..76559cca5 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -189,6 +189,8 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G for (int i=0; iwrite (&pparams, &pparamsEdited); + // TODO: We may update the crop on coarse rotate events here, like in ToolPanelCoordinator::panelChanged + if (event==rtengine::EvAutoExp || event==rtengine::EvClip) for (int i=0; isignal_value_changed().connect( sigc::mem_fun(*this, &Crop::refreshSize) ); nx = ny = nw = nh = 0; - nsx = nsy = nsw = nsh = 0; - lastScale = 1.0; lastRotationDeg = 0; show_all (); } @@ -217,15 +215,17 @@ void Crop::read (const ProcParams* pp, const ParamsEdited* pedited) { hconn.block (true); rconn.block (true); fconn.block (true); + econn.block (true); oconn.block (true); gconn.block (true); + enabled->set_active (pp->crop.enabled); // check if the new values are larger than the maximum double tmp, maxw, maxh; w->get_range (tmp, maxw); h->get_range (tmp, maxh); - if (pp->crop.x + pp->crop.w > maxw || pp->crop.y + pp->crop.h > maxh) + if (pp->crop.x + pp->crop.w > (int)maxw || pp->crop.y + pp->crop.h > (int)maxh) setDimensions (pp->crop.x + pp->crop.w, pp->crop.y + pp->crop.h); ratio->set_active_text (pp->crop.ratio); @@ -263,14 +263,6 @@ void Crop::read (const ProcParams* pp, const ParamsEdited* pedited) { nw = pp->crop.w; nh = pp->crop.h; - if (pp->resize.enabled) - lastScale = pp->resize.scale; - else - lastScale = 1.0; - nsx = nx / lastScale; - nsy = ny / lastScale; - nsw = nw / lastScale; - nsh = nh / lastScale; lastRotationDeg = pp->coarse.rotate; wDirty = false; @@ -302,6 +294,7 @@ void Crop::read (const ProcParams* pp, const ParamsEdited* pedited) { hconn.block (false); rconn.block (false); fconn.block (false); + econn.block (false); oconn.block (false); gconn.block (false); @@ -354,6 +347,41 @@ void Crop::write (ProcParams* pp, ParamsEdited* pedited) { } +void Crop::trim (ProcParams* pp, int ow, int oh) { + + int xmin = pp->crop.x; + int ymin = pp->crop.y; + + if (xmin > ow || ymin > oh) { + // the crop is completely out of the image, so we disable the crop + pp->crop.enabled = false; + // and we set the values to the defaults + pp->crop.x = 0; + pp->crop.y = 0; + pp->crop.w = ow; + pp->crop.h = oh; + // the ratio is now not guaranteed, so we set it off + pp->crop.fixratio = false; + } + else { + bool unsetRatio = false; + if ((xmin + pp->crop.w) > ow) { + // crop overflow in the width dimension ; we trim it + pp->crop.w = ow-xmin; + unsetRatio = true; + } + if ((ymin + pp->crop.h) > oh) { + // crop overflow in the height dimension ; we trim it + pp->crop.h = oh-ymin; + unsetRatio = true; + } + if (unsetRatio) { + // the ratio is certainly not respected anymore, so we set it off + pp->crop.fixratio = false; + } + } +} + void Crop::selectPressed () { if (clistener) @@ -407,32 +435,15 @@ int refreshspins (void* data) { return 0; } -void Crop::resizeScaleChanged (double rsc) { - - lastScale = rsc; - - nx = (int)round (nsx * rsc); - ny = (int)round (nsy * rsc); - nw = (int)round (nsw * rsc); - nh = (int)round (nsh * rsc); - - if (nx+nw > maxw || ny+nh > maxh) - setDimensions (nx+nw, ny+nh); - - g_idle_add (refreshspins, new RefreshSpinHelper (this, false)); -} - void Crop::hFlipCrop () { nx = maxw - nx - nw; - nsx = nx / lastScale; g_idle_add (refreshspins, new RefreshSpinHelper (this, false)); } void Crop::vFlipCrop () { ny = maxh - ny - nh; - nsy = ny / lastScale; g_idle_add (refreshspins, new RefreshSpinHelper (this, false)); } @@ -461,10 +472,6 @@ void Crop::rotateCrop (int deg) { ny = maxh - ny - nh; break; } - nsx = nx / lastScale; - nsy = ny / lastScale; - nsw = nw / lastScale; - nsh = nh / lastScale; lastRotationDeg = deg; g_idle_add (refreshspins, new RefreshSpinHelper (this, false)); @@ -561,25 +568,29 @@ void Crop::refreshSize () { } } +/* + * Set the maximum dimensions of the image. This method can be called with wrong values, then + * called with the good ones !? + */ void Crop::setDimensions (int mw, int mh) { maxw = mw; maxh = mh; - xconn.block (true); - yconn.block (true); - wconn.block (true); - hconn.block (true); + bool xconnWasBlocked = xconn.block (true); + bool yconnWasBlocked = yconn.block (true); + bool wconnWasBlocked = wconn.block (true); + bool hconnWasBlocked = hconn.block (true); w->set_range (0, maxw); h->set_range (0, maxh); x->set_range (0, maxw); y->set_range (0, maxh); - xconn.block (false); - yconn.block (false); - wconn.block (false); - hconn.block (false); + if (!xconnWasBlocked) xconn.block (false); + if (!yconnWasBlocked) yconn.block (false); + if (!wconnWasBlocked) wconn.block (false); + if (!hconnWasBlocked) hconn.block (false); if (enabled->get_active()==false) { nx = 0; @@ -587,12 +598,8 @@ void Crop::setDimensions (int mw, int mh) { nw = mw; nh = mh; - nsx = nx / lastScale; - nsy = ny / lastScale; - nsw = nw / lastScale; - nsh = nh / lastScale; refreshSpins (); - } + } refreshSize (); } @@ -671,11 +678,6 @@ void Crop::cropMoved (int &X, int &Y, int &W, int &H) { nw = W; nh = H; - nsx = nx / lastScale; - nsy = ny / lastScale; - nsw = nw / lastScale; - nsh = nh / lastScale; - g_idle_add (refreshspins, new RefreshSpinHelper (this, false)); // Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins)); } @@ -706,11 +708,6 @@ void Crop::cropWidth1Resized (int &X, int &Y, int &W, int &H) { nw = W; nh = H; - nsx = nx / lastScale; - nsy = ny / lastScale; - nsw = nw / lastScale; - nsh = nh / lastScale; - g_idle_add (refreshspins, new RefreshSpinHelper (this, false)); // Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins)); } @@ -743,11 +740,6 @@ void Crop::cropWidth2Resized (int &X, int &Y, int &W, int &H) { nw = W; nh = H; - nsx = nx / lastScale; - nsy = ny / lastScale; - nsw = nw / lastScale; - nsh = nh / lastScale; - g_idle_add (refreshspins, new RefreshSpinHelper (this, false)); // Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins)); } @@ -779,11 +771,6 @@ void Crop::cropHeight1Resized (int &X, int &Y, int &W, int &H) { nw = W; nh = H; - nsx = nx / lastScale; - nsy = ny / lastScale; - nsw = nw / lastScale; - nsh = nh / lastScale; - g_idle_add (refreshspins, new RefreshSpinHelper (this, false)); // Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins)); } @@ -815,11 +802,6 @@ void Crop::cropHeight2Resized (int &X, int &Y, int &W, int &H) { nw = W; nh = H; - nsx = nx / lastScale; - nsy = ny / lastScale; - nsw = nw / lastScale; - nsh = nh / lastScale; - g_idle_add (refreshspins, new RefreshSpinHelper (this, false)); // Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins)); } @@ -831,11 +813,6 @@ void Crop::cropInit (int &x, int &y, int &w, int &h) { nw = 1; nh = 1; - nsx = nx / lastScale; - nsy = ny / lastScale; - nsw = nw / lastScale; - nsh = nh / lastScale; - w = 1; h = 1; econn.block (true); @@ -926,11 +903,6 @@ void Crop::cropResized (int &x, int &y, int& x2, int& y2) { nw = W; nh = H; - nsx = nx / lastScale; - nsy = ny / lastScale; - nsw = nw / lastScale; - nsh = nh / lastScale; - g_idle_add (refreshspins, new RefreshSpinHelper (this, false)); // Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins)); } diff --git a/rtgui/crop.h b/rtgui/crop.h index a3cac6a36..62a36095d 100644 --- a/rtgui/crop.h +++ b/rtgui/crop.h @@ -51,7 +51,6 @@ class Crop : public Gtk::VBox, public CropGUIListener, public FoldableToolPanel, Gtk::VBox* dpibox; int maxw, maxh; int nx, ny, nw, nh; - double nsx, nsy, nsw, nsh, lastScale; int lastRotationDeg; sigc::connection xconn, yconn, wconn, hconn, econn, fconn, rconn, oconn, gconn; bool wDirty, hDirty, xDirty, yDirty, lastEnabled, lastAspect; @@ -67,7 +66,7 @@ class Crop : public Gtk::VBox, public CropGUIListener, public FoldableToolPanel, void ratioChanged (); void refreshSize (); void selectPressed (); - void setDimensions (int mw, int mh); + void setDimensions (int mw, int mh); void enabledChanged (); void positionChanged (); void widthChanged (); @@ -75,6 +74,7 @@ class Crop : public Gtk::VBox, public CropGUIListener, public FoldableToolPanel, bool refreshSpins (bool notify=false); void notifyListener (); void sizeChanged (int w, int h, int ow, int oh); + void trim (rtengine::procparams::ProcParams* pp, int ow, int oh); void readOptions (); void writeOptions (); diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 6edb47316..4ac47d661 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -1029,11 +1029,6 @@ bool EditorPanel::idle_sentToGimp(ProgressConnector *pc,rtengine::IImage16* return false; } -/* -void EditorPanel::saveOptions () { -} -*/ - void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) { if (beforeIpc) { diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index 891d948c9..c0c4f9c6a 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -270,6 +270,8 @@ void LCurve::adjusterChanged (Adjuster* a, double newval) { Glib::ustring costr; if (a==brightness) costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), a->getValue()); + else if (a==saturationlimiter) + costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(1), a->getValue()); else costr = Glib::ustring::format ((int)a->getValue()); @@ -280,7 +282,7 @@ void LCurve::adjusterChanged (Adjuster* a, double newval) { else if (a==saturation) listener->panelChanged (EvLSaturation, costr); else if (a==saturationlimiter) - listener->panelChanged (EvLSatLimiter, costr); + listener->panelChanged (EvLSatLimit, costr); } //attempt to hide unused channels diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index ff920fd78..820ed8e5a 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -28,138 +28,139 @@ ParamsEdited::ParamsEdited () { void ParamsEdited::set (bool v) { - toneCurve.curve = v; - toneCurve.brightness = v; - toneCurve.black = v; - toneCurve.contrast = v; - toneCurve.saturation = v; - toneCurve.shcompr = v; - toneCurve.hlcompr = v; - toneCurve.hlcomprthresh = v; - toneCurve.autoexp = v; - toneCurve.clip = v; - toneCurve.expcomp = v; - labCurve.lcurve = v; - labCurve.acurve = v; - labCurve.bcurve = v; - labCurve.brightness = v; - labCurve.contrast = v; - labCurve.saturation = v; - labCurve.avoidclip = v; - labCurve.enable_saturationlimiter = v; - labCurve.saturationlimit = v; - sharpening.enabled = v; - sharpening.radius = v; - sharpening.amount = v; - sharpening.threshold = v; - sharpening.edgesonly = v; - sharpening.edges_radius = v; - sharpening.edges_tolerance = v; - sharpening.halocontrol = v; - sharpening.halocontrol_amount= v; - sharpening.method = v; - sharpening.deconvamount = v; - sharpening.deconvradius = v; - sharpening.deconviter = v; - sharpening.deconvdamping = v; - colorBoost.amount = v; - colorBoost.avoidclip = v; - colorBoost.enable_saturationlimiter = v; - colorBoost.saturationlimit = v; - wb.method = v; - wb.green = v; - wb.temperature = v; - colorShift.a = v; - colorShift.b = v; - lumaDenoise.enabled = v; - lumaDenoise.radius = v; - lumaDenoise.edgetolerance = v; - colorDenoise.enabled = v; - colorDenoise.amount = v; - defringe.enabled = v; - defringe.radius = v; - defringe.threshold = v; - impulseDenoise.enabled = v; - impulseDenoise.thresh = v; - dirpyrDenoise.enabled = v; - dirpyrDenoise.luma = v; + toneCurve.curve = v; + toneCurve.brightness = v; + toneCurve.black = v; + toneCurve.contrast = v; + toneCurve.saturation = v; + toneCurve.shcompr = v; + toneCurve.hlcompr = v; + toneCurve.hlcomprthresh = v; + toneCurve.autoexp = v; + toneCurve.clip = v; + toneCurve.expcomp = v; + labCurve.lcurve = v; + labCurve.acurve = v; + labCurve.bcurve = v; + labCurve.brightness = v; + labCurve.contrast = v; + labCurve.saturation = v; + labCurve.avoidclip = v; + labCurve.enable_saturationlimiter = v; + labCurve.saturationlimit = v; + sharpening.enabled = v; + sharpening.radius = v; + sharpening.amount = v; + sharpening.threshold = v; + sharpening.edgesonly = v; + sharpening.edges_radius = v; + sharpening.edges_tolerance = v; + sharpening.halocontrol = v; + sharpening.halocontrol_amount= v; + sharpening.method = v; + sharpening.deconvamount = v; + sharpening.deconvradius = v; + sharpening.deconviter = v; + sharpening.deconvdamping = v; + colorBoost.amount = v; + colorBoost.avoidclip = v; + colorBoost.enable_saturationlimiter = v; + colorBoost.saturationlimit = v; + wb.method = v; + wb.green = v; + wb.temperature = v; + colorShift.a = v; + colorShift.b = v; + lumaDenoise.enabled = v; + lumaDenoise.radius = v; + lumaDenoise.edgetolerance = v; + colorDenoise.enabled = v; + colorDenoise.amount = v; + defringe.enabled = v; + defringe.radius = v; + defringe.threshold = v; + impulseDenoise.enabled = v; + impulseDenoise.thresh = v; + dirpyrDenoise.enabled = v; + dirpyrDenoise.luma = v; dirpyrDenoise.chroma = v; dirpyrDenoise.gamma = v; - sh.enabled = v; - sh.hq = v; - sh.highlights = v; - sh.htonalwidth = v; - sh.shadows = v; - sh.stonalwidth = v; - sh.localcontrast = v; - sh.radius = v; - crop.enabled = v; - crop.x = v; - crop.y = v; - crop.w = v; - crop.h = v; - crop.fixratio = v; - crop.ratio = v; - crop.orientation = v; - crop.guide = v; - coarse.rotate = v; - coarse.hflip = v; - coarse.vflip = v; - commonTrans.autofill = v; - rotate.degree = v; - distortion.uselensfun = v; - distortion.amount = v; - perspective.horizontal = v; - perspective.vertical = v; - cacorrection.red = v; - cacorrection.blue = v; - vignetting.amount = v; - vignetting.radius = v; - vignetting.strength = v; - vignetting.centerX = v; - vignetting.centerY = v; - chmixer.red[0] = v; - chmixer.red[1] = v; - chmixer.red[2] = v; - chmixer.green[0] = v; - chmixer.green[1] = v; - chmixer.green[2] = v; - chmixer.blue[0] = v; - chmixer.blue[1] = v; - chmixer.blue[2] = v; - hlrecovery.enabled = v; - hlrecovery.method = v; - resize.scale = v; - resize.method = v; - resize.dataspec = v; - resize.width = v; - resize.height = v; - resize.enabled = v; - icm.input = v; - icm.gammaOnInput = v; - icm.working = v; - icm.output = v; - raw.ccSteps = v; - raw.dmethod = v; - raw.dcbIterations = v; - raw.dcbEnhance = v; - raw.dfAuto = v; - raw.caCorrection = v; - raw.hotDeadPixel = v; - raw.caBlue = v; - raw.caRed = v; - raw.darkFrame = v; - raw.exPos = v; - raw.exCorrection = v; - raw.exPreser = v; - raw.greenEq = v; - raw.linenoise = v; - equalizer.enabled = v; - dirpyrequalizer.enabled = v; - hsvequalizer.enabled = v; - for(int i = 0; i < 8; i++) { - equalizer.c[i] = v; - } + sh.enabled = v; + sh.hq = v; + sh.highlights = v; + sh.htonalwidth = v; + sh.shadows = v; + sh.stonalwidth = v; + sh.localcontrast = v; + sh.radius = v; + crop.enabled = v; + crop.x = v; + crop.y = v; + crop.w = v; + crop.h = v; + crop.fixratio = v; + crop.ratio = v; + crop.orientation = v; + crop.guide = v; + coarse.rotate = v; + coarse.hflip = v; + coarse.vflip = v; + commonTrans.autofill = v; + rotate.degree = v; + distortion.uselensfun = v; + distortion.amount = v; + perspective.horizontal = v; + perspective.vertical = v; + cacorrection.red = v; + cacorrection.blue = v; + vignetting.amount = v; + vignetting.radius = v; + vignetting.strength = v; + vignetting.centerX = v; + vignetting.centerY = v; + chmixer.red[0] = v; + chmixer.red[1] = v; + chmixer.red[2] = v; + chmixer.green[0] = v; + chmixer.green[1] = v; + chmixer.green[2] = v; + chmixer.blue[0] = v; + chmixer.blue[1] = v; + chmixer.blue[2] = v; + hlrecovery.enabled = v; + hlrecovery.method = v; + resize.scale = v; + resize.appliesTo = v; + resize.method = v; + resize.dataspec = v; + resize.width = v; + resize.height = v; + resize.enabled = v; + icm.input = v; + icm.gammaOnInput = v; + icm.working = v; + icm.output = v; + raw.ccSteps = v; + raw.dmethod = v; + raw.dcbIterations = v; + raw.dcbEnhance = v; + raw.dfAuto = v; + raw.caCorrection = v; + raw.hotDeadPixel = v; + raw.caBlue = v; + raw.caRed = v; + raw.darkFrame = v; + raw.exPos = v; + raw.exCorrection = v; + raw.exPreser = v; + raw.greenEq = v; + raw.linenoise = v; + equalizer.enabled = v; + dirpyrequalizer.enabled = v; + hsvequalizer.enabled = v; + for(int i = 0; i < 8; i++) { + equalizer.c[i] = v; + } for(int i = 0; i < 5; i++) { dirpyrequalizer.mult[i] = v; } @@ -168,8 +169,8 @@ void ParamsEdited::set (bool v) { hsvequalizer.val[i] = v; hsvequalizer.hue[i] = v; } - exif.clear (); - iptc.clear (); + exif.clear (); + iptc.clear (); } using namespace rtengine; @@ -188,23 +189,23 @@ void ParamsEdited::initFrom (const std::vector toneCurve.brightness = toneCurve.brightness && p.toneCurve.brightness == other.toneCurve.brightness; toneCurve.black = toneCurve.black && p.toneCurve.black == other.toneCurve.black; toneCurve.contrast = toneCurve.contrast && p.toneCurve.contrast == other.toneCurve.contrast; - toneCurve.saturation = toneCurve.saturation && p.toneCurve.saturation == other.toneCurve.saturation; - toneCurve.shcompr = toneCurve.shcompr && p.toneCurve.shcompr == other.toneCurve.shcompr; + toneCurve.saturation = toneCurve.saturation && p.toneCurve.saturation == other.toneCurve.saturation; + toneCurve.shcompr = toneCurve.shcompr && p.toneCurve.shcompr == other.toneCurve.shcompr; toneCurve.hlcompr = toneCurve.hlcompr && p.toneCurve.hlcompr == other.toneCurve.hlcompr; toneCurve.hlcomprthresh = toneCurve.hlcomprthresh && p.toneCurve.hlcomprthresh == other.toneCurve.hlcomprthresh; toneCurve.autoexp = toneCurve.autoexp && p.toneCurve.autoexp == other.toneCurve.autoexp; toneCurve.clip = toneCurve.clip && p.toneCurve.clip == other.toneCurve.clip; toneCurve.expcomp = toneCurve.expcomp && p.toneCurve.expcomp == other.toneCurve.expcomp; labCurve.lcurve = labCurve.lcurve && p.labCurve.lcurve == other.labCurve.lcurve; - labCurve.acurve = labCurve.acurve && p.labCurve.acurve == other.labCurve.acurve; + labCurve.acurve = labCurve.acurve && p.labCurve.acurve == other.labCurve.acurve; labCurve.bcurve = labCurve.bcurve && p.labCurve.bcurve == other.labCurve.bcurve; labCurve.brightness = labCurve.brightness && p.labCurve.brightness == other.labCurve.brightness; labCurve.contrast = labCurve.contrast && p.labCurve.contrast == other.labCurve.contrast; - labCurve.saturation = labCurve.saturation && p.labCurve.saturation == other.labCurve.saturation; + labCurve.saturation = labCurve.saturation && p.labCurve.saturation == other.labCurve.saturation; labCurve.avoidclip = labCurve.avoidclip && p.labCurve.avoidclip == other.labCurve.avoidclip; labCurve.enable_saturationlimiter = labCurve.enable_saturationlimiter && p.labCurve.enable_saturationlimiter == other.labCurve.enable_saturationlimiter; labCurve.saturationlimit = labCurve.saturationlimit && p.labCurve.saturationlimit == other.labCurve.saturationlimit; - sharpening.enabled = sharpening.enabled && p.sharpening.enabled == other.sharpening.enabled; + sharpening.enabled = sharpening.enabled && p.sharpening.enabled == other.sharpening.enabled; sharpening.radius = sharpening.radius && p.sharpening.radius == other.sharpening.radius; sharpening.amount = sharpening.amount && p.sharpening.amount == other.sharpening.amount; sharpening.threshold = sharpening.threshold && p.sharpening.threshold == other.sharpening.threshold; @@ -232,17 +233,17 @@ void ParamsEdited::initFrom (const std::vector lumaDenoise.edgetolerance = lumaDenoise.edgetolerance && p.lumaDenoise.edgetolerance == other.lumaDenoise.edgetolerance; colorDenoise.enabled = colorDenoise.enabled && p.colorDenoise.enabled == other.colorDenoise.enabled; colorDenoise.amount = colorDenoise.amount && p.colorDenoise.amount == other.colorDenoise.amount; - defringe.enabled = defringe.enabled && p.defringe.enabled == other.defringe.enabled; + defringe.enabled = defringe.enabled && p.defringe.enabled == other.defringe.enabled; defringe.radius = defringe.radius && p.defringe.radius == other.defringe.radius; defringe.threshold = defringe.threshold && p.defringe.threshold == other.defringe.threshold; - impulseDenoise.enabled = impulseDenoise.enabled && p.impulseDenoise.enabled == other.impulseDenoise.enabled; - impulseDenoise.thresh = impulseDenoise.thresh && p.impulseDenoise.thresh == other.impulseDenoise.thresh; + impulseDenoise.enabled = impulseDenoise.enabled && p.impulseDenoise.enabled == other.impulseDenoise.enabled; + impulseDenoise.thresh = impulseDenoise.thresh && p.impulseDenoise.thresh == other.impulseDenoise.thresh; - dirpyrDenoise.enabled = dirpyrDenoise.enabled && p.dirpyrDenoise.enabled == other.dirpyrDenoise.enabled; + dirpyrDenoise.enabled = dirpyrDenoise.enabled && p.dirpyrDenoise.enabled == other.dirpyrDenoise.enabled; dirpyrDenoise.luma = dirpyrDenoise.luma && p.dirpyrDenoise.luma == other.dirpyrDenoise.luma; dirpyrDenoise.chroma = dirpyrDenoise.chroma && p.dirpyrDenoise.chroma == other.dirpyrDenoise.chroma; - dirpyrDenoise.gamma = dirpyrDenoise.gamma && p.dirpyrDenoise.gamma == other.dirpyrDenoise.gamma; + dirpyrDenoise.gamma = dirpyrDenoise.gamma && p.dirpyrDenoise.gamma == other.dirpyrDenoise.gamma; sh.enabled = sh.enabled && p.sh.enabled == other.sh.enabled; sh.hq = sh.hq && p.sh.hq == other.sh.hq; @@ -289,6 +290,7 @@ void ParamsEdited::initFrom (const std::vector hlrecovery.enabled = hlrecovery.enabled && p.hlrecovery.enabled == other.hlrecovery.enabled; hlrecovery.method = hlrecovery.method && p.hlrecovery.method == other.hlrecovery.method; resize.scale = resize.scale && p.resize.scale == other.resize.scale; + resize.appliesTo = resize.appliesTo && p.resize.appliesTo == other.resize.appliesTo; resize.method = resize.method && p.resize.method == other.resize.method; resize.dataspec = resize.dataspec && p.resize.dataspec == other.resize.dataspec; resize.width = resize.width && p.resize.width == other.resize.width; @@ -317,14 +319,14 @@ void ParamsEdited::initFrom (const std::vector for(int i = 0; i < 8; i++) { equalizer.c[i] = equalizer.c[i] && p.equalizer.c[i] == other.equalizer.c[i]; } - dirpyrequalizer.enabled = dirpyrequalizer.enabled && p.dirpyrequalizer.enabled == other.dirpyrequalizer.enabled; + dirpyrequalizer.enabled = dirpyrequalizer.enabled && p.dirpyrequalizer.enabled == other.dirpyrequalizer.enabled; for(int i = 0; i < 8; i++) { dirpyrequalizer.mult[i] = dirpyrequalizer.mult[i] && p.dirpyrequalizer.mult[i] == other.dirpyrequalizer.mult[i]; } - hsvequalizer.enabled = hsvequalizer.enabled && p.hsvequalizer.enabled == other.hsvequalizer.enabled; + hsvequalizer.enabled = hsvequalizer.enabled && p.hsvequalizer.enabled == other.hsvequalizer.enabled; for(int i = 0; i < 8; i++) { hsvequalizer.sat[i] = hsvequalizer.sat[i] && p.hsvequalizer.sat[i] == other.hsvequalizer.sat[i]; - hsvequalizer.val[i] = hsvequalizer.val[i] && p.hsvequalizer.val[i] == other.hsvequalizer.val[i]; + hsvequalizer.val[i] = hsvequalizer.val[i] && p.hsvequalizer.val[i] == other.hsvequalizer.val[i]; hsvequalizer.hue[i] = hsvequalizer.hue[i] && p.hsvequalizer.hue[i] == other.hsvequalizer.hue[i]; } // exif = exif && p.exif==other.exif @@ -440,6 +442,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (hlrecovery.enabled) toEdit.hlrecovery.enabled = mods.hlrecovery.enabled; if (hlrecovery.method) toEdit.hlrecovery.method = mods.hlrecovery.method; if (resize.scale) toEdit.resize.scale = mods.resize.scale; + if (resize.appliesTo) toEdit.resize.appliesTo = mods.resize.appliesTo; if (resize.method) toEdit.resize.method = mods.resize.method; if (resize.dataspec) toEdit.resize.dataspec = mods.resize.dataspec; if (resize.width) toEdit.resize.width = mods.resize.width; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 8004a90af..200befbee 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -235,6 +235,7 @@ class ResizeParamsEdited { public: bool scale; + bool appliesTo; bool method; bool dataspec; bool width; @@ -321,9 +322,9 @@ class ParamsEdited { LumaDenoiseParamsEdited lumaDenoise; ColorDenoiseParamsEdited colorDenoise; - DefringeParamsEdited defringe; - DirPyrDenoiseParamsEdited dirpyrDenoise; - ImpulseDenoiseParamsEdited impulseDenoise; + DefringeParamsEdited defringe; + DirPyrDenoiseParamsEdited dirpyrDenoise; + ImpulseDenoiseParamsEdited impulseDenoise; SHParamsEdited sh; CropParamsEdited crop; @@ -340,8 +341,8 @@ class ParamsEdited { ColorManagementParamsEdited icm; EqualizerParamsEdited equalizer; RAWParamsEdited raw; - DirPyrEqualizerParamsEdited dirpyrequalizer; - HSVEqualizerParamsEdited hsvequalizer; + DirPyrEqualizerParamsEdited dirpyrequalizer; + HSVEqualizerParamsEdited hsvequalizer; std::vector exif; std::vector iptc; diff --git a/rtgui/resize.cc b/rtgui/resize.cc index 25f762002..273b25b9d 100644 --- a/rtgui/resize.cc +++ b/rtgui/resize.cc @@ -25,12 +25,23 @@ using namespace rtengine::procparams; Resize::Resize () : Gtk::VBox(), FoldableToolPanel(this), maxw(100000), maxh(100000) { + cropw = 0; + croph = 0; + enabled = Gtk::manage (new Gtk::CheckButton (M("GENERAL_ENABLED"))); pack_start(*enabled); pack_start(*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_SHRINK, 2); Gtk::Table* combos = Gtk::manage (new Gtk::Table (2, 2)); + appliesTo = Gtk::manage (new Gtk::ComboBoxText ()); + appliesTo->append_text (M("TP_RESIZE_CROPPEDAREA")); + appliesTo->append_text (M("TP_RESIZE_FULLIMAGE")); + appliesTo->set_active (0); + + combos->attach (*Gtk::manage (new Gtk::Label (M("TP_RESIZE_APPLIESTO"))), 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + combos->attach (*appliesTo, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + method = Gtk::manage (new Gtk::ComboBoxText ()); method->append_text (M("TP_RESIZE_NEAREST")); method->append_text (M("TP_RESIZE_BILINEAR")); @@ -42,22 +53,23 @@ Resize::Resize () : Gtk::VBox(), FoldableToolPanel(this), maxw(100000), maxh(100 method->append_text (M("TP_RESIZE_LANCZOS")); method->set_active (0); - combos->attach (*Gtk::manage (new Gtk::Label (M("TP_RESIZE_METHOD"))), 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - combos->attach (*method, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + combos->attach (*Gtk::manage (new Gtk::Label (M("TP_RESIZE_METHOD"))), 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + combos->attach (*method, 1, 2, 1, 2, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); spec = Gtk::manage (new Gtk::ComboBoxText ()); spec->append_text (M("TP_RESIZE_SCALE")); spec->append_text (M("TP_RESIZE_WIDTH")); spec->append_text (M("TP_RESIZE_HEIGHT")); - method->set_active (0); + spec->append_text (M("TP_RESIZE_FITBOX")); + spec->set_active (0); - combos->attach (*Gtk::manage (new Gtk::Label (M("TP_RESIZE_SPECIFY"))), 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - combos->attach (*spec, 1, 2, 1, 2, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + combos->attach (*Gtk::manage (new Gtk::Label (M("TP_RESIZE_SPECIFY"))), 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + combos->attach (*spec, 1, 2, 2, 3, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); pack_start (*combos, Gtk::PACK_SHRINK, 4); - scale = new Adjuster (M("TP_RESIZE_SCALE"), 0.2, 4, 0.01, 1); - scale->setAdjusterListener (this); + scale = new Adjuster (M("TP_RESIZE_SCALE"), 0.01, 4, 0.01, 1.); + scale->setAdjusterListener (this); pack_start (*scale, Gtk::PACK_SHRINK, 4); @@ -91,8 +103,9 @@ Resize::Resize () : Gtk::VBox(), FoldableToolPanel(this), maxw(100000), maxh(100 wconn = w->signal_value_changed().connect ( sigc::mem_fun(*this, &Resize::entryWChanged), true); hconn = h->signal_value_changed().connect ( sigc::mem_fun(*this, &Resize::entryHChanged), true); + aconn = appliesTo->signal_changed().connect ( sigc::mem_fun(*this, &Resize::appliesToChanged) ); method->signal_changed().connect ( sigc::mem_fun(*this, &Resize::methodChanged) ); - spec->signal_changed().connect ( sigc::mem_fun(*this, &Resize::specChanged) ); + sconn = spec->signal_changed().connect ( sigc::mem_fun(*this, &Resize::specChanged) ); enaConn = enabled->signal_toggled().connect ( sigc::mem_fun(*this, &Resize::enabledToggled) ); show_all(); @@ -107,14 +120,24 @@ Resize::~Resize () { void Resize::read (const ProcParams* pp, const ParamsEdited* pedited) { disableListener (); + aconn.block (true); wconn.block (true); hconn.block (true); + sconn.block (true); + scale->block(true); scale->setValue (pp->resize.scale); w->set_value (pp->resize.width); h->set_value (pp->resize.height); enabled->set_active (pp->resize.enabled); spec->set_active (pp->resize.dataspec); + updateGUI(); + + appliesTo->set_active (0); + if (pp->resize.appliesTo == "Cropped area") + appliesTo->set_active (0); + else if (pp->resize.appliesTo == "Full image") + appliesTo->set_active (1); method->set_active (2); if (pp->resize.method == "Nearest") @@ -141,23 +164,36 @@ void Resize::read (const ProcParams* pp, const ParamsEdited* pedited) { wDirty = pedited->resize.width; hDirty = pedited->resize.height; scale->setEditedState (pedited->resize.scale ? Edited : UnEdited); + if (!pedited->resize.appliesTo) + method->set_active (2); if (!pedited->resize.method) - method->set_active (5); + method->set_active (8); if (!pedited->resize.dataspec) - spec->set_active (3); + spec->set_active (4); enabled->set_inconsistent (!pedited->resize.enabled); } lastEnabled = pp->resize.enabled; + scale->block(false); + sconn.block (false); wconn.block (false); hconn.block (false); + aconn.block (false); enableListener (); } void Resize::write (ProcParams* pp, ParamsEdited* pedited) { + int dataSpec = spec->get_active_row_number(); + + pp->resize.scale = scale->getValue(); + + pp->resize.appliesTo = "Cropped area"; + if (appliesTo->get_active_row_number() == 0) + pp->resize.appliesTo = "Cropped area"; + else if (appliesTo->get_active_row_number() == 1) + pp->resize.appliesTo = "Full image"; - pp->resize.scale = scale->getValue (); pp->resize.method = "Bicubic"; if (method->get_active_row_number() == 0) pp->resize.method = "Nearest"; @@ -176,15 +212,17 @@ void Resize::write (ProcParams* pp, ParamsEdited* pedited) { else if (method->get_active_row_number() == 7) pp->resize.method = "Lanczos"; - pp->resize.dataspec = spec->get_active_row_number(); - pp->resize.width = round (w->get_value ()); - pp->resize.height = round(h->get_value ()); + pp->resize.dataspec = dataSpec; + pp->resize.width = w->get_value_as_int (); + pp->resize.height = h->get_value_as_int (); pp->resize.enabled = enabled->get_active (); + //printf(" L:%d H:%d\n", pp->resize.width, pp->resize.height); if (pedited) { pedited->resize.enabled = !enabled->get_inconsistent(); - pedited->resize.dataspec = spec->get_active_row_number() != 3; - pedited->resize.method = method->get_active_row_number() != 5; + pedited->resize.dataspec = dataSpec != 4; + pedited->resize.appliesTo = appliesTo->get_active_row_number() != 2; + pedited->resize.method = method->get_active_row_number() != 8; if (pedited->resize.dataspec) { pedited->resize.scale = scale->getEditedState (); pedited->resize.width = wDirty; @@ -213,14 +251,44 @@ void Resize::adjusterChanged (Adjuster* a, double newval) { if (!batchMode) { wconn.block (true); hconn.block (true); - h->set_value (maxh * a->getValue ()); - w->set_value (maxw * a->getValue ()); + h->set_value ((croph && appliesTo->get_active_row_number()==0 ? croph : maxh) * a->getValue ()); + w->set_value ((cropw && appliesTo->get_active_row_number()==0 ? cropw : maxw) * a->getValue ()); wconn.block (false); hconn.block (false); } if (listener && (enabled->get_active () || batchMode)) - listener->panelChanged (EvResizeScale, Glib::ustring::format (std::setw(5), std::fixed, std::setprecision(4), scale->getValue())); + listener->panelChanged (EvResizeScale, Glib::ustring::format (std::setw(5), std::fixed, std::setprecision(2), scale->getValue())); +} + +int Resize::getComputedWidth() { + + if (cropw && appliesTo->get_active_row_number()==0) + // we use the crop dimensions + return (int)((double)(cropw) * (h->get_value()/(double)(croph)) + 0.5); + else + // we use the image dimensions + return (int)((double)(maxw) * (h->get_value()/(double)(maxh)) + 0.5); +} + +int Resize::getComputedHeight() { + + if (croph && appliesTo->get_active_row_number()==0) + // we use the crop dimensions + return (int)((double)(croph) * (w->get_value()/(double)(cropw)) + 0.5); + else + // we use the image dimensions + return (int)((double)(maxh) * (w->get_value()/(double)(maxw)) + 0.5); +} + +void Resize::appliesToChanged () { + + //printf("\nPASSAGE EN MODE \"%s\"\n\n", appliesTo->get_active_text().c_str()); + setDimensions(); + if (listener && (enabled->get_active () || batchMode)) { + //printf("Appel du listener\n"); + listener->panelChanged (EvResizeAppliesTo, appliesTo->get_active_text()); + } } void Resize::methodChanged () { @@ -229,65 +297,155 @@ void Resize::methodChanged () { listener->panelChanged (EvResizeMethod, method->get_active_text()); } -struct setrdimparams { - Resize* resize; - int mw; - int mh; - int ow; - int oh; -}; +void Resize::update (bool isCropped, int cw, int ch, int ow, int oh) { -int setrdim (void* data) { + // updating crop values now + if (isCropped) { + cropw = cw; + croph = ch; + } + else { + cropw = 0; + croph = 0; + } - gdk_threads_enter (); - setrdimparams* params = (setrdimparams*)data; - params->resize->setDimensions (params->mw, params->mh, params->ow, params->oh); - delete params; - gdk_threads_leave (); - return 0; + // updating the full image dimensions + if (ow && oh) { + maxw = ow; + maxh = oh; + } + // updating the GUI synchronously + setDimensions(); } void Resize::sizeChanged (int mw, int mh, int ow, int oh) { - setrdimparams* params = new setrdimparams; - params->mw = mw; - params->mh = mh; - params->ow = ow; - params->oh = oh; - params->resize = this; - g_idle_add (setrdim, params); -} - -void Resize::setDimensions (int mw, int mh, int ow, int oh) { - + // updating max values now maxw = ow; maxh = oh; - + + // updating the GUI synchronously + setDimensions(); +} + +void Resize::setDimensions () { + + int refw, refh; + wconn.block (true); hconn.block (true); + scale->block(true); - w->set_range (32, 4*maxw); - h->set_range (32, 4*maxh); + if (appliesTo->get_active_row_number()==0 && cropw) { + // Applies to Cropped area + refw = cropw; + refh = croph; + } + else { + // Applies to Full image or crop is disabled + refw = maxw; + refh = maxh; + } + w->set_range (32, 4*refw); + h->set_range (32, 4*refh); + double tmpScale; + switch (spec->get_active_row_number()) { + case (0): // Scale mode + w->set_value((double)((int)( (double)(refw) * scale->getValue() + 0.5) )); + h->set_value((double)((int)( (double)(refh) * scale->getValue() + 0.5) )); + break; + case (1): // Width mode + tmpScale = w->get_value() / (double)refw; + scale->setValue (tmpScale); + h->set_value((double)((int)( (double)(refh) * tmpScale + 0.5) )); + break; + case (2): // Height mode + tmpScale = h->get_value() / (double)refh; + scale->setValue (tmpScale); + w->set_value((double)((int)( (double)(refw) * tmpScale + 0.5) )); + case (3): { // Bounding box mode + double wSliderValue = w->get_value(); + double hSliderValue = h->get_value(); + if ( (wSliderValue/hSliderValue) < ((double)refw/(double)refh)) { + tmpScale = wSliderValue / (double)refw; + } + else { + tmpScale = hSliderValue / (double)refh; + } + scale->setValue (tmpScale); + break; + } + default: + break; + } + + scale->block(false); wconn.block (false); hconn.block (false); } +void Resize::fitBoxScale() { + double tmpScale; + double neww = w->get_value (); + double newh = h->get_value (); + + if (cropw && appliesTo->get_active_row_number()==0) { + // we use the crop dimensions + if (((double)(cropw) / (double)(croph)) > (neww / newh)) { + // the new scale is given by the image width + tmpScale = neww / (double)(cropw); + } + else { + // the new scale is given by the image height + tmpScale = newh / (double)(croph); + } + } + else { + // we use the image dimensions + if (((double)(maxw) / (double)(maxh)) > (neww / newh)) { + // the new scale is given by the image width + tmpScale = neww / (double)(maxw); + } + else { + // the new scale is given by the image height + tmpScale = newh / (double)(maxh); + } + } + scale->setValue (tmpScale); +} + void Resize::entryWChanged () { wDirty = true; - if (!batchMode && listener) { - hconn.block (true); - h->set_value (w->get_value () * maxh / maxw); - hconn.block (false); - scale->setValue (w->get_value () / maxw); + // updating width + if (!batchMode) { + if (spec->get_active_row_number() == 3) { + // Fit box mode + fitBoxScale(); + } + else { + // Other modes + hconn.block (true); + scale->block (true); + + h->set_value ((double)(getComputedHeight())); + scale->setValue (w->get_value () / (cropw && appliesTo->get_active_row_number()==0 ? (double)cropw : (double)maxw)); + + scale->block (false); + hconn.block (false); + } } - if (listener && (enabled->get_active () || batchMode)) - listener->panelChanged (EvResizeWidth, Glib::ustring::format ((int)w->get_value())); - - + if (listener) { + if (spec->get_active_row_number() == 3) + notifyBBox(); + else { + if (enabled->get_active () || batchMode) + listener->panelChanged (EvResizeWidth, Glib::ustring::format (w->get_value_as_int())); + } + } } void Resize::entryHChanged () { @@ -295,39 +453,96 @@ void Resize::entryHChanged () { hDirty = true; if (!batchMode && listener) { - wconn.block (true); - w->set_value (h->get_value () * maxw / maxh); - wconn.block (false); - scale->setValue (h->get_value () / maxh); + if (spec->get_active_row_number() == 3) { + // Fit box mode + fitBoxScale(); + } + else { + // Other modes + wconn.block (true); + scale->block (true); + + w->set_value ((double)(getComputedWidth())); + scale->setValue (h->get_value () / (croph && appliesTo->get_active_row_number()==0 ? (double)croph : (double)maxh)); + + scale->block (false); + wconn.block (false); + } } - if (listener && (enabled->get_active () || batchMode)) - listener->panelChanged (EvResizeHeight, Glib::ustring::format ((int)h->get_value())); + if (listener) { + if (spec->get_active_row_number() == 3) + notifyBBox(); + else { + if (enabled->get_active () || batchMode) + listener->panelChanged (EvResizeHeight, Glib::ustring::format (h->get_value_as_int())); + } + } } void Resize::specChanged () { + switch (spec->get_active_row_number()) { + case (0): + // Scale mode + scale->sliderChanged (); + break; + case (1): + // Width mode + w->set_value((double)(getComputedWidth())); + entryWChanged (); + break; + case (2): + // Height mode + h->set_value((double)(getComputedHeight())); + entryHChanged (); + break; + case (3): + // Bounding box mode + notifyBBox(); + default: + break; + } + updateGUI(); +} + +void Resize::updateGUI () { + removeIfThere (this, scale, false); removeIfThere (this, sizeBox, false); - if (spec->get_active_row_number() == 0) { + switch (spec->get_active_row_number()) { + case (0): + // Scale mode pack_start (*scale, Gtk::PACK_SHRINK, 4); - scale->sliderChanged (); - } - else if (spec->get_active_row_number() == 1) { + break; + case (1): + // Width mode pack_start (*sizeBox, Gtk::PACK_SHRINK, 4); w->set_sensitive (true); h->set_sensitive (false); - entryWChanged (); - } - else if (spec->get_active_row_number() == 2) { + break; + case (2): + // Height mode pack_start (*sizeBox, Gtk::PACK_SHRINK, 4); - h->set_sensitive (true); w->set_sensitive (false); - entryHChanged (); + h->set_sensitive (true); + break; + case (3): + // Bounding box mode + pack_start (*sizeBox, Gtk::PACK_SHRINK, 4); + w->set_sensitive (true); + h->set_sensitive (true); + default: + break; } } +void Resize::notifyBBox() { + if (listener && (enabled->get_active () || batchMode)) + listener->panelChanged (EvResizeBoundingBox, Glib::ustring::compose("(%1x%2)",(int)w->get_value(), (int)h->get_value() )); +} + void Resize::setBatchMode (bool batchMode) { method->append_text (M("GENERAL_UNCHANGED")); diff --git a/rtgui/resize.h b/rtgui/resize.h index e80cef164..85a795a53 100644 --- a/rtgui/resize.h +++ b/rtgui/resize.h @@ -29,12 +29,14 @@ class Resize : public Gtk::VBox, public AdjusterListener, public FoldableToolPan Gtk::CheckButton* enabled; Adjuster* scale; Gtk::VBox* sizeBox; + Gtk::ComboBoxText* appliesTo; Gtk::ComboBoxText* method; Gtk::ComboBoxText* spec; Gtk::SpinButton* w; Gtk::SpinButton* h; int maxw, maxh; - sigc::connection wconn, hconn, enaConn; + int cropw, croph; + sigc::connection sconn, aconn, wconn, hconn, enaConn; bool wDirty, hDirty, lastEnabled; public: @@ -47,14 +49,24 @@ class Resize : public Gtk::VBox, public AdjusterListener, public FoldableToolPan void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); void setBatchMode (bool batchMode); - void adjusterChanged (Adjuster* a, double newval); - void entryWChanged (); - void entryHChanged (); - void methodChanged (); - void specChanged (); - void sizeChanged (int w, int h, int ow, int oh); - void setDimensions (int w, int h, int ow, int oh); - void enabledToggled (); + void adjusterChanged (Adjuster* a, double newval); + void entryWChanged (); + void entryHChanged (); + void appliesToChanged (); + void methodChanged (); + void specChanged (); + void update (bool isCropped, int cw, int ch, int ow=0, int oh=0); + void setGUIFromCrop (bool isCropped, int cw, int ch); + void sizeChanged (int w, int h, int ow, int oh); + void setDimensions (); + void enabledToggled (); + + private: + void fitBoxScale (); + int getComputedWidth (); + int getComputedHeight (); + void notifyBBox (); + void updateGUI (); }; #endif diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 1f1295433..34a8e0f19 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -20,6 +20,7 @@ #include #include #include +#include using namespace rtengine::procparams; @@ -36,19 +37,19 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) { shadowshighlights = Gtk::manage (new ShadowsHighlights ()); lumadenoise = Gtk::manage (new LumaDenoise ()); colordenoise = Gtk::manage (new ColorDenoise ()); - impulsedenoise = Gtk::manage (new ImpulseDenoise ()); - defringe = Gtk::manage (new Defringe ()); - dirpyrdenoise = Gtk::manage (new DirPyrDenoise ()); + impulsedenoise = Gtk::manage (new ImpulseDenoise ()); + defringe = Gtk::manage (new Defringe ()); + dirpyrdenoise = Gtk::manage (new DirPyrDenoise ()); sharpening = Gtk::manage (new Sharpening ()); lcurve = Gtk::manage (new LCurve ()); colorboost = Gtk::manage (new ColorBoost ()); colorshift = Gtk::manage (new ColorShift ()); - lensgeom = Gtk::manage (new LensGeometry ()); + lensgeom = Gtk::manage (new LensGeometry ()); distortion = Gtk::manage (new Distortion ()); rotate = Gtk::manage (new Rotate ()); whitebalance = Gtk::manage (new WhiteBalance ()); vignetting = Gtk::manage (new Vignetting ()); - perspective = Gtk::manage (new PerspCorrection ()); + perspective = Gtk::manage (new PerspCorrection ()); cacorrection = Gtk::manage (new CACorrection ()); hlrecovery = Gtk::manage (new HLRecovery ()); chmixer = Gtk::manage (new ChMixer ()); @@ -59,7 +60,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) { iptcpanel = Gtk::manage (new IPTCPanel ()); equalizer = Gtk::manage (new Equalizer ()); dirpyrequalizer = Gtk::manage (new DirPyrEqualizer ()); - hsvequalizer = Gtk::manage (new HSVEqualizer ()); + hsvequalizer = Gtk::manage (new HSVEqualizer ()); rawprocess = Gtk::manage (new RawProcess ()); preprocess = Gtk::manage (new PreProcess ()); @@ -71,14 +72,14 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) { addPanel (detailsPanel, sharpening, M("TP_SHARPENING_LABEL")); toolPanels.push_back (sharpening); //addPanel (colorPanel, colorboost, M("TP_COLORBOOST_LABEL")); toolPanels.push_back (colorboost); //addPanel (colorPanel, colorshift, M("TP_COLORSHIFT_LABEL")); toolPanels.push_back (colorshift); - addPanel (colorPanel, hsvequalizer, M("TP_HSVEQUALIZER_LABEL")); toolPanels.push_back (hsvequalizer); - addPanel (exposurePanel, lcurve, M("TP_LABCURVE_LABEL")); toolPanels.push_back (lcurve); - addPanel (detailsPanel, impulsedenoise, M("TP_IMPULSEDENOISE_LABEL")); toolPanels.push_back (impulsedenoise); + addPanel (colorPanel, hsvequalizer, M("TP_HSVEQUALIZER_LABEL")); toolPanels.push_back (hsvequalizer); + addPanel (exposurePanel, lcurve, M("TP_LABCURVE_LABEL")); toolPanels.push_back (lcurve); + addPanel (detailsPanel, impulsedenoise, M("TP_IMPULSEDENOISE_LABEL")); toolPanels.push_back (impulsedenoise); //addPanel (detailsPanel, lumadenoise, M("TP_LUMADENOISE_LABEL")); toolPanels.push_back (lumadenoise); //addPanel (detailsPanel, colordenoise, M("TP_COLORDENOISE_LABEL")); toolPanels.push_back (colordenoise); - addPanel (detailsPanel, dirpyrdenoise, M("TP_DIRPYRDENOISE_LABEL")); toolPanels.push_back (dirpyrdenoise); - addPanel (detailsPanel, defringe, M("TP_DEFRINGE_LABEL")); toolPanels.push_back (defringe); - addPanel (detailsPanel, dirpyrequalizer, M("TP_DIRPYREQUALIZER_LABEL")); toolPanels.push_back (dirpyrequalizer); + addPanel (detailsPanel, dirpyrdenoise, M("TP_DIRPYRDENOISE_LABEL")); toolPanels.push_back (dirpyrdenoise); + addPanel (detailsPanel, defringe, M("TP_DEFRINGE_LABEL")); toolPanels.push_back (defringe); + addPanel (detailsPanel, dirpyrequalizer, M("TP_DIRPYREQUALIZER_LABEL")); toolPanels.push_back (dirpyrequalizer); //addPanel (detailsPanel, equalizer, M("TP_EQUALIZER_LABEL")); toolPanels.push_back (equalizer); addPanel (transformPanel, crop, M("TP_CROP_LABEL")); toolPanels.push_back (crop); addPanel (transformPanel, resize, M("TP_RESIZE_LABEL")); toolPanels.push_back (resize); @@ -173,11 +174,7 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib:: toolPanels[i]->write (params); // some transformations make the crop change for convenience - if (event==rtengine::EvResizeScale) { - crop->resizeScaleChanged (params->resize.scale); - crop->write (params); - } - else if (event==rtengine::EvCTHFlip) { + if (event==rtengine::EvCTHFlip) { crop->hFlipCrop (); crop->write (params); } @@ -188,6 +185,12 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib:: else if (event==rtengine::EvCTRotate) { crop->rotateCrop (params->coarse.rotate); crop->write (params); + resize->update (params->crop.enabled, params->crop.w, params->crop.h, ipc->getFullWidth(), ipc->getFullHeight()); + resize->write (params); + } + else if (event==rtengine::EvCrop) { + resize->update (params->crop.enabled, params->crop.w, params->crop.h); + resize->write (params); } ipc->paramsUpdateReady (); @@ -200,11 +203,25 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib:: void ToolPanelCoordinator::profileChange (const ProcParams *nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited) { + int fw, fh, tr; + if (!ipc) return; - ProcParams* params = ipc->getParamsForUpdate (event); + ProcParams *params = ipc->getParamsForUpdate (event); *params = *nparams; - for (int i=0; iread (nparams); + + tr = TR_NONE; + if (params->coarse.rotate==90) tr |= TR_R90; + if (params->coarse.rotate==180) tr |= TR_R180; + if (params->coarse.rotate==270) tr |= TR_R270; + + // trimming overflowing cropped area + rtengine::ImageSource *ii = (rtengine::ImageSource*)ipc->getInitialImage(); + ii->getFullSize (fw, fh, tr); + crop->trim(params, fw, fh); + + // updating the GUI with updated values + for (unsigned int i=0; iread (params); ipc->paramsUpdateReady (); diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 5d757c591..cdd9c9e9d 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -91,14 +91,14 @@ class ToolPanelCoordinator : public ToolPanelListener, ShadowsHighlights* shadowshighlights; LumaDenoise* lumadenoise; ColorDenoise* colordenoise; - Defringe* defringe; - ImpulseDenoise* impulsedenoise; - DirPyrDenoise* dirpyrdenoise; + Defringe* defringe; + ImpulseDenoise* impulsedenoise; + DirPyrDenoise* dirpyrdenoise; Sharpening* sharpening; LCurve* lcurve; Equalizer * equalizer; - DirPyrEqualizer * dirpyrequalizer; - HSVEqualizer * hsvequalizer; + DirPyrEqualizer * dirpyrequalizer; + HSVEqualizer * hsvequalizer; RawProcess* rawprocess; PreProcess* preprocess;