From 3d40d9cdcebe34cb8f7f8dcb890e1c752ddae25a Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Mon, 1 Jan 2018 09:39:38 +0100 Subject: [PATCH 01/22] fixed non-uniform spacing in denoise gui --- rtgui/dirpyrdenoise.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc index bb367becc..f79770a62 100644 --- a/rtgui/dirpyrdenoise.cc +++ b/rtgui/dirpyrdenoise.cc @@ -119,15 +119,15 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP bluechro = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_CHROMINANCE_BLUEYELLOW"), -100, 100, 0.1, 0)); Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); - hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_DIRPYRDENOISE_MAIN_COLORSPACE") + ": ")), Gtk::PACK_SHRINK, 4); + hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_DIRPYRDENOISE_MAIN_COLORSPACE") + ": ")), Gtk::PACK_SHRINK, 1); hb1->set_tooltip_markup (M("TP_DIRPYRDENOISE_MAIN_COLORSPACE_TOOLTIP")); dmethod = Gtk::manage (new MyComboBoxText ()); dmethod->append (M("TP_DIRPYRDENOISE_MAIN_COLORSPACE_LAB")); dmethod->append (M("TP_DIRPYRDENOISE_MAIN_COLORSPACE_RGB")); dmethod->set_active(0); - hb1->pack_end (*dmethod, Gtk::PACK_EXPAND_WIDGET, 4); - pack_start( *hb1, Gtk::PACK_SHRINK, 4); + hb1->pack_end (*dmethod, Gtk::PACK_EXPAND_WIDGET, 1); + pack_start(*hb1, Gtk::PACK_SHRINK, 1); dmethodconn = dmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::dmethodChanged) ); @@ -220,7 +220,7 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP ctboxrgb->pack_start (*labrgb, Gtk::PACK_SHRINK, 1); Gtk::HBox* hb11 = Gtk::manage (new Gtk::HBox ()); - hb11->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_DIRPYRDENOISE_MAIN_MODE") + ": ")), Gtk::PACK_SHRINK, 4); + hb11->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_DIRPYRDENOISE_MAIN_MODE") + ": ")), Gtk::PACK_SHRINK, 1); hb11->set_tooltip_markup (M("TP_DIRPYRDENOISE_MAIN_MODE_TOOLTIP")); smethod = Gtk::manage (new MyComboBoxText ()); @@ -230,15 +230,15 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP // smethod->append (M("TP_DIRPYRDENOISE_MAIN_MODE_SHALAL")); // smethod->append (M("TP_DIRPYRDENOISE_MAIN_MODE_SHBIBI")); smethod->set_active(1); - hb11->pack_start (*smethod, Gtk::PACK_EXPAND_WIDGET, 4); - pack_start( *hb11, Gtk::PACK_SHRINK, 4); + hb11->pack_start (*smethod, Gtk::PACK_EXPAND_WIDGET, 1); + pack_start( *hb11, Gtk::PACK_SHRINK, 1); smethodconn = smethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::smethodChanged) ); gamma = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_MAIN_GAMMA"), 1.0, 3.0, 0.01, 1.7)); gamma->set_tooltip_text (M("TP_DIRPYRDENOISE_MAIN_GAMMA_TOOLTIP")); gamma->setAdjusterListener (this); gamma->show(); - pack_start (*gamma); + pack_start (*gamma, Gtk::PACK_EXPAND_WIDGET, 1); passes = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_MEDIAN_PASSES"), 1.0, 3.0, 1., 1.)); passes->set_tooltip_text (M("TP_DIRPYRDENOISE_MEDIAN_PASSES_TOOLTIP")); From 0b7b1d6ab36b94b6f6adf4b3c4e0212cdecaa15b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Mon, 1 Jan 2018 12:13:29 +0100 Subject: [PATCH 02/22] Fix null pointer dereference (as hinted by Coverity) Plus some `const` fixes. --- rtengine/imagedata.cc | 22 +++++++++++++--------- rtexif/rtexif.cc | 6 +++--- rtexif/rtexif.h | 6 +++--- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index f3516e5a8..640eee96e 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -474,14 +474,14 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* uint16 bitspersample = 0, samplesperpixel = 0, sampleformat = 0, photometric = 0, compression = 0; - rtexif::Tag* bps = frameRootDir->findTag("BitsPerSample"); - rtexif::Tag* spp = frameRootDir->findTag("SamplesPerPixel"); - rtexif::Tag* sf = frameRootDir->findTag("SampleFormat"); - rtexif::Tag* pi = frameRootDir->findTag("PhotometricInterpretation"); - rtexif::Tag* c = frameRootDir->findTag("Compression"); + const rtexif::Tag* const bps = frameRootDir->findTag("BitsPerSample"); + const rtexif::Tag* const spp = frameRootDir->findTag("SamplesPerPixel"); + const rtexif::Tag* const sf = frameRootDir->findTag("SampleFormat"); + const rtexif::Tag* const pi = frameRootDir->findTag("PhotometricInterpretation"); + const rtexif::Tag* const c = frameRootDir->findTag("Compression"); if (mnote && (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX")))) { - rtexif::Tag* hdr = mnote->findTag("HDR"); + const rtexif::Tag* const hdr = mnote->findTag("HDR"); if (hdr) { if (hdr->toInt() > 0 && hdr->toInt(2) > 0) { isHDR = true; @@ -490,7 +490,7 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* #endif } } else { - rtexif::Tag* dm = mnote->findTag("DriveMode"); + const rtexif::Tag* const dm = mnote->findTag("DriveMode"); if (dm) { char buffer[60]; dm->toString(buffer, 3); @@ -505,7 +505,7 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* } if (!isHDR) { - rtexif::Tag* q = mnote->findTag("Quality"); + const rtexif::Tag* const q = mnote->findTag("Quality"); if (q && q->toInt() == 7) { isPixelShift = true; #if PRINT_HDR_PS_DETECTION @@ -530,7 +530,11 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* sampleformat = sf->toInt(); } - if ((!bps & !spp) || !pi) { + if ( + !bps + || !spp + || !pi + ) { return; } diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index b6b5b55fe..a90ec18b5 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -1572,7 +1572,7 @@ double Tag::toDouble (int ofs) const /** * @brief Create an array of the elements */ -double *Tag::toDoubleArray (int ofs) +double* Tag::toDoubleArray (int ofs) const { double *values = new double[count]; @@ -1583,7 +1583,7 @@ double *Tag::toDoubleArray (int ofs) return values; } -void Tag::toRational (int& num, int& denom, int ofs) +void Tag::toRational (int& num, int& denom, int ofs) const { switch (type) { @@ -1632,7 +1632,7 @@ void Tag::toRational (int& num, int& denom, int ofs) } } -void Tag::toString (char* buffer, int ofs) +void Tag::toString (char* buffer, int ofs) const { if (type == UNDEFINED && !directory) { diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index 937945aac..822407389 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -282,9 +282,9 @@ public: int toInt (int ofs = 0, TagType astype = INVALID) const; void fromInt (int v); double toDouble (int ofs = 0) const; - double *toDoubleArray (int ofs = 0); - void toRational (int& num, int& denom, int ofs = 0); - void toString (char* buffer, int ofs = 0); + double* toDoubleArray (int ofs = 0) const; + void toRational (int& num, int& denom, int ofs = 0) const; + void toString (char* buffer, int ofs = 0) const; void fromString (const char* v, int size = -1); void setInt (int v, int ofs = 0, TagType astype = LONG); From b3dd5244ad2a5d1eb2d9b435a7ae8f15add7d7b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Mon, 1 Jan 2018 12:30:10 +0100 Subject: [PATCH 03/22] Fix (currently impossible) null pointer dereference (Coverity) Plus some `const` fixes, this time removing constness. --- rtengine/FTblockDN.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index 334f97f05..ddd7e4587 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -78,8 +78,10 @@ namespace { template -void do_median_denoise(float **src, float **dst, float upperBound, const int width, const int height, const ImProcFunctions::Median medianType, const int iterations, const int numThreads, float **buffer) +void do_median_denoise(float **src, float **dst, float upperBound, int width, int height, ImProcFunctions::Median medianType, int iterations, int numThreads, float **buffer) { + iterations = max(1, iterations); + typedef ImProcFunctions::Median Median; int border = 1; From ecee587402fa21ef836ba93974d396592bc4b6fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Mon, 1 Jan 2018 12:35:41 +0100 Subject: [PATCH 04/22] Fix pass-by-value (Coverity) Plus some `const` adjustments. (Groundhog day?) --- rtengine/rawimagesource.cc | 2 +- rtengine/rawimagesource.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index d8fba268a..3eac99396 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -3884,7 +3884,7 @@ lab2ProphotoRgbD50(float L, float A, float B, float& r, float& g, float& b) } // Converts raw image including ICC input profile to working space - floating point version -void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParams &cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], const std::string &camName) +void RawImageSource::colorSpaceConversion_ (Imagefloat* im, const ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], const std::string &camName) { // MyTime t1, t2, t3; diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index d1496d4fd..a64991604 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -39,7 +39,7 @@ private: static DiagonalCurve *phaseOneIccCurveInv; static LUTf invGrad; // for fast_demosaic static LUTf initInvGrad (); - static void colorSpaceConversion_ (Imagefloat* im, ColorManagementParams &cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName); + static void colorSpaceConversion_ (Imagefloat* im, const ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName); int defTransform (int tran); protected: @@ -189,7 +189,7 @@ public: void convertColorSpace(Imagefloat* image, const ColorManagementParams &cmp, const ColorTemp &wb); static bool findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in); - static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName) + static void colorSpaceConversion (Imagefloat* im, const ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName) { colorSpaceConversion_ (im, cmp, wb, pre_mul, embedded, camprofile, cam, camName); } From 1054083661ac3cf74bff47933dcf59b792d53236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Mon, 1 Jan 2018 12:43:51 +0100 Subject: [PATCH 05/22] Fix pass-by-value (Coverity) --- rtengine/imagesource.h | 2 +- rtengine/rawimagesource.cc | 2 +- rtengine/rawimagesource.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index b76a962eb..29a125149 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -71,7 +71,7 @@ public: virtual void demosaic (const RAWParams &raw) {}; virtual void retinex (ColorManagementParams cmp, const RetinexParams &deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {}; virtual void retinexPrepareCurves (const RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) {}; - virtual void retinexPrepareBuffers (ColorManagementParams cmp, const RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI) {}; + virtual void retinexPrepareBuffers (const ColorManagementParams& cmp, const RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI) {}; virtual void flushRawData () {}; virtual void flushRGB () {}; virtual void HLRecovery_Global (ToneCurveParams hrp) {}; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 3eac99396..d1bc90636 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -2091,7 +2091,7 @@ void RawImageSource::demosaic(const RAWParams &raw) //void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexParams retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI) -void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, const RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI) +void RawImageSource::retinexPrepareBuffers(const ColorManagementParams& cmp, const RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI) { bool useHsl = (retinexParams.retinexcolorspace == "HSLLOG" || retinexParams.retinexcolorspace == "HSLLIN"); conversionBuffer[0] (W - 2 * border, H - 2 * border); diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index a64991604..382be0b44 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -121,7 +121,7 @@ public: void demosaic (const RAWParams &raw); void retinex (ColorManagementParams cmp, const RetinexParams &deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI); void retinexPrepareCurves (const RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI); - void retinexPrepareBuffers (ColorManagementParams cmp, const RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI); + void retinexPrepareBuffers (const ColorManagementParams& cmp, const RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI); void flushRawData (); void flushRGB (); void HLRecovery_Global (ToneCurveParams hrp); From ce2be7ad874cca49d2bca0e4ab8d6b0c7e025b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Mon, 1 Jan 2018 12:48:35 +0100 Subject: [PATCH 06/22] Fix pass-by-value (Coverity) --- rtengine/imagesource.h | 2 +- rtengine/rawimagesource.cc | 2 +- rtengine/rawimagesource.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 29a125149..261995f08 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -69,7 +69,7 @@ public: virtual int load (const Glib::ustring &fname) = 0; virtual void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse, bool prepareDenoise = true) {}; virtual void demosaic (const RAWParams &raw) {}; - virtual void retinex (ColorManagementParams cmp, const RetinexParams &deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {}; + virtual void retinex (const ColorManagementParams& cmp, const RetinexParams &deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {}; virtual void retinexPrepareCurves (const RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) {}; virtual void retinexPrepareBuffers (const ColorManagementParams& cmp, const RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI) {}; virtual void flushRawData () {}; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index d1bc90636..b948b8bdd 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -2360,7 +2360,7 @@ void RawImageSource::retinexPrepareCurves(const RetinexParams &retinexParams, LU retinexParams.getCurves(retinextransmissionCurve, retinexgaintransmissionCurve); } -void RawImageSource::retinex(ColorManagementParams cmp, const RetinexParams &deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) +void RawImageSource::retinex(const ColorManagementParams& cmp, const RetinexParams &deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) { MyTime t4, t5; t4.set(); diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 382be0b44..cdd7ca675 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -119,7 +119,7 @@ public: int load (const Glib::ustring &fname); void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse, bool prepareDenoise = true); void demosaic (const RAWParams &raw); - void retinex (ColorManagementParams cmp, const RetinexParams &deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI); + void retinex (const ColorManagementParams& cmp, const RetinexParams &deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI); void retinexPrepareCurves (const RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI); void retinexPrepareBuffers (const ColorManagementParams& cmp, const RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI); void flushRawData (); From c760b95844a5d8047ed7d1c9466d736406d69228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Mon, 1 Jan 2018 12:52:11 +0100 Subject: [PATCH 07/22] Remove dead member (Coverity) --- rtgui/filmsimulation.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rtgui/filmsimulation.h b/rtgui/filmsimulation.h index c813f9c85..8f627c352 100644 --- a/rtgui/filmsimulation.h +++ b/rtgui/filmsimulation.h @@ -17,10 +17,10 @@ public: Glib::ustring getSelectedClut(); void setSelectedClut( Glib::ustring filename ); void setBatchMode(bool yes); - + private: void updateUnchangedEntry(); // in batchMode we need to add an extra entry "(Unchanged)". We do this whenever the widget is mapped (connecting to signal_map()), unless options.multiDisplayMode (see the comment below about cm2 in this case) - + class ClutColumns : public Gtk::TreeModel::ColumnRecord { public: @@ -45,7 +45,6 @@ private: static std::unique_ptr cm; // we use a shared TreeModel for all the combo boxes, to save time (no need to reparse the clut dir multiple times)... static std::unique_ptr cm2; // ... except when options.multiDisplayMode (i.e. editors in their own window), where we need two. This is because we might have two combo boxes displayed at the same time in this case - int count; // the number of clut entries bool batchMode; }; From 820b6c8ae92a12c2134fef67bb9e554735ebbe1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Mon, 1 Jan 2018 12:57:19 +0100 Subject: [PATCH 08/22] Remove useless call (Coverity) --- rtengine/imagedata.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 640eee96e..5fb1e98f6 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -838,8 +838,6 @@ rtexif::TagDirectory* FramesData::getBestExifData (ImageSource *imgSource, procp */ } - frames[imgNum]->getExifData (); - td = getFrameExifData (imgNum); rtexif::Tag* makeTag; if (td && (makeTag = td->findTag("Make", true))) { From b73970e94fe7fa55ad91370e24cb3d041e159ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Mon, 1 Jan 2018 13:04:01 +0100 Subject: [PATCH 09/22] Fix unintended sign extent (Coverity) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Would hit us at 716Mpx (26755px²). --- rtengine/rawimage.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index de392623d..8d7292113 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -695,7 +695,7 @@ float** RawImage::compress_image(int frameNum, bool freeImage) } else if (colors == 1) { // Monochrome if (!allocation) { - allocation = new float[height * width]; + allocation = new float[static_cast(height) * static_cast(width)]; data = new float*[height]; for (int i = 0; i < height; i++) { @@ -704,7 +704,7 @@ float** RawImage::compress_image(int frameNum, bool freeImage) } } else { if (!allocation) { - allocation = new float[3 * height * width]; + allocation = new float[3UL * static_cast(height) * static_cast(width)]; data = new float*[height]; for (int i = 0; i < height; i++) { From 835204430478cf9102b8f09be0b251f3d1b4d2dd Mon Sep 17 00:00:00 2001 From: heckflosse Date: Mon, 1 Jan 2018 15:59:35 +0100 Subject: [PATCH 10/22] Left colour bar for CC and CL curve in lab tools are inverted, fixes #4270 --- rtgui/labcurve.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index 8b2b2a217..6cbf11825 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -143,7 +143,7 @@ LCurve::LCurve () : FoldableToolPanel(this, "labcurves", M("TP_LABCURVE_LABEL"), ); ccshape->setBottomBarColorProvider(this, 2); - ccshape->setLeftBarColorProvider(this, 2); + ccshape->setLeftBarColorProvider(this, 7); ccshape->setRangeDefaultMilestones(0.05, 0.2, 0.58); lcshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_LABCURVE_CURVEEDITOR_LC"))); @@ -162,7 +162,7 @@ LCurve::LCurve () : FoldableToolPanel(this, "labcurves", M("TP_LABCURVE_LABEL"), clshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_CL_TOOLTIP")); clshape->setEditID(EUID_Lab_CLCurve, BT_SINGLEPLANE_FLOAT); - clshape->setLeftBarColorProvider(this, 2); + clshape->setLeftBarColorProvider(this, 7); clshape->setRangeDefaultMilestones(0.25, 0.5, 0.75); milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); @@ -627,6 +627,12 @@ void LCurve::colorForValue (double valX, double valY, enum ColorCaller::ElemType } Color::hsv2rgb01(h, 0.5f, 0.5f, R, G, B); + } else if (callerId == 7) { // cc and cl - left bar + + float value = (1.f - 0.7f) * float(valX) + 0.7f; + // whole hue range + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + Color::hsv2rgb01(float(valY), 1.f - float(valX), value, R, G, B); } caller->ccRed = double(R); From 5340f2c10336caaa3716ea53634d747217f9fc37 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Mon, 1 Jan 2018 21:40:34 +0100 Subject: [PATCH 11/22] Fixed whole hue range curve bar gradient, closes #4271 --- rtgui/labcurve.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index 6cbf11825..ae5774960 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -578,7 +578,7 @@ void LCurve::colorForValue (double valX, double valY, enum ColorCaller::ElemType float value = (1.f - 0.7f) * float(valX) + 0.7f; // whole hue range // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + Color::hsv2rgb01(float(valY*0.8), float(valX), value, R, G, B); } else if (callerId == 6) { // cc - left bar float value = (1.f - 0.7f) * float(valX) + 0.7f; @@ -613,7 +613,7 @@ void LCurve::colorForValue (double valX, double valY, enum ColorCaller::ElemType } else { // whole hue range // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + Color::hsv2rgb01(float(valY*0.8), float(valX), value, R, G, B); } } else if (callerId == 4) { // LH - bottom bar Color::hsv2rgb01(float(valX), 0.5f, float(valY), R, G, B); @@ -632,7 +632,7 @@ void LCurve::colorForValue (double valX, double valY, enum ColorCaller::ElemType float value = (1.f - 0.7f) * float(valX) + 0.7f; // whole hue range // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(float(valY), 1.f - float(valX), value, R, G, B); + Color::hsv2rgb01(float(valY*0.8), 1.f - float(valX), value, R, G, B); } caller->ccRed = double(R); From b624248a13a9bedaee9a1279882d6a782e46839f Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Mon, 1 Jan 2018 22:02:15 +0100 Subject: [PATCH 12/22] LCurve::colorForValue formatting --- rtgui/labcurve.cc | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index ae5774960..1cde4262d 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -571,43 +571,30 @@ void LCurve::colorForValue (double valX, double valY, enum ColorCaller::ElemType } if (callerId == 1) { // ch - main curve - Color::hsv2rgb01(float(valX), float(valY), 0.5f, R, G, B); } else if (callerId == 2) { // cc - bottom bar - float value = (1.f - 0.7f) * float(valX) + 0.7f; // whole hue range // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) Color::hsv2rgb01(float(valY*0.8), float(valX), value, R, G, B); } else if (callerId == 6) { // cc - left bar - float value = (1.f - 0.7f) * float(valX) + 0.7f; - float hue = (1.14056f - 0.92f) * float(valY) + 0.92f; - - if (hue > 1.0f) { - hue -= 1.0f; - } - - // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(hue, float(valX), value, R, G, B); - - // whole hue range + float hue = (1.14056f - 0.92f) * float(valY) + 0.92f; + if (hue > 1.0f) { + hue -= 1.0f; + } // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - // Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + Color::hsv2rgb01(hue, float(valX), value, R, G, B); } else if (callerId == 3) { // lc - bottom bar - float value = (1.f - 0.7f) * float(valX) + 0.7f; - if (lcredsk->get_active()) { // skin range // -0.1 rad < Hue < 1.6 rad // Y axis / from 0.92 up to 0.14056 float hue = (1.14056f - 0.92f) * float(valY) + 0.92f; - if (hue > 1.0f) { hue -= 1.0f; } - // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) Color::hsv2rgb01(hue, float(valX), value, R, G, B); } else { @@ -619,16 +606,13 @@ void LCurve::colorForValue (double valX, double valY, enum ColorCaller::ElemType Color::hsv2rgb01(float(valX), 0.5f, float(valY), R, G, B); } else if (callerId == 5) { // HH - bottom bar float h = float((valY - 0.5) * 0.3 + valX); - if (h > 1.0f) { h -= 1.0f; } else if (h < 0.0f) { h += 1.0f; } - Color::hsv2rgb01(h, 0.5f, 0.5f, R, G, B); } else if (callerId == 7) { // cc and cl - left bar - float value = (1.f - 0.7f) * float(valX) + 0.7f; // whole hue range // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) From e9782e15e2969bb47b820aff090b2e5fc8b17257 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Mon, 1 Jan 2018 22:28:56 +0100 Subject: [PATCH 13/22] Fixed accidently broken shadows/highlight tool --- rtengine/improcfun.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index bfe4ee021..6a39befef 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -3553,8 +3553,8 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer float chMixBG = float (params->chmixer.blue[1]); float chMixBB = float (params->chmixer.blue[2]); - int shHighlights = params->sh.highlights / 100.f; - int shShadows = params->sh.shadows / 100.f; + int shHighlights = params->sh.highlights; + int shShadows = params->sh.shadows; bool blackwhite = params->blackwhite.enabled; bool complem = params->blackwhite.enabledcc; float bwr = float (params->blackwhite.mixerRed); @@ -3722,13 +3722,14 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer float g = gtemp[ti * TS + tj]; float b = btemp[ti * TS + tj]; + float mapval = 1.f + shmap->map[i][j]; float factor = 1.f; if (mapval > h_th) { - factor = (1.f - shHighlights) + shHighlights * h_th / mapval; + factor = (h_th + (100.0 - shHighlights) * (mapval - h_th) / 100.0) / mapval; } else if (mapval < s_th) { - factor = (s_th - (1.f - shShadows) * (s_th - mapval)) / mapval; + factor = (s_th - (100.0 - shShadows) * (s_th - mapval) / 100.0) / mapval; } rtemp[ti * TS + tj] = factor * r; From 0ac3bafbcad71033a2d503eb78a0955358251329 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Mon, 1 Jan 2018 22:48:16 +0100 Subject: [PATCH 14/22] some tweaks to the cropping GUI, inspired by recent comments on pixls.us --- rtgui/cropwindow.cc | 22 ++++++++++++++++++---- rtgui/imagearea.cc | 4 ++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index f4510682e..b8bbfe4fc 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -313,7 +313,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) changeZoom (zoom11index, true, action_x, action_y); fitZoom = false; } else { - zoomFit (); + zoomFitCrop (); } } else { zoom11 (); @@ -612,6 +612,10 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) } needRedraw = true; + + if (fitZoom) { + zoomFitCrop(); + } } else if (state == SCropWinMove) { if (iarea->showColorPickers () && !colorPickers.empty()) { needRedraw = true; @@ -722,6 +726,10 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) cropgl->cropManipReady (); iarea->setToolHand (); needRedraw = true; + + if (fitZoom) { + zoomFitCrop(); + } } if (decorated) { @@ -1356,6 +1364,12 @@ void CropWindow::expose (Cairo::RefPtr cr) drawObservedFrame (cr); } } else { + CropParams cropParams = cropHandler.cropParams; + if (state == SNormal && cropParams.guide != "None") { + cropParams.guide = "Frame"; + } + bool useBgColor = (state == SNormal); + if (cropHandler.cropPixbuf) { imgW = cropHandler.cropPixbuf->get_width (); imgH = cropHandler.cropPixbuf->get_height (); @@ -1772,7 +1786,7 @@ void CropWindow::expose (Cairo::RefPtr cr) if (cropHandler.cropParams.enabled) { int cropX, cropY; cropHandler.getPosition (cropX, cropY); - drawCrop (cr, x + imgAreaX + imgX, y + imgAreaY + imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, cropHandler.isFullDisplay ()); + drawCrop (cr, x + imgAreaX + imgX, y + imgAreaY + imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropParams, (this == iarea->mainCropWindow), useBgColor, cropHandler.isFullDisplay ()); } if (observedCropWin) { @@ -1853,7 +1867,7 @@ void CropWindow::expose (Cairo::RefPtr cr) cr->fill(); if (cropHandler.cropParams.enabled) { - drawCrop (cr, x + imgAreaX + imgX, y + imgAreaY + imgY, rough->get_width(), rough->get_height(), cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, cropHandler.isFullDisplay ()); + drawCrop (cr, x + imgAreaX + imgX, y + imgAreaY + imgY, rough->get_width(), rough->get_height(), cropX, cropY, zoomSteps[cropZoom].zoom, cropParams, (this == iarea->mainCropWindow), useBgColor, cropHandler.isFullDisplay ()); } if (observedCropWin) { @@ -2097,7 +2111,7 @@ void CropWindow::zoomFitCrop () centerY = cropHandler.cropParams.y + cropHandler.cropParams.h / 2; setCropAnchorPosition(centerX, centerY); changeZoom (cz, true, centerX, centerY); - fitZoom = false; + fitZoom = true; //false; } else { zoomFit(); } diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index c0d334482..e22da4dfb 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -638,7 +638,7 @@ void ImageArea::initialImageArrived (CropWindow* cw) if (mainCropWindow) { if(firstOpen || options.prevdemo != PD_Sidecar || (!options.rememberZoomAndPan) ) { - mainCropWindow->zoomFit (); + mainCropWindow->zoomFitCrop (); firstOpen = false; mainCropWindow->cropHandler.getFullImageSize(fullImageWidth, fullImageHeight); } else { @@ -646,7 +646,7 @@ void ImageArea::initialImageArrived (CropWindow* cw) mainCropWindow->cropHandler.getFullImageSize(w, h); if(w != fullImageWidth || h != fullImageHeight) { - mainCropWindow->zoomFit (); + mainCropWindow->zoomFitCrop (); } fullImageWidth = w; From 99112832663da19a789d0ff2f189130fb8f6306f Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Mon, 1 Jan 2018 22:51:25 +0100 Subject: [PATCH 15/22] More full hue range curve bar fixes, #4271 This one fixes the CIECAM02 color curve, and the Color Toning opacity curves. --- rtgui/colorappearance.cc | 2 +- rtgui/colortoning.cc | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/rtgui/colorappearance.cc b/rtgui/colorappearance.cc index c9fb1baa3..f8dee05df 100644 --- a/rtgui/colorappearance.cc +++ b/rtgui/colorappearance.cc @@ -1536,7 +1536,7 @@ void ColorAppearance::colorForValue (double valX, double valY, enum ColorCaller: float value = (1.f - 0.7f) * float (valX) + 0.7f; // whole hue range // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01 (float (valY), float (valX), value, R, G, B); + Color::hsv2rgb01 (float (valY*0.8), float (valX), value, R, G, B); } caller->ccRed = double (R); diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index b53f7e5db..180b4235a 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -41,7 +41,7 @@ ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLOR colorCurveEditorG->setCurveListener (this); colorShape = static_cast(colorCurveEditorG->addCurve(CT_Flat, "", nullptr, false, false)); - colorShape->setCurveColorProvider(this, 1); + colorShape->setCurveColorProvider(this, 4); std::vector milestones; // whole hue range @@ -951,8 +951,8 @@ void ColorToning::colorForValue (double valX, double valY, enum ColorCaller::Ele float R = 0.f, G = 0.f, B = 0.f; - if (callerId == 1) { // ch - main curve - Color::hsv2rgb01(float(valY), 1.0f, 0.5f, R, G, B); + if (callerId == 1) { // opacity curve left bar(s) + Color::hsv2rgb01(float(valY*0.8), 1.0f, 0.5f, R, G, B); } else if (callerId == 2) { // Slider 1 background if (valY <= 0.5) // the hue range @@ -983,6 +983,8 @@ void ColorToning::colorForValue (double valX, double valY, enum ColorCaller::Ele G = (gray * (1.0 - valX)) + G * valX; B = (gray * (1.0 - valX)) + B * valX; } + } else if (callerId == 4) { // color curve vertical and horizontal crosshair + Color::hsv2rgb01(float(valY), 1.0f, 0.5f, R, G, B); } caller->ccRed = double(R); From e229b9519e515d17bac3b53ebb63aa7ff281bb15 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Mon, 1 Jan 2018 23:41:07 +0100 Subject: [PATCH 16/22] made ToolPanel::setListener virtual (needed by MetaDataPanel to work properly) --- rtgui/toolpanel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtgui/toolpanel.h b/rtgui/toolpanel.h index d5814c040..d3d7439a9 100644 --- a/rtgui/toolpanel.h +++ b/rtgui/toolpanel.h @@ -88,7 +88,7 @@ public: { multiImage = m; } - void setListener (ToolPanelListener* tpl) + virtual void setListener (ToolPanelListener* tpl) { listener = tpl; } From 8168611c23c356632f6d2b4dd01a3aec46ee54ea Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Wed, 3 Jan 2018 15:44:34 +0100 Subject: [PATCH 17/22] added preferences to control the behaviour of the crop tool --- rtdata/languages/default | 6 ++++++ rtgui/cropwindow.cc | 23 +++++++++++++++++------ rtgui/filebrowserentry.cc | 10 ++++++++++ rtgui/imagearea.cc | 12 ++++++++++-- rtgui/options.cc | 10 ++++++++++ rtgui/options.h | 7 ++++++- rtgui/preferences.cc | 22 ++++++++++++++++++++++ rtgui/preferences.h | 3 +++ rtgui/previewwindow.cc | 13 ++++++++++++- 9 files changed, 96 insertions(+), 10 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 92bbaa08f..25af81141 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -976,6 +976,12 @@ PREFERENCES_CLUTSCACHE;HaldCLUT Cache PREFERENCES_CLUTSCACHE_LABEL;Maximum number of cached CLUTs PREFERENCES_CLUTSDIR;HaldCLUT directory PREFERENCES_CMMBPC;Black point compensation +PREFERENCES_CROP;Crop editing +PREFERENCES_CROP_GUIDES;Guides shown when not editing the crop +PREFERENCES_CROP_GUIDES_NONE;None +PREFERENCES_CROP_GUIDES_FRAME;Frame +PREFERENCES_CROP_GUIDES_FULL;Original +PREFERENCES_CROP_AUTO_FIT;Automatically zoom to fit the crop area PREFERENCES_CURVEBBOXPOS;Position of curve copy & paste buttons PREFERENCES_CURVEBBOXPOS_ABOVE;Above PREFERENCES_CURVEBBOXPOS_BELOW;Below diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index b8bbfe4fc..001805362 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -312,8 +312,10 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) screenCoordToImage (x, y, action_x, action_y); changeZoom (zoom11index, true, action_x, action_y); fitZoom = false; + } else if (options.cropAutoFit) { + zoomFitCrop(); } else { - zoomFitCrop (); + zoomFit(); } } else { zoom11 (); @@ -613,7 +615,7 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) needRedraw = true; - if (fitZoom) { + if (fitZoom && options.cropAutoFit) { zoomFitCrop(); } } else if (state == SCropWinMove) { @@ -727,7 +729,7 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) iarea->setToolHand (); needRedraw = true; - if (fitZoom) { + if (fitZoom && options.cropAutoFit) { zoomFitCrop(); } } @@ -1365,8 +1367,17 @@ void CropWindow::expose (Cairo::RefPtr cr) } } else { CropParams cropParams = cropHandler.cropParams; - if (state == SNormal && cropParams.guide != "None") { - cropParams.guide = "Frame"; + if (state == SNormal) { + switch (options.cropGuides) { + case Options::CROP_GUIDE_NONE: + cropParams.guide = "None"; + break; + case Options::CROP_GUIDE_FRAME: + cropParams.guide = "Frame"; + break; + default: + break; + } } bool useBgColor = (state == SNormal); @@ -2111,7 +2122,7 @@ void CropWindow::zoomFitCrop () centerY = cropHandler.cropParams.y + cropHandler.cropParams.h / 2; setCropAnchorPosition(centerX, centerY); changeZoom (cz, true, centerX, centerY); - fitZoom = true; //false; + fitZoom = options.cropAutoFit; } else { zoomFit(); } diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc index c3adae3aa..cb3844687 100644 --- a/rtgui/filebrowserentry.cc +++ b/rtgui/filebrowserentry.cc @@ -168,6 +168,16 @@ void FileBrowserEntry::customBackBufferUpdate (Cairo::RefPtr c) drawCrop (c, prex, prey, prew, preh, 0, 0, scale, cropParams, true, false); } else { rtengine::procparams::CropParams cparams = thumbnail->getProcParams().crop; + switch (options.cropGuides) { + case Options::CROP_GUIDE_NONE: + cparams.guide = "None"; + break; + case Options::CROP_GUIDE_FRAME: + cparams.guide = "Frame"; + break; + default: + break; + } if (cparams.enabled && !thumbnail->isQuick()) { // Quick thumb have arbitrary sizes, so don't apply the crop drawCrop (c, prex, prey, prew, preh, 0, 0, scale, cparams, true, false); diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index e22da4dfb..0344e04b7 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -638,7 +638,11 @@ void ImageArea::initialImageArrived (CropWindow* cw) if (mainCropWindow) { if(firstOpen || options.prevdemo != PD_Sidecar || (!options.rememberZoomAndPan) ) { - mainCropWindow->zoomFitCrop (); + if (options.cropAutoFit) { + mainCropWindow->zoomFitCrop(); + } else { + mainCropWindow->zoomFit(); + } firstOpen = false; mainCropWindow->cropHandler.getFullImageSize(fullImageWidth, fullImageHeight); } else { @@ -646,7 +650,11 @@ void ImageArea::initialImageArrived (CropWindow* cw) mainCropWindow->cropHandler.getFullImageSize(w, h); if(w != fullImageWidth || h != fullImageHeight) { - mainCropWindow->zoomFitCrop (); + if (options.cropAutoFit) { + mainCropWindow->zoomFitCrop(); + } else { + mainCropWindow->zoomFit(); + } } fullImageWidth = w; diff --git a/rtgui/options.cc b/rtgui/options.cc index 127ea990f..449aa3809 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -614,6 +614,8 @@ void Options::setDefaults () gimpPluginShowInfoDialog = true; maxRecentFolders = 15; rtSettings.lensfunDbDirectory = ""; // set also in main.cc and main-cli.cc + cropGuides = CROP_GUIDE_FULL; + cropAutoFit = false; } Options* Options::copyFrom (Options* other) @@ -1386,6 +1388,12 @@ void Options::readFromFile (Glib::ustring fname) if (keyFile.has_key ("Crop Settings", "PPI")) { cropPPI = keyFile.get_integer ("Crop Settings", "PPI"); } + if (keyFile.has_key("Crop Settings", "GuidesMode")) { + cropGuides = CropGuidesMode(std::max(int(CROP_GUIDE_NONE), std::min(keyFile.get_integer("Crop Settings", "GuidesMode"), int(CROP_GUIDE_FULL)))); + } + if (keyFile.has_key("Crop Settings", "AutoFit")) { + cropAutoFit = keyFile.get_boolean("Crop Settings", "AutoFit"); + } } if (keyFile.has_group ("Color Management")) { @@ -2018,6 +2026,8 @@ void Options::saveToFile (Glib::ustring fname) //keyFile.set_integer_list ("GUI", "CurvePanelsExpanded", crvopen); keyFile.set_integer ("Crop Settings", "PPI", cropPPI); + keyFile.set_integer("Crop Settings", "GuidesMode", cropGuides); + keyFile.set_boolean("Crop Settings", "AutoFit", cropAutoFit); keyFile.set_string ("Color Management", "PrinterProfile", rtSettings.printerProfile); keyFile.set_integer ("Color Management", "PrinterIntent", rtSettings.printerIntent); diff --git a/rtgui/options.h b/rtgui/options.h index feeca7983..31d17ef9b 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -191,7 +191,6 @@ public: int showFilePanelState; // 0: normal, 1: maximized, 2: normal, 3: hidden bool showInfo; bool mainNBVertical; // main notebook vertical tabs? - int cropPPI; bool showClippedHighlights; bool showClippedShadows; int highlightThreshold; @@ -261,6 +260,12 @@ public: bool showFilmStripToolBar; + // cropping options + int cropPPI; + enum CropGuidesMode { CROP_GUIDE_NONE, CROP_GUIDE_FRAME, CROP_GUIDE_FULL }; + CropGuidesMode cropGuides; + bool cropAutoFit; + // Performance options Glib::ustring clutsDir; int rgbDenoiseThreadLimit; // maximum number of threads for the denoising tool ; 0 = use the maximum available diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index b53e884f5..2be5f3664 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -582,6 +582,22 @@ Gtk::Widget* Preferences::getProcParamsPanel () cdf->add(*dirgrid); mvbpp->pack_start (*cdf, Gtk::PACK_SHRINK, 4 ); + // Crop + Gtk::Frame *cropframe = Gtk::manage(new Gtk::Frame(M("PREFERENCES_CROP"))); + Gtk::VBox *cropvb = Gtk::manage(new Gtk::VBox()); + Gtk::HBox *crophb = Gtk::manage(new Gtk::HBox()); + cropGuides = Gtk::manage(new Gtk::ComboBoxText()); + cropGuides->append(M("PREFERENCES_CROP_GUIDES_NONE")); + cropGuides->append(M("PREFERENCES_CROP_GUIDES_FRAME")); + cropGuides->append(M("PREFERENCES_CROP_GUIDES_FULL")); + crophb->pack_start(*Gtk::manage(new Gtk::Label(M("PREFERENCES_CROP_GUIDES") + ": ")), Gtk::PACK_SHRINK, 4); + crophb->pack_start(*cropGuides); + cropvb->pack_start(*crophb); + cropAutoFit = Gtk::manage(new Gtk::CheckButton(M("PREFERENCES_CROP_AUTO_FIT"))); + cropvb->pack_start(*cropAutoFit); + cropframe->add(*cropvb); + mvbpp->pack_start(*cropframe, Gtk::PACK_SHRINK, 4); + return mvbpp; } @@ -1840,6 +1856,9 @@ void Preferences::storePreferences () moptions.sndLngEditProcDone = txtSndLngEditProcDone->get_text (); moptions.sndLngEditProcDoneSecs = spbSndLngEditProcDoneSecs->get_value (); #endif + + moptions.cropGuides = Options::CropGuidesMode(cropGuides->get_active_row_number()); + moptions.cropAutoFit = cropAutoFit->get_active(); } void Preferences::fillPreferences () @@ -2070,6 +2089,9 @@ void Preferences::fillPreferences () } } + cropGuides->set_active(moptions.cropGuides); + cropAutoFit->set_active(moptions.cropAutoFit); + addc.block (false); setc.block (false); cpfconn.block (false); diff --git a/rtgui/preferences.h b/rtgui/preferences.h index 7ce592457..cb0e6c709 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -204,6 +204,9 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener DynamicProfilePanel *dynProfilePanel; + Gtk::ComboBoxText *cropGuides; + Gtk::CheckButton *cropAutoFit; + Glib::ustring storedValueRaw; Glib::ustring storedValueImg; diff --git a/rtgui/previewwindow.cc b/rtgui/previewwindow.cc index cd4e0c75c..06ce3ad18 100644 --- a/rtgui/previewwindow.cc +++ b/rtgui/previewwindow.cc @@ -86,7 +86,18 @@ void PreviewWindow::updatePreviewImage () cc->fill(); if (previewHandler->getCropParams().enabled) { - drawCrop (cc, imgX, imgY, imgW, imgH, 0, 0, zoom, previewHandler->getCropParams(), true, false); + rtengine::CropParams cparams = previewHandler->getCropParams(); + switch (options.cropGuides) { + case Options::CROP_GUIDE_NONE: + cparams.guide = "None"; + break; + case Options::CROP_GUIDE_FRAME: + cparams.guide = "Frame"; + break; + default: + break; + } + drawCrop (cc, imgX, imgY, imgW, imgH, 0, 0, zoom, cparams, true, false); } } } From 6591551a7c2b06831c4ba13345550afee2d8aa40 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Wed, 3 Jan 2018 16:02:48 +0100 Subject: [PATCH 18/22] added "As Image" crop ratio --- rtengine/procparams.cc | 2 +- rtgui/crop.cc | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 97b54e37f..8fbab7a8d 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -1520,7 +1520,7 @@ CropParams::CropParams() : w(15000), h(15000), fixratio(true), - ratio("3:2"), + ratio("As Image"), orientation("As Image"), guide("Frame") { diff --git a/rtgui/crop.cc b/rtgui/crop.cc index 546d910ba..29c64501d 100644 --- a/rtgui/crop.cc +++ b/rtgui/crop.cc @@ -57,6 +57,7 @@ int notifyListenerUI (void* data) Crop::Crop(): FoldableToolPanel(this, "crop", M("TP_CROP_LABEL"), false, true), crop_ratios{ + {M("GENERAL_ASIMAGE"), 0.0}, {"3:2", 3.0 / 2.0}, // L1.5, P0.666... {"4:3", 4.0 / 3.0}, // L1.333..., P0.75 {"16:9", 16.0 / 9.0}, // L1.777..., P0.5625 @@ -292,10 +293,14 @@ void Crop::read (const ProcParams* pp, const ParamsEdited* pedited) setDimensions (pp->crop.x + pp->crop.w, pp->crop.y + pp->crop.h); } - ratio->set_active_text (pp->crop.ratio); + if (pp->crop.ratio == "As Image") { + ratio->set_active(0); + } else { + ratio->set_active_text (pp->crop.ratio); + } fixr->set_active (pp->crop.fixratio); - const bool flip_orientation = pp->crop.fixratio && crop_ratios[ratio->get_active_row_number()].value < 1.0; + const bool flip_orientation = pp->crop.fixratio && crop_ratios[ratio->get_active_row_number()].value > 0 && crop_ratios[ratio->get_active_row_number()].value < 1.0; if (pp->crop.orientation == "Landscape") { orientation->set_active (flip_orientation ? 1 : 0); @@ -390,7 +395,7 @@ void Crop::write (ProcParams* pp, ParamsEdited* pedited) pp->crop.ratio = ratio->get_active_text (); // for historical reasons we store orientation different if ratio is written as 2:3 instead of 3:2, but in GUI 'landscape' is always long side horizontal regardless of the ratio is written short or long side first. - const bool flip_orientation = fixr->get_active() && crop_ratios[ratio->get_active_row_number()].value < 1.0; + const bool flip_orientation = fixr->get_active() && crop_ratios[ratio->get_active_row_number()].value > 0 && crop_ratios[ratio->get_active_row_number()].value < 1.0; if (orientation->get_active_row_number() == 0) { pp->crop.orientation = flip_orientation ? "Portrait" : "Landscape"; @@ -1265,6 +1270,9 @@ double Crop::getRatio () } r = crop_ratios[ratio->get_active_row_number()].value; + if (!r) { + r = maxh <= maxw ? float(maxh)/float(maxw) : float(maxw)/float(maxh); + } if (r < 1.0) { r = 1.0 / r; // convert to long side first (eg 4:5 becomes 5:4) From 23934649eb99641205c759ab06ceb3cfc7b76e4f Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 3 Jan 2018 19:29:18 +0100 Subject: [PATCH 19/22] Speedup for weighted tone curve --- rtengine/curves.h | 79 ++++++++++++++++++++++++++++++++++++++++++- rtengine/improcfun.cc | 8 +---- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/rtengine/curves.h b/rtengine/curves.h index e8b65c33d..73cc37ff6 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -828,8 +828,12 @@ class WeightedStdToneCurve : public ToneCurve { private: float Triangle(float refX, float refY, float X2) const; +#if defined( __SSE2__ ) && defined( __x86_64__ ) + vfloat Triangle(vfloat refX, vfloat refY, vfloat X2) const; +#endif public: void Apply(float& r, float& g, float& b) const; + void BatchApply(const size_t start, const size_t end, float *r, float *g, float *b) const; }; class LuminanceToneCurve : public ToneCurve @@ -1003,6 +1007,17 @@ inline float WeightedStdToneCurve::Triangle(float a, float a1, float b) const return a1; } +#if defined( __SSE2__ ) && defined( __x86_64__ ) +inline vfloat WeightedStdToneCurve::Triangle(vfloat a, vfloat a1, vfloat b) const +{ + vfloat a2 = a1 - a; + vmask cmask = vmaskf_lt(b, a); + vfloat b3 = vself(cmask, b, F2V(65535.f) - b); + vfloat a3 = vself(cmask, a, F2V(65535.f) - a); + return b + a2 * b3 / a3; +} +#endif + // Tone curve modifying the value channel only, preserving hue and saturation // values in 0xffff space inline void WeightedStdToneCurve::Apply (float& r, float& g, float& b) const @@ -1010,6 +1025,9 @@ inline void WeightedStdToneCurve::Apply (float& r, float& g, float& b) const assert (lutToneCurve); + r = CLIP(r); + g = CLIP(g); + b = CLIP(b); float r1 = lutToneCurve[r]; float g1 = Triangle(r, r1, g); float b1 = Triangle(r, r1, b); @@ -1022,11 +1040,70 @@ inline void WeightedStdToneCurve::Apply (float& r, float& g, float& b) const float r3 = Triangle(b, b3, r); float g3 = Triangle(b, b3, g); - r = CLIP( r1 * 0.50f + r2 * 0.25f + r3 * 0.25f); + r = CLIP(r1 * 0.50f + r2 * 0.25f + r3 * 0.25f); g = CLIP(g1 * 0.25f + g2 * 0.50f + g3 * 0.25f); b = CLIP(b1 * 0.25f + b2 * 0.25f + b3 * 0.50f); } +inline void WeightedStdToneCurve::BatchApply(const size_t start, const size_t end, float *r, float *g, float *b) const { + assert (lutToneCurve); + assert (lutToneCurve.getClip() & LUT_CLIP_BELOW); + assert (lutToneCurve.getClip() & LUT_CLIP_ABOVE); + + // All pointers must have the same alignment for SSE usage. In the loop body below, + // we will only check `r`, assuming that the same result would hold for `g` and `b`. + assert (reinterpret_cast(r) % 16 == reinterpret_cast(g) % 16); + assert (reinterpret_cast(g) % 16 == reinterpret_cast(b) % 16); + + size_t i = start; + while (true) { + if (i >= end) { + // If we get to the end before getting to an aligned address, just return. + // (Or, for non-SSE mode, if we get to the end.) + return; +#if defined( __SSE2__ ) && defined( __x86_64__ ) + } else if (reinterpret_cast(&r[i]) % 16 == 0) { + // Otherwise, we get to the first aligned address; go to the SSE part. + break; +#endif + } + Apply(r[i], g[i], b[i]); + i++; + } + +#if defined( __SSE2__ ) && defined( __x86_64__ ) + const vfloat c65535v = F2V(65535.f); + const vfloat zd5v = F2V(0.5f); + const vfloat zd25v = F2V(0.25f); + + for (; i + 3 < end; i += 4) { + vfloat r_val = LIMV(LVF(r[i]), ZEROV, c65535v); + vfloat g_val = LIMV(LVF(g[i]), ZEROV, c65535v); + vfloat b_val = LIMV(LVF(b[i]), ZEROV, c65535v); + vfloat r1 = lutToneCurve[r_val]; + vfloat g1 = Triangle(r_val, r1, g_val); + vfloat b1 = Triangle(r_val, r1, b_val); + + vfloat g2 = lutToneCurve[g_val]; + vfloat r2 = Triangle(g_val, g2, r_val); + vfloat b2 = Triangle(g_val, g2, b_val); + + vfloat b3 = lutToneCurve[b_val]; + vfloat r3 = Triangle(b_val, b3, r_val); + vfloat g3 = Triangle(b_val, b3, g_val); + + STVF(r[i], LIMV(r1 * zd5v + r2 * zd25v + r3 * zd25v, ZEROV, c65535v)); + STVF(g[i], LIMV(g1 * zd25v + g2 * zd5v + g3 * zd25v, ZEROV, c65535v)); + STVF(b[i], LIMV(b1 * zd25v + b2 * zd25v + b3 * zd5v, ZEROV, c65535v)); + } + + // Remainder in non-SSE. + for (; i < end; ++i) { + Apply(r[i], g[i], b[i]); + } +#endif +} + // Tone curve modifying the value channel only, preserving hue and saturation // values in 0xffff space inline void SatAndValueBlendingToneCurve::Apply (float& r, float& g, float& b) const diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 6a39befef..c639ffbec 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -222,14 +222,8 @@ void customToneCurve(const ToneCurve &customToneCurve, ToneCurveParams::TcMode c } } else if (curveMode == ToneCurveParams::TcMode::WEIGHTEDSTD) { // apply the curve to the rgb channels, weighted const WeightedStdToneCurve& userToneCurve = static_cast (customToneCurve); - for (int i = istart, ti = 0; i < tH; i++, ti++) { - for (int j = jstart, tj = 0; j < tW; j++, tj++) { - rtemp[ti * tileSize + tj] = CLIP (rtemp[ti * tileSize + tj]); - gtemp[ti * tileSize + tj] = CLIP (gtemp[ti * tileSize + tj]); - btemp[ti * tileSize + tj] = CLIP (btemp[ti * tileSize + tj]); - userToneCurve.Apply (rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]); - } + userToneCurve.BatchApply(0, tW - jstart, &rtemp[ti * tileSize], >emp[ti * tileSize], &btemp[ti * tileSize]); } } else if (curveMode == ToneCurveParams::TcMode::LUMINANCE) { // apply the curve to the luminance channel const LuminanceToneCurve& userToneCurve = static_cast (customToneCurve); From a43886032f1f3c873d4925b9224efcde3c759ee6 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 4 Jan 2018 09:29:53 +0100 Subject: [PATCH 20/22] small tweak to the "zoom to fit crop" functionality --- rtgui/imagearea.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index 0344e04b7..4c4f78a38 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -638,7 +638,7 @@ void ImageArea::initialImageArrived (CropWindow* cw) if (mainCropWindow) { if(firstOpen || options.prevdemo != PD_Sidecar || (!options.rememberZoomAndPan) ) { - if (options.cropAutoFit) { + if (options.cropAutoFit || options.bgcolor != 0) { mainCropWindow->zoomFitCrop(); } else { mainCropWindow->zoomFit(); From ea1e001d15bf3eeb14c60098287a1c364ba47c7b Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 4 Jan 2018 19:03:02 +0100 Subject: [PATCH 21/22] Speedup for 'Saturation and Value Blending' tonecurve --- rtengine/color.h | 42 ++++++++++++++--- rtengine/curves.h | 102 ++++++++++++++++++++++++++++++++++++------ rtengine/improcfun.cc | 29 ++++-------- 3 files changed, 134 insertions(+), 39 deletions(-) diff --git a/rtengine/color.h b/rtengine/color.h index 049defb70..f2092f530 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -298,6 +298,36 @@ public: } } + static inline void rgb2hsvtc(float r, float g, float b, float &h, float &s, float &v) + { + const float var_Min = min(r, g, b); + const float var_Max = max(r, g, b); + const float del_Max = var_Max - var_Min; + + v = var_Max / 65535.f; + + if (del_Max < 0.00001f) { + h = 0.f; + s = 0.f; + } else { + s = del_Max / var_Max; + + if (r == var_Max) { + h = (g - b) / del_Max; + } else if (g == var_Max) { + h = 2.f + (b - r) / del_Max; + } else { /*if ( b == var_Max ) */ + h = 4.f + (r - g) / del_Max; + } + + if (h < 0.f) { + h += 6.f; + } else if (h > 6.f) { + h -= 6.f; + } + } + } + /** * @brief Convert hue saturation value in red green blue * @param h hue channel [0 ; 1] @@ -312,14 +342,14 @@ public: static inline void hsv2rgbdcp (float h, float s, float v, float &r, float &g, float &b) { // special version for dcp which saves 1 division (in caller) and six multiplications (inside this function) - int sector = h; // sector 0 to 5, floor() is very slow, and h is always >0 - float f = h - sector; // fractional part of h + const int sector = h; // sector 0 to 5, floor() is very slow, and h is always > 0 + const float f = h - sector; // fractional part of h v *= 65535.f; - float vs = v * s; - float p = v - vs; - float q = v - f * vs; - float t = p + v - q; + const float vs = v * s; + const float p = v - vs; + const float q = v - f * vs; + const float t = p + v - q; switch (sector) { case 1: diff --git a/rtengine/curves.h b/rtengine/curves.h index e8b65c33d..f537bf6c5 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -828,8 +828,12 @@ class WeightedStdToneCurve : public ToneCurve { private: float Triangle(float refX, float refY, float X2) const; +#if defined( __SSE2__ ) && defined( __x86_64__ ) + vfloat Triangle(vfloat refX, vfloat refY, vfloat X2) const; +#endif public: void Apply(float& r, float& g, float& b) const; + void BatchApply(const size_t start, const size_t end, float *r, float *g, float *b) const; }; class LuminanceToneCurve : public ToneCurve @@ -1003,6 +1007,17 @@ inline float WeightedStdToneCurve::Triangle(float a, float a1, float b) const return a1; } +#if defined( __SSE2__ ) && defined( __x86_64__ ) +inline vfloat WeightedStdToneCurve::Triangle(vfloat a, vfloat a1, vfloat b) const +{ + vfloat a2 = a1 - a; + vmask cmask = vmaskf_lt(b, a); + vfloat b3 = vself(cmask, b, F2V(65535.f) - b); + vfloat a3 = vself(cmask, a, F2V(65535.f) - a); + return b + a2 * b3 / a3; +} +#endif + // Tone curve modifying the value channel only, preserving hue and saturation // values in 0xffff space inline void WeightedStdToneCurve::Apply (float& r, float& g, float& b) const @@ -1010,6 +1025,9 @@ inline void WeightedStdToneCurve::Apply (float& r, float& g, float& b) const assert (lutToneCurve); + r = CLIP(r); + g = CLIP(g); + b = CLIP(b); float r1 = lutToneCurve[r]; float g1 = Triangle(r, r1, g); float b1 = Triangle(r, r1, b); @@ -1022,11 +1040,70 @@ inline void WeightedStdToneCurve::Apply (float& r, float& g, float& b) const float r3 = Triangle(b, b3, r); float g3 = Triangle(b, b3, g); - r = CLIP( r1 * 0.50f + r2 * 0.25f + r3 * 0.25f); + r = CLIP(r1 * 0.50f + r2 * 0.25f + r3 * 0.25f); g = CLIP(g1 * 0.25f + g2 * 0.50f + g3 * 0.25f); b = CLIP(b1 * 0.25f + b2 * 0.25f + b3 * 0.50f); } +inline void WeightedStdToneCurve::BatchApply(const size_t start, const size_t end, float *r, float *g, float *b) const { + assert (lutToneCurve); + assert (lutToneCurve.getClip() & LUT_CLIP_BELOW); + assert (lutToneCurve.getClip() & LUT_CLIP_ABOVE); + + // All pointers must have the same alignment for SSE usage. In the loop body below, + // we will only check `r`, assuming that the same result would hold for `g` and `b`. + assert (reinterpret_cast(r) % 16 == reinterpret_cast(g) % 16); + assert (reinterpret_cast(g) % 16 == reinterpret_cast(b) % 16); + + size_t i = start; + while (true) { + if (i >= end) { + // If we get to the end before getting to an aligned address, just return. + // (Or, for non-SSE mode, if we get to the end.) + return; +#if defined( __SSE2__ ) && defined( __x86_64__ ) + } else if (reinterpret_cast(&r[i]) % 16 == 0) { + // Otherwise, we get to the first aligned address; go to the SSE part. + break; +#endif + } + Apply(r[i], g[i], b[i]); + i++; + } + +#if defined( __SSE2__ ) && defined( __x86_64__ ) + const vfloat c65535v = F2V(65535.f); + const vfloat zd5v = F2V(0.5f); + const vfloat zd25v = F2V(0.25f); + + for (; i + 3 < end; i += 4) { + vfloat r_val = LIMV(LVF(r[i]), ZEROV, c65535v); + vfloat g_val = LIMV(LVF(g[i]), ZEROV, c65535v); + vfloat b_val = LIMV(LVF(b[i]), ZEROV, c65535v); + vfloat r1 = lutToneCurve[r_val]; + vfloat g1 = Triangle(r_val, r1, g_val); + vfloat b1 = Triangle(r_val, r1, b_val); + + vfloat g2 = lutToneCurve[g_val]; + vfloat r2 = Triangle(g_val, g2, r_val); + vfloat b2 = Triangle(g_val, g2, b_val); + + vfloat b3 = lutToneCurve[b_val]; + vfloat r3 = Triangle(b_val, b3, r_val); + vfloat g3 = Triangle(b_val, b3, g_val); + + STVF(r[i], LIMV(r1 * zd5v + r2 * zd25v + r3 * zd25v, ZEROV, c65535v)); + STVF(g[i], LIMV(g1 * zd25v + g2 * zd5v + g3 * zd25v, ZEROV, c65535v)); + STVF(b[i], LIMV(b1 * zd25v + b2 * zd25v + b3 * zd5v, ZEROV, c65535v)); + } + + // Remainder in non-SSE. + for (; i < end; ++i) { + Apply(r[i], g[i], b[i]); + } +#endif +} + // Tone curve modifying the value channel only, preserving hue and saturation // values in 0xffff space inline void SatAndValueBlendingToneCurve::Apply (float& r, float& g, float& b) const @@ -1034,29 +1111,28 @@ inline void SatAndValueBlendingToneCurve::Apply (float& r, float& g, float& b) c assert (lutToneCurve); + r = CLIP(r); + g = CLIP(g); + b = CLIP(b); + + const float lum = (r + g + b) / 3.f; + const float newLum = lutToneCurve[lum]; + float h, s, v; - float lum = (r + g + b) / 3.f; - //float lum = Color::rgbLuminance(r, g, b); - float newLum = lutToneCurve[lum]; - - if (newLum == lum) { - return; - } - - Color::rgb2hsv(r, g, b, h, s, v); + Color::rgb2hsvtc(r, g, b, h, s, v); float dV; if (newLum > lum) { // Linearly targeting Value = 1 and Saturation = 0 - float coef = (newLum - lum) / (65535.f - lum); + const float coef = (newLum - lum) / (65535.f - lum); dV = (1.f - v) * coef; s *= 1.f - coef; } else { // Linearly targeting Value = 0 - float coef = (newLum - lum) / lum ; + const float coef = (newLum - lum) / lum ; dV = v * coef; } - Color::hsv2rgb(h, s, v + dV, r, g, b); + Color::hsv2rgbdcp(h, s, v + dV, r, g, b); } } diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 6a39befef..34c43be0e 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -197,39 +197,28 @@ void proPhotoBlue(float *rtemp, float *gtemp, float *btemp, int istart, int tH, void customToneCurve(const ToneCurve &customToneCurve, ToneCurveParams::TcMode curveMode, float *rtemp, float *gtemp, float *btemp, int istart, int tH, int jstart, int tW, int tileSize, PerceptualToneCurveState ptcApplyState) { if (curveMode == ToneCurveParams::TcMode::STD) { // Standard + const StandardToneCurve& userToneCurve = static_cast (customToneCurve); for (int i = istart, ti = 0; i < tH; i++, ti++) { - const StandardToneCurve& userToneCurve = static_cast (customToneCurve); - userToneCurve.BatchApply ( - 0, tW - jstart, - &rtemp[ti * tileSize], >emp[ti * tileSize], &btemp[ti * tileSize]); + userToneCurve.BatchApply(0, tW - jstart, &rtemp[ti * tileSize], >emp[ti * tileSize], &btemp[ti * tileSize]); } } else if (curveMode == ToneCurveParams::TcMode::FILMLIKE) { // Adobe like + const AdobeToneCurve& userToneCurve = static_cast (customToneCurve); for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { - const AdobeToneCurve& userToneCurve = static_cast (customToneCurve); - userToneCurve.Apply (rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]); + userToneCurve.Apply(rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]); } } } else if (curveMode == ToneCurveParams::TcMode::SATANDVALBLENDING) { // apply the curve on the saturation and value channels + const SatAndValueBlendingToneCurve& userToneCurve = static_cast (customToneCurve); for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { - const SatAndValueBlendingToneCurve& userToneCurve = static_cast (customToneCurve); - rtemp[ti * tileSize + tj] = CLIP (rtemp[ti * tileSize + tj]); - gtemp[ti * tileSize + tj] = CLIP (gtemp[ti * tileSize + tj]); - btemp[ti * tileSize + tj] = CLIP (btemp[ti * tileSize + tj]); - userToneCurve.Apply (rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]); + userToneCurve.Apply(rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]); } } } else if (curveMode == ToneCurveParams::TcMode::WEIGHTEDSTD) { // apply the curve to the rgb channels, weighted const WeightedStdToneCurve& userToneCurve = static_cast (customToneCurve); - for (int i = istart, ti = 0; i < tH; i++, ti++) { - for (int j = jstart, tj = 0; j < tW; j++, tj++) { - rtemp[ti * tileSize + tj] = CLIP (rtemp[ti * tileSize + tj]); - gtemp[ti * tileSize + tj] = CLIP (gtemp[ti * tileSize + tj]); - btemp[ti * tileSize + tj] = CLIP (btemp[ti * tileSize + tj]); - userToneCurve.Apply (rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]); - } + userToneCurve.BatchApply(0, tW - jstart, &rtemp[ti * tileSize], >emp[ti * tileSize], &btemp[ti * tileSize]); } } else if (curveMode == ToneCurveParams::TcMode::LUMINANCE) { // apply the curve to the luminance channel const LuminanceToneCurve& userToneCurve = static_cast (customToneCurve); @@ -239,7 +228,7 @@ void customToneCurve(const ToneCurve &customToneCurve, ToneCurveParams::TcMode c rtemp[ti * tileSize + tj] = CLIP (rtemp[ti * tileSize + tj]); gtemp[ti * tileSize + tj] = CLIP (gtemp[ti * tileSize + tj]); btemp[ti * tileSize + tj] = CLIP (btemp[ti * tileSize + tj]); - userToneCurve.Apply (rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]); + userToneCurve.Apply(rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]); } } } else if (curveMode == ToneCurveParams::TcMode::PERCEPTUAL) { // apply curve while keeping color appearance constant @@ -250,7 +239,7 @@ void customToneCurve(const ToneCurve &customToneCurve, ToneCurveParams::TcMode c rtemp[ti * tileSize + tj] = CLIP (rtemp[ti * tileSize + tj]); gtemp[ti * tileSize + tj] = CLIP (gtemp[ti * tileSize + tj]); btemp[ti * tileSize + tj] = CLIP (btemp[ti * tileSize + tj]); - userToneCurve.Apply (rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj], ptcApplyState); + userToneCurve.Apply(rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj], ptcApplyState); } } } From 0f25bfe87b2b20d65348605c020bde469565da96 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 4 Jan 2018 23:15:53 +0100 Subject: [PATCH 22/22] Don't check the impossible cases in rgb2hsvtc() --- rtengine/color.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/rtengine/color.h b/rtengine/color.h index f2092f530..2b6d40174 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -313,18 +313,12 @@ public: s = del_Max / var_Max; if (r == var_Max) { - h = (g - b) / del_Max; + h = (g < b ? 6.f : 0.f) + (g - b) / del_Max; } else if (g == var_Max) { h = 2.f + (b - r) / del_Max; } else { /*if ( b == var_Max ) */ h = 4.f + (r - g) / del_Max; } - - if (h < 0.f) { - h += 6.f; - } else if (h > 6.f) { - h -= 6.f; - } } }