From 105517c56112aa2170c2b9903640ad2aaf870891 Mon Sep 17 00:00:00 2001 From: lewiatan Date: Fri, 16 Feb 2018 22:02:00 +0100 Subject: [PATCH 01/42] support rating tag from EXIF/XMP --- rtengine/imagedata.cc | 17 ++++++++++++++++- rtengine/imagedata.h | 5 ++++- rtengine/rtengine.h | 2 ++ rtexif/rtexif.cc | 6 ++++++ rtgui/cacheimagedata.cc | 2 +- rtgui/cacheimagedata.h | 2 ++ rtgui/thumbnail.cc | 1 + rtgui/thumbnail.h | 5 ++++- 8 files changed, 36 insertions(+), 4 deletions(-) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 4e38c612a..a84d6423c 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -71,7 +71,7 @@ FramesMetaData* FramesMetaData::fromFile (const Glib::ustring& fname, std::uniqu FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir) : frameRootDir(frameRootDir_), iptc(nullptr), time(), timeStamp(), iso_speed(0), aperture(0.), focal_len(0.), focal_len35mm(0.), focus_dist(0.f), - shutter(0.), expcomp(0.), make("Unknown"), model("Unknown"), orientation("Unknown"), lens("Unknown"), + shutter(0.), expcomp(0.), make("Unknown"), model("Unknown"), orientation("Unknown"), rating(0), lens("Unknown"), sampleFormat(IIOSF_UNKNOWN), isPixelShift(false), isHDR(false) { memset (&time, 0, sizeof(time)); @@ -97,6 +97,7 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* serial.clear(); orientation.clear(); lens.clear(); + rating = 0; tag = newFrameRootDir->findTag("Make"); if (!tag) { @@ -187,6 +188,11 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* orientation = tag->valueToString (); } + tag = newFrameRootDir->findTagUpward("Rating"); + if (tag) { + rating = tag->toInt(); + } + tag = newFrameRootDir->findTagUpward("MakerNote"); rtexif::TagDirectory* mnote = nullptr; if (tag) { @@ -876,6 +882,11 @@ std::string FrameData::getOrientation () const return orientation; } +int FrameData::getRating () const +{ + return rating; +} + void FramesData::setDCRawFrameCount (unsigned int frameCount) @@ -1168,6 +1179,10 @@ std::string FramesData::getOrientation(unsigned int frame) const } ); } +int FramesData::getRating (unsigned int frame) const +{ + return frames.empty() || frame >= frames.size() ? 0 : frames.at(frame)->getRating (); +} //------inherited functions--------------// diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index c6889e653..b65049e2d 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -49,6 +49,7 @@ protected: std::string make, model, serial; std::string orientation; std::string lens; + int rating; IIOSampleFormat sampleFormat; // each frame has the knowledge of "being an" @@ -84,6 +85,7 @@ public: std::string getLens () const; std::string getSerialNumber () const; std::string getOrientation () const; + int getRating () const; }; class FramesData : public FramesMetaData { @@ -125,7 +127,8 @@ public: std::string getModel (unsigned int frame = 0) const override; std::string getLens (unsigned int frame = 0) const override; std::string getSerialNumber (unsigned int frame = 0) const; - std::string getOrientation (unsigned int frame = 0) const override; + std::string getOrientation (unsigned int frame = 0) const; + int getRating (unsigned int frame = 0) const override; }; diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 6264d43ae..8df6e9ef5 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -133,6 +133,8 @@ public: virtual std::string getLens (unsigned int frame = 0) const = 0; /** @return the orientation of the image */ virtual std::string getOrientation (unsigned int frame = 0) const = 0; + /** @return the rating of the image */ + virtual int getRating (unsigned int frame = 0) const = 0; /** @return true if the file is a PixelShift shot (Pentax and Sony bodies) */ virtual bool getPixelShift () const = 0; diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index 571fd4e6b..312cbd1c7 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -3037,6 +3037,12 @@ void ExifManager::parse (bool isRaw, bool skipIgnored) } } + if (!root->getTag ("Rating")) { + Tag *t = new Tag (root, root->getAttrib("Rating")); + t->initInt (0, LONG); + root->addTag (t); + } + // --- detecting image root IFD based on SubFileType, or if not provided, on PhotometricInterpretation bool frameRootDetected = false; diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 35aeb6c91..1c4ac83ea 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -27,7 +27,7 @@ CacheImageData::CacheImageData () : md5(""), supported(false), format(FT_Invalid), rankOld(-1), inTrashOld(false), recentlySaved(false), timeValid(false), year(0), month(0), day(0), hour(0), min(0), sec(0), exifValid(false), frameCount(1), - fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), isHDR (false), + fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), rating(0), isHDR (false), isPixelShift (false), sensortype(rtengine::ST_NONE), sampleFormat(rtengine::IIOSF_UNKNOWN), redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), rotate(0), thumbImgType(0) { diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index d3aea803b..9de9d186f 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -54,6 +54,7 @@ public: double focalLen, focalLen35mm; float focusDist; unsigned iso; + int rating; bool isHDR; bool isPixelShift; int sensortype; @@ -108,6 +109,7 @@ public: std::string getModel (unsigned int frame = 0) const override { return camModel; } std::string getLens (unsigned int frame = 0) const override { return lens; } std::string getOrientation (unsigned int frame = 0) const override { return ""; } // TODO + int getRating (unsigned int frame = 0) const override { return rating; } // FIXME-piotr : missing rating bool getPixelShift () const override { return isPixelShift; } bool getHDR (unsigned int frame = 0) const override { return isHDR; } std::string getImageType (unsigned int frame) const override { return isPixelShift ? "PS" : isHDR ? "HDR" : "STD"; } diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 757708002..e0509f457 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -813,6 +813,7 @@ int Thumbnail::infoFromImage (const Glib::ustring& fname, std::unique_ptrgetLens(); cfs.camMake = idata->getMake(); cfs.camModel = idata->getModel(); + cfs.rating = idata->getRating(); if (idata->getOrientation() == "Rotate 90 CW") { deg = 90; diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index 0bcdd470a..2c0cba2b0 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -164,7 +164,10 @@ public: return cfs.md5; } - int getRank () const; + int getRank () const + { + return cfs.rating; + } void setRank (int rank); int getColorLabel () const; From 7512093c205090608c316cd3e866af9feaa0ce66 Mon Sep 17 00:00:00 2001 From: lewiatan Date: Sat, 17 Feb 2018 22:08:25 +0100 Subject: [PATCH 02/42] support rating tag from EXIF/XMP- fixes --- rtgui/cacheimagedata.cc | 5 +++++ rtgui/thumbnail.h | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 1c4ac83ea..47318990d 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -66,6 +66,10 @@ int CacheImageData::load (const Glib::ustring& fname) rankOld = keyFile.get_integer ("General", "Rank"); } + if (keyFile.has_key ("General", "Rating")) { + rating = keyFile.get_integer ("General", "Rating"); + } + if (keyFile.has_key ("General", "InTrash")) { inTrashOld = keyFile.get_boolean ("General", "InTrash"); } @@ -227,6 +231,7 @@ int CacheImageData::save (const Glib::ustring& fname) keyFile.set_boolean ("General", "Supported", supported); keyFile.set_integer ("General", "Format", format); keyFile.set_boolean ("General", "RecentlySaved", recentlySaved); + keyFile.set_integer ("General", "Rating", rating); // remove the old implementation of Rank and InTrash from cache if (keyFile.has_key ("General", "Rank")) { diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index 2c0cba2b0..75b1ecdd5 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -168,7 +168,13 @@ public: { return cfs.rating; } - void setRank (int rank); + void setRank (int rank) + { + if (cfs.rating != rank) { + cfs.rating = rank; + } + pparamsValid = true; // FIXME-piotr Is this the right way to refresh the cache? Probably not since pparams and cache should be 2 different things + } int getColorLabel () const; void setColorLabel (int colorlabel); From 820024972aaf9e3dc92e385bd13da2039a1a826a Mon Sep 17 00:00:00 2001 From: Eric Jiang Date: Thu, 16 May 2019 17:09:46 -0700 Subject: [PATCH 03/42] Use rating from EXIF/XMP where available --- rtengine/imagedata.cc | 10 +++++++++- rtengine/imagedata.h | 2 +- rtengine/procparams.cc | 5 ++++- rtgui/thumbnail.cc | 11 +++++++++-- rtgui/thumbnail.h | 13 ++----------- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index a84d6423c..b9720ec8a 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -188,10 +188,18 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* orientation = tag->valueToString (); } + // Look for Rating metadata in the following order: + // 1. EXIF + // 2. XMP + // 3. pp3 sidecar file tag = newFrameRootDir->findTagUpward("Rating"); - if (tag) { + if (tag && tag->toInt() != 0) { rating = tag->toInt(); } + char sXMPRating[64]; + if (newFrameRootDir->getXMPTagValue("xmp:Rating", sXMPRating)) { + rating = atoi(sXMPRating); + } tag = newFrameRootDir->findTagUpward("MakerNote"); rtexif::TagDirectory* mnote = nullptr; diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index b65049e2d..097a5cc80 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -48,8 +48,8 @@ protected: double expcomp; std::string make, model, serial; std::string orientation; - std::string lens; int rating; + std::string lens; IIOSampleFormat sampleFormat; // each frame has the knowledge of "being an" diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 6d914bb27..f492e5900 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2832,7 +2832,10 @@ void ProcParams::setDefaults() exif.clear(); iptc.clear(); - rank = 0; + // -1 means that there's no pp3 data with rank yet. In this case, the + // embedded Rating metadata should take precedence. -1 should never be + // written to pp3 on disk. + rank = -1; colorlabel = 0; inTrash = false; diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index e0509f457..39f4ca093 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -1006,15 +1006,22 @@ void Thumbnail::setFileName (const Glib::ustring &fn) int Thumbnail::getRank () const { - return pparams->rank; + // prefer the user-set rank over the embedded Rating + // pparams->rank == -1 means that there is no saved rank yet, so we should + // next look for the embedded Rating metadata. + if (pparams->rank != -1) { + return pparams->rank; + } else { + return cfs.rating; + } } void Thumbnail::setRank (int rank) { if (pparams->rank != rank) { pparams->rank = rank; - pparamsValid = true; } + pparamsValid = true; } int Thumbnail::getColorLabel () const diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index 75b1ecdd5..0bcdd470a 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -164,17 +164,8 @@ public: return cfs.md5; } - int getRank () const - { - return cfs.rating; - } - void setRank (int rank) - { - if (cfs.rating != rank) { - cfs.rating = rank; - } - pparamsValid = true; // FIXME-piotr Is this the right way to refresh the cache? Probably not since pparams and cache should be 2 different things - } + int getRank () const; + void setRank (int rank); int getColorLabel () const; void setColorLabel (int colorlabel); From a25655cafdd5f96cb11c4f0012ff2304095c0192 Mon Sep 17 00:00:00 2001 From: Eric Jiang Date: Thu, 16 May 2019 19:37:27 -0700 Subject: [PATCH 04/42] Check that metadata rating is between 0 and 5 Does not handle Rating=-1 meaning Rejected yet. --- rtengine/imagedata.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index b9720ec8a..26fe80f03 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -200,6 +200,16 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* if (newFrameRootDir->getXMPTagValue("xmp:Rating", sXMPRating)) { rating = atoi(sXMPRating); } + // guard against out-of-range values + if (rating > 5) { + rating = 5; + } + // Currently, Rating=-1 is not supported. A value of -1 should mean + // "Rejected" according to the specification. Maybe in the future, Rating=-1 + // sets InTrash=true? + if (rating < 0) { + rating = 0; + } tag = newFrameRootDir->findTagUpward("MakerNote"); rtexif::TagDirectory* mnote = nullptr; From 9df80089491f918df4b07ea8f82c01ed5a04b282 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Tue, 4 Jun 2019 21:31:03 +0200 Subject: [PATCH 05/42] Film negative processing: first usable version. Only supports bayer raw files, thumbnails don't work Added performance improvements suggested by heckflosse. Lowered median sampling step from 7 to 5 since calculation is now much faster. Added support for Fuji X-Trans raw files. Applied SSE2 patch provided by @heckflosse, improves performance in main processing loop. Moved film negative processing stuff in its own compilation unit. Code cleanup: removed redundant omp directives. Added check for dead pixels, going above threshold after inversion. ST_BAYER only for now. Reverted leftover hack in cropwindow.cc --- .gitignore | 1 + rtdata/languages/Catala | 9 + rtdata/languages/Chinese (Simplified) | 9 + rtdata/languages/Deutsch | 13 + rtdata/languages/English (UK) | 9 + rtdata/languages/English (US) | 9 + rtdata/languages/Italiano | 9 + rtdata/languages/Magyar | 9 + rtdata/languages/Nederlands | 9 + rtdata/languages/Polish | 9 + rtdata/languages/Portugues (Brasil) | 9 + rtdata/languages/Russian | 9 + rtdata/languages/Serbian (Cyrilic Characters) | 9 + rtdata/languages/Swedish | 9 + rtdata/languages/default | 9 + rtengine/CMakeLists.txt | 1 + rtengine/filmnegativeproc.cc | 321 ++++++++++++++++++ rtengine/imagesource.h | 3 + rtengine/improccoordinator.cc | 31 ++ rtengine/improccoordinator.h | 1 + rtengine/procparams.cc | 41 +++ rtengine/procparams.h | 19 ++ rtengine/rawimagesource.h | 4 + rtengine/rtengine.h | 1 + rtengine/simpleprocess.cc | 5 + rtgui/CMakeLists.txt | 1 + rtgui/filmnegative.cc | 320 +++++++++++++++++ rtgui/filmnegative.h | 91 +++++ rtgui/paramsedited.cc | 29 ++ rtgui/paramsedited.h | 10 + rtgui/toolpanelcoord.cc | 18 +- rtgui/toolpanelcoord.h | 8 +- 32 files changed, 1033 insertions(+), 2 deletions(-) create mode 100644 rtengine/filmnegativeproc.cc create mode 100644 rtgui/filmnegative.cc create mode 100644 rtgui/filmnegative.h diff --git a/.gitignore b/.gitignore index 21ebf986a..fc65c877c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ .project .settings .directory +.vscode CMakeCache.txt CMakeFiles diff --git a/rtdata/languages/Catala b/rtdata/languages/Catala index 73970424b..f9bcf25b2 100644 --- a/rtdata/languages/Catala +++ b/rtdata/languages/Catala @@ -1314,6 +1314,8 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1851,6 +1853,13 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified) index fde2aab1b..78807ddd4 100644 --- a/rtdata/languages/Chinese (Simplified) +++ b/rtdata/languages/Chinese (Simplified) @@ -1361,6 +1361,8 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1798,6 +1800,13 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 7f562d51c..fd2d0d07a 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -2360,3 +2360,16 @@ ZOOMPANEL_ZOOMFITSCREEN;An Bildschirm anpassen.\nTaste: Alt + f ZOOMPANEL_ZOOMIN;Hineinzoomen\nTaste: + ZOOMPANEL_ZOOMOUT;Herauszoomen\nTaste: - +!!!!!!!!!!!!!!!!!!!!!!!!! +! Untranslated keys follow; remove the ! prefix after an entry is translated. +!!!!!!!!!!!!!!!!!!!!!!!!! + +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index cda91f29a..24bffbb0a 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -838,6 +838,8 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1665,6 +1667,13 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index 9affa9444..5dad9591a 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -748,6 +748,8 @@ !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1636,6 +1638,13 @@ !TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano index bedba34f6..98d86b69d 100644 --- a/rtdata/languages/Italiano +++ b/rtdata/languages/Italiano @@ -1539,6 +1539,8 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1903,6 +1905,13 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/Magyar b/rtdata/languages/Magyar index d1947b893..7aa5b30c3 100644 --- a/rtdata/languages/Magyar +++ b/rtdata/languages/Magyar @@ -1248,6 +1248,8 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1816,6 +1818,13 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands index b8b30e64c..508f06384 100644 --- a/rtdata/languages/Nederlands +++ b/rtdata/languages/Nederlands @@ -2036,6 +2036,8 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -2230,6 +2232,13 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !TP_EXPOSURE_CLAMPOOG;Clip out-of-gamut colors !TP_EXPOSURE_HISTMATCHING;Auto-Matched Tone Curve !TP_EXPOSURE_HISTMATCHING_TOOLTIP;Automatically adjust sliders and curves (except exposure compensation) to match the look of the embedded JPEG thumbnail. +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_ICM_WORKING_TRC;Tone response curve: !TP_ICM_WORKING_TRC_CUSTOM;Custom !TP_ICM_WORKING_TRC_GAMMA;Gamma diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish index 05f099ea6..e35f583ff 100644 --- a/rtdata/languages/Polish +++ b/rtdata/languages/Polish @@ -1621,6 +1621,8 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1929,6 +1931,13 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_EXPOSURE_HISTMATCHING_TOOLTIP;Automatically adjust sliders and curves (except exposure compensation) to match the look of the embedded JPEG thumbnail. !TP_EXPOSURE_TCMODE_LUMINANCE;Luminance !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_ICM_APPLYBASELINEEXPOSUREOFFSET;Baseline exposure !TP_ICM_APPLYBASELINEEXPOSUREOFFSET_TOOLTIP;Employ the embedded DCP baseline exposure offset. The setting is only available if the selected DCP has one. diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil) index da9a620df..0bafe632f 100644 --- a/rtdata/languages/Portugues (Brasil) +++ b/rtdata/languages/Portugues (Brasil) @@ -2258,6 +2258,8 @@ ZOOMPANEL_ZOOMOUT;Menos Zoom\nAtalho: - !FILEBROWSER_EMPTYTRASHHINT;Permanently delete all files in trash. !HISTORY_MSG_COLORTONING_LABREGION_OFFSET;CT - region offset !HISTORY_MSG_COLORTONING_LABREGION_POWER;CT - region power +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed !MAIN_FRAME_PLACES_DEL;Remove !PREFERENCES_APPEARANCE_PSEUDOHIDPI;Pseudo-HiDPI mode !PREFERENCES_CACHECLEAR_SAFETY;Only files in the cache are cleared. Processing profiles stored alongside the source images are not touched. @@ -2271,6 +2273,13 @@ ZOOMPANEL_ZOOMOUT;Menos Zoom\nAtalho: - !TP_COLORTONING_LABREGION_OFFSET;Offset !TP_COLORTONING_LABREGION_POWER;Power !TP_CROP_PPI;PPI +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected !TP_LENSPROFILE_LENS_WARNING;Warning: the crop factor used for lens profiling is larger than the crop factor of the camera, the results might be wrong. diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian index c2b43033e..9e43f1098 100644 --- a/rtdata/languages/Russian +++ b/rtdata/languages/Russian @@ -1706,6 +1706,8 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !HISTORY_MSG_COLORTONING_LABREGION_SLOPE;CT - region slope !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D !HISTORY_MSG_ICM_OUTPUT_TYPE;Output - Type @@ -1974,6 +1976,13 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !TP_DISTORTION_AUTO_TIP;Automatically corrects lens distortion in raw files by matching it against the embedded JPEG image if one exists and has had its lens disortion auto-corrected by the camera. !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FLATFIELD_CLIPCONTROL;Clip control !TP_FLATFIELD_CLIPCONTROL_TOOLTIP;Clip control avoids clipped highlights caused by applying the flat field. If there are already clipped highlights before applying the flat field, clip control can lead to color cast. diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters) index 21a34119a..ce1452821 100644 --- a/rtdata/languages/Serbian (Cyrilic Characters) +++ b/rtdata/languages/Serbian (Cyrilic Characters) @@ -1514,6 +1514,8 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1902,6 +1904,13 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish index 14dc4069f..cd3b9b3fc 100644 --- a/rtdata/languages/Swedish +++ b/rtdata/languages/Swedish @@ -1863,6 +1863,8 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +!HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -2117,6 +2119,13 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !TP_EXPOSURE_CLAMPOOG;Clip out-of-gamut colors !TP_EXPOSURE_HISTMATCHING;Auto-Matched Tone Curve !TP_EXPOSURE_HISTMATCHING_TOOLTIP;Automatically adjust sliders and curves (except exposure compensation) to match the look of the embedded JPEG thumbnail. +!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_GREEN;Green exponent +!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +!TP_FILMNEGATIVE_LABEL;Film Negative +!TP_FILMNEGATIVE_PICK;Pick white and black spots +!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FLATFIELD_CLIPCONTROL;Clip control !TP_FLATFIELD_CLIPCONTROL_TOOLTIP;Clip control avoids clipped highlights caused by applying the flat field. If there are already clipped highlights before applying the flat field, clip control can lead to color cast. !TP_ICM_APPLYBASELINEEXPOSUREOFFSET_TOOLTIP;Employ the embedded DCP baseline exposure offset. The setting is only available if the selected DCP has one. diff --git a/rtdata/languages/default b/rtdata/languages/default index 5ea726218..e6a546a7e 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -747,6 +747,8 @@ HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;Dehaze - Show depth map HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold +HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative +HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed HISTORY_MSG_HISTMATCHING;Auto-matched tone curve HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1635,6 +1637,13 @@ TP_EXPOSURE_TCMODE_STANDARD;Standard TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points TP_EXPOS_WHITEPOINT_LABEL;Raw White Points +TP_FILMNEGATIVE_BLUE;Blue exponent +TP_FILMNEGATIVE_GREEN;Green exponent +TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. +TP_FILMNEGATIVE_LABEL;Film Negative +TP_FILMNEGATIVE_PICK;Pick white and black spots +TP_FILMNEGATIVE_RED;Red exponent +TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots TP_FILMSIMULATION_LABEL;Film Simulation TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? TP_FILMSIMULATION_STRENGTH;Strength diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index a1037f5a3..dfa843fd0 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -132,6 +132,7 @@ set(RTENGINESOURCEFILES ipdehaze.cc iplabregions.cc lj92.c + filmnegativeproc.cc ) if(LENSFUN_HAS_LOAD_DIRECTORY) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc new file mode 100644 index 000000000..dba623ab4 --- /dev/null +++ b/rtengine/filmnegativeproc.cc @@ -0,0 +1,321 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include +#include + +#include "rtengine.h" +#include "rawimagesource.h" +#include "mytime.h" +#include "procparams.h" +#ifdef _OPENMP +#include +#endif +#include "opthelper.h" +#include "rt_algo.h" + +namespace rtengine +{ + +extern const Settings* settings; + +bool RawImageSource::channelsAvg(Coord spotPos, int spotSize, float avgs[3], const FilmNegativeParams ¶ms) +{ + avgs[0] = avgs[1] = avgs[2] = 0.f; // Channel averages + + if(ri->getSensorType() != ST_BAYER && ri->getSensorType() != ST_FUJI_XTRANS) + return false; + + if (settings->verbose) + printf("Spot coord: x=%d y=%d\n", spotPos.x, spotPos.y); + + int x1 = spotPos.x - spotSize / 2; + int x2 = spotPos.x + spotSize / 2; + int y1 = spotPos.y - spotSize / 2; + int y2 = spotPos.y + spotSize / 2; + + if(x1<0 || x2>W || y1<0 || y2>H) + return false; // Spot goes outside bounds, bail out. + + int pxCount[3] = {0}; // Per-channel sample counts + for(int c=spotPos.x-spotSize; cgetSensorType() == ST_BAYER) ? FC(r,c) : ri->XTRANSFC(r,c); + + pxCount[ch]++; + // If film negative is currently enabled, undo the effect by elevating to 1/exp, + // in order to sample the original, linear value + if(params.enabled) + avgs[ch] += powf(rawData[r][c], -1 / (ch==0 ? params.redExp : ch==1 ? params.greenExp : params.blueExp)); + else + avgs[ch] += rawData[r][c]; + } + } + + for(int ch=0; ch<3; ch++) + avgs[ch] = avgs[ch] / (pxCount[ch]); + + return true; +} + +// Calculate logarithms in arbitrary base +float logBase(float base, float num) { + return log(num) / log(base); +} + +bool RawImageSource::getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, float newExps[3]) +{ + float clearVals[3], denseVals[3]; + + newExps[0] = currentParams.redExp; + newExps[1] = currentParams.greenExp; + newExps[2] = currentParams.blueExp; + + int spotSize = 32; // TODO : make this confugurable ? + Coord spot; + // Sample first spot + transformPosition (spotA.x, spotA.y, tran, spot.x, spot.y); + if(!channelsAvg(spot, spotSize, clearVals, currentParams)) + return false; + + // Sample second spot + transformPosition (spotB.x, spotB.y, tran, spot.x, spot.y); + if(!channelsAvg(spot, spotSize, denseVals, currentParams)) + return false; + + // Detect which one is the dense spot, based on green channel + if(clearVals[1] < denseVals[1]) + std::swap(clearVals, denseVals); + + if (settings->verbose) { + printf("Clear film values: R=%f G=%f B=%f\n", clearVals[0], clearVals[1], clearVals[2]); + printf("Dense film values: R=%f G=%f B=%f\n", denseVals[0], denseVals[1], denseVals[2]); + } + + float denseGreenRatio = clearVals[1] / denseVals[1]; + + // Calculate exponents for each channel, based on the ratio between the bright and dark values, + // compared to the ratio in the reference channel (green) + for(int ch=0; ch<3; ch++) + if(ch==1) + newExps[ch] = 1.f; // Green is the reference channel + else + newExps[ch] = CLAMP(logBase(clearVals[ch] / denseVals[ch], denseGreenRatio), 0.3f, 3.f); + + if (settings->verbose) + printf("New exponents: R=%f G=%f B=%f\n", newExps[0], newExps[1], newExps[2]); + + return true; +} + +void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams ¶ms) +{ + if(!params.enabled) + return; + + float exps[3] = { (float)params.redExp, (float)params.greenExp, (float)params.blueExp }; + + MyTime t1, t2, t3,t4, t5, t6; + t1.set(); + + if(ri->getSensorType() == ST_BAYER) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int row = 0; row < H; row ++) { + int col = 0; + // Exponents are expressed as positive in the parameters, so negate them in order + // to get the reciprocals. Avoid trouble with zeroes, minimum pixel value is 1. + const float exps0 = -exps[FC(row, col)]; + const float exps1 = -exps[FC(row, col + 1)]; +#ifdef __SSE2__ + const vfloat expsv = _mm_setr_ps(exps0, exps1, exps0, exps1); + const vfloat onev = F2V(1.f); + for (; col < W - 3; col+=4) { + STVFU(rawData[row][col], pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv)); + } +#endif // __SSE2__ + for (; col < W - 1; col+=2) { + rawData[row][col] = pow_F(max(rawData[row][col], 1.f), exps0); + rawData[row][col + 1] = pow_F(max(rawData[row][col + 1], 1.f), exps1); + } + if (col < W) { + rawData[row][col] = pow_F(max(rawData[row][col], 1.f), exps0); + } + } + } else if(ri->getSensorType() == ST_FUJI_XTRANS) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int row = 0; row < H; row ++) { + int col = 0; + // Exponents are expressed as positive in the parameters, so negate them in order + // to get the reciprocals. Avoid trouble with zeroes, minimum pixel value is 1. + const float expsc[6] = {-exps[ri->XTRANSFC(row, 0)], -exps[ri->XTRANSFC(row, 1)], -exps[ri->XTRANSFC(row, 2)], -exps[ri->XTRANSFC(row, 3)], -exps[ri->XTRANSFC(row, 4)], -exps[ri->XTRANSFC(row, 5)]}; +#ifdef __SSE2__ + const vfloat expsv0 = _mm_setr_ps(expsc[0], expsc[1], expsc[2], expsc[3]); + const vfloat expsv1 = _mm_setr_ps(expsc[4], expsc[5], expsc[0], expsc[1]); + const vfloat expsv2 = _mm_setr_ps(expsc[2], expsc[3], expsc[4], expsc[5]); + const vfloat onev = F2V(1.f); + for (; col < W - 11; col+=12) { + STVFU(rawData[row][col], pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv0)); + STVFU(rawData[row][col + 4], pow_F(vmaxf(LVFU(rawData[row][col + 4]), onev), expsv1)); + STVFU(rawData[row][col + 8], pow_F(vmaxf(LVFU(rawData[row][col + 8]), onev), expsv2)); + } +#endif // __SSE2__ + for (; col < W - 5; col+=6) { + for (int c = 0; c < 6; ++c) { + rawData[row][col + c] = pow_F(max(rawData[row][col + c], 1.f), expsc[c]); + } + } + for (int c = 0; col < W; col++, c++) { + rawData[row][col + c] = pow_F(max(rawData[row][col + c], 1.f), expsc[c]); + } + } + } + + + t2.set(); + if (settings->verbose) + printf("Pow loop time us: %d\n", t2.etime(t1)); + + // Channel vectors to calculate medians + std::vector cvs[3] = { + std::vector(), + std::vector(), + std::vector() + }; + + // Sample one every 5 pixels, and push the value in the appropriate channel vector. + // Chose an odd step, not multiple of the CFA size, to get a chance to visit each channel. + if(ri->getSensorType() == ST_BAYER) { + for (int row = 0; row < H; row+=5) { + for (int col = 0; col < W; col+=5) { + int c = FC(row, col); // three colors, 0=R, 1=G, 2=B + cvs[c].push_back(rawData[row][col]); + } + } + } else if(ri->getSensorType() == ST_FUJI_XTRANS) { + for (int row = 0; row < H; row+=5) { + for (int col = 0; col < W; col+=5) { + int c = ri->XTRANSFC(row, col); // three colors, 0=R, 1=G, 2=B + cvs[c].push_back(rawData[row][col]); + } + } + } + + const float MAX_OUT_VALUE = 65000.f; + + t3.set(); + if (settings->verbose) + printf("Median vector fill loop time us: %d\n", t3.etime(t2)); + + float medians[3]; // Channel median values + float mults[3] = { 1.f }; // Channel normalization multipliers + + for (int c=0; c<3; c++) { + // Find median values for each channel using a histogram search function + findMinMaxPercentile(&cvs[c][0], cvs[c].size(), 0.5f, medians[c], 0.5f, medians[c], true); + // Determine the channel multipler so that N times the median becomes 65k. This clips away + // the values in the dark border surrounding the negative (due to the film holder, for example), + // the reciprocal of which have blown up to stellar values. + mults[c] = MAX_OUT_VALUE / (medians[c] * 24); + } + + + t4.set(); + if (settings->verbose) { + printf("Sample count : %lu, %lu, %lu\n", cvs[0].size(), cvs[1].size(), cvs[2].size()); + printf("Medians : %f %f %f\n", medians[0], medians[1], medians[2] ); + printf("Computed multipliers : %f %f %f\n", mults[0], mults[1], mults[2] ); + printf("Median calc time us: %d\n", t4.etime(t3)); + } + + + if(ri->getSensorType() == ST_BAYER) { + +#ifdef _OPENMP + #pragma omp for nowait +#endif + for (int row = 0; row < H; row ++) { + for (int col = 0; col < W; col++) { + int c = FC(row, col); // three colors, 0=R, 1=G, 2=B + // Apply the multipliers + rawData[row][col] *= mults[c]; + } + } + + } else if(ri->getSensorType() == ST_FUJI_XTRANS) { + +#ifdef _OPENMP + #pragma omp for nowait +#endif + for (int row = 0; row < H; row ++) { + for (int col = 0; col < W; col++) { + int c = ri->XTRANSFC(row, col); // three colors, 0=R, 1=G, 2=B + // Apply the multipliers + rawData[row][col] *= mults[c]; + } + } + + } + + + t5.set(); + if (settings->verbose) + printf("Mult loop time us: %d\n", t5.etime(t4)); + + + PixelsMap bitmapBads(W, H); + + int totBP = 0; // Hold count of bad pixels to correct + + if(ri->getSensorType() == ST_BAYER) { + + +#ifdef _OPENMP + #pragma omp parallel for reduction(+:totBP) schedule(dynamic,16) +#endif + + for(int i = 0; i < H; i++) + for(int j = 0; j < W; j++) { + if (rawData[i][j] >= MAX_OUT_VALUE) { + bitmapBads.set(j, i); + totBP++; + } + } + + if (totBP > 0) { + interpolateBadPixelsBayer( bitmapBads, rawData ); + } + + } else if(ri->getSensorType() == ST_FUJI_XTRANS) { + + // TODO + + } + + t6.set(); + if (settings->verbose) { + printf("Bad pixels count: %d\n", totBP); + printf("Bad pixels interpolation time us: %d\n", t6.etime(t5)); + } +} + +} \ No newline at end of file diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index a18cca9d7..e3321b599 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -43,6 +43,7 @@ struct LensProfParams; struct RAWParams; struct RetinexParams; struct ToneCurveParams; +struct FilmNegativeParams; } @@ -77,6 +78,8 @@ public: ~ImageSource () override {} virtual int load (const Glib::ustring &fname) = 0; virtual void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, bool prepareDenoise = true) {}; + virtual void filmNegativeProcess (const procparams::FilmNegativeParams ¶ms) {}; + virtual bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, float newExps[3]) { return false; }; virtual void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold) {}; virtual void retinex (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &deh, const procparams::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 procparams::RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) {}; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 01f9892bf..2d0d490ad 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -277,6 +277,11 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) imgsrc->getRAWHistogram(histRedRaw, histGreenRaw, histBlueRaw); highDetailPreprocessComputed = highDetailNeeded; + + // After preprocess, run film negative processing if enabled + if((todo & M_RAW) && (imgsrc->getSensorType() == ST_BAYER || imgsrc->getSensorType() == ST_FUJI_XTRANS) && params->filmNegative.enabled) { + imgsrc->filmNegativeProcess (params->filmNegative); + } } /* @@ -1250,6 +1255,32 @@ void ImProcCoordinator::getSpotWB(int x, int y, int rect, double& temp, double& } } +bool ImProcCoordinator::getFilmNegativeExponents(int xA, int yA, int xB, int yB, float* newExps) +{ + + { + MyMutex::MyLock lock(mProcessing); + + auto xlate = [this](int x, int y) { + std::vector points, red, green, blue; + + points.push_back(Coord2D(x, y)); + ipf.transCoord(fw, fh, points, red, green, blue); + return green[0]; + }; + + int tr = getCoarseBitMask(params->coarse); + + Coord2D p1 = xlate(xA, yA); + Coord2D p2 = xlate(xB, yB); + + return imgsrc->getFilmNegativeExponents(p1, p2, tr, params->filmNegative, newExps); + + } // end of mutex locking + +} + + void ImProcCoordinator::getAutoCrop(double ratio, int &x, int &y, int &w, int &h) { diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index c293f0c16..d10db8d70 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -269,6 +269,7 @@ public: bool getAutoWB (double& temp, double& green, double equal, double tempBias) override; void getCamWB (double& temp, double& green) override; void getSpotWB (int x, int y, int rectSize, double& temp, double& green) override; + bool getFilmNegativeExponents(int xA, int yA, int xB, int yB, float* newExps) override; void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) override; bool getHighQualComputed() override; void setHighQualComputed() override; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index c24ee0049..9780255da 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2735,6 +2735,32 @@ bool MetaDataParams::operator!=(const MetaDataParams &other) const } +FilmNegativeParams::FilmNegativeParams() : + enabled(false), + redExp(1.36), + greenExp(1.0), + blueExp(0.86) +{ +} + +bool FilmNegativeParams::operator ==(const FilmNegativeParams& other) const +{ + return + enabled == other.enabled + && redExp == other.redExp + && greenExp == other.greenExp + && blueExp == other.blueExp; +} + +bool FilmNegativeParams::operator !=(const FilmNegativeParams& other) const +{ + return !(*this == other); +} + + + + + ProcParams::ProcParams() { setDefaults(); @@ -3566,6 +3592,13 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo // MetaData saveToKeyfile(!pedited || pedited->metadata.mode, "MetaData", "Mode", metadata.mode, keyFile); +// Film negative + saveToKeyfile(!pedited || pedited->filmNegative.enabled, "Film Negative", "Enabled", filmNegative.enabled, keyFile); + saveToKeyfile(!pedited || pedited->filmNegative.redExp, "Film Negative", "RedExponent", filmNegative.redExp, keyFile); + saveToKeyfile(!pedited || pedited->filmNegative.greenExp, "Film Negative", "GreenExponent", filmNegative.greenExp, keyFile); + saveToKeyfile(!pedited || pedited->filmNegative.blueExp, "Film Negative", "BlueExponent", filmNegative.blueExp, keyFile); + + // EXIF change list if (!pedited || pedited->exif) { for (ExifPairs::const_iterator i = exif.begin(); i != exif.end(); ++i) { @@ -5109,6 +5142,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "RAW X-Trans", "PreBlackBlue", pedited, raw.xtranssensor.blackblue, pedited->raw.xtranssensor.exBlackBlue); } + if (keyFile.has_group("Film Negative")) { + assignFromKeyfile(keyFile, "Film Negative", "Enabled", pedited, filmNegative.enabled, pedited->filmNegative.enabled); + assignFromKeyfile(keyFile, "Film Negative", "RedExponent", pedited, filmNegative.redExp, pedited->filmNegative.redExp); + assignFromKeyfile(keyFile, "Film Negative", "GreenExponent", pedited, filmNegative.greenExp, pedited->filmNegative.greenExp); + assignFromKeyfile(keyFile, "Film Negative", "BlueExponent", pedited, filmNegative.blueExp, pedited->filmNegative.blueExp); + } + + if (keyFile.has_group("MetaData")) { int mode = int(MetaDataParams::TUNNEL); assignFromKeyfile(keyFile, "MetaData", "Mode", pedited, mode, pedited->metadata.mode); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 0982fda48..3f9ff0342 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1501,6 +1501,23 @@ struct RAWParams { static Glib::ustring getFlatFieldBlurTypeString(FlatFieldBlurType type); }; + +/** + * Parameters of film negative + */ +struct FilmNegativeParams { + bool enabled; + double redExp; + double greenExp; + double blueExp; + + FilmNegativeParams(); + + bool operator ==(const FilmNegativeParams& other) const; + bool operator !=(const FilmNegativeParams& other) const; +}; + + /** * This class holds all the processing parameters applied on the images */ @@ -1559,6 +1576,8 @@ public: ExifPairs exif; ///< List of modifications appplied on the exif tags of the input image IPTCPairs iptc; ///< The IPTC tags and values to be saved to the output image + FilmNegativeParams filmNegative; ///< Film negative parameters + /** * The constructor only sets the hand-wired defaults. */ diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 530211715..56fec7146 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -44,6 +44,8 @@ private: static LUTf initInvGrad (); static void colorSpaceConversion_ (Imagefloat* im, const procparams::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); + bool channelsAvg(Coord spotPos, int spotSize, float avgs[3], const FilmNegativeParams ¶ms); + protected: MyMutex getImageMutex; // locks getImage @@ -116,6 +118,8 @@ public: int load(const Glib::ustring &fname) override { return load(fname, false); } int load(const Glib::ustring &fname, bool firstFrameOnly); void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, bool prepareDenoise = true) override; + void filmNegativeProcess (const procparams::FilmNegativeParams ¶ms) override; + bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, float newExps[3]) override; void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold) override; void retinex (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &deh, const procparams::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) override; void retinexPrepareCurves (const procparams::RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) override; diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 6264d43ae..cc46cfca8 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -499,6 +499,7 @@ public: virtual bool getAutoWB (double& temp, double& green, double equal, double tempBias) = 0; virtual void getCamWB (double& temp, double& green) = 0; virtual void getSpotWB (int x, int y, int rectSize, double& temp, double& green) = 0; + virtual bool getFilmNegativeExponents(int xA, int yA, int xB, int yB, float* newExps) = 0; virtual void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) = 0; virtual void saveInputICCReference (const Glib::ustring& fname, bool apply_wb) = 0; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 8b9bee738..e270f093f 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -209,6 +209,11 @@ private: imgsrc->setCurrentFrame (params.raw.bayersensor.imageNum); imgsrc->preprocess ( params.raw, params.lensProf, params.coarse, params.dirpyrDenoise.enabled); + // After preprocess, run film negative processing if enabled + if(imgsrc->getSensorType() == ST_BAYER && params.filmNegative.enabled) { + imgsrc->filmNegativeProcess (params.filmNegative); + } + if (pl) { pl->setProgress (0.20); } diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index 3af955be8..4c775bdcc 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -161,6 +161,7 @@ set(NONCLISOURCEFILES labgrid.cc softlight.cc dehaze.cc + filmnegative.cc ) include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc new file mode 100644 index 000000000..bf4c22837 --- /dev/null +++ b/rtgui/filmnegative.cc @@ -0,0 +1,320 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include "filmnegative.h" + +#include + +#include "rtimage.h" +#include "options.h" +#include "editwidgets.h" +#include "eventmapper.h" + + +using namespace rtengine; +using namespace rtengine::procparams; + + +FilmNegative::FilmNegative () : FoldableToolPanel(this, "filmnegative", M("TP_FILMNEGATIVE_LABEL"), false, true), EditSubscriber(ET_OBJECTS) +{ + + auto mkExponentAdjuster = [this](Glib::ustring label, double defaultVal) { + Adjuster *adj = Gtk::manage(new Adjuster (label, 0.3, 3, 0.01, defaultVal)); //exponent + adj->setAdjusterListener (this); + + if (adj->delay < options.adjusterMaxDelay) { + adj->delay = options.adjusterMaxDelay; + } + + adj->show(); + return adj; + }; + + redExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_RED"), 1.36); + greenExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_GREEN"), 1.0); + blueExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_BLUE"), 0.86); + + auto m = ProcEventMapper::getInstance(); + EvFilmNegativeEnabled = m->newEvent(ALL, "HISTORY_MSG_FILMNEGATIVE_ENABLED"); + EvFilmNegativeExponents = m->newEvent(ALL, "HISTORY_MSG_FILMNEGATIVE_EXPONENTS"); + + + spotgrid = Gtk::manage(new Gtk::Grid()); + spotgrid->get_style_context()->add_class("grid-spacing"); + setExpandAlignProperties(spotgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + + spotbutton = Gtk::manage (new Gtk::ToggleButton (M("TP_FILMNEGATIVE_PICK"))); + setExpandAlignProperties(spotbutton, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + spotbutton->get_style_context()->add_class("independent"); + spotbutton->set_tooltip_text(M("TP_FILMNEGATIVE_GUESS_TOOLTIP")); + spotbutton->set_image (*Gtk::manage (new RTImage ("color-picker-small.png"))); + + // TODO make spot size configurable ? + + // Gtk::Label* slab = Gtk::manage (new Gtk::Label (M("TP_WBALANCE_SIZE"))); + // setExpandAlignProperties(slab, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + + // Gtk::Grid* wbsizehelper = Gtk::manage(new Gtk::Grid()); + // wbsizehelper->set_name("WB-Size-Helper"); + // setExpandAlignProperties(wbsizehelper, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + + // spotsize = Gtk::manage (new MyComboBoxText ()); + // setExpandAlignProperties(spotsize, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + // spotsize->append ("2"); + // spotsize->set_active(0); + // spotsize->append ("4"); + + spotgrid->attach (*spotbutton, 0, 1, 1, 1); +// spotgrid->attach (*slab, 1, 0, 1, 1); + // spotgrid->attach (*wbsizehelper, 2, 0, 1, 1); + + pack_start (*redExp, Gtk::PACK_SHRINK, 0); + pack_start (*greenExp, Gtk::PACK_SHRINK, 0); + pack_start (*blueExp, Gtk::PACK_SHRINK, 0); + pack_start (*spotgrid, Gtk::PACK_SHRINK, 0 ); + + spotbutton->signal_toggled().connect( sigc::mem_fun(*this, &FilmNegative::editToggled) ); +// spotsize->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::spotSizeChanged) ); + + + // Editing geometry; create the spot rectangle + Rectangle *spotRect = new Rectangle(); + spotRect->filled = false; + + EditSubscriber::visibleGeometry.push_back( spotRect ); + + // Stick a dummy rectangle over the whole image in mouseOverGeometry. + // This is to make sure the getCursor call is fired everywhere. + Rectangle *imgRect = new Rectangle(); + imgRect->filled = true; + + EditSubscriber::mouseOverGeometry.push_back( imgRect ); + +} + +FilmNegative::~FilmNegative() +{ +// idle_register.destroy(); + + for (std::vector::const_iterator i = visibleGeometry.begin(); i != visibleGeometry.end(); ++i) { + delete *i; + } + + for (std::vector::const_iterator i = mouseOverGeometry.begin(); i != mouseOverGeometry.end(); ++i) { + delete *i; + } + +} + + + +void FilmNegative::enabledChanged() +{ + if (listener) { + if (get_inconsistent()) { + listener->panelChanged(EvFilmNegativeEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged(EvFilmNegativeEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(EvFilmNegativeEnabled, M("GENERAL_DISABLED")); + } + } +} + + +void FilmNegative::adjusterChanged(Adjuster* a, double newval) +{ + if (listener && getEnabled()) { + if(a == redExp || a == greenExp || a == blueExp) { + listener->panelChanged (EvFilmNegativeExponents, Glib::ustring::compose ( + "R=%1 ; G=%2 ; B=%3", redExp->getTextValue(), greenExp->getTextValue(), blueExp->getTextValue())); + } + } +} + +void FilmNegative::adjusterAutoToggled(Adjuster* a, bool newval) +{ +} + +void FilmNegative::setEditProvider (EditDataProvider* provider) +{ + EditSubscriber::setEditProvider(provider); +} + +void FilmNegative::editToggled () +{ + if (spotbutton->get_active()) { + subscribe(); + + int w, h; + getEditProvider()->getImageSize(w, h); + + // Stick a dummy rectangle over the whole image in mouseOverGeometry. + // This is to make sure the getCursor call is fired everywhere. + const auto imgRect = static_cast(mouseOverGeometry.at(0)); + imgRect->setXYWH(0, 0, w, h); + + } else { + this->refSpotCoords.clear(); + unsubscribe(); + } +} + + +void FilmNegative::read (const ProcParams* pp, const ParamsEdited* pedited) +{ + disableListener (); + + if(pedited) { + redExp->setEditedState(pedited->filmNegative.redExp ? Edited : UnEdited); + greenExp->setEditedState(pedited->filmNegative.greenExp ? Edited : UnEdited); + blueExp->setEditedState(pedited->filmNegative.blueExp ? Edited : UnEdited); + set_inconsistent(multiImage && !pedited->filmNegative.enabled); + } + + setEnabled(pp->filmNegative.enabled); + redExp->setValue(pp->filmNegative.redExp); + greenExp->setValue(pp->filmNegative.greenExp); + blueExp->setValue(pp->filmNegative.blueExp); + + enableListener (); +} + +void FilmNegative::write (ProcParams* pp, ParamsEdited* pedited) +{ + pp->filmNegative.redExp = redExp->getValue(); + pp->filmNegative.greenExp = greenExp->getValue(); + pp->filmNegative.blueExp = blueExp->getValue(); + pp->filmNegative.enabled = getEnabled(); + + if (pedited) { + pedited->filmNegative.redExp = redExp->getEditedState(); + pedited->filmNegative.greenExp = greenExp->getEditedState(); + pedited->filmNegative.blueExp = blueExp->getEditedState(); + pedited->filmNegative.enabled = !get_inconsistent(); + } +} + +void FilmNegative::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ + redExp->setValue(defParams->filmNegative.redExp); + greenExp->setValue(defParams->filmNegative.greenExp); + blueExp->setValue(defParams->filmNegative.blueExp); + + if (pedited) { + redExp->setDefaultEditedState (pedited->filmNegative.redExp ? Edited : UnEdited); + greenExp->setDefaultEditedState (pedited->filmNegative.greenExp ? Edited : UnEdited); + blueExp->setDefaultEditedState (pedited->filmNegative.blueExp ? Edited : UnEdited); + } else { + redExp->setDefaultEditedState (Irrelevant); + greenExp->setDefaultEditedState (Irrelevant); + blueExp->setDefaultEditedState (Irrelevant); + } +} + +void FilmNegative::setBatchMode (bool batchMode) +{ + spotConn.disconnect(); + removeIfThere(this, spotgrid, false); + ToolPanel::setBatchMode (batchMode); + redExp->showEditedCB (); + greenExp->showEditedCB (); + blueExp->showEditedCB (); +} + +bool FilmNegative::mouseOver(int modifierKey) +{ + EditDataProvider *provider = getEditProvider(); + const auto spotRect = static_cast(visibleGeometry.at(0)); + spotRect->setXYWH(provider->posImage.x - 16, provider->posImage.y - 16, 32, 32); + + return true; +} + +bool FilmNegative::button1Pressed(int modifierKey) +{ + EditDataProvider *provider = getEditProvider(); + + if(provider) { // debug. remove me + printf("x=%d y=%d pv1=%f pv2=%f pv3=%f\n", provider->posImage.x, provider->posImage.y, provider->getPipetteVal1(), provider->getPipetteVal2(), provider->getPipetteVal3()); + } + + EditSubscriber::action = EditSubscriber::Action::NONE; + + if (listener) { + + refSpotCoords.push_back(provider->posImage); + + if(refSpotCoords.size() == 2) { + + // User has selected 2 reference gray spots. Calculating new exponents + // from channel values and updating parameters. + + float newExps[3]; + if(fnp->getFilmNegativeExponents(refSpotCoords[0], refSpotCoords[1], newExps)) { + disableListener(); + redExp->setValue(newExps[0]); + greenExp->setValue(newExps[1]); + blueExp->setValue(newExps[2]); + enableListener(); + + if (listener && getEnabled()) { + listener->panelChanged (EvFilmNegativeExponents, Glib::ustring::compose ( + "R=%1 ; G=%2 ; B=%3", redExp->getTextValue(), greenExp->getTextValue(), blueExp->getTextValue())); + } + } + + switchOffEditMode(); + } + } + + return true; +} + +bool FilmNegative::button1Released () +{ + EditDataProvider *provider = getEditProvider(); + + if(provider) { // debug. remove me + printf("x=%d y=%d pv1=%f pv2=%f pv3=%f\n", provider->posImage.x, provider->posImage.y, provider->getPipetteVal1(), provider->getPipetteVal2(), provider->getPipetteVal3()); + } + + EditSubscriber::action = EditSubscriber::Action::NONE; + return true; +} + +// TODO remove me ; couldn't make Action::PICKING work +bool FilmNegative::pick1 (bool picked) { + EditDataProvider *provider = getEditProvider(); + if(provider) { // debug. remove me + printf("Picked pick=%d x=%d y=%d pv1=%f pv2=%f pv3=%f\n", picked, provider->posImage.x, provider->posImage.y, provider->getPipetteVal1(), provider->getPipetteVal2(), provider->getPipetteVal3()); + } + return true; +} + +CursorShape FilmNegative::getCursor(int objectID) const +{ + return CSSpotWB; +} + +void FilmNegative::switchOffEditMode () +{ + refSpotCoords.clear(); + unsubscribe(); + spotbutton->set_active(false); +} \ No newline at end of file diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h new file mode 100644 index 000000000..614e60fb5 --- /dev/null +++ b/rtgui/filmnegative.h @@ -0,0 +1,91 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#ifndef _NEG_H_ +#define _NEG_H_ + +#include +#include "toolpanel.h" +#include "adjuster.h" +#include "guiutils.h" +#include "wbprovider.h" +#include "editcallbacks.h" +#include "../rtengine/procparams.h" + + +class FilmNegProvider +{ +public: + virtual ~FilmNegProvider() = default; + virtual bool getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, float* newExps) = 0; +}; + +class FilmNegative : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public EditSubscriber +{ + +private: + rtengine::ProcEvent EvFilmNegativeExponents; + rtengine::ProcEvent EvFilmNegativeEnabled; + + std::vector refSpotCoords; + + FilmNegProvider *fnp; + + Adjuster* redExp; + Adjuster* greenExp; + Adjuster* blueExp; + + Gtk::Grid* spotgrid; + Gtk::ToggleButton* spotbutton; + sigc::connection spotConn; + + void editToggled (); + +public: + + FilmNegative (); + ~FilmNegative () override; + + void setFilmNegProvider(FilmNegProvider* p) + { + fnp = p; + }; + + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; + void setBatchMode (bool batchMode) override; + + void adjusterChanged (Adjuster* a, double newval) override; + void adjusterAutoToggled(Adjuster* a, bool newval) override; + void spotPressed (); + void enabledChanged() override; + + void setEditProvider (EditDataProvider* provider) override; + + // EditSubscriber interface + CursorShape getCursor(int objectID) const override; + bool mouseOver(int modifierKey) override; + bool button1Pressed(int modifierKey) override; + bool button1Released() override; + void switchOffEditMode () override; + bool pick1(bool picked) override; + +}; + +#endif diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 2c29b4f5b..3a5ab041a 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -580,6 +580,10 @@ void ParamsEdited::set(bool v) dehaze.showDepthMap = v; dehaze.depth = v; metadata.mode = v; + filmNegative.enabled = v; + filmNegative.redExp = v; + filmNegative.greenExp = v; + filmNegative.blueExp = v; exif = v; iptc = v; @@ -1142,6 +1146,10 @@ void ParamsEdited::initFrom(const std::vector& dehaze.showDepthMap = dehaze.showDepthMap && p.dehaze.showDepthMap == other.dehaze.showDepthMap; dehaze.depth = dehaze.depth && p.dehaze.depth == other.dehaze.depth; metadata.mode = metadata.mode && p.metadata.mode == other.metadata.mode; + filmNegative.enabled = filmNegative.enabled && p.filmNegative.enabled == other.filmNegative.enabled; + filmNegative.redExp = filmNegative.redExp && p.filmNegative.redExp == other.filmNegative.redExp; + filmNegative.greenExp = filmNegative.greenExp && p.filmNegative.greenExp == other.filmNegative.greenExp; + filmNegative.blueExp = filmNegative.blueExp && p.filmNegative.blueExp == other.filmNegative.blueExp; // How the hell can we handle that??? // exif = exif && p.exif==other.exif @@ -3175,6 +3183,22 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.metadata.mode = mods.metadata.mode; } + if (filmNegative.enabled) { + toEdit.filmNegative.enabled = mods.filmNegative.enabled; + } + + if (filmNegative.redExp) { + toEdit.filmNegative.redExp = mods.filmNegative.redExp; + } + + if (filmNegative.greenExp) { + toEdit.filmNegative.greenExp = mods.filmNegative.greenExp; + } + + if (filmNegative.blueExp) { + toEdit.filmNegative.blueExp = mods.filmNegative.blueExp; + } + // Exif changes are added to the existing ones if (exif) for (procparams::ExifPairs::const_iterator i = mods.exif.begin(); i != mods.exif.end(); ++i) { @@ -3216,3 +3240,8 @@ bool RetinexParamsEdited::isUnchanged() const { return enabled && retinexcolorspace && gammaretinex && gam && slope; } + +bool FilmNegativeParamsEdited::isUnchanged() const +{ + return enabled && redExp && greenExp && blueExp; +} \ No newline at end of file diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 95701e01a..57e6f2cdd 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -666,6 +666,15 @@ struct MetaDataParamsEdited { bool mode; }; +struct FilmNegativeParamsEdited { + bool enabled; + bool redExp; + bool greenExp; + bool blueExp; + + bool isUnchanged() const; +}; + struct ParamsEdited { GeneralParamsEdited general; ToneCurveParamsEdited toneCurve; @@ -710,6 +719,7 @@ struct ParamsEdited { SoftLightParamsEdited softlight; DehazeParamsEdited dehaze; MetaDataParamsEdited metadata; + FilmNegativeParamsEdited filmNegative; bool exif; bool iptc; diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 41e25387e..bd9720dfd 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -92,6 +92,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit bayerrawexposure = Gtk::manage (new BayerRAWExposure ()); xtransrawexposure = Gtk::manage (new XTransRAWExposure ()); fattal = Gtk::manage (new FattalToneMapping ()); + filmNegative = Gtk::manage (new FilmNegative ()); // So Demosaic, Line noise filter, Green Equilibration, Ca-Correction (garder le nom de section identique!) and Black-Level will be moved in a "Bayer sensor" tool, // and a separate Demosaic and Black Level tool will be created in an "X-Trans sensor" tool @@ -154,6 +155,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit addfavoritePanel (rawPanel, preprocess); addfavoritePanel (rawPanel, darkframe); addfavoritePanel (rawPanel, flatfield); + addfavoritePanel (rawPanel, filmNegative); int favoriteCount = 0; for(auto it = favorites.begin(); it != favorites.end(); ++it) { @@ -255,6 +257,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit distortion->setLensGeomListener (this); crop->setCropPanelListener (this); icm->setICMPanelListener (this); + filmNegative->setFilmNegProvider (this); toolBar = new ToolBar (); toolBar->setToolBarListener (this); @@ -305,6 +308,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt sensorbayer->FoldableToolPanel::show(); preprocess->FoldableToolPanel::show(); flatfield->FoldableToolPanel::show(); + filmNegative->FoldableToolPanel::show(); retinex->FoldableToolPanel::setGrayedOut(false); return false; @@ -320,6 +324,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt sensorbayer->FoldableToolPanel::hide(); preprocess->FoldableToolPanel::show(); flatfield->FoldableToolPanel::show(); + filmNegative->FoldableToolPanel::show(); retinex->FoldableToolPanel::setGrayedOut(false); return false; @@ -335,6 +340,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt sensorxtrans->FoldableToolPanel::hide(); preprocess->FoldableToolPanel::hide(); flatfield->FoldableToolPanel::show(); + filmNegative->FoldableToolPanel::hide(); retinex->FoldableToolPanel::setGrayedOut(false); return false; @@ -349,6 +355,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt sensorxtrans->FoldableToolPanel::hide(); preprocess->FoldableToolPanel::hide(); flatfield->FoldableToolPanel::hide(); + filmNegative->FoldableToolPanel::hide(); retinex->FoldableToolPanel::setGrayedOut(false); return false; @@ -360,6 +367,7 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt [this]() -> bool { rawPanelSW->set_sensitive(false); + filmNegative->FoldableToolPanel::hide(); retinex->FoldableToolPanel::setGrayedOut(true); return false; @@ -476,7 +484,7 @@ void ToolPanelCoordinator::profileChange( lParams[1] = *mergedParams; pe.initFrom (lParams); - filterRawRefresh = pe.raw.isUnchanged() && pe.lensProf.isUnchanged() && pe.retinex.isUnchanged(); + filterRawRefresh = pe.raw.isUnchanged() && pe.lensProf.isUnchanged() && pe.retinex.isUnchanged() && pe.filmNegative.isUnchanged(); } *params = *mergedParams; @@ -1014,3 +1022,11 @@ void ToolPanelCoordinator::setEditProvider (EditDataProvider *provider) toolPanels.at (i)->setEditProvider (provider); } } + +bool ToolPanelCoordinator::getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, float* newExps) +{ + if(!ipc) + return false; + + return ipc->getFilmNegativeExponents(spotA.x, spotA.y, spotB.x, spotB.y, newExps); +} diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 1ac74871a..9910f9757 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -82,6 +82,7 @@ #include "softlight.h" #include "dehaze.h" #include "guiutils.h" +#include "filmnegative.h" class ImageEditorCoordinator; @@ -97,7 +98,8 @@ class ToolPanelCoordinator : public CropPanelListener, public ICMPanelListener, public ImageAreaToolListener, - public rtengine::ImageTypeListener + public rtengine::ImageTypeListener, + public FilmNegProvider { protected: WhiteBalance* whitebalance; @@ -152,6 +154,7 @@ protected: XTransRAWExposure* xtransrawexposure; FattalToneMapping *fattal; MetaDataPanel* metadata; + FilmNegative* filmNegative; std::vector paramcListeners; @@ -288,6 +291,9 @@ public: rtengine::RawImage* getFF() override; Glib::ustring GetCurrentImageFilePath() override; + // FilmNegProvider interface + bool getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, float* newExps) override; + // rotatelistener interface void straightenRequested () override; void autoCropRequested () override; From b990b898754e05648b8ee88c87c1ab9e82c19805 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sat, 8 Jun 2019 15:13:44 +0200 Subject: [PATCH 06/42] interpolateBadPixelsXtrans() : fix oob access --- rtengine/rawimagesource.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 0f0d31c40..b8c422545 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1298,6 +1298,7 @@ int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads ) for(dx = -2, dy = 0; dx <= 2 && !distance2PixelFound; dx += 4) if(ri->XTRANSFC(row, col + dx) == pixelColor) { distance2PixelFound = true; + break; } if(!distance2PixelFound) @@ -1306,6 +1307,7 @@ int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads ) for(dx = 0, dy = -2; dy <= 2 && !distance2PixelFound; dy += 4) if(ri->XTRANSFC(row + dy, col) == pixelColor) { distance2PixelFound = true; + break; } // calculate the value of its virtual counterpart (marked with a V in above examples) From d2366e633c61792fc1d5ae2d7caf76de5a2a0005 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Sun, 9 Jun 2019 13:09:29 +0200 Subject: [PATCH 07/42] Enabled bad pixels interpolation for ST_XTRANS after upstream fix c0a033e --- rtengine/filmnegativeproc.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index dba623ab4..d2a798abe 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -307,7 +307,21 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p } else if(ri->getSensorType() == ST_FUJI_XTRANS) { - // TODO +#ifdef _OPENMP + #pragma omp parallel for reduction(+:totBP) schedule(dynamic,16) +#endif + + for(int i = 0; i < H; i++) + for(int j = 0; j < W; j++) { + if (rawData[i][j] >= MAX_OUT_VALUE) { + bitmapBads.set(j, i); + totBP++; + } + } + + if (totBP > 0) { + interpolateBadPixelsXtrans( bitmapBads ); + } } From df4513f5956f884d8a4e25a89cc0322aa59e0ee3 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 9 Jun 2019 14:36:38 +0200 Subject: [PATCH 08/42] Avoid integer overflow when accessing luts with very large values --- rtengine/LUT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/LUT.h b/rtengine/LUT.h index de668cca8..9f16995d0 100644 --- a/rtengine/LUT.h +++ b/rtengine/LUT.h @@ -444,7 +444,7 @@ public: } idx = 0; - } else if (idx > maxs) { + } else if (index > maxsf) { if (clip & LUT_CLIP_ABOVE) { return data[upperBound]; } From 91565728e50ab2eefe743c6a13295ba50f54522d Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Sun, 9 Jun 2019 19:25:15 +0200 Subject: [PATCH 09/42] Clamped output values to a max of 65535.f after applying multipliers, to avoid trouble further down the processing pipeline. --- rtengine/filmnegativeproc.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index d2a798abe..64f7a697b 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -255,9 +255,10 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p #endif for (int row = 0; row < H; row ++) { for (int col = 0; col < W; col++) { - int c = FC(row, col); // three colors, 0=R, 1=G, 2=B - // Apply the multipliers - rawData[row][col] *= mults[c]; + int c = FC(row, col); // three colors, 0=R, 1=G, 2=B + // Apply the multipliers, clamp max output value to 65535 + float out = rawData[row][col] * mults[c]; + rawData[row][col] = out > 65535.f ? 65535.f : out; } } @@ -268,9 +269,10 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p #endif for (int row = 0; row < H; row ++) { for (int col = 0; col < W; col++) { - int c = ri->XTRANSFC(row, col); // three colors, 0=R, 1=G, 2=B - // Apply the multipliers - rawData[row][col] *= mults[c]; + int c = ri->XTRANSFC(row, col); // three colors, 0=R, 1=G, 2=B + // Apply the multipliers, clamp max output value to 65535 + float out = rawData[row][col] * mults[c]; + rawData[row][col] = out > 65535.f ? 65535.f : out; } } From b95bdb1aea7ef0de3378b06ca46da6b3c2d0e8be Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Mon, 10 Jun 2019 22:05:54 +0200 Subject: [PATCH 10/42] Linked red and blue exponent adjuster to the green adjuster, in order to maintain the ratio between exponents if the user moves the green adjuster (master). Switched back to vector sort for median calculations: the results of the histogram search function diverge more and more from the simple median calculation as the exponents increase. At 2.0 the test picture is already impossible to WB as the multipliers are too far off (2.78226e+08 histo vs 9.7927e+11 sort), and the normal WB sliders can't compensate for those huge factors. --- rtengine/filmnegativeproc.cc | 25 ++++++++++++++----------- rtgui/filmnegative.cc | 24 ++++++++++++++++++++---- rtgui/filmnegative.h | 2 ++ 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index 64f7a697b..948e86957 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -104,8 +104,8 @@ bool RawImageSource::getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int std::swap(clearVals, denseVals); if (settings->verbose) { - printf("Clear film values: R=%f G=%f B=%f\n", clearVals[0], clearVals[1], clearVals[2]); - printf("Dense film values: R=%f G=%f B=%f\n", denseVals[0], denseVals[1], denseVals[2]); + printf("Clear film values: R=%g G=%g B=%g\n", clearVals[0], clearVals[1], clearVals[2]); + printf("Dense film values: R=%g G=%g B=%g\n", denseVals[0], denseVals[1], denseVals[2]); } float denseGreenRatio = clearVals[1] / denseVals[1]; @@ -119,7 +119,7 @@ bool RawImageSource::getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int newExps[ch] = CLAMP(logBase(clearVals[ch] / denseVals[ch], denseGreenRatio), 0.3f, 3.f); if (settings->verbose) - printf("New exponents: R=%f G=%f B=%f\n", newExps[0], newExps[1], newExps[2]); + printf("New exponents: R=%g G=%g B=%g\n", newExps[0], newExps[1], newExps[2]); return true; } @@ -230,20 +230,23 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p float mults[3] = { 1.f }; // Channel normalization multipliers for (int c=0; c<3; c++) { - // Find median values for each channel using a histogram search function - findMinMaxPercentile(&cvs[c][0], cvs[c].size(), 0.5f, medians[c], 0.5f, medians[c], true); - // Determine the channel multipler so that N times the median becomes 65k. This clips away - // the values in the dark border surrounding the negative (due to the film holder, for example), - // the reciprocal of which have blown up to stellar values. - mults[c] = MAX_OUT_VALUE / (medians[c] * 24); + // Find median values for each channel + if(cvs[c].size() > 0) { + std::sort(cvs[c].begin(), cvs[c].end()); + medians[c] = cvs[c].at(cvs[c].size() / 2); + // Determine the channel multipler so that N times the median becomes 65k. This clips away + // the values in the dark border surrounding the negative (due to the film holder, for example), + // the reciprocal of which have blown up to stellar values. + mults[c] = MAX_OUT_VALUE / (medians[c] * 24); + } } t4.set(); if (settings->verbose) { printf("Sample count : %lu, %lu, %lu\n", cvs[0].size(), cvs[1].size(), cvs[2].size()); - printf("Medians : %f %f %f\n", medians[0], medians[1], medians[2] ); - printf("Computed multipliers : %f %f %f\n", mults[0], mults[1], mults[2] ); + printf("Medians : %g %g %g\n", medians[0], medians[1], medians[2] ); + printf("Computed multipliers : %g %g %g\n", mults[0], mults[1], mults[2] ); printf("Median calc time us: %d\n", t4.etime(t3)); } diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index bf4c22837..94c6db4dd 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -34,7 +34,7 @@ FilmNegative::FilmNegative () : FoldableToolPanel(this, "filmnegative", M("TP_FI { auto mkExponentAdjuster = [this](Glib::ustring label, double defaultVal) { - Adjuster *adj = Gtk::manage(new Adjuster (label, 0.3, 3, 0.01, defaultVal)); //exponent + Adjuster *adj = Gtk::manage(new Adjuster (label, 0.3, 5, 0.001, defaultVal)); //exponent adj->setAdjusterListener (this); if (adj->delay < options.adjusterMaxDelay) { @@ -49,6 +49,9 @@ FilmNegative::FilmNegative () : FoldableToolPanel(this, "filmnegative", M("TP_FI greenExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_GREEN"), 1.0); blueExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_BLUE"), 0.86); + redRatio = redExp->getValue() / greenExp->getValue(); + blueRatio = blueExp->getValue() / greenExp->getValue(); + auto m = ProcEventMapper::getInstance(); EvFilmNegativeEnabled = m->newEvent(ALL, "HISTORY_MSG_FILMNEGATIVE_ENABLED"); EvFilmNegativeExponents = m->newEvent(ALL, "HISTORY_MSG_FILMNEGATIVE_EXPONENTS"); @@ -139,10 +142,23 @@ void FilmNegative::enabledChanged() void FilmNegative::adjusterChanged(Adjuster* a, double newval) { - if (listener && getEnabled()) { + if (listener) { if(a == redExp || a == greenExp || a == blueExp) { - listener->panelChanged (EvFilmNegativeExponents, Glib::ustring::compose ( - "R=%1 ; G=%2 ; B=%3", redExp->getTextValue(), greenExp->getTextValue(), blueExp->getTextValue())); + disableListener(); + if(a == greenExp) { + redExp->setValue(a->getValue() * redRatio); + blueExp->setValue(a->getValue() * blueRatio); + } else if(a == redExp) { + redRatio = newval / greenExp->getValue(); + } else if(a == blueExp) { + blueRatio = newval / greenExp->getValue(); + } + enableListener(); + + if(getEnabled()) { + listener->panelChanged (EvFilmNegativeExponents, Glib::ustring::compose ( + "R=%1 ; G=%2 ; B=%3", redExp->getTextValue(), greenExp->getTextValue(), blueExp->getTextValue())); + } } } } diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h index 614e60fb5..5d6c8ce03 100644 --- a/rtgui/filmnegative.h +++ b/rtgui/filmnegative.h @@ -54,6 +54,8 @@ private: Gtk::ToggleButton* spotbutton; sigc::connection spotConn; + double redRatio, blueRatio; + void editToggled (); public: From 223ae8abcee359c2f807ef272443c606aa471621 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Tue, 11 Jun 2019 00:19:18 +0200 Subject: [PATCH 11/42] Bugfix: exponent adjusters were not following the master (green) slider after exponents auto-calc via dual spot picking; updated redRatio/blueRatio after calculation. --- rtgui/filmnegative.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 94c6db4dd..b4fdc895c 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -154,7 +154,7 @@ void FilmNegative::adjusterChanged(Adjuster* a, double newval) blueRatio = newval / greenExp->getValue(); } enableListener(); - + if(getEnabled()) { listener->panelChanged (EvFilmNegativeExponents, Glib::ustring::compose ( "R=%1 ; G=%2 ; B=%3", redExp->getTextValue(), greenExp->getTextValue(), blueExp->getTextValue())); @@ -287,6 +287,8 @@ bool FilmNegative::button1Pressed(int modifierKey) redExp->setValue(newExps[0]); greenExp->setValue(newExps[1]); blueExp->setValue(newExps[2]); + redRatio = redExp->getValue() / greenExp->getValue(); + blueRatio = blueExp->getValue() / greenExp->getValue(); enableListener(); if (listener && getEnabled()) { From e1c9197ed5b547bb114a87fa7bb8789218323326 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Tue, 11 Jun 2019 20:08:46 +0200 Subject: [PATCH 12/42] Moved median calculation block before exponentiation. This way findMinMaxPercentile() can be used again because it works on the original raw file values (which are in a much more reasonable range). Patch kindly provided by @heckflosse ;-) --- rtengine/filmnegativeproc.cc | 115 +++++++++++++++++------------------ 1 file changed, 57 insertions(+), 58 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index 948e86957..e00891b1a 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -134,6 +134,61 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p MyTime t1, t2, t3,t4, t5, t6; t1.set(); + // Channel vectors to calculate medians + std::vector cvs[3] = { + std::vector(), + std::vector(), + std::vector() + }; + + // Sample one every 5 pixels, and push the value in the appropriate channel vector. + // Chose an odd step, not multiple of the CFA size, to get a chance to visit each channel. + if(ri->getSensorType() == ST_BAYER) { + for (int row = 0; row < H; row+=5) { + for (int col = 0; col < W; col+=5) { + int c = FC(row, col); // three colors, 0=R, 1=G, 2=B + cvs[c].push_back(rawData[row][col]); + } + } + } else if(ri->getSensorType() == ST_FUJI_XTRANS) { + for (int row = 0; row < H; row+=5) { + for (int col = 0; col < W; col+=5) { + int c = ri->XTRANSFC(row, col); // three colors, 0=R, 1=G, 2=B + cvs[c].push_back(rawData[row][col]); + } + } + } + + const float MAX_OUT_VALUE = 65000.f; + + t2.set(); + if (settings->verbose) + printf("Median vector fill loop time us: %d\n", t2.etime(t1)); + + float medians[3]; // Channel median values + float mults[3] = { 1.f }; // Channel normalization multipliers + + for (int c=0; c<3; c++) { + // Find median values for each channel + if(cvs[c].size() > 0) { + findMinMaxPercentile(&cvs[c][0], cvs[c].size(), 0.5f, medians[c], 0.5f, medians[c], true); + medians[c] = pow_F(max(medians[c], 1.f), -exps[c]); + // Determine the channel multipler so that N times the median becomes 65k. This clips away + // the values in the dark border surrounding the negative (due to the film holder, for example), + // the reciprocal of which have blown up to stellar values. + mults[c] = MAX_OUT_VALUE / (medians[c] * 24); + } + } + + t3.set(); + if (settings->verbose) { + printf("Sample count : %lu, %lu, %lu\n", cvs[0].size(), cvs[1].size(), cvs[2].size()); + printf("Medians : %g %g %g\n", medians[0], medians[1], medians[2] ); + printf("Computed multipliers : %g %g %g\n", mults[0], mults[1], mults[2] ); + printf("Median calc time us: %d\n", t3.etime(t2)); + } + + if(ri->getSensorType() == ST_BAYER) { #ifdef _OPENMP #pragma omp parallel for schedule(dynamic, 16) @@ -191,65 +246,9 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p } - t2.set(); - if (settings->verbose) - printf("Pow loop time us: %d\n", t2.etime(t1)); - - // Channel vectors to calculate medians - std::vector cvs[3] = { - std::vector(), - std::vector(), - std::vector() - }; - - // Sample one every 5 pixels, and push the value in the appropriate channel vector. - // Chose an odd step, not multiple of the CFA size, to get a chance to visit each channel. - if(ri->getSensorType() == ST_BAYER) { - for (int row = 0; row < H; row+=5) { - for (int col = 0; col < W; col+=5) { - int c = FC(row, col); // three colors, 0=R, 1=G, 2=B - cvs[c].push_back(rawData[row][col]); - } - } - } else if(ri->getSensorType() == ST_FUJI_XTRANS) { - for (int row = 0; row < H; row+=5) { - for (int col = 0; col < W; col+=5) { - int c = ri->XTRANSFC(row, col); // three colors, 0=R, 1=G, 2=B - cvs[c].push_back(rawData[row][col]); - } - } - } - - const float MAX_OUT_VALUE = 65000.f; - - t3.set(); - if (settings->verbose) - printf("Median vector fill loop time us: %d\n", t3.etime(t2)); - - float medians[3]; // Channel median values - float mults[3] = { 1.f }; // Channel normalization multipliers - - for (int c=0; c<3; c++) { - // Find median values for each channel - if(cvs[c].size() > 0) { - std::sort(cvs[c].begin(), cvs[c].end()); - medians[c] = cvs[c].at(cvs[c].size() / 2); - // Determine the channel multipler so that N times the median becomes 65k. This clips away - // the values in the dark border surrounding the negative (due to the film holder, for example), - // the reciprocal of which have blown up to stellar values. - mults[c] = MAX_OUT_VALUE / (medians[c] * 24); - } - } - - t4.set(); - if (settings->verbose) { - printf("Sample count : %lu, %lu, %lu\n", cvs[0].size(), cvs[1].size(), cvs[2].size()); - printf("Medians : %g %g %g\n", medians[0], medians[1], medians[2] ); - printf("Computed multipliers : %g %g %g\n", mults[0], mults[1], mults[2] ); - printf("Median calc time us: %d\n", t4.etime(t3)); - } - + if (settings->verbose) + printf("Pow loop time us: %d\n", t4.etime(t3)); if(ri->getSensorType() == ST_BAYER) { From 2bbf8bd864fa65092b96c3db917ed38e0e6e9f60 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Tue, 11 Jun 2019 20:26:13 +0200 Subject: [PATCH 13/42] Changed events action from ALL to FIRST , this way the histogram is updated after enabling/disabling or moving the adjusters. --- rtgui/filmnegative.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index b4fdc895c..2af69677f 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -53,8 +53,8 @@ FilmNegative::FilmNegative () : FoldableToolPanel(this, "filmnegative", M("TP_FI blueRatio = blueExp->getValue() / greenExp->getValue(); auto m = ProcEventMapper::getInstance(); - EvFilmNegativeEnabled = m->newEvent(ALL, "HISTORY_MSG_FILMNEGATIVE_ENABLED"); - EvFilmNegativeExponents = m->newEvent(ALL, "HISTORY_MSG_FILMNEGATIVE_EXPONENTS"); + EvFilmNegativeEnabled = m->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_ENABLED"); + EvFilmNegativeExponents = m->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_EXPONENTS"); spotgrid = Gtk::manage(new Gtk::Grid()); From 8fa30d496d334312fa58e5c5e8d364f9cba9848c Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Tue, 11 Jun 2019 21:02:16 +0200 Subject: [PATCH 14/42] Now that medians are known *before* processing, moved multiplication step inside the same loop as exponentiation for further optimization. Patch kindly provided by @heckflosse ;-) --- rtengine/filmnegativeproc.cc | 65 +++++++++++++----------------------- 1 file changed, 23 insertions(+), 42 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index e00891b1a..5766fbf1e 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -29,6 +29,9 @@ #include "opthelper.h" #include "rt_algo.h" +//#define BENCHMARK +#include "StopWatch.h" + namespace rtengine { @@ -126,6 +129,8 @@ bool RawImageSource::getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams ¶ms) { +// BENCHFUNMICRO + if(!params.enabled) return; @@ -199,19 +204,23 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p // to get the reciprocals. Avoid trouble with zeroes, minimum pixel value is 1. const float exps0 = -exps[FC(row, col)]; const float exps1 = -exps[FC(row, col + 1)]; + const float mult0 = mults[FC(row, col)]; + const float mult1 = mults[FC(row, col + 1)]; #ifdef __SSE2__ const vfloat expsv = _mm_setr_ps(exps0, exps1, exps0, exps1); + const vfloat multsv = _mm_setr_ps(mult0, mult1, mult0, mult1); const vfloat onev = F2V(1.f); + const vfloat c65535v = F2V(65535.f); for (; col < W - 3; col+=4) { - STVFU(rawData[row][col], pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv)); + STVFU(rawData[row][col], vminf(multsv * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv), c65535v)); } #endif // __SSE2__ for (; col < W - 1; col+=2) { - rawData[row][col] = pow_F(max(rawData[row][col], 1.f), exps0); - rawData[row][col + 1] = pow_F(max(rawData[row][col + 1], 1.f), exps1); + rawData[row][col] = rtengine::min(mult0 * pow_F(max(rawData[row][col], 1.f), exps0), 65535.f); + rawData[row][col + 1] = rtengine::min(mult1 * pow_F(max(rawData[row][col + 1], 1.f), exps1), 65535.f); } if (col < W) { - rawData[row][col] = pow_F(max(rawData[row][col], 1.f), exps0); + rawData[row][col] = rtengine::min(mult0 * pow_F(max(rawData[row][col], 1.f), exps0), 65535.f); } } } else if(ri->getSensorType() == ST_FUJI_XTRANS) { @@ -223,24 +232,29 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p // Exponents are expressed as positive in the parameters, so negate them in order // to get the reciprocals. Avoid trouble with zeroes, minimum pixel value is 1. const float expsc[6] = {-exps[ri->XTRANSFC(row, 0)], -exps[ri->XTRANSFC(row, 1)], -exps[ri->XTRANSFC(row, 2)], -exps[ri->XTRANSFC(row, 3)], -exps[ri->XTRANSFC(row, 4)], -exps[ri->XTRANSFC(row, 5)]}; + const float multsc[6] = {mults[ri->XTRANSFC(row, 0)], mults[ri->XTRANSFC(row, 1)], mults[ri->XTRANSFC(row, 2)], mults[ri->XTRANSFC(row, 3)], mults[ri->XTRANSFC(row, 4)], mults[ri->XTRANSFC(row, 5)]}; #ifdef __SSE2__ const vfloat expsv0 = _mm_setr_ps(expsc[0], expsc[1], expsc[2], expsc[3]); const vfloat expsv1 = _mm_setr_ps(expsc[4], expsc[5], expsc[0], expsc[1]); const vfloat expsv2 = _mm_setr_ps(expsc[2], expsc[3], expsc[4], expsc[5]); + const vfloat multsv0 = _mm_setr_ps(multsc[0], multsc[1], multsc[2], multsc[3]); + const vfloat multsv1 = _mm_setr_ps(multsc[4], multsc[5], multsc[0], multsc[1]); + const vfloat multsv2 = _mm_setr_ps(multsc[2], multsc[3], multsc[4], multsc[5]); const vfloat onev = F2V(1.f); + const vfloat c65535v = F2V(65535.f); for (; col < W - 11; col+=12) { - STVFU(rawData[row][col], pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv0)); - STVFU(rawData[row][col + 4], pow_F(vmaxf(LVFU(rawData[row][col + 4]), onev), expsv1)); - STVFU(rawData[row][col + 8], pow_F(vmaxf(LVFU(rawData[row][col + 8]), onev), expsv2)); + STVFU(rawData[row][col], vminf(multsv0 * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv0), c65535v)); + STVFU(rawData[row][col + 4], vminf(multsv1 * pow_F(vmaxf(LVFU(rawData[row][col + 4]), onev), expsv1), c65535v)); + STVFU(rawData[row][col + 8], vminf(multsv2 * pow_F(vmaxf(LVFU(rawData[row][col + 8]), onev), expsv2), c65535v)); } #endif // __SSE2__ for (; col < W - 5; col+=6) { for (int c = 0; c < 6; ++c) { - rawData[row][col + c] = pow_F(max(rawData[row][col + c], 1.f), expsc[c]); + rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(max(rawData[row][col + c], 1.f), expsc[c]), 65535.f); } } for (int c = 0; col < W; col++, c++) { - rawData[row][col + c] = pow_F(max(rawData[row][col + c], 1.f), expsc[c]); + rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(max(rawData[row][col + c], 1.f), expsc[c]), 65535.f); } } } @@ -250,41 +264,8 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p if (settings->verbose) printf("Pow loop time us: %d\n", t4.etime(t3)); - if(ri->getSensorType() == ST_BAYER) { - -#ifdef _OPENMP - #pragma omp for nowait -#endif - for (int row = 0; row < H; row ++) { - for (int col = 0; col < W; col++) { - int c = FC(row, col); // three colors, 0=R, 1=G, 2=B - // Apply the multipliers, clamp max output value to 65535 - float out = rawData[row][col] * mults[c]; - rawData[row][col] = out > 65535.f ? 65535.f : out; - } - } - - } else if(ri->getSensorType() == ST_FUJI_XTRANS) { - -#ifdef _OPENMP - #pragma omp for nowait -#endif - for (int row = 0; row < H; row ++) { - for (int col = 0; col < W; col++) { - int c = ri->XTRANSFC(row, col); // three colors, 0=R, 1=G, 2=B - // Apply the multipliers, clamp max output value to 65535 - float out = rawData[row][col] * mults[c]; - rawData[row][col] = out > 65535.f ? 65535.f : out; - } - } - - } - t5.set(); - if (settings->verbose) - printf("Mult loop time us: %d\n", t5.etime(t4)); - PixelsMap bitmapBads(W, H); From 5ddc4a3e0ee3f63ec684f05b175e1215111659f9 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Tue, 11 Jun 2019 22:13:16 +0200 Subject: [PATCH 15/42] Added missing checkbox for film negative feature in partial apply / partial paste dialogs. --- rtdata/languages/default | 1 + rtgui/partialpastedlg.cc | 18 ++++++++++++++++++ rtgui/partialpastedlg.h | 3 +++ 3 files changed, 22 insertions(+) diff --git a/rtdata/languages/default b/rtdata/languages/default index e6a546a7e..1c6a1acba 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -985,6 +985,7 @@ PARTIALPASTE_EVERYTHING;Everything PARTIALPASTE_EXIFCHANGES;Exif PARTIALPASTE_EXPOSURE;Exposure PARTIALPASTE_FILMSIMULATION;Film simulation +PARTIALPASTE_FILMNEGATIVE;Film Negative PARTIALPASTE_FLATFIELDAUTOSELECT;Flat-field auto-selection PARTIALPASTE_FLATFIELDBLURRADIUS;Flat-field blur radius PARTIALPASTE_FLATFIELDBLURTYPE;Flat-field blur type diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index 734f7c29b..ef18e2953 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -134,6 +134,9 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren raw_ca_autocorrect = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAWCACORR_AUTO"))); raw_caredblue = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAWCACORR_CAREDBLUE"))); raw_ca_avoid_colourshift = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAWCACORR_AVOIDCOLORSHIFT"))); + //--- + filmNegative = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_FILMNEGATIVE")) ); + Gtk::VBox* vboxes[8]; Gtk::HSeparator* hseps[8]; @@ -249,6 +252,9 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren vboxes[7]->pack_start (*raw_ca_autocorrect, Gtk::PACK_SHRINK, 2); vboxes[7]->pack_start (*raw_caredblue, Gtk::PACK_SHRINK, 2); vboxes[7]->pack_start (*raw_ca_avoid_colourshift, Gtk::PACK_SHRINK, 2); + vboxes[7]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); + vboxes[7]->pack_start (*filmNegative, Gtk::PACK_SHRINK, 2); + Gtk::VBox* vbCol1 = Gtk::manage (new Gtk::VBox ()); Gtk::VBox* vbCol2 = Gtk::manage (new Gtk::VBox ()); @@ -396,6 +402,8 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren raw_ca_autocorrectConn = raw_ca_autocorrect->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); raw_caredblueConn = raw_caredblue->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); raw_ca_avoid_colourshiftconn = raw_ca_avoid_colourshift->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); + //--- + filmNegativeConn = filmNegative->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); add_button (M("GENERAL_OK"), Gtk::RESPONSE_OK); add_button (M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL); @@ -467,6 +475,7 @@ void PartialPasteDlg::rawToggled () ConnectionBlocker raw_ca_autocorrectBlocker(raw_ca_autocorrectConn); ConnectionBlocker raw_caredblueBlocker(raw_caredblueConn); ConnectionBlocker raw_ca_avoid_colourshiftBlocker(raw_ca_avoid_colourshiftconn); + ConnectionBlocker filmNegativeBlocker(filmNegativeConn); raw->set_inconsistent (false); @@ -495,6 +504,7 @@ void PartialPasteDlg::rawToggled () raw_ca_autocorrect->set_active (raw->get_active ()); raw_caredblue->set_active (raw->get_active ()); raw_ca_avoid_colourshift->set_active (raw->get_active ()); + filmNegative->set_active (raw->get_active()); } void PartialPasteDlg::basicToggled () @@ -966,6 +976,14 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param filterPE.raw.ff_AutoClipControl = falsePE.raw.ff_AutoClipControl; } + if (!filmNegative->get_active ()) { + filterPE.filmNegative.enabled = falsePE.filmNegative.enabled; + filterPE.filmNegative.redExp = falsePE.filmNegative.redExp; + filterPE.filmNegative.greenExp = falsePE.filmNegative.greenExp; + filterPE.filmNegative.blueExp = falsePE.filmNegative.blueExp; + } + + if (dstPE) { *dstPE = filterPE; } diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h index 0325fa063..b5b93b11a 100644 --- a/rtgui/partialpastedlg.h +++ b/rtgui/partialpastedlg.h @@ -130,6 +130,8 @@ public: Gtk::CheckButton* ff_BlurType; Gtk::CheckButton* ff_ClipControl; + Gtk::CheckButton* filmNegative; + sigc::connection everythingConn, basicConn, detailConn, colorConn, lensConn, compositionConn, metaConn, rawConn, advancedConn; sigc::connection wbConn, exposureConn, localcontrastConn, shConn, pcvignetteConn, gradientConn, labcurveConn, colorappearanceConn; @@ -140,6 +142,7 @@ public: sigc::connection metadataConn, exifchConn, iptcConn, icmConn; sigc::connection df_fileConn, df_AutoSelectConn, ff_fileConn, ff_AutoSelectConn, ff_BlurRadiusConn, ff_BlurTypeConn, ff_ClipControlConn; sigc::connection raw_caredblueConn, raw_ca_autocorrectConn, raw_ca_avoid_colourshiftconn, raw_hotpix_filtConn, raw_deadpix_filtConn, raw_pdaf_lines_filterConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_borderConn, raw_imagenumConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_pixelshiftConn, raw_dcb_enhanceConn, raw_exposConn, raw_blackConn; + sigc::connection filmNegativeConn; public: PartialPasteDlg (const Glib::ustring &title, Gtk::Window* parent); From 8d0755eddc6d3aa02de4b39154ca40edde7865c9 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Tue, 11 Jun 2019 22:50:36 +0200 Subject: [PATCH 16/42] Raised default master exponent from 1.0 to 2.0, to get a reasonable contrast right from the start. --- rtengine/filmnegativeproc.cc | 4 ++-- rtengine/procparams.cc | 6 +++--- rtgui/filmnegative.cc | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index 5766fbf1e..db98fdf02 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -117,9 +117,9 @@ bool RawImageSource::getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int // compared to the ratio in the reference channel (green) for(int ch=0; ch<3; ch++) if(ch==1) - newExps[ch] = 1.f; // Green is the reference channel + newExps[ch] = 2.f; // Green is the reference channel else - newExps[ch] = CLAMP(logBase(clearVals[ch] / denseVals[ch], denseGreenRatio), 0.3f, 3.f); + newExps[ch] = CLAMP(2.f * logBase(clearVals[ch] / denseVals[ch], denseGreenRatio), 0.3f, 6.f); if (settings->verbose) printf("New exponents: R=%g G=%g B=%g\n", newExps[0], newExps[1], newExps[2]); diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 9780255da..bb5c86494 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2737,9 +2737,9 @@ bool MetaDataParams::operator!=(const MetaDataParams &other) const FilmNegativeParams::FilmNegativeParams() : enabled(false), - redExp(1.36), - greenExp(1.0), - blueExp(0.86) + redExp(2.72), + greenExp(2.0), + blueExp(1.72) { } diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 2af69677f..8f1fb5610 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -34,7 +34,7 @@ FilmNegative::FilmNegative () : FoldableToolPanel(this, "filmnegative", M("TP_FI { auto mkExponentAdjuster = [this](Glib::ustring label, double defaultVal) { - Adjuster *adj = Gtk::manage(new Adjuster (label, 0.3, 5, 0.001, defaultVal)); //exponent + Adjuster *adj = Gtk::manage(new Adjuster (label, 0.3, 6, 0.001, defaultVal)); //exponent adj->setAdjusterListener (this); if (adj->delay < options.adjusterMaxDelay) { @@ -45,9 +45,9 @@ FilmNegative::FilmNegative () : FoldableToolPanel(this, "filmnegative", M("TP_FI return adj; }; - redExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_RED"), 1.36); - greenExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_GREEN"), 1.0); - blueExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_BLUE"), 0.86); + redExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_RED"), 2.72); + greenExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_GREEN"), 2.0); + blueExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_BLUE"), 1.72); redRatio = redExp->getValue() / greenExp->getValue(); blueRatio = blueExp->getValue() / greenExp->getValue(); From c819cb63a253b7ee1e884c43063537317e610b42 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Wed, 12 Jun 2019 22:11:34 +0200 Subject: [PATCH 17/42] Speed boost in the median vectors fill via loop unrolling --- rtengine/filmnegativeproc.cc | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index db98fdf02..7c7103dc6 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -150,16 +150,28 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p // Chose an odd step, not multiple of the CFA size, to get a chance to visit each channel. if(ri->getSensorType() == ST_BAYER) { for (int row = 0; row < H; row+=5) { - for (int col = 0; col < W; col+=5) { - int c = FC(row, col); // three colors, 0=R, 1=G, 2=B - cvs[c].push_back(rawData[row][col]); + int col = 0; + int c0 = FC(row, col); + int c1 = FC(row, col + 5); + for (; col < W - 5; col+=10) { + cvs[c0].push_back(rawData[row][col]); + cvs[c1].push_back(rawData[row][col + 5]); + } + if (col < W) { + cvs[c0].push_back(rawData[row][col]); } } } else if(ri->getSensorType() == ST_FUJI_XTRANS) { for (int row = 0; row < H; row+=5) { - for (int col = 0; col < W; col+=5) { - int c = ri->XTRANSFC(row, col); // three colors, 0=R, 1=G, 2=B - cvs[c].push_back(rawData[row][col]); + int col = 0; + const unsigned int cs[6] = {ri->XTRANSFC(row, 0), ri->XTRANSFC(row, 5), ri->XTRANSFC(row, 10), ri->XTRANSFC(row, 15), ri->XTRANSFC(row, 20), ri->XTRANSFC(row, 25)}; + for (; col < W - 25; col += 30) { + for (int c = 0; c < 6; ++c) { + cvs[cs[c]].push_back(rawData[row][col + c * 5]); + } + } + for (int c = 0; col < W; col += 5, ++c) { + cvs[cs[c]].push_back(rawData[row][col]); } } } From 015cffc73ab416d9d8788938dceb78e08ec127e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Thu, 13 Jun 2019 09:52:13 +0200 Subject: [PATCH 18/42] Peripheral cleanups and a fix - Whitespace, braces, sorting - Fixed missing filmnegative in `ProcParams::operator ==(ProcParams)` --- rtengine/CMakeLists.txt | 42 +- rtengine/imagesource.h | 20 +- rtengine/improccoordinator.cc | 38 +- rtengine/procparams.cc | 10 +- rtengine/procparams.h | 10 +- rtengine/rawimagesource.h | 3 - rtengine/simpleprocess.cc | 2 +- rtgui/CMakeLists.txt | 22 +- rtgui/paramsedited.cc | 772 +++++++++++++++++----------------- rtgui/partialpastedlg.cc | 4 - rtgui/toolpanelcoord.cc | 5 +- 11 files changed, 457 insertions(+), 471 deletions(-) diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index dfa843fd0..385ba921e 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -30,18 +30,15 @@ link_directories("${PROJECT_SOURCE_DIR}/rtexif" set(CAMCONSTSFILE "camconst.json") set(RTENGINESOURCEFILES - CA_correct_RT.cc - EdgePreservingDecomposition.cc - FTblockDN.cc - PF_correct_RT.cc ahd_demosaic_RT.cc amaze_demosaic_RT.cc - cJSON.c + CA_correct_RT.cc calc_distort.cc camconst.cc cfa_linedn_RT.cc ciecam02.cc cieimage.cc + cJSON.c clutstore.cc color.cc colortemp.cc @@ -58,12 +55,18 @@ set(RTENGINESOURCEFILES dual_demosaic_RT.cc dynamicprofile.cc eahd_demosaic.cc + EdgePreservingDecomposition.cc fast_demo.cc ffmanager.cc + filmnegativeproc.cc flatcurves.cc + FTblockDN.cc + gamutwarning.cc gauss.cc green_equil_RT.cc + guidedfilter.cc hilite_recon.cc + histmatching.cc hphd_demosaic_RT.cc iccjpeg.cc iccstore.cc @@ -78,10 +81,15 @@ set(RTENGINESOURCEFILES improcfun.cc impulse_denoise.cc init.cc + ipdehaze.cc iplab2rgb.cc + iplabregions.cc + iplocalcontrast.cc ipresize.cc ipretinex.cc + ipshadowshighlights.cc ipsharpen.cc + ipsoftlight.cc iptransform.cc ipvibrance.cc ipwavelet.cc @@ -89,8 +97,8 @@ set(RTENGINESOURCEFILES jpeg_ijg/jpeg_memsrc.cc klt/convolve.cc klt/error.cc - klt/klt.cc klt/klt_util.cc + klt/klt.cc klt/pnmio.cc klt/pyramid.cc klt/selectGoodFeatures.cc @@ -99,8 +107,11 @@ set(RTENGINESOURCEFILES klt/writeFeatures.cc labimage.cc lcp.cc + lj92.c loadinitial.cc myfile.cc + pdaflinesfilter.cc + PF_correct_RT.cc pipettebuffer.cc pixelshift.cc previewimage.cc @@ -112,28 +123,17 @@ set(RTENGINESOURCEFILES rcd_demosaic.cc refreshmap.cc rt_algo.cc + rtlensfun.cc rtthumbnail.cc shmap.cc simpleprocess.cc slicer.cc stdimagesource.cc - utils.cc - rtlensfun.cc tmo_fattal02.cc - iplocalcontrast.cc - histmatching.cc - pdaflinesfilter.cc - gamutwarning.cc - ipshadowshighlights.cc - xtrans_demosaic.cc + utils.cc vng4_demosaic_RT.cc - ipsoftlight.cc - guidedfilter.cc - ipdehaze.cc - iplabregions.cc - lj92.c - filmnegativeproc.cc - ) + xtrans_demosaic.cc +) if(LENSFUN_HAS_LOAD_DIRECTORY) set_source_files_properties(rtlensfun.cc PROPERTIES COMPILE_DEFINITIONS RT_LENSFUN_HAS_LOAD_DIRECTORY) diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index e3321b599..0a34b6bc8 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -16,20 +16,21 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#ifndef _IMAGESOURCE_ -#define _IMAGESOURCE_ +#pragma once + +#include #include -#include -#include "rtengine.h" + #include "colortemp.h" #include "coord2d.h" #include "dcp.h" -#include "LUT.h" -#include "imagedata.h" -#include "image8.h" #include "image16.h" +#include "image8.h" +#include "imagedata.h" #include "imagefloat.h" +#include "LUT.h" +#include "rtengine.h" namespace rtengine { @@ -39,11 +40,11 @@ namespace procparams struct CoarseTransformParams; struct ColorManagementParams; +struct FilmNegativeParams; struct LensProfParams; struct RAWParams; struct RetinexParams; struct ToneCurveParams; -struct FilmNegativeParams; } @@ -57,6 +58,7 @@ public: double cam_xyz[3][3] = {}; }; +// TODO: Move implementation to .cc (Flössie) class ImageSource : public InitialImage { @@ -180,5 +182,5 @@ public: } virtual void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) = 0; }; + } -#endif diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 2d0d490ad..fb6250183 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -279,8 +279,15 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) highDetailPreprocessComputed = highDetailNeeded; // After preprocess, run film negative processing if enabled - if((todo & M_RAW) && (imgsrc->getSensorType() == ST_BAYER || imgsrc->getSensorType() == ST_FUJI_XTRANS) && params->filmNegative.enabled) { - imgsrc->filmNegativeProcess (params->filmNegative); + if ( + (todo & M_RAW) + && ( + imgsrc->getSensorType() == ST_BAYER + || imgsrc->getSensorType() == ST_FUJI_XTRANS + ) + && params->filmNegative.enabled + ) { + imgsrc->filmNegativeProcess(params->filmNegative); } } @@ -1257,30 +1264,29 @@ void ImProcCoordinator::getSpotWB(int x, int y, int rect, double& temp, double& bool ImProcCoordinator::getFilmNegativeExponents(int xA, int yA, int xB, int yB, float* newExps) { + MyMutex::MyLock lock(mProcessing); - { - MyMutex::MyLock lock(mProcessing); + const auto xlate = + [this](int x, int y) -> Coord2D + { + const std::vector points = {Coord2D(x, y)}; - auto xlate = [this](int x, int y) { - std::vector points, red, green, blue; - - points.push_back(Coord2D(x, y)); + std::vector red; + std::vector green; + std::vector blue; ipf.transCoord(fw, fh, points, red, green, blue); + return green[0]; }; - int tr = getCoarseBitMask(params->coarse); + const int tr = getCoarseBitMask(params->coarse); - Coord2D p1 = xlate(xA, yA); - Coord2D p2 = xlate(xB, yB); - - return imgsrc->getFilmNegativeExponents(p1, p2, tr, params->filmNegative, newExps); - - } // end of mutex locking + const Coord2D p1 = xlate(xA, yA); + const Coord2D p2 = xlate(xB, yB); + return imgsrc->getFilmNegativeExponents(p1, p2, tr, params->filmNegative, newExps); } - void ImProcCoordinator::getAutoCrop(double ratio, int &x, int &y, int &w, int &h) { diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index bb5c86494..ade3b0581 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2734,7 +2734,6 @@ bool MetaDataParams::operator!=(const MetaDataParams &other) const return !(*this == other); } - FilmNegativeParams::FilmNegativeParams() : enabled(false), redExp(2.72), @@ -2757,10 +2756,6 @@ bool FilmNegativeParams::operator !=(const FilmNegativeParams& other) const return !(*this == other); } - - - - ProcParams::ProcParams() { setDefaults(); @@ -3598,7 +3593,6 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->filmNegative.greenExp, "Film Negative", "GreenExponent", filmNegative.greenExp, keyFile); saveToKeyfile(!pedited || pedited->filmNegative.blueExp, "Film Negative", "BlueExponent", filmNegative.blueExp, keyFile); - // EXIF change list if (!pedited || pedited->exif) { for (ExifPairs::const_iterator i = exif.begin(); i != exif.end(); ++i) { @@ -5149,7 +5143,6 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Film Negative", "BlueExponent", pedited, filmNegative.blueExp, pedited->filmNegative.blueExp); } - if (keyFile.has_group("MetaData")) { int mode = int(MetaDataParams::TUNNEL); assignFromKeyfile(keyFile, "MetaData", "Mode", pedited, mode, pedited->metadata.mode); @@ -5272,7 +5265,8 @@ bool ProcParams::operator ==(const ProcParams& other) const && metadata == other.metadata && exif == other.exif && iptc == other.iptc - && dehaze == other.dehaze; + && dehaze == other.dehaze + && filmNegative == other.filmNegative; } bool ProcParams::operator !=(const ProcParams& other) const diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 3f9ff0342..2af018035 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -728,7 +728,6 @@ struct DirPyrDenoiseParams { bool operator !=(const DirPyrDenoiseParams& other) const; void getCurves(NoiseCurve& lCurve, NoiseCurve& cCurve) const; - }; // EPD related parameters. @@ -1056,7 +1055,6 @@ struct ColorManagementParams { bool operator !=(const ColorManagementParams& other) const; }; - /** * Parameters for metadata handling */ @@ -1295,7 +1293,6 @@ struct HSVEqualizerParams { bool operator !=(const HSVEqualizerParams& other) const; }; - /** * Film simualtion params */ @@ -1310,7 +1307,6 @@ struct FilmSimulationParams { bool operator !=(const FilmSimulationParams& other) const; }; - struct SoftLightParams { bool enabled; int strength; @@ -1334,7 +1330,6 @@ struct DehazeParams { bool operator!=(const DehazeParams &other) const; }; - /** * Parameters for RAW demosaicing, common to all sensor type */ @@ -1501,7 +1496,6 @@ struct RAWParams { static Glib::ustring getFlatFieldBlurTypeString(FlatFieldBlurType type); }; - /** * Parameters of film negative */ @@ -1517,7 +1511,6 @@ struct FilmNegativeParams { bool operator !=(const FilmNegativeParams& other) const; }; - /** * This class holds all the processing parameters applied on the images */ @@ -1566,6 +1559,7 @@ public: FilmSimulationParams filmSimulation; ///< film simulation parameters SoftLightParams softlight; ///< softlight parameters DehazeParams dehaze; ///< dehaze parameters + FilmNegativeParams filmNegative; ///< Film negative parameters int rank; ///< Custom image quality ranking int colorlabel; ///< Custom color label bool inTrash; ///< Marks deleted image @@ -1576,8 +1570,6 @@ public: ExifPairs exif; ///< List of modifications appplied on the exif tags of the input image IPTCPairs iptc; ///< The IPTC tags and values to be saved to the output image - FilmNegativeParams filmNegative; ///< Film negative parameters - /** * The constructor only sets the hand-wired defaults. */ diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 56fec7146..6e039e7f8 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -36,7 +36,6 @@ namespace rtengine class RawImageSource : public ImageSource { - private: static DiagonalCurve *phaseOneIccCurve; static DiagonalCurve *phaseOneIccCurveInv; @@ -46,7 +45,6 @@ private: int defTransform (int tran); bool channelsAvg(Coord spotPos, int spotSize, float avgs[3], const FilmNegativeParams ¶ms); - protected: MyMutex getImageMutex; // locks getImage @@ -110,7 +108,6 @@ protected: inline void getRowStartEnd (int x, int &start, int &end); static void getProfilePreprocParams(cmsHPROFILE in, float& gammafac, float& lineFac, float& lineSum); - public: RawImageSource (); ~RawImageSource () override; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index e270f093f..4bdaa6ff1 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -210,7 +210,7 @@ private: imgsrc->preprocess ( params.raw, params.lensProf, params.coarse, params.dirpyrDenoise.enabled); // After preprocess, run film negative processing if enabled - if(imgsrc->getSensorType() == ST_BAYER && params.filmNegative.enabled) { + if (imgsrc->getSensorType() == ST_BAYER && params.filmNegative.enabled) { imgsrc->filmNegativeProcess (params.filmNegative); } diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index 4c775bdcc..bdd166938 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -8,7 +8,7 @@ set(CLISOURCEFILES paramsedited.cc pathutils.cc threadutils.cc - ) +) set(NONCLISOURCEFILES adjuster.cc @@ -43,6 +43,7 @@ set(NONCLISOURCEFILES curveeditorgroup.cc darkframe.cc defringe.cc + dehaze.cc diagonalcurveeditorsubgroup.cc dirbrowser.cc dirpyrdenoise.cc @@ -55,15 +56,18 @@ set(NONCLISOURCEFILES editwidgets.cc editwindow.cc epd.cc + eventmapper.cc exiffiltersettings.cc exifpanel.cc exportpanel.cc extprog.cc + fattaltonemap.cc filebrowser.cc filebrowserentry.cc filecatalog.cc filepanel.cc filethumbnailbuttonset.cc + filmnegative.cc filmsimulation.cc filterpanel.cc flatcurveeditorsubgroup.cc @@ -83,12 +87,15 @@ set(NONCLISOURCEFILES inspector.cc iptcpanel.cc labcurve.cc + labgrid.cc lensgeom.cc lensprofile.cc + localcontrast.cc lockablecolorpicker.cc lwbutton.cc lwbuttonset.cc main.cc + metadatapanel.cc multilangmgr.cc mycurve.cc mydiagonalcurve.cc @@ -122,8 +129,8 @@ set(NONCLISOURCEFILES rgbcurves.cc rotate.cc rtimage.cc - rtsurface.cc rtscalable.cc + rtsurface.cc rtwindow.cc saveasdlg.cc saveformatpanel.cc @@ -134,6 +141,7 @@ set(NONCLISOURCEFILES sharpening.cc sharpenmicro.cc shcselector.cc + softlight.cc soundman.cc splash.cc threadutils.cc @@ -154,15 +162,7 @@ set(NONCLISOURCEFILES xtransprocess.cc xtransrawexposure.cc zoompanel.cc - fattaltonemap.cc - localcontrast.cc - eventmapper.cc - metadatapanel.cc - labgrid.cc - softlight.cc - dehaze.cc - filmnegative.cc - ) +) include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 3a5ab041a..7d52d309a 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -1163,15 +1163,15 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng bool dontforceSet = !forceSet; if (toneCurve.curve) { - toEdit.toneCurve.curve = mods.toneCurve.curve; + toEdit.toneCurve.curve = mods.toneCurve.curve; } if (toneCurve.curve2) { - toEdit.toneCurve.curve2 = mods.toneCurve.curve2; + toEdit.toneCurve.curve2 = mods.toneCurve.curve2; } if (toneCurve.curveMode) { - toEdit.toneCurve.curveMode = mods.toneCurve.curveMode; + toEdit.toneCurve.curveMode = mods.toneCurve.curveMode; } if (toneCurve.curveMode2) { @@ -1183,11 +1183,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (toneCurve.black) { - toEdit.toneCurve.black = dontforceSet && options.baBehav[ADDSET_TC_BLACKLEVEL] ? toEdit.toneCurve.black + mods.toneCurve.black : mods.toneCurve.black; + toEdit.toneCurve.black = dontforceSet && options.baBehav[ADDSET_TC_BLACKLEVEL] ? toEdit.toneCurve.black + mods.toneCurve.black : mods.toneCurve.black; } if (toneCurve.contrast) { - toEdit.toneCurve.contrast = dontforceSet && options.baBehav[ADDSET_TC_CONTRAST] ? toEdit.toneCurve.contrast + mods.toneCurve.contrast : mods.toneCurve.contrast; + toEdit.toneCurve.contrast = dontforceSet && options.baBehav[ADDSET_TC_CONTRAST] ? toEdit.toneCurve.contrast + mods.toneCurve.contrast : mods.toneCurve.contrast; } if (toneCurve.saturation) { @@ -1195,43 +1195,43 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (toneCurve.shcompr) { - toEdit.toneCurve.shcompr = dontforceSet && options.baBehav[ADDSET_TC_SHCOMP] ? toEdit.toneCurve.shcompr + mods.toneCurve.shcompr : mods.toneCurve.shcompr; + toEdit.toneCurve.shcompr = dontforceSet && options.baBehav[ADDSET_TC_SHCOMP] ? toEdit.toneCurve.shcompr + mods.toneCurve.shcompr : mods.toneCurve.shcompr; } if (toneCurve.autoexp) { - toEdit.toneCurve.autoexp = mods.toneCurve.autoexp; + toEdit.toneCurve.autoexp = mods.toneCurve.autoexp; } if (toneCurve.clip) { - toEdit.toneCurve.clip = mods.toneCurve.clip; + toEdit.toneCurve.clip = mods.toneCurve.clip; } if (toneCurve.expcomp) { - toEdit.toneCurve.expcomp = dontforceSet && options.baBehav[ADDSET_TC_EXPCOMP] ? toEdit.toneCurve.expcomp + mods.toneCurve.expcomp : mods.toneCurve.expcomp; + toEdit.toneCurve.expcomp = dontforceSet && options.baBehav[ADDSET_TC_EXPCOMP] ? toEdit.toneCurve.expcomp + mods.toneCurve.expcomp : mods.toneCurve.expcomp; } if (toneCurve.hlcompr) { - toEdit.toneCurve.hlcompr = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPAMOUNT] ? toEdit.toneCurve.hlcompr + mods.toneCurve.hlcompr : mods.toneCurve.hlcompr; + toEdit.toneCurve.hlcompr = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPAMOUNT] ? toEdit.toneCurve.hlcompr + mods.toneCurve.hlcompr : mods.toneCurve.hlcompr; } if (toneCurve.hlcomprthresh) { - toEdit.toneCurve.hlcomprthresh = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPTHRESH] ? toEdit.toneCurve.hlcomprthresh + mods.toneCurve.hlcomprthresh : mods.toneCurve.hlcomprthresh; + toEdit.toneCurve.hlcomprthresh = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPTHRESH] ? toEdit.toneCurve.hlcomprthresh + mods.toneCurve.hlcomprthresh : mods.toneCurve.hlcomprthresh; } if (toneCurve.hrenabled) { - toEdit.toneCurve.hrenabled = mods.toneCurve.hrenabled; + toEdit.toneCurve.hrenabled = mods.toneCurve.hrenabled; } if (toneCurve.method) { - toEdit.toneCurve.method = mods.toneCurve.method; + toEdit.toneCurve.method = mods.toneCurve.method; } if (toneCurve.histmatching) { - toEdit.toneCurve.histmatching = mods.toneCurve.histmatching; + toEdit.toneCurve.histmatching = mods.toneCurve.histmatching; } if (toneCurve.fromHistMatching) { - toEdit.toneCurve.fromHistMatching = mods.toneCurve.fromHistMatching; + toEdit.toneCurve.fromHistMatching = mods.toneCurve.fromHistMatching; } if (toneCurve.clampOOG) { @@ -1239,132 +1239,132 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (retinex.enabled) { - toEdit.retinex.enabled = mods.retinex.enabled; + toEdit.retinex.enabled = mods.retinex.enabled; } if (retinex.cdcurve) { - toEdit.retinex.cdcurve = mods.retinex.cdcurve; + toEdit.retinex.cdcurve = mods.retinex.cdcurve; } if (retinex.mapcurve) { - toEdit.retinex.mapcurve = mods.retinex.mapcurve; + toEdit.retinex.mapcurve = mods.retinex.mapcurve; } if (retinex.cdHcurve) { - toEdit.retinex.cdHcurve = mods.retinex.cdHcurve; + toEdit.retinex.cdHcurve = mods.retinex.cdHcurve; } if (retinex.lhcurve) { - toEdit.retinex.lhcurve = mods.retinex.lhcurve; + toEdit.retinex.lhcurve = mods.retinex.lhcurve; } if (retinex.transmissionCurve) { - toEdit.retinex.transmissionCurve = mods.retinex.transmissionCurve; + toEdit.retinex.transmissionCurve = mods.retinex.transmissionCurve; } if (retinex.gaintransmissionCurve) { - toEdit.retinex.gaintransmissionCurve = mods.retinex.gaintransmissionCurve; + toEdit.retinex.gaintransmissionCurve = mods.retinex.gaintransmissionCurve; } if (retinex.retinexMethod) { - toEdit.retinex.retinexMethod = mods.retinex.retinexMethod; + toEdit.retinex.retinexMethod = mods.retinex.retinexMethod; } if (retinex.mapMethod) { - toEdit.retinex.mapMethod = mods.retinex.mapMethod; + toEdit.retinex.mapMethod = mods.retinex.mapMethod; } if (retinex.viewMethod) { - toEdit.retinex.viewMethod = mods.retinex.viewMethod; + toEdit.retinex.viewMethod = mods.retinex.viewMethod; } if (retinex.retinexcolorspace) { - toEdit.retinex.retinexcolorspace = mods.retinex.retinexcolorspace; + toEdit.retinex.retinexcolorspace = mods.retinex.retinexcolorspace; } if (retinex.gammaretinex) { - toEdit.retinex.gammaretinex = mods.retinex.gammaretinex; + toEdit.retinex.gammaretinex = mods.retinex.gammaretinex; } if (retinex.gam) { - toEdit.retinex.gam = dontforceSet && options.baBehav[ADDSET_RETI_GAM] ? toEdit.retinex.gam + mods.retinex.gam : mods.retinex.gam; + toEdit.retinex.gam = dontforceSet && options.baBehav[ADDSET_RETI_GAM] ? toEdit.retinex.gam + mods.retinex.gam : mods.retinex.gam; } if (retinex.slope) { - toEdit.retinex.slope = dontforceSet && options.baBehav[ADDSET_RETI_SLO] ? toEdit.retinex.slope + mods.retinex.slope : mods.retinex.slope; + toEdit.retinex.slope = dontforceSet && options.baBehav[ADDSET_RETI_SLO] ? toEdit.retinex.slope + mods.retinex.slope : mods.retinex.slope; } if (retinex.str) { - toEdit.retinex.str = dontforceSet && options.baBehav[ADDSET_RETI_STR] ? toEdit.retinex.str + mods.retinex.str : mods.retinex.str; + toEdit.retinex.str = dontforceSet && options.baBehav[ADDSET_RETI_STR] ? toEdit.retinex.str + mods.retinex.str : mods.retinex.str; } if (retinex.scal) { - toEdit.retinex.scal = mods.retinex.scal; + toEdit.retinex.scal = mods.retinex.scal; } if (retinex.iter) { - toEdit.retinex.iter = mods.retinex.iter; + toEdit.retinex.iter = mods.retinex.iter; } if (retinex.grad) { - toEdit.retinex.grad = mods.retinex.grad; + toEdit.retinex.grad = mods.retinex.grad; } if (retinex.grads) { - toEdit.retinex.grads = mods.retinex.grads; + toEdit.retinex.grads = mods.retinex.grads; } // if (retinex.scal) { -// toEdit.retinex.scal = dontforceSet && options.baBehav[ADDSET_RETI_SCAL] ? toEdit.retinex.scal + mods.retinex.scal : mods.retinex.scal; +// toEdit.retinex.scal = dontforceSet && options.baBehav[ADDSET_RETI_SCAL] ? toEdit.retinex.scal + mods.retinex.scal : mods.retinex.scal; // } if (retinex.medianmap) { - toEdit.retinex.medianmap = mods.retinex.medianmap; + toEdit.retinex.medianmap = mods.retinex.medianmap; } if (retinex.neigh) { - toEdit.retinex.neigh = dontforceSet && options.baBehav[ADDSET_RETI_NEIGH] ? toEdit.retinex.neigh + mods.retinex.neigh : mods.retinex.neigh; + toEdit.retinex.neigh = dontforceSet && options.baBehav[ADDSET_RETI_NEIGH] ? toEdit.retinex.neigh + mods.retinex.neigh : mods.retinex.neigh; } if (retinex.limd) { - toEdit.retinex.limd = dontforceSet && options.baBehav[ADDSET_RETI_LIMD] ? toEdit.retinex.limd + mods.retinex.limd : mods.retinex.limd; + toEdit.retinex.limd = dontforceSet && options.baBehav[ADDSET_RETI_LIMD] ? toEdit.retinex.limd + mods.retinex.limd : mods.retinex.limd; } if (retinex.highl) { - toEdit.retinex.highl = mods.retinex.highl; + toEdit.retinex.highl = mods.retinex.highl; } if (retinex.skal) { - toEdit.retinex.skal = mods.retinex.skal; + toEdit.retinex.skal = mods.retinex.skal; } if (retinex.offs) { - toEdit.retinex.offs = dontforceSet && options.baBehav[ADDSET_RETI_OFFS] ? toEdit.retinex.offs + mods.retinex.offs : mods.retinex.offs; + toEdit.retinex.offs = dontforceSet && options.baBehav[ADDSET_RETI_OFFS] ? toEdit.retinex.offs + mods.retinex.offs : mods.retinex.offs; } if (retinex.vart) { - toEdit.retinex.vart = dontforceSet && options.baBehav[ADDSET_RETI_VART] ? toEdit.retinex.vart + mods.retinex.vart : mods.retinex.vart; + toEdit.retinex.vart = dontforceSet && options.baBehav[ADDSET_RETI_VART] ? toEdit.retinex.vart + mods.retinex.vart : mods.retinex.vart; } if (retinex.highlights) { - toEdit.retinex.highlights = mods.retinex.highlights; + toEdit.retinex.highlights = mods.retinex.highlights; } if (retinex.htonalwidth) { - toEdit.retinex.htonalwidth = mods.retinex.htonalwidth; + toEdit.retinex.htonalwidth = mods.retinex.htonalwidth; } if (retinex.shadows) { - toEdit.retinex.shadows = mods.retinex.shadows; + toEdit.retinex.shadows = mods.retinex.shadows; } if (retinex.stonalwidth) { - toEdit.retinex.stonalwidth = mods.retinex.stonalwidth; + toEdit.retinex.stonalwidth = mods.retinex.stonalwidth; } if (retinex.radius) { - toEdit.retinex.radius = mods.retinex.radius; + toEdit.retinex.radius = mods.retinex.radius; } @@ -1373,47 +1373,47 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (labCurve.lcurve) { - toEdit.labCurve.lcurve = mods.labCurve.lcurve; + toEdit.labCurve.lcurve = mods.labCurve.lcurve; } if (labCurve.acurve) { - toEdit.labCurve.acurve = mods.labCurve.acurve; + toEdit.labCurve.acurve = mods.labCurve.acurve; } if (labCurve.bcurve) { - toEdit.labCurve.bcurve = mods.labCurve.bcurve; + toEdit.labCurve.bcurve = mods.labCurve.bcurve; } if (labCurve.cccurve) { - toEdit.labCurve.cccurve = mods.labCurve.cccurve; + toEdit.labCurve.cccurve = mods.labCurve.cccurve; } if (labCurve.chcurve) { - toEdit.labCurve.chcurve = mods.labCurve.chcurve; + toEdit.labCurve.chcurve = mods.labCurve.chcurve; } if (labCurve.lhcurve) { - toEdit.labCurve.lhcurve = mods.labCurve.lhcurve; + toEdit.labCurve.lhcurve = mods.labCurve.lhcurve; } if (labCurve.hhcurve) { - toEdit.labCurve.hhcurve = mods.labCurve.hhcurve; + toEdit.labCurve.hhcurve = mods.labCurve.hhcurve; } if (labCurve.lccurve) { - toEdit.labCurve.lccurve = mods.labCurve.lccurve; + toEdit.labCurve.lccurve = mods.labCurve.lccurve; } if (labCurve.clcurve) { - toEdit.labCurve.clcurve = mods.labCurve.clcurve; + toEdit.labCurve.clcurve = mods.labCurve.clcurve; } if (labCurve.brightness) { - toEdit.labCurve.brightness = dontforceSet && options.baBehav[ADDSET_LC_BRIGHTNESS] ? toEdit.labCurve.brightness + mods.labCurve.brightness : mods.labCurve.brightness; + toEdit.labCurve.brightness = dontforceSet && options.baBehav[ADDSET_LC_BRIGHTNESS] ? toEdit.labCurve.brightness + mods.labCurve.brightness : mods.labCurve.brightness; } if (labCurve.contrast) { - toEdit.labCurve.contrast = dontforceSet && options.baBehav[ADDSET_LC_CONTRAST] ? toEdit.labCurve.contrast + mods.labCurve.contrast : mods.labCurve.contrast; + toEdit.labCurve.contrast = dontforceSet && options.baBehav[ADDSET_LC_CONTRAST] ? toEdit.labCurve.contrast + mods.labCurve.contrast : mods.labCurve.contrast; } if (labCurve.chromaticity) { @@ -1429,7 +1429,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (labCurve.lcredsk) { - toEdit.labCurve.lcredsk = mods.labCurve.lcredsk; + toEdit.labCurve.lcredsk = mods.labCurve.lcredsk; } if (localContrast.enabled) { @@ -1454,23 +1454,23 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (rgbCurves.lumamode) { - toEdit.rgbCurves.lumamode = mods.rgbCurves.lumamode; + toEdit.rgbCurves.lumamode = mods.rgbCurves.lumamode; } if (rgbCurves.rcurve) { - toEdit.rgbCurves.rcurve = mods.rgbCurves.rcurve; + toEdit.rgbCurves.rcurve = mods.rgbCurves.rcurve; } if (rgbCurves.gcurve) { - toEdit.rgbCurves.gcurve = mods.rgbCurves.gcurve; + toEdit.rgbCurves.gcurve = mods.rgbCurves.gcurve; } if (rgbCurves.bcurve) { - toEdit.rgbCurves.bcurve = mods.rgbCurves.bcurve; + toEdit.rgbCurves.bcurve = mods.rgbCurves.bcurve; } if (colorToning.enabled) { - toEdit.colorToning.enabled = mods.colorToning.enabled; + toEdit.colorToning.enabled = mods.colorToning.enabled; } if (colorToning.twocolor) { @@ -1478,7 +1478,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.opacityCurve) { - toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; + toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; } if (colorToning.colorCurve) { @@ -1486,11 +1486,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.enabled) { - toEdit.colorToning.enabled = mods.colorToning.enabled; + toEdit.colorToning.enabled = mods.colorToning.enabled; } if (colorToning.opacityCurve) { - toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; + toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; } if (colorToning.satprotectionthreshold) { @@ -1498,7 +1498,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.autosat) { - toEdit.colorToning.autosat = mods.colorToning.autosat; + toEdit.colorToning.autosat = mods.colorToning.autosat; } if (colorToning.saturatedopacity) { @@ -1506,23 +1506,23 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.strength) { - toEdit.colorToning.strength = dontforceSet && options.baBehav[ADDSET_COLORTONING_STRENGTH] ? toEdit.colorToning.strength + mods.colorToning.strength : mods.colorToning.strength; + toEdit.colorToning.strength = dontforceSet && options.baBehav[ADDSET_COLORTONING_STRENGTH] ? toEdit.colorToning.strength + mods.colorToning.strength : mods.colorToning.strength; } if (colorToning.shadowsColSat) { - toEdit.colorToning.shadowsColSat = mods.colorToning.shadowsColSat; + toEdit.colorToning.shadowsColSat = mods.colorToning.shadowsColSat; } if (colorToning.hlColSat) { - toEdit.colorToning.hlColSat = mods.colorToning.hlColSat; + toEdit.colorToning.hlColSat = mods.colorToning.hlColSat; } if (colorToning.balance) { - toEdit.colorToning.balance = dontforceSet && options.baBehav[ADDSET_COLORTONING_BALANCE] ? toEdit.colorToning.balance + mods.colorToning.balance : mods.colorToning.balance; + toEdit.colorToning.balance = dontforceSet && options.baBehav[ADDSET_COLORTONING_BALANCE] ? toEdit.colorToning.balance + mods.colorToning.balance : mods.colorToning.balance; } if (colorToning.clcurve) { - toEdit.colorToning.clcurve = mods.colorToning.clcurve; + toEdit.colorToning.clcurve = mods.colorToning.clcurve; } if (colorToning.method) { @@ -1530,11 +1530,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.cl2curve) { - toEdit.colorToning.cl2curve = mods.colorToning.cl2curve; + toEdit.colorToning.cl2curve = mods.colorToning.cl2curve; } if (colorToning.lumamode) { - toEdit.colorToning.lumamode = mods.colorToning.lumamode; + toEdit.colorToning.lumamode = mods.colorToning.lumamode; } if (colorToning.satlow) { @@ -1542,7 +1542,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.sathigh) { - toEdit.colorToning.sathigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.sathigh + mods.colorToning.sathigh : mods.colorToning.sathigh; + toEdit.colorToning.sathigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.sathigh + mods.colorToning.sathigh : mods.colorToning.sathigh; } if (colorToning.redlow) { @@ -1550,11 +1550,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.greenlow) { - toEdit.colorToning.greenlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenlow + mods.colorToning.greenlow : mods.colorToning.greenlow; + toEdit.colorToning.greenlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenlow + mods.colorToning.greenlow : mods.colorToning.greenlow; } if (colorToning.bluelow) { - toEdit.colorToning.bluelow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluelow + mods.colorToning.bluelow : mods.colorToning.bluelow; + toEdit.colorToning.bluelow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluelow + mods.colorToning.bluelow : mods.colorToning.bluelow; } if (colorToning.redmed) { @@ -1562,15 +1562,15 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.greenmed) { - toEdit.colorToning.greenmed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenmed + mods.colorToning.greenmed : mods.colorToning.greenmed; + toEdit.colorToning.greenmed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenmed + mods.colorToning.greenmed : mods.colorToning.greenmed; } if (colorToning.bluemed) { - toEdit.colorToning.bluemed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluemed + mods.colorToning.bluemed : mods.colorToning.bluemed; + toEdit.colorToning.bluemed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluemed + mods.colorToning.bluemed : mods.colorToning.bluemed; } if (colorToning.redhigh) { - toEdit.colorToning.redhigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redhigh + mods.colorToning.redhigh : mods.colorToning.redhigh; + toEdit.colorToning.redhigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redhigh + mods.colorToning.redhigh : mods.colorToning.redhigh; } if (colorToning.greenhigh) { @@ -1578,7 +1578,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorToning.bluehigh) { - toEdit.colorToning.bluehigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluehigh + mods.colorToning.bluehigh : mods.colorToning.bluehigh; + toEdit.colorToning.bluehigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluehigh + mods.colorToning.bluehigh : mods.colorToning.bluehigh; } if (colorToning.labgridALow) { @@ -1606,7 +1606,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (sharpenEdge.enabled) { - toEdit.sharpenEdge.enabled = mods.sharpenEdge.enabled; + toEdit.sharpenEdge.enabled = mods.sharpenEdge.enabled; } if (sharpenEdge.passes) { @@ -1618,47 +1618,47 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (sharpenEdge.threechannels) { - toEdit.sharpenEdge.threechannels = mods.sharpenEdge.threechannels; + toEdit.sharpenEdge.threechannels = mods.sharpenEdge.threechannels; } if (sharpenMicro.enabled) { - toEdit.sharpenMicro.enabled = mods.sharpenMicro.enabled; + toEdit.sharpenMicro.enabled = mods.sharpenMicro.enabled; } if (sharpenMicro.matrix) { - toEdit.sharpenMicro.matrix = mods.sharpenMicro.matrix; + toEdit.sharpenMicro.matrix = mods.sharpenMicro.matrix; } if (sharpenMicro.amount) { - toEdit.sharpenMicro.amount = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_AMOUNT] ? toEdit.sharpenMicro.amount + mods.sharpenMicro.amount : mods.sharpenMicro.amount; + toEdit.sharpenMicro.amount = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_AMOUNT] ? toEdit.sharpenMicro.amount + mods.sharpenMicro.amount : mods.sharpenMicro.amount; } if (sharpenMicro.contrast) { - toEdit.sharpenMicro.contrast = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_CONTRAST] ? toEdit.sharpenMicro.contrast + mods.sharpenMicro.contrast : mods.sharpenMicro.contrast; + toEdit.sharpenMicro.contrast = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_CONTRAST] ? toEdit.sharpenMicro.contrast + mods.sharpenMicro.contrast : mods.sharpenMicro.contrast; } if (sharpenMicro.uniformity) { - toEdit.sharpenMicro.uniformity = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY] ? toEdit.sharpenMicro.uniformity + mods.sharpenMicro.uniformity : mods.sharpenMicro.uniformity; + toEdit.sharpenMicro.uniformity = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY] ? toEdit.sharpenMicro.uniformity + mods.sharpenMicro.uniformity : mods.sharpenMicro.uniformity; } if (sharpening.enabled) { - toEdit.sharpening.enabled = mods.sharpening.enabled; + toEdit.sharpening.enabled = mods.sharpening.enabled; } if (sharpening.contrast) { - toEdit.sharpening.contrast = dontforceSet && options.baBehav[ADDSET_SHARP_CONTRAST] ? toEdit.sharpening.contrast + mods.sharpening.contrast : mods.sharpening.contrast; + toEdit.sharpening.contrast = dontforceSet && options.baBehav[ADDSET_SHARP_CONTRAST] ? toEdit.sharpening.contrast + mods.sharpening.contrast : mods.sharpening.contrast; } if (sharpening.radius) { - toEdit.sharpening.radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.radius + mods.sharpening.radius : mods.sharpening.radius; + toEdit.sharpening.radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.radius + mods.sharpening.radius : mods.sharpening.radius; } if (sharpening.blurradius) { - toEdit.sharpening.blurradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.blurradius + mods.sharpening.blurradius : mods.sharpening.blurradius; + toEdit.sharpening.blurradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.blurradius + mods.sharpening.blurradius : mods.sharpening.blurradius; } if (sharpening.amount) { - toEdit.sharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.amount + mods.sharpening.amount : mods.sharpening.amount; + toEdit.sharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.amount + mods.sharpening.amount : mods.sharpening.amount; } if (sharpening.threshold) { @@ -1666,7 +1666,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (sharpening.edgesonly) { - toEdit.sharpening.edgesonly = mods.sharpening.edgesonly; + toEdit.sharpening.edgesonly = mods.sharpening.edgesonly; } if (sharpening.edges_radius) { @@ -1686,19 +1686,19 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (sharpening.method) { - toEdit.sharpening.method = mods.sharpening.method; + toEdit.sharpening.method = mods.sharpening.method; } if (sharpening.deconvamount) { - toEdit.sharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.deconvamount + mods.sharpening.deconvamount : mods.sharpening.deconvamount; + toEdit.sharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.deconvamount + mods.sharpening.deconvamount : mods.sharpening.deconvamount; } if (sharpening.deconvradius) { - toEdit.sharpening.deconvradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.deconvradius + mods.sharpening.deconvradius : mods.sharpening.deconvradius; + toEdit.sharpening.deconvradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.deconvradius + mods.sharpening.deconvradius : mods.sharpening.deconvradius; } if (sharpening.deconviter) { - toEdit.sharpening.deconviter = dontforceSet && options.baBehav[ADDSET_SHARP_ITER] ? toEdit.sharpening.deconviter + mods.sharpening.deconviter : mods.sharpening.deconviter; + toEdit.sharpening.deconviter = dontforceSet && options.baBehav[ADDSET_SHARP_ITER] ? toEdit.sharpening.deconviter + mods.sharpening.deconviter : mods.sharpening.deconviter; } if (sharpening.deconvdamping) { @@ -1706,19 +1706,19 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (prsharpening.enabled) { - toEdit.prsharpening.enabled = mods.prsharpening.enabled; + toEdit.prsharpening.enabled = mods.prsharpening.enabled; } if (prsharpening.contrast) { - toEdit.prsharpening.contrast = dontforceSet && options.baBehav[ADDSET_SHARP_CONTRAST] ? toEdit.prsharpening.contrast + mods.prsharpening.contrast : mods.prsharpening.contrast; + toEdit.prsharpening.contrast = dontforceSet && options.baBehav[ADDSET_SHARP_CONTRAST] ? toEdit.prsharpening.contrast + mods.prsharpening.contrast : mods.prsharpening.contrast; } if (prsharpening.radius) { - toEdit.prsharpening.radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.prsharpening.radius + mods.prsharpening.radius : mods.prsharpening.radius; + toEdit.prsharpening.radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.prsharpening.radius + mods.prsharpening.radius : mods.prsharpening.radius; } if (prsharpening.amount) { - toEdit.prsharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.prsharpening.amount + mods.prsharpening.amount : mods.prsharpening.amount; + toEdit.prsharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.prsharpening.amount + mods.prsharpening.amount : mods.prsharpening.amount; } if (prsharpening.threshold) { @@ -1726,11 +1726,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (prsharpening.edgesonly) { - toEdit.prsharpening.edgesonly = mods.prsharpening.edgesonly; + toEdit.prsharpening.edgesonly = mods.prsharpening.edgesonly; } if (prsharpening.edges_radius) { - toEdit.prsharpening.edges_radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.prsharpening.edges_radius + mods.prsharpening.edges_radius : mods.prsharpening.edges_radius; + toEdit.prsharpening.edges_radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.prsharpening.edges_radius + mods.prsharpening.edges_radius : mods.prsharpening.edges_radius; } if (prsharpening.edges_tolerance) { @@ -1738,7 +1738,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (prsharpening.halocontrol) { - toEdit.prsharpening.halocontrol = mods.prsharpening.halocontrol; + toEdit.prsharpening.halocontrol = mods.prsharpening.halocontrol; } if (prsharpening.halocontrol_amount) { @@ -1746,19 +1746,19 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (prsharpening.method) { - toEdit.prsharpening.method = mods.prsharpening.method; + toEdit.prsharpening.method = mods.prsharpening.method; } if (prsharpening.deconvamount) { - toEdit.prsharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.prsharpening.deconvamount + mods.prsharpening.deconvamount : mods.prsharpening.deconvamount; + toEdit.prsharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.prsharpening.deconvamount + mods.prsharpening.deconvamount : mods.prsharpening.deconvamount; } if (prsharpening.deconvradius) { - toEdit.prsharpening.deconvradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.prsharpening.deconvradius + mods.prsharpening.deconvradius : mods.prsharpening.deconvradius; + toEdit.prsharpening.deconvradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.prsharpening.deconvradius + mods.prsharpening.deconvradius : mods.prsharpening.deconvradius; } if (prsharpening.deconviter) { - toEdit.prsharpening.deconviter = dontforceSet && options.baBehav[ADDSET_SHARP_ITER] ? toEdit.prsharpening.deconviter + mods.prsharpening.deconviter : mods.prsharpening.deconviter; + toEdit.prsharpening.deconviter = dontforceSet && options.baBehav[ADDSET_SHARP_ITER] ? toEdit.prsharpening.deconviter + mods.prsharpening.deconviter : mods.prsharpening.deconviter; } if (prsharpening.deconvdamping) { @@ -1766,79 +1766,79 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (vibrance.enabled) { - toEdit.vibrance.enabled = mods.vibrance.enabled; + toEdit.vibrance.enabled = mods.vibrance.enabled; } if (vibrance.pastels) { - toEdit.vibrance.pastels = dontforceSet && options.baBehav[ADDSET_VIBRANCE_PASTELS] ? toEdit.vibrance.pastels + mods.vibrance.pastels : mods.vibrance.pastels; + toEdit.vibrance.pastels = dontforceSet && options.baBehav[ADDSET_VIBRANCE_PASTELS] ? toEdit.vibrance.pastels + mods.vibrance.pastels : mods.vibrance.pastels; } if (vibrance.saturated) { - toEdit.vibrance.saturated = dontforceSet && options.baBehav[ADDSET_VIBRANCE_SATURATED] ? toEdit.vibrance.saturated + mods.vibrance.saturated : mods.vibrance.saturated; + toEdit.vibrance.saturated = dontforceSet && options.baBehav[ADDSET_VIBRANCE_SATURATED] ? toEdit.vibrance.saturated + mods.vibrance.saturated : mods.vibrance.saturated; } if (vibrance.psthreshold) { - toEdit.vibrance.psthreshold = mods.vibrance.psthreshold; + toEdit.vibrance.psthreshold = mods.vibrance.psthreshold; } if (vibrance.protectskins) { - toEdit.vibrance.protectskins = mods.vibrance.protectskins; + toEdit.vibrance.protectskins = mods.vibrance.protectskins; } if (vibrance.avoidcolorshift) { - toEdit.vibrance.avoidcolorshift = mods.vibrance.avoidcolorshift; + toEdit.vibrance.avoidcolorshift = mods.vibrance.avoidcolorshift; } if (vibrance.pastsattog) { - toEdit.vibrance.pastsattog = mods.vibrance.pastsattog; + toEdit.vibrance.pastsattog = mods.vibrance.pastsattog; } if (vibrance.skintonescurve) { - toEdit.vibrance.skintonescurve = mods.vibrance.skintonescurve; + toEdit.vibrance.skintonescurve = mods.vibrance.skintonescurve; } - //if (colorBoost.amount) toEdit.colorBoost.amount = dontforceSet && options.baBehav[ADDSET_CBOOST_AMOUNT] ? toEdit.colorBoost.amount + mods.colorBoost.amount : mods.colorBoost.amount; - //if (colorBoost.avoidclip) toEdit.colorBoost.avoidclip = mods.colorBoost.avoidclip; - //if (colorBoost.enable_saturationlimiter)toEdit.colorBoost.enable_saturationlimiter = mods.colorBoost.enable_saturationlimiter; - //if (colorBoost.saturationlimit) toEdit.colorBoost.saturationlimit = mods.colorBoost.saturationlimit; + //if (colorBoost.amount) toEdit.colorBoost.amount = dontforceSet && options.baBehav[ADDSET_CBOOST_AMOUNT] ? toEdit.colorBoost.amount + mods.colorBoost.amount : mods.colorBoost.amount; + //if (colorBoost.avoidclip) toEdit.colorBoost.avoidclip = mods.colorBoost.avoidclip; + //if (colorBoost.enable_saturationlimiter)toEdit.colorBoost.enable_saturationlimiter = mods.colorBoost.enable_saturationlimiter; + //if (colorBoost.saturationlimit) toEdit.colorBoost.saturationlimit = mods.colorBoost.saturationlimit; if (wb.enabled) { toEdit.wb.enabled = mods.wb.enabled; } if (wb.method) { - toEdit.wb.method = mods.wb.method; + toEdit.wb.method = mods.wb.method; } if (wb.equal) { - toEdit.wb.equal = dontforceSet && options.baBehav[ADDSET_WB_EQUAL] ? toEdit.wb.equal + mods.wb.equal : mods.wb.equal; + toEdit.wb.equal = dontforceSet && options.baBehav[ADDSET_WB_EQUAL] ? toEdit.wb.equal + mods.wb.equal : mods.wb.equal; } if (wb.tempBias) { - toEdit.wb.tempBias = dontforceSet && options.baBehav[ADDSET_WB_TEMPBIAS] ? toEdit.wb.tempBias + mods.wb.tempBias : mods.wb.tempBias; + toEdit.wb.tempBias = dontforceSet && options.baBehav[ADDSET_WB_TEMPBIAS] ? toEdit.wb.tempBias + mods.wb.tempBias : mods.wb.tempBias; } if (wb.green) { - toEdit.wb.green = dontforceSet && options.baBehav[ADDSET_WB_GREEN] ? toEdit.wb.green + mods.wb.green : mods.wb.green; + toEdit.wb.green = dontforceSet && options.baBehav[ADDSET_WB_GREEN] ? toEdit.wb.green + mods.wb.green : mods.wb.green; } if (wb.temperature) { - toEdit.wb.temperature = dontforceSet && options.baBehav[ADDSET_WB_TEMPERATURE] ? toEdit.wb.temperature + mods.wb.temperature : mods.wb.temperature; + toEdit.wb.temperature = dontforceSet && options.baBehav[ADDSET_WB_TEMPERATURE] ? toEdit.wb.temperature + mods.wb.temperature : mods.wb.temperature; } - //if (colorShift.a) toEdit.colorShift.a = dontforceSet && options.baBehav[ADDSET_CS_BLUEYELLOW] ? toEdit.colorShift.a + mods.colorShift.a : mods.colorShift.a; - //if (colorShift.b) toEdit.colorShift.b = dontforceSet && options.baBehav[ADDSET_CS_GREENMAGENTA] ? toEdit.colorShift.b + mods.colorShift.b : mods.colorShift.b; - //if (lumaDenoise.enabled) toEdit.lumaDenoise.enabled = mods.lumaDenoise.enabled; - //if (lumaDenoise.radius) toEdit.lumaDenoise.radius = mods.lumaDenoise.radius; - //if (lumaDenoise.edgetolerance) toEdit.lumaDenoise.edgetolerance = dontforceSet && options.baBehav[ADDSET_LD_EDGETOLERANCE] ? toEdit.lumaDenoise.edgetolerance + mods.lumaDenoise.edgetolerance : mods.lumaDenoise.edgetolerance; - //if (colorDenoise.enabled) toEdit.colorDenoise.enabled = mods.colorDenoise.enabled; - //if (colorDenoise.amount) toEdit.colorDenoise.amount = mods.colorDenoise.amount; + //if (colorShift.a) toEdit.colorShift.a = dontforceSet && options.baBehav[ADDSET_CS_BLUEYELLOW] ? toEdit.colorShift.a + mods.colorShift.a : mods.colorShift.a; + //if (colorShift.b) toEdit.colorShift.b = dontforceSet && options.baBehav[ADDSET_CS_GREENMAGENTA] ? toEdit.colorShift.b + mods.colorShift.b : mods.colorShift.b; + //if (lumaDenoise.enabled) toEdit.lumaDenoise.enabled = mods.lumaDenoise.enabled; + //if (lumaDenoise.radius) toEdit.lumaDenoise.radius = mods.lumaDenoise.radius; + //if (lumaDenoise.edgetolerance) toEdit.lumaDenoise.edgetolerance = dontforceSet && options.baBehav[ADDSET_LD_EDGETOLERANCE] ? toEdit.lumaDenoise.edgetolerance + mods.lumaDenoise.edgetolerance : mods.lumaDenoise.edgetolerance; + //if (colorDenoise.enabled) toEdit.colorDenoise.enabled = mods.colorDenoise.enabled; + //if (colorDenoise.amount) toEdit.colorDenoise.amount = mods.colorDenoise.amount; if (defringe.enabled) { - toEdit.defringe.enabled = mods.defringe.enabled; + toEdit.defringe.enabled = mods.defringe.enabled; } if (defringe.radius) { - toEdit.defringe.radius = mods.defringe.radius; + toEdit.defringe.radius = mods.defringe.radius; } if (defringe.threshold) { @@ -1846,23 +1846,23 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (defringe.huecurve) { - toEdit.defringe.huecurve = mods.defringe.huecurve; + toEdit.defringe.huecurve = mods.defringe.huecurve; } if (colorappearance.curve) { - toEdit.colorappearance.curve = mods.colorappearance.curve; + toEdit.colorappearance.curve = mods.colorappearance.curve; } if (colorappearance.curve2) { - toEdit.colorappearance.curve2 = mods.colorappearance.curve2; + toEdit.colorappearance.curve2 = mods.colorappearance.curve2; } if (colorappearance.curve3) { - toEdit.colorappearance.curve3 = mods.colorappearance.curve3; + toEdit.colorappearance.curve3 = mods.colorappearance.curve3; } if (colorappearance.curveMode) { - toEdit.colorappearance.curveMode = mods.colorappearance.curveMode; + toEdit.colorappearance.curveMode = mods.colorappearance.curveMode; } if (colorappearance.curveMode2) { @@ -1874,11 +1874,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorappearance.enabled) { - toEdit.colorappearance.enabled = mods.colorappearance.enabled; + toEdit.colorappearance.enabled = mods.colorappearance.enabled; } if (colorappearance.degree) { - toEdit.colorappearance.degree = dontforceSet && options.baBehav[ADDSET_CAT_DEGREE] ? toEdit.colorappearance.degree + mods.colorappearance.degree : mods.colorappearance.degree; + toEdit.colorappearance.degree = dontforceSet && options.baBehav[ADDSET_CAT_DEGREE] ? toEdit.colorappearance.degree + mods.colorappearance.degree : mods.colorappearance.degree; } if (colorappearance.autodegree) { @@ -1886,7 +1886,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorappearance.degreeout) { - toEdit.colorappearance.degreeout = mods.colorappearance.degreeout; + toEdit.colorappearance.degreeout = mods.colorappearance.degreeout; } if (colorappearance.autodegreeout) { @@ -1894,95 +1894,95 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (colorappearance.surround) { - toEdit.colorappearance.surround = mods.colorappearance.surround; + toEdit.colorappearance.surround = mods.colorappearance.surround; } if (colorappearance.surrsrc) { - toEdit.colorappearance.surrsrc = mods.colorappearance.surrsrc; + toEdit.colorappearance.surrsrc = mods.colorappearance.surrsrc; } if (colorappearance.autoadapscen) { - toEdit.colorappearance.autoadapscen = mods.colorappearance.autoadapscen; + toEdit.colorappearance.autoadapscen = mods.colorappearance.autoadapscen; } if (colorappearance.adapscen) { - toEdit.colorappearance.adapscen = dontforceSet && options.baBehav[ADDSET_CAT_ADAPTSCENE] ? toEdit.colorappearance.adapscen + mods.colorappearance.adapscen : mods.colorappearance.adapscen; + toEdit.colorappearance.adapscen = dontforceSet && options.baBehav[ADDSET_CAT_ADAPTSCENE] ? toEdit.colorappearance.adapscen + mods.colorappearance.adapscen : mods.colorappearance.adapscen; } if (colorappearance.autoybscen) { - toEdit.colorappearance.autoybscen = mods.colorappearance.autoybscen; + toEdit.colorappearance.autoybscen = mods.colorappearance.autoybscen; } if (colorappearance.ybscen) { - toEdit.colorappearance.ybscen = mods.colorappearance.ybscen; + toEdit.colorappearance.ybscen = mods.colorappearance.ybscen; } if (colorappearance.adaplum) { - toEdit.colorappearance.adaplum = dontforceSet && options.baBehav[ADDSET_CAT_ADAPTVIEWING] ? toEdit.colorappearance.adaplum + mods.colorappearance.adaplum : mods.colorappearance.adaplum; + toEdit.colorappearance.adaplum = dontforceSet && options.baBehav[ADDSET_CAT_ADAPTVIEWING] ? toEdit.colorappearance.adaplum + mods.colorappearance.adaplum : mods.colorappearance.adaplum; } if (colorappearance.badpixsl) { - toEdit.colorappearance.badpixsl = dontforceSet && options.baBehav[ADDSET_CAT_BADPIX] ? toEdit.colorappearance.badpixsl + mods.colorappearance.badpixsl : mods.colorappearance.badpixsl; + toEdit.colorappearance.badpixsl = dontforceSet && options.baBehav[ADDSET_CAT_BADPIX] ? toEdit.colorappearance.badpixsl + mods.colorappearance.badpixsl : mods.colorappearance.badpixsl; } if (colorappearance.wbmodel) { - toEdit.colorappearance.wbmodel = mods.colorappearance.wbmodel; + toEdit.colorappearance.wbmodel = mods.colorappearance.wbmodel; } if (colorappearance.algo) { - toEdit.colorappearance.algo = mods.colorappearance.algo; + toEdit.colorappearance.algo = mods.colorappearance.algo; } if (colorappearance.tempout) { - toEdit.colorappearance.tempout = mods.colorappearance.tempout; + toEdit.colorappearance.tempout = mods.colorappearance.tempout; } if (colorappearance.greenout) { - toEdit.colorappearance.greenout = mods.colorappearance.greenout; + toEdit.colorappearance.greenout = mods.colorappearance.greenout; } if (colorappearance.tempsc) { - toEdit.colorappearance.tempsc = mods.colorappearance.tempsc; + toEdit.colorappearance.tempsc = mods.colorappearance.tempsc; } if (colorappearance.greensc) { - toEdit.colorappearance.greensc = mods.colorappearance.greensc; + toEdit.colorappearance.greensc = mods.colorappearance.greensc; } if (colorappearance.ybout) { - toEdit.colorappearance.ybout = mods.colorappearance.ybout; + toEdit.colorappearance.ybout = mods.colorappearance.ybout; } if (colorappearance.jlight) { - toEdit.colorappearance.jlight = dontforceSet && options.baBehav[ADDSET_CAT_LIGHT] ? toEdit.colorappearance.jlight + mods.colorappearance.jlight : mods.colorappearance.jlight; + toEdit.colorappearance.jlight = dontforceSet && options.baBehav[ADDSET_CAT_LIGHT] ? toEdit.colorappearance.jlight + mods.colorappearance.jlight : mods.colorappearance.jlight; } if (colorappearance.qbright) { - toEdit.colorappearance.qbright = dontforceSet && options.baBehav[ADDSET_CAT_BRIGHT] ? toEdit.colorappearance.qbright + mods.colorappearance.qbright : mods.colorappearance.qbright; + toEdit.colorappearance.qbright = dontforceSet && options.baBehav[ADDSET_CAT_BRIGHT] ? toEdit.colorappearance.qbright + mods.colorappearance.qbright : mods.colorappearance.qbright; } if (colorappearance.chroma) { - toEdit.colorappearance.chroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA] ? toEdit.colorappearance.chroma + mods.colorappearance.chroma : mods.colorappearance.chroma; + toEdit.colorappearance.chroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA] ? toEdit.colorappearance.chroma + mods.colorappearance.chroma : mods.colorappearance.chroma; } if (colorappearance.schroma) { - toEdit.colorappearance.schroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA_S] ? toEdit.colorappearance.schroma + mods.colorappearance.schroma : mods.colorappearance.schroma; + toEdit.colorappearance.schroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA_S] ? toEdit.colorappearance.schroma + mods.colorappearance.schroma : mods.colorappearance.schroma; } if (colorappearance.mchroma) { - toEdit.colorappearance.mchroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA_M] ? toEdit.colorappearance.mchroma + mods.colorappearance.mchroma : mods.colorappearance.mchroma; + toEdit.colorappearance.mchroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA_M] ? toEdit.colorappearance.mchroma + mods.colorappearance.mchroma : mods.colorappearance.mchroma; } if (colorappearance.contrast) { - toEdit.colorappearance.contrast = dontforceSet && options.baBehav[ADDSET_CAT_CONTRAST] ? toEdit.colorappearance.contrast + mods.colorappearance.contrast : mods.colorappearance.contrast; + toEdit.colorappearance.contrast = dontforceSet && options.baBehav[ADDSET_CAT_CONTRAST] ? toEdit.colorappearance.contrast + mods.colorappearance.contrast : mods.colorappearance.contrast; } if (colorappearance.qcontrast) { - toEdit.colorappearance.qcontrast = dontforceSet && options.baBehav[ADDSET_CAT_CONTRAST_Q] ? toEdit.colorappearance.qcontrast + mods.colorappearance.qcontrast : mods.colorappearance.qcontrast; + toEdit.colorappearance.qcontrast = dontforceSet && options.baBehav[ADDSET_CAT_CONTRAST_Q] ? toEdit.colorappearance.qcontrast + mods.colorappearance.qcontrast : mods.colorappearance.qcontrast; } if (colorappearance.colorh) { - toEdit.colorappearance.colorh = dontforceSet && options.baBehav[ADDSET_CAT_HUE] ? toEdit.colorappearance.colorh + mods.colorappearance.colorh : mods.colorappearance.colorh; + toEdit.colorappearance.colorh = dontforceSet && options.baBehav[ADDSET_CAT_HUE] ? toEdit.colorappearance.colorh + mods.colorappearance.colorh : mods.colorappearance.colorh; } if (colorappearance.rstprotection) { @@ -2008,47 +2008,47 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng // if (colorappearance.sharpcie) toEdit.colorappearance.sharpcie = mods.colorappearance.sharpcie; if (impulseDenoise.enabled) { - toEdit.impulseDenoise.enabled = mods.impulseDenoise.enabled; + toEdit.impulseDenoise.enabled = mods.impulseDenoise.enabled; } if (impulseDenoise.thresh) { - toEdit.impulseDenoise.thresh = mods.impulseDenoise.thresh; + toEdit.impulseDenoise.thresh = mods.impulseDenoise.thresh; } if (dirpyrDenoise.enabled) { - toEdit.dirpyrDenoise.enabled = mods.dirpyrDenoise.enabled; + toEdit.dirpyrDenoise.enabled = mods.dirpyrDenoise.enabled; } if (dirpyrDenoise.enhance) { - toEdit.dirpyrDenoise.enhance = mods.dirpyrDenoise.enhance; + toEdit.dirpyrDenoise.enhance = mods.dirpyrDenoise.enhance; } if (dirpyrDenoise.median) { - toEdit.dirpyrDenoise.median = mods.dirpyrDenoise.median; + toEdit.dirpyrDenoise.median = mods.dirpyrDenoise.median; } if (dirpyrDenoise.luma) { - toEdit.dirpyrDenoise.luma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMA] ? toEdit.dirpyrDenoise.luma + mods.dirpyrDenoise.luma : mods.dirpyrDenoise.luma; + toEdit.dirpyrDenoise.luma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMA] ? toEdit.dirpyrDenoise.luma + mods.dirpyrDenoise.luma : mods.dirpyrDenoise.luma; } if (dirpyrDenoise.lcurve) { - toEdit.dirpyrDenoise.lcurve = mods.dirpyrDenoise.lcurve; + toEdit.dirpyrDenoise.lcurve = mods.dirpyrDenoise.lcurve; } if (dirpyrDenoise.cccurve) { - toEdit.dirpyrDenoise.cccurve = mods.dirpyrDenoise.cccurve; + toEdit.dirpyrDenoise.cccurve = mods.dirpyrDenoise.cccurve; } if (dirpyrDenoise.Ldetail) { - toEdit.dirpyrDenoise.Ldetail = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMDET] ? toEdit.dirpyrDenoise.Ldetail + mods.dirpyrDenoise.Ldetail : mods.dirpyrDenoise.Ldetail; + toEdit.dirpyrDenoise.Ldetail = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMDET] ? toEdit.dirpyrDenoise.Ldetail + mods.dirpyrDenoise.Ldetail : mods.dirpyrDenoise.Ldetail; } if (dirpyrDenoise.chroma) { - toEdit.dirpyrDenoise.chroma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMA] ? toEdit.dirpyrDenoise.chroma + mods.dirpyrDenoise.chroma : mods.dirpyrDenoise.chroma; + toEdit.dirpyrDenoise.chroma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMA] ? toEdit.dirpyrDenoise.chroma + mods.dirpyrDenoise.chroma : mods.dirpyrDenoise.chroma; } if (dirpyrDenoise.redchro) { - toEdit.dirpyrDenoise.redchro = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMARED] ? toEdit.dirpyrDenoise.redchro + mods.dirpyrDenoise.redchro : mods.dirpyrDenoise.redchro; + toEdit.dirpyrDenoise.redchro = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMARED] ? toEdit.dirpyrDenoise.redchro + mods.dirpyrDenoise.redchro : mods.dirpyrDenoise.redchro; } if (dirpyrDenoise.bluechro) { @@ -2056,68 +2056,68 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (dirpyrDenoise.gamma) { - toEdit.dirpyrDenoise.gamma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_GAMMA] ? toEdit.dirpyrDenoise.gamma + mods.dirpyrDenoise.gamma : mods.dirpyrDenoise.gamma; + toEdit.dirpyrDenoise.gamma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_GAMMA] ? toEdit.dirpyrDenoise.gamma + mods.dirpyrDenoise.gamma : mods.dirpyrDenoise.gamma; } if (dirpyrDenoise.passes) { - toEdit.dirpyrDenoise.passes = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_PASSES] ? toEdit.dirpyrDenoise.passes + mods.dirpyrDenoise.passes : mods.dirpyrDenoise.passes; + toEdit.dirpyrDenoise.passes = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_PASSES] ? toEdit.dirpyrDenoise.passes + mods.dirpyrDenoise.passes : mods.dirpyrDenoise.passes; } -// if (dirpyrDenoise.perform) toEdit.dirpyrDenoise.perform = mods.dirpyrDenoise.perform; +// if (dirpyrDenoise.perform) toEdit.dirpyrDenoise.perform = mods.dirpyrDenoise.perform; if (dirpyrDenoise.dmethod) { - toEdit.dirpyrDenoise.dmethod = mods.dirpyrDenoise.dmethod; + toEdit.dirpyrDenoise.dmethod = mods.dirpyrDenoise.dmethod; } if (dirpyrDenoise.Lmethod) { - toEdit.dirpyrDenoise.Lmethod = mods.dirpyrDenoise.Lmethod; + toEdit.dirpyrDenoise.Lmethod = mods.dirpyrDenoise.Lmethod; } if (dirpyrDenoise.Cmethod) { - toEdit.dirpyrDenoise.Cmethod = mods.dirpyrDenoise.Cmethod; + toEdit.dirpyrDenoise.Cmethod = mods.dirpyrDenoise.Cmethod; } if (dirpyrDenoise.C2method) { - toEdit.dirpyrDenoise.C2method = mods.dirpyrDenoise.C2method; + toEdit.dirpyrDenoise.C2method = mods.dirpyrDenoise.C2method; } if (dirpyrDenoise.smethod) { - toEdit.dirpyrDenoise.smethod = mods.dirpyrDenoise.smethod; + toEdit.dirpyrDenoise.smethod = mods.dirpyrDenoise.smethod; } if (dirpyrDenoise.medmethod) { - toEdit.dirpyrDenoise.medmethod = mods.dirpyrDenoise.medmethod; + toEdit.dirpyrDenoise.medmethod = mods.dirpyrDenoise.medmethod; } if (dirpyrDenoise.methodmed) { - toEdit.dirpyrDenoise.methodmed = mods.dirpyrDenoise.methodmed; + toEdit.dirpyrDenoise.methodmed = mods.dirpyrDenoise.methodmed; } if (dirpyrDenoise.rgbmethod) { - toEdit.dirpyrDenoise.rgbmethod = mods.dirpyrDenoise.rgbmethod; + toEdit.dirpyrDenoise.rgbmethod = mods.dirpyrDenoise.rgbmethod; } if (epd.enabled) { - toEdit.epd.enabled = mods.epd.enabled; + toEdit.epd.enabled = mods.epd.enabled; } if (epd.strength) { - toEdit.epd.strength = mods.epd.strength; + toEdit.epd.strength = mods.epd.strength; } if (epd.gamma) { - toEdit.epd.gamma = mods.epd.gamma; + toEdit.epd.gamma = mods.epd.gamma; } if (epd.edgeStopping) { - toEdit.epd.edgeStopping = mods.epd.edgeStopping; + toEdit.epd.edgeStopping = mods.epd.edgeStopping; } if (epd.scale) { - toEdit.epd.scale = mods.epd.scale; + toEdit.epd.scale = mods.epd.scale; } if (epd.reweightingIterates) { - toEdit.epd.reweightingIterates = mods.epd.reweightingIterates; + toEdit.epd.reweightingIterates = mods.epd.reweightingIterates; } if (fattal.enabled) { @@ -2137,31 +2137,31 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (sh.enabled) { - toEdit.sh.enabled = mods.sh.enabled; + toEdit.sh.enabled = mods.sh.enabled; } if (sh.highlights) { - toEdit.sh.highlights = dontforceSet && options.baBehav[ADDSET_SH_HIGHLIGHTS] ? toEdit.sh.highlights + mods.sh.highlights : mods.sh.highlights; + toEdit.sh.highlights = dontforceSet && options.baBehav[ADDSET_SH_HIGHLIGHTS] ? toEdit.sh.highlights + mods.sh.highlights : mods.sh.highlights; } if (sh.htonalwidth) { - toEdit.sh.htonalwidth = mods.sh.htonalwidth; + toEdit.sh.htonalwidth = mods.sh.htonalwidth; } if (sh.shadows) { - toEdit.sh.shadows = dontforceSet && options.baBehav[ADDSET_SH_SHADOWS] ? toEdit.sh.shadows + mods.sh.shadows : mods.sh.shadows; + toEdit.sh.shadows = dontforceSet && options.baBehav[ADDSET_SH_SHADOWS] ? toEdit.sh.shadows + mods.sh.shadows : mods.sh.shadows; } if (sh.stonalwidth) { - toEdit.sh.stonalwidth = mods.sh.stonalwidth; + toEdit.sh.stonalwidth = mods.sh.stonalwidth; } if (sh.radius) { - toEdit.sh.radius = mods.sh.radius; + toEdit.sh.radius = mods.sh.radius; } if (sh.lab) { - toEdit.sh.lab = mods.sh.lab; + toEdit.sh.lab = mods.sh.lab; } if (crop.enabled) { @@ -2169,27 +2169,27 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (crop.x) { - toEdit.crop.x = mods.crop.x; + toEdit.crop.x = mods.crop.x; } if (crop.y) { - toEdit.crop.y = mods.crop.y; + toEdit.crop.y = mods.crop.y; } if (crop.w) { - toEdit.crop.w = mods.crop.w; + toEdit.crop.w = mods.crop.w; } if (crop.h) { - toEdit.crop.h = mods.crop.h; + toEdit.crop.h = mods.crop.h; } if (crop.fixratio) { - toEdit.crop.fixratio = mods.crop.fixratio; + toEdit.crop.fixratio = mods.crop.fixratio; } if (crop.ratio) { - toEdit.crop.ratio = mods.crop.ratio; + toEdit.crop.ratio = mods.crop.ratio; } if (crop.orientation) { @@ -2197,51 +2197,51 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (crop.guide) { - toEdit.crop.guide = mods.crop.guide; + toEdit.crop.guide = mods.crop.guide; } if (coarse.rotate) { - toEdit.coarse.rotate = mods.coarse.rotate; + toEdit.coarse.rotate = mods.coarse.rotate; } if (coarse.hflip) { - toEdit.coarse.hflip = mods.coarse.hflip; + toEdit.coarse.hflip = mods.coarse.hflip; } if (coarse.vflip) { - toEdit.coarse.vflip = mods.coarse.vflip; + toEdit.coarse.vflip = mods.coarse.vflip; } if (commonTrans.autofill) { - toEdit.commonTrans.autofill = mods.commonTrans.autofill; + toEdit.commonTrans.autofill = mods.commonTrans.autofill; } if (rotate.degree) { - toEdit.rotate.degree = dontforceSet && options.baBehav[ADDSET_ROTATE_DEGREE] ? toEdit.rotate.degree + mods.rotate.degree : mods.rotate.degree; + toEdit.rotate.degree = dontforceSet && options.baBehav[ADDSET_ROTATE_DEGREE] ? toEdit.rotate.degree + mods.rotate.degree : mods.rotate.degree; } if (distortion.amount) { - toEdit.distortion.amount = dontforceSet && options.baBehav[ADDSET_DIST_AMOUNT] ? toEdit.distortion.amount + mods.distortion.amount : mods.distortion.amount; + toEdit.distortion.amount = dontforceSet && options.baBehav[ADDSET_DIST_AMOUNT] ? toEdit.distortion.amount + mods.distortion.amount : mods.distortion.amount; } if (lensProf.lcMode) { - toEdit.lensProf.lcMode = mods.lensProf.lcMode; + toEdit.lensProf.lcMode = mods.lensProf.lcMode; } if (lensProf.lcpFile) { - toEdit.lensProf.lcpFile = mods.lensProf.lcpFile; + toEdit.lensProf.lcpFile = mods.lensProf.lcpFile; } if (lensProf.useDist) { - toEdit.lensProf.useDist = mods.lensProf.useDist; + toEdit.lensProf.useDist = mods.lensProf.useDist; } if (lensProf.useVign) { - toEdit.lensProf.useVign = mods.lensProf.useVign; + toEdit.lensProf.useVign = mods.lensProf.useVign; } if (lensProf.useCA) { - toEdit.lensProf.useCA = mods.lensProf.useCA; + toEdit.lensProf.useCA = mods.lensProf.useCA; } if (lensProf.lfCameraMake) { @@ -2257,47 +2257,47 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (perspective.horizontal) { - toEdit.perspective.horizontal = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.horizontal + mods.perspective.horizontal : mods.perspective.horizontal; + toEdit.perspective.horizontal = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.horizontal + mods.perspective.horizontal : mods.perspective.horizontal; } if (perspective.vertical) { - toEdit.perspective.vertical = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.vertical + mods.perspective.vertical : mods.perspective.vertical; + toEdit.perspective.vertical = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.vertical + mods.perspective.vertical : mods.perspective.vertical; } if (gradient.enabled) { - toEdit.gradient.enabled = mods.gradient.enabled; + toEdit.gradient.enabled = mods.gradient.enabled; } if (gradient.degree) { - toEdit.gradient.degree = dontforceSet && options.baBehav[ADDSET_GRADIENT_DEGREE] ? toEdit.gradient.degree + mods.gradient.degree : mods.gradient.degree; + toEdit.gradient.degree = dontforceSet && options.baBehav[ADDSET_GRADIENT_DEGREE] ? toEdit.gradient.degree + mods.gradient.degree : mods.gradient.degree; } if (gradient.feather) { - toEdit.gradient.feather = dontforceSet && options.baBehav[ADDSET_GRADIENT_FEATHER] ? toEdit.gradient.feather + mods.gradient.feather : mods.gradient.feather; + toEdit.gradient.feather = dontforceSet && options.baBehav[ADDSET_GRADIENT_FEATHER] ? toEdit.gradient.feather + mods.gradient.feather : mods.gradient.feather; } if (gradient.strength) { - toEdit.gradient.strength = dontforceSet && options.baBehav[ADDSET_GRADIENT_STRENGTH] ? toEdit.gradient.strength + mods.gradient.strength : mods.gradient.strength; + toEdit.gradient.strength = dontforceSet && options.baBehav[ADDSET_GRADIENT_STRENGTH] ? toEdit.gradient.strength + mods.gradient.strength : mods.gradient.strength; } if (gradient.centerX) { - toEdit.gradient.centerX = dontforceSet && options.baBehav[ADDSET_GRADIENT_CENTER] ? toEdit.gradient.centerX + mods.gradient.centerX : mods.gradient.centerX; + toEdit.gradient.centerX = dontforceSet && options.baBehav[ADDSET_GRADIENT_CENTER] ? toEdit.gradient.centerX + mods.gradient.centerX : mods.gradient.centerX; } if (gradient.centerY) { - toEdit.gradient.centerY = dontforceSet && options.baBehav[ADDSET_GRADIENT_CENTER] ? toEdit.gradient.centerY + mods.gradient.centerY : mods.gradient.centerY; + toEdit.gradient.centerY = dontforceSet && options.baBehav[ADDSET_GRADIENT_CENTER] ? toEdit.gradient.centerY + mods.gradient.centerY : mods.gradient.centerY; } if (pcvignette.enabled) { - toEdit.pcvignette.enabled = mods.pcvignette.enabled; + toEdit.pcvignette.enabled = mods.pcvignette.enabled; } if (pcvignette.strength) { - toEdit.pcvignette.strength = dontforceSet && options.baBehav[ADDSET_PCVIGNETTE_STRENGTH] ? toEdit.pcvignette.strength + mods.pcvignette.strength : mods.pcvignette.strength; + toEdit.pcvignette.strength = dontforceSet && options.baBehav[ADDSET_PCVIGNETTE_STRENGTH] ? toEdit.pcvignette.strength + mods.pcvignette.strength : mods.pcvignette.strength; } if (pcvignette.feather) { - toEdit.pcvignette.feather = dontforceSet && options.baBehav[ADDSET_PCVIGNETTE_FEATHER] ? toEdit.pcvignette.feather + mods.pcvignette.feather : mods.pcvignette.feather; + toEdit.pcvignette.feather = dontforceSet && options.baBehav[ADDSET_PCVIGNETTE_FEATHER] ? toEdit.pcvignette.feather + mods.pcvignette.feather : mods.pcvignette.feather; } if (pcvignette.roundness) { @@ -2305,19 +2305,19 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (cacorrection.red) { - toEdit.cacorrection.red = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.red + mods.cacorrection.red : mods.cacorrection.red; + toEdit.cacorrection.red = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.red + mods.cacorrection.red : mods.cacorrection.red; } if (cacorrection.blue) { - toEdit.cacorrection.blue = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.blue + mods.cacorrection.blue : mods.cacorrection.blue; + toEdit.cacorrection.blue = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.blue + mods.cacorrection.blue : mods.cacorrection.blue; } if (vignetting.amount) { - toEdit.vignetting.amount = dontforceSet && options.baBehav[ADDSET_VIGN_AMOUNT] ? toEdit.vignetting.amount + mods.vignetting.amount : mods.vignetting.amount; + toEdit.vignetting.amount = dontforceSet && options.baBehav[ADDSET_VIGN_AMOUNT] ? toEdit.vignetting.amount + mods.vignetting.amount : mods.vignetting.amount; } if (vignetting.radius) { - toEdit.vignetting.radius = dontforceSet && options.baBehav[ADDSET_VIGN_RADIUS] ? toEdit.vignetting.radius + mods.vignetting.radius : mods.vignetting.radius; + toEdit.vignetting.radius = dontforceSet && options.baBehav[ADDSET_VIGN_RADIUS] ? toEdit.vignetting.radius + mods.vignetting.radius : mods.vignetting.radius; } if (vignetting.strength) { @@ -2338,92 +2338,92 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng for (int i = 0; i < 3; i++) { if (chmixer.red[i]) { - toEdit.chmixer.red[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.red[i] + mods.chmixer.red[i] : mods.chmixer.red[i]; + toEdit.chmixer.red[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.red[i] + mods.chmixer.red[i] : mods.chmixer.red[i]; } if (chmixer.green[i]) { - toEdit.chmixer.green[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.green[i] + mods.chmixer.green[i] : mods.chmixer.green[i]; + toEdit.chmixer.green[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.green[i] + mods.chmixer.green[i] : mods.chmixer.green[i]; } if (chmixer.blue[i]) { - toEdit.chmixer.blue[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.blue[i] + mods.chmixer.blue[i] : mods.chmixer.blue[i]; + toEdit.chmixer.blue[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.blue[i] + mods.chmixer.blue[i] : mods.chmixer.blue[i]; } } if (blackwhite.enabled) { - toEdit.blackwhite.enabled = mods.blackwhite.enabled; + toEdit.blackwhite.enabled = mods.blackwhite.enabled; } if (blackwhite.method) { - toEdit.blackwhite.method = mods.blackwhite.method; + toEdit.blackwhite.method = mods.blackwhite.method; } if (blackwhite.luminanceCurve) { - toEdit.blackwhite.luminanceCurve = mods.blackwhite.luminanceCurve; + toEdit.blackwhite.luminanceCurve = mods.blackwhite.luminanceCurve; } if (blackwhite.autoc) { - toEdit.blackwhite.autoc = mods.blackwhite.autoc; + toEdit.blackwhite.autoc = mods.blackwhite.autoc; } if (blackwhite.setting) { - toEdit.blackwhite.setting = mods.blackwhite.setting; + toEdit.blackwhite.setting = mods.blackwhite.setting; } if (blackwhite.enabledcc) { - toEdit.blackwhite.enabledcc = mods.blackwhite.enabledcc; + toEdit.blackwhite.enabledcc = mods.blackwhite.enabledcc; } if (blackwhite.filter) { - toEdit.blackwhite.filter = mods.blackwhite.filter; + toEdit.blackwhite.filter = mods.blackwhite.filter; } if (blackwhite.mixerRed) { - toEdit.blackwhite.mixerRed = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerRed + mods.blackwhite.mixerRed : mods.blackwhite.mixerRed; + toEdit.blackwhite.mixerRed = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerRed + mods.blackwhite.mixerRed : mods.blackwhite.mixerRed; } if (blackwhite.mixerOrange) { - toEdit.blackwhite.mixerOrange = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerOrange + mods.blackwhite.mixerOrange : mods.blackwhite.mixerOrange; + toEdit.blackwhite.mixerOrange = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerOrange + mods.blackwhite.mixerOrange : mods.blackwhite.mixerOrange; } if (blackwhite.mixerYellow) { - toEdit.blackwhite.mixerYellow = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerYellow + mods.blackwhite.mixerYellow : mods.blackwhite.mixerYellow; + toEdit.blackwhite.mixerYellow = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerYellow + mods.blackwhite.mixerYellow : mods.blackwhite.mixerYellow; } if (blackwhite.mixerGreen) { - toEdit.blackwhite.mixerGreen = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerGreen + mods.blackwhite.mixerGreen : mods.blackwhite.mixerGreen; + toEdit.blackwhite.mixerGreen = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerGreen + mods.blackwhite.mixerGreen : mods.blackwhite.mixerGreen; } if (blackwhite.mixerCyan) { - toEdit.blackwhite.mixerCyan = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerCyan + mods.blackwhite.mixerCyan : mods.blackwhite.mixerCyan; + toEdit.blackwhite.mixerCyan = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerCyan + mods.blackwhite.mixerCyan : mods.blackwhite.mixerCyan; } if (blackwhite.mixerBlue) { - toEdit.blackwhite.mixerBlue = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerBlue + mods.blackwhite.mixerBlue : mods.blackwhite.mixerBlue; + toEdit.blackwhite.mixerBlue = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerBlue + mods.blackwhite.mixerBlue : mods.blackwhite.mixerBlue; } if (blackwhite.mixerMagenta) { - toEdit.blackwhite.mixerMagenta = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerMagenta + mods.blackwhite.mixerMagenta : mods.blackwhite.mixerMagenta; + toEdit.blackwhite.mixerMagenta = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerMagenta + mods.blackwhite.mixerMagenta : mods.blackwhite.mixerMagenta; } if (blackwhite.mixerPurple) { - toEdit.blackwhite.mixerPurple = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerPurple + mods.blackwhite.mixerPurple : mods.blackwhite.mixerPurple; + toEdit.blackwhite.mixerPurple = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerPurple + mods.blackwhite.mixerPurple : mods.blackwhite.mixerPurple; } if (blackwhite.gammaRed) { - toEdit.blackwhite.gammaRed = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaRed + mods.blackwhite.gammaRed : mods.blackwhite.gammaRed; + toEdit.blackwhite.gammaRed = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaRed + mods.blackwhite.gammaRed : mods.blackwhite.gammaRed; } if (blackwhite.gammaGreen) { - toEdit.blackwhite.gammaGreen = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaGreen + mods.blackwhite.gammaGreen : mods.blackwhite.gammaGreen; + toEdit.blackwhite.gammaGreen = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaGreen + mods.blackwhite.gammaGreen : mods.blackwhite.gammaGreen; } if (blackwhite.gammaBlue) { - toEdit.blackwhite.gammaBlue = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaBlue + mods.blackwhite.gammaBlue : mods.blackwhite.gammaBlue; + toEdit.blackwhite.gammaBlue = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaBlue + mods.blackwhite.gammaBlue : mods.blackwhite.gammaBlue; } if (blackwhite.beforeCurve) { - toEdit.blackwhite.beforeCurve = mods.blackwhite.beforeCurve; + toEdit.blackwhite.beforeCurve = mods.blackwhite.beforeCurve; } if (blackwhite.beforeCurveMode) { @@ -2431,19 +2431,19 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (blackwhite.afterCurve) { - toEdit.blackwhite.afterCurve = mods.blackwhite.afterCurve; + toEdit.blackwhite.afterCurve = mods.blackwhite.afterCurve; } if (blackwhite.afterCurveMode) { - toEdit.blackwhite.afterCurveMode = mods.blackwhite.afterCurveMode; + toEdit.blackwhite.afterCurveMode = mods.blackwhite.afterCurveMode; } if (blackwhite.algo) { - toEdit.blackwhite.algo = mods.blackwhite.algo; + toEdit.blackwhite.algo = mods.blackwhite.algo; } if (resize.scale) { - toEdit.resize.scale = dontforceSet && options.baBehav[ADDSET_RESIZE_SCALE] ? toEdit.resize.scale + mods.resize.scale : mods.resize.scale; + toEdit.resize.scale = dontforceSet && options.baBehav[ADDSET_RESIZE_SCALE] ? toEdit.resize.scale + mods.resize.scale : mods.resize.scale; } if (resize.appliesTo) { @@ -2451,23 +2451,23 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (resize.method) { - toEdit.resize.method = mods.resize.method; + toEdit.resize.method = mods.resize.method; } if (resize.dataspec) { - toEdit.resize.dataspec = mods.resize.dataspec; + toEdit.resize.dataspec = mods.resize.dataspec; } if (resize.width) { - toEdit.resize.width = mods.resize.width; + toEdit.resize.width = mods.resize.width; } if (resize.height) { - toEdit.resize.height = mods.resize.height; + toEdit.resize.height = mods.resize.height; } if (resize.enabled) { - toEdit.resize.enabled = mods.resize.enabled; + toEdit.resize.enabled = mods.resize.enabled; } if (resize.allowUpscaling) { @@ -2527,47 +2527,47 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (raw.bayersensor.method) { - toEdit.raw.bayersensor.method = mods.raw.bayersensor.method; + toEdit.raw.bayersensor.method = mods.raw.bayersensor.method; } if (raw.bayersensor.border) { - toEdit.raw.bayersensor.border = mods.raw.bayersensor.border; + toEdit.raw.bayersensor.border = mods.raw.bayersensor.border; } if (raw.bayersensor.imageNum) { - toEdit.raw.bayersensor.imageNum = mods.raw.bayersensor.imageNum; + toEdit.raw.bayersensor.imageNum = mods.raw.bayersensor.imageNum; } if (raw.bayersensor.ccSteps) { - toEdit.raw.bayersensor.ccSteps = mods.raw.bayersensor.ccSteps; + toEdit.raw.bayersensor.ccSteps = mods.raw.bayersensor.ccSteps; } if (raw.bayersensor.exBlack0) { - toEdit.raw.bayersensor.black0 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black0 + mods.raw.bayersensor.black0 : mods.raw.bayersensor.black0; + toEdit.raw.bayersensor.black0 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black0 + mods.raw.bayersensor.black0 : mods.raw.bayersensor.black0; } if (raw.bayersensor.exBlack1) { - toEdit.raw.bayersensor.black1 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black1 + mods.raw.bayersensor.black1 : mods.raw.bayersensor.black1; + toEdit.raw.bayersensor.black1 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black1 + mods.raw.bayersensor.black1 : mods.raw.bayersensor.black1; } if (raw.bayersensor.exBlack2) { - toEdit.raw.bayersensor.black2 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black2 + mods.raw.bayersensor.black2 : mods.raw.bayersensor.black2; + toEdit.raw.bayersensor.black2 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black2 + mods.raw.bayersensor.black2 : mods.raw.bayersensor.black2; } if (raw.bayersensor.exBlack3) { - toEdit.raw.bayersensor.black3 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black3 + mods.raw.bayersensor.black3 : mods.raw.bayersensor.black3; + toEdit.raw.bayersensor.black3 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black3 + mods.raw.bayersensor.black3 : mods.raw.bayersensor.black3; } if (raw.bayersensor.exTwoGreen) { - toEdit.raw.bayersensor.twogreen = mods.raw.bayersensor.twogreen; + toEdit.raw.bayersensor.twogreen = mods.raw.bayersensor.twogreen; } if (raw.bayersensor.dcbIterations) { - toEdit.raw.bayersensor.dcb_iterations = mods.raw.bayersensor.dcb_iterations; + toEdit.raw.bayersensor.dcb_iterations = mods.raw.bayersensor.dcb_iterations; } if (raw.bayersensor.dcbEnhance) { - toEdit.raw.bayersensor.dcb_enhance = mods.raw.bayersensor.dcb_enhance; + toEdit.raw.bayersensor.dcb_enhance = mods.raw.bayersensor.dcb_enhance; } if (raw.bayersensor.lmmseIterations) { @@ -2639,11 +2639,11 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (raw.bayersensor.greenEq) { - toEdit.raw.bayersensor.greenthresh = dontforceSet && options.baBehav[ADDSET_PREPROCESS_GREENEQUIL] ? toEdit.raw.bayersensor.greenthresh + mods.raw.bayersensor.greenthresh : mods.raw.bayersensor.greenthresh; + toEdit.raw.bayersensor.greenthresh = dontforceSet && options.baBehav[ADDSET_PREPROCESS_GREENEQUIL] ? toEdit.raw.bayersensor.greenthresh + mods.raw.bayersensor.greenthresh : mods.raw.bayersensor.greenthresh; } if (raw.bayersensor.linenoise) { - toEdit.raw.bayersensor.linenoise = dontforceSet && options.baBehav[ADDSET_PREPROCESS_LINEDENOISE] ? toEdit.raw.bayersensor.linenoise + mods.raw.bayersensor.linenoise : mods.raw.bayersensor.linenoise; + toEdit.raw.bayersensor.linenoise = dontforceSet && options.baBehav[ADDSET_PREPROCESS_LINEDENOISE] ? toEdit.raw.bayersensor.linenoise + mods.raw.bayersensor.linenoise : mods.raw.bayersensor.linenoise; } if (raw.bayersensor.linenoiseDirection) { @@ -2655,67 +2655,67 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (raw.xtranssensor.method) { - toEdit.raw.xtranssensor.method = mods.raw.xtranssensor.method; + toEdit.raw.xtranssensor.method = mods.raw.xtranssensor.method; } if (raw.xtranssensor.dualDemosaicAutoContrast) { - toEdit.raw.xtranssensor.dualDemosaicAutoContrast = mods.raw.xtranssensor.dualDemosaicAutoContrast; + toEdit.raw.xtranssensor.dualDemosaicAutoContrast = mods.raw.xtranssensor.dualDemosaicAutoContrast; } if (raw.xtranssensor.dualDemosaicContrast) { - toEdit.raw.xtranssensor.dualDemosaicContrast = mods.raw.xtranssensor.dualDemosaicContrast; + toEdit.raw.xtranssensor.dualDemosaicContrast = mods.raw.xtranssensor.dualDemosaicContrast; } if (raw.xtranssensor.ccSteps) { - toEdit.raw.xtranssensor.ccSteps = mods.raw.xtranssensor.ccSteps; + toEdit.raw.xtranssensor.ccSteps = mods.raw.xtranssensor.ccSteps; } if (raw.xtranssensor.border) { - toEdit.raw.xtranssensor.border = mods.raw.xtranssensor.border; + toEdit.raw.xtranssensor.border = mods.raw.xtranssensor.border; } if (raw.xtranssensor.exBlackRed) { - toEdit.raw.xtranssensor.blackred = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackred + mods.raw.xtranssensor.blackred : mods.raw.xtranssensor.blackred; + toEdit.raw.xtranssensor.blackred = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackred + mods.raw.xtranssensor.blackred : mods.raw.xtranssensor.blackred; } if (raw.xtranssensor.exBlackGreen) { - toEdit.raw.xtranssensor.blackgreen = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackgreen + mods.raw.xtranssensor.blackgreen : mods.raw.xtranssensor.blackgreen; + toEdit.raw.xtranssensor.blackgreen = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackgreen + mods.raw.xtranssensor.blackgreen : mods.raw.xtranssensor.blackgreen; } if (raw.xtranssensor.exBlackBlue) { - toEdit.raw.xtranssensor.blackblue = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackblue + mods.raw.xtranssensor.blackblue : mods.raw.xtranssensor.blackblue; + toEdit.raw.xtranssensor.blackblue = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackblue + mods.raw.xtranssensor.blackblue : mods.raw.xtranssensor.blackblue; } if (raw.ca_autocorrect) { - toEdit.raw.ca_autocorrect = mods.raw.ca_autocorrect; + toEdit.raw.ca_autocorrect = mods.raw.ca_autocorrect; } if (raw.ca_avoidcolourshift) { - toEdit.raw.ca_avoidcolourshift = mods.raw.ca_avoidcolourshift; + toEdit.raw.ca_avoidcolourshift = mods.raw.ca_avoidcolourshift; } if (raw.caautoiterations) { - toEdit.raw.caautoiterations = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.caautoiterations + mods.raw.caautoiterations : mods.raw.caautoiterations; + toEdit.raw.caautoiterations = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.caautoiterations + mods.raw.caautoiterations : mods.raw.caautoiterations; } if (raw.cared) { - toEdit.raw.cared = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cared + mods.raw.cared : mods.raw.cared; + toEdit.raw.cared = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cared + mods.raw.cared : mods.raw.cared; } if (raw.cablue) { - toEdit.raw.cablue = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cablue + mods.raw.cablue : mods.raw.cablue; + toEdit.raw.cablue = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cablue + mods.raw.cablue : mods.raw.cablue; } if (raw.exPos) { - toEdit.raw.expos = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_LINEAR] ? toEdit.raw.expos + mods.raw.expos : mods.raw.expos; + toEdit.raw.expos = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_LINEAR] ? toEdit.raw.expos + mods.raw.expos : mods.raw.expos; } if (raw.hotPixelFilter) { - toEdit.raw.hotPixelFilter = mods.raw.hotPixelFilter; + toEdit.raw.hotPixelFilter = mods.raw.hotPixelFilter; } if (raw.deadPixelFilter) { - toEdit.raw.deadPixelFilter = mods.raw.deadPixelFilter; + toEdit.raw.deadPixelFilter = mods.raw.deadPixelFilter; } if (raw.hotdeadpix_thresh) { @@ -2723,27 +2723,27 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (raw.darkFrame) { - toEdit.raw.dark_frame = mods.raw.dark_frame; + toEdit.raw.dark_frame = mods.raw.dark_frame; } if (raw.df_autoselect) { - toEdit.raw.df_autoselect = mods.raw.df_autoselect; + toEdit.raw.df_autoselect = mods.raw.df_autoselect; } if (raw.ff_file) { - toEdit.raw.ff_file = mods.raw.ff_file; + toEdit.raw.ff_file = mods.raw.ff_file; } if (raw.ff_AutoSelect) { - toEdit.raw.ff_AutoSelect = mods.raw.ff_AutoSelect; + toEdit.raw.ff_AutoSelect = mods.raw.ff_AutoSelect; } if (raw.ff_BlurRadius) { - toEdit.raw.ff_BlurRadius = mods.raw.ff_BlurRadius; + toEdit.raw.ff_BlurRadius = mods.raw.ff_BlurRadius; } if (raw.ff_BlurType) { - toEdit.raw.ff_BlurType = mods.raw.ff_BlurType; + toEdit.raw.ff_BlurType = mods.raw.ff_BlurType; } if (raw.ff_AutoClipControl) { @@ -2751,135 +2751,135 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (raw.ff_clipControl) { - toEdit.raw.ff_clipControl = dontforceSet && options.baBehav[ADDSET_RAWFFCLIPCONTROL] ? toEdit.raw.ff_clipControl + mods.raw.ff_clipControl : mods.raw.ff_clipControl; + toEdit.raw.ff_clipControl = dontforceSet && options.baBehav[ADDSET_RAWFFCLIPCONTROL] ? toEdit.raw.ff_clipControl + mods.raw.ff_clipControl : mods.raw.ff_clipControl; } if (wavelet.enabled) { - toEdit.wavelet.enabled = mods.wavelet.enabled; + toEdit.wavelet.enabled = mods.wavelet.enabled; } if (wavelet.strength) { - toEdit.wavelet.strength = mods.wavelet.strength; + toEdit.wavelet.strength = mods.wavelet.strength; } if (wavelet.balance) { - toEdit.wavelet.balance = mods.wavelet.balance; + toEdit.wavelet.balance = mods.wavelet.balance; } if (wavelet.iter) { - toEdit.wavelet.iter = mods.wavelet.iter; + toEdit.wavelet.iter = mods.wavelet.iter; } if (wavelet.median) { - toEdit.wavelet.median = mods.wavelet.median; + toEdit.wavelet.median = mods.wavelet.median; } if (wavelet.medianlev) { - toEdit.wavelet.medianlev = mods.wavelet.medianlev; + toEdit.wavelet.medianlev = mods.wavelet.medianlev; } if (wavelet.linkedg) { - toEdit.wavelet.linkedg = mods.wavelet.linkedg; + toEdit.wavelet.linkedg = mods.wavelet.linkedg; } if (wavelet.cbenab) { - toEdit.wavelet.cbenab = mods.wavelet.cbenab; + toEdit.wavelet.cbenab = mods.wavelet.cbenab; } if (wavelet.greenhigh) { - toEdit.wavelet.greenhigh = mods.wavelet.greenhigh; + toEdit.wavelet.greenhigh = mods.wavelet.greenhigh; } if (wavelet.bluehigh) { - toEdit.wavelet.bluehigh = mods.wavelet.bluehigh; + toEdit.wavelet.bluehigh = mods.wavelet.bluehigh; } if (wavelet.greenmed) { - toEdit.wavelet.greenmed = mods.wavelet.greenmed; + toEdit.wavelet.greenmed = mods.wavelet.greenmed; } if (wavelet.bluemed) { - toEdit.wavelet.bluemed = mods.wavelet.bluemed; + toEdit.wavelet.bluemed = mods.wavelet.bluemed; } if (wavelet.greenlow) { - toEdit.wavelet.greenlow = mods.wavelet.greenlow; + toEdit.wavelet.greenlow = mods.wavelet.greenlow; } if (wavelet.bluelow) { - toEdit.wavelet.bluelow = mods.wavelet.bluelow; + toEdit.wavelet.bluelow = mods.wavelet.bluelow; } if (wavelet.lipst) { - toEdit.wavelet.lipst = mods.wavelet.lipst; + toEdit.wavelet.lipst = mods.wavelet.lipst; } if (wavelet.Medgreinf) { - toEdit.wavelet.Medgreinf = mods.wavelet.Medgreinf; + toEdit.wavelet.Medgreinf = mods.wavelet.Medgreinf; } if (wavelet.avoid) { - toEdit.wavelet.avoid = mods.wavelet.avoid; + toEdit.wavelet.avoid = mods.wavelet.avoid; } if (wavelet.tmr) { - toEdit.wavelet.tmr = mods.wavelet.tmr; + toEdit.wavelet.tmr = mods.wavelet.tmr; } if (wavelet.Lmethod) { - toEdit.wavelet.Lmethod = mods.wavelet.Lmethod; + toEdit.wavelet.Lmethod = mods.wavelet.Lmethod; } if (wavelet.CLmethod) { - toEdit.wavelet.CLmethod = mods.wavelet.CLmethod; + toEdit.wavelet.CLmethod = mods.wavelet.CLmethod; } if (wavelet.Backmethod) { - toEdit.wavelet.Backmethod = mods.wavelet.Backmethod; + toEdit.wavelet.Backmethod = mods.wavelet.Backmethod; } if (wavelet.Tilesmethod) { - toEdit.wavelet.Tilesmethod = mods.wavelet.Tilesmethod; + toEdit.wavelet.Tilesmethod = mods.wavelet.Tilesmethod; } if (wavelet.daubcoeffmethod) { - toEdit.wavelet.daubcoeffmethod = mods.wavelet.daubcoeffmethod; + toEdit.wavelet.daubcoeffmethod = mods.wavelet.daubcoeffmethod; } if (wavelet.CHmethod) { - toEdit.wavelet.CHmethod = mods.wavelet.CHmethod; + toEdit.wavelet.CHmethod = mods.wavelet.CHmethod; } if (wavelet.CHSLmethod) { - toEdit.wavelet.CHSLmethod = mods.wavelet.CHSLmethod; + toEdit.wavelet.CHSLmethod = mods.wavelet.CHSLmethod; } if (wavelet.EDmethod) { - toEdit.wavelet.EDmethod = mods.wavelet.EDmethod; + toEdit.wavelet.EDmethod = mods.wavelet.EDmethod; } if (wavelet.NPmethod) { - toEdit.wavelet.NPmethod = mods.wavelet.NPmethod; + toEdit.wavelet.NPmethod = mods.wavelet.NPmethod; } if (wavelet.BAmethod) { - toEdit.wavelet.BAmethod = mods.wavelet.BAmethod; + toEdit.wavelet.BAmethod = mods.wavelet.BAmethod; } if (wavelet.TMmethod) { - toEdit.wavelet.TMmethod = mods.wavelet.TMmethod; + toEdit.wavelet.TMmethod = mods.wavelet.TMmethod; } if (wavelet.HSmethod) { - toEdit.wavelet.HSmethod = mods.wavelet.HSmethod; + toEdit.wavelet.HSmethod = mods.wavelet.HSmethod; } if (wavelet.Dirmethod) { - toEdit.wavelet.Dirmethod = mods.wavelet.Dirmethod; + toEdit.wavelet.Dirmethod = mods.wavelet.Dirmethod; } if (wavelet.edgthresh) { - toEdit.wavelet.edgthresh = mods.wavelet.edgthresh; + toEdit.wavelet.edgthresh = mods.wavelet.edgthresh; } if (wavelet.sky) { @@ -2895,39 +2895,39 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (wavelet.sup) { - toEdit.wavelet.sup = mods.wavelet.sup; + toEdit.wavelet.sup = mods.wavelet.sup; } if (wavelet.hllev) { - toEdit.wavelet.hllev = mods.wavelet.hllev; + toEdit.wavelet.hllev = mods.wavelet.hllev; } if (wavelet.bllev) { - toEdit.wavelet.bllev = mods.wavelet.bllev; + toEdit.wavelet.bllev = mods.wavelet.bllev; } if (wavelet.edgcont) { - toEdit.wavelet.edgcont = mods.wavelet.edgcont; + toEdit.wavelet.edgcont = mods.wavelet.edgcont; } if (wavelet.level0noise) { - toEdit.wavelet.level0noise = mods.wavelet.level0noise; + toEdit.wavelet.level0noise = mods.wavelet.level0noise; } if (wavelet.level1noise) { - toEdit.wavelet.level1noise = mods.wavelet.level1noise; + toEdit.wavelet.level1noise = mods.wavelet.level1noise; } if (wavelet.level2noise) { - toEdit.wavelet.level2noise = mods.wavelet.level2noise; + toEdit.wavelet.level2noise = mods.wavelet.level2noise; } if (wavelet.level3noise) { - toEdit.wavelet.level3noise = mods.wavelet.level3noise; + toEdit.wavelet.level3noise = mods.wavelet.level3noise; } if (wavelet.pastlev) { - toEdit.wavelet.pastlev = mods.wavelet.pastlev; + toEdit.wavelet.pastlev = mods.wavelet.pastlev; } if (wavelet.satlev) { @@ -2935,7 +2935,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (wavelet.ccwcurve) { - toEdit.wavelet.ccwcurve = mods.wavelet.ccwcurve; + toEdit.wavelet.ccwcurve = mods.wavelet.ccwcurve; } if (wavelet.opacityCurveRG) { @@ -2947,7 +2947,7 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (wavelet.opacityCurveW) { - toEdit.wavelet.opacityCurveW = mods.wavelet.opacityCurveW; + toEdit.wavelet.opacityCurveW = mods.wavelet.opacityCurveW; } if (wavelet.opacityCurveWL) { @@ -2955,44 +2955,44 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (wavelet.hhcurve) { - toEdit.wavelet.hhcurve = mods.wavelet.hhcurve; + toEdit.wavelet.hhcurve = mods.wavelet.hhcurve; } if (wavelet.Chcurve) { - toEdit.wavelet.Chcurve = mods.wavelet.Chcurve; + toEdit.wavelet.Chcurve = mods.wavelet.Chcurve; } if (wavelet.wavclCurve) { toEdit.wavelet.wavclCurve = mods.wavelet.wavclCurve; } - //if (wavelet.enacont) toEdit.wavelet.enacont = mods.wavelet.enacont; + //if (wavelet.enacont) toEdit.wavelet.enacont = mods.wavelet.enacont; if (wavelet.expcontrast) { - toEdit.wavelet.expcontrast = mods.wavelet.expcontrast; + toEdit.wavelet.expcontrast = mods.wavelet.expcontrast; } if (wavelet.expchroma) { - toEdit.wavelet.expchroma = mods.wavelet.expchroma; + toEdit.wavelet.expchroma = mods.wavelet.expchroma; } if (wavelet.expedge) { - toEdit.wavelet.expedge = mods.wavelet.expedge; + toEdit.wavelet.expedge = mods.wavelet.expedge; } if (wavelet.expresid) { - toEdit.wavelet.expresid = mods.wavelet.expresid; + toEdit.wavelet.expresid = mods.wavelet.expresid; } if (wavelet.expfinal) { - toEdit.wavelet.expfinal = mods.wavelet.expfinal; + toEdit.wavelet.expfinal = mods.wavelet.expfinal; } if (wavelet.exptoning) { - toEdit.wavelet.exptoning = mods.wavelet.exptoning; + toEdit.wavelet.exptoning = mods.wavelet.exptoning; } if (wavelet.expnoise) { - toEdit.wavelet.expnoise = mods.wavelet.expnoise; + toEdit.wavelet.expnoise = mods.wavelet.expnoise; } for (int i = 0; i < 9; i++) { @@ -3012,19 +3012,19 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (wavelet.hueskin) { - toEdit.wavelet.hueskin = mods.wavelet.hueskin; + toEdit.wavelet.hueskin = mods.wavelet.hueskin; } if (wavelet.hueskin2) { - toEdit.wavelet.hueskin2 = mods.wavelet.hueskin2; + toEdit.wavelet.hueskin2 = mods.wavelet.hueskin2; } if (wavelet.edgesensi) { - toEdit.wavelet.edgesensi = mods.wavelet.edgesensi; + toEdit.wavelet.edgesensi = mods.wavelet.edgesensi; } if (wavelet.edgeampli) { - toEdit.wavelet.edgeampli = mods.wavelet.edgeampli; + toEdit.wavelet.edgeampli = mods.wavelet.edgeampli; } if (wavelet.resconH) { @@ -3097,20 +3097,20 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng if (dirpyrequalizer.enabled) { - toEdit.dirpyrequalizer.enabled = mods.dirpyrequalizer.enabled; + toEdit.dirpyrequalizer.enabled = mods.dirpyrequalizer.enabled; } if (dirpyrequalizer.gamutlab) { - toEdit.dirpyrequalizer.gamutlab = mods.dirpyrequalizer.gamutlab; + toEdit.dirpyrequalizer.gamutlab = mods.dirpyrequalizer.gamutlab; } if (dirpyrequalizer.cbdlMethod) { - toEdit.dirpyrequalizer.cbdlMethod = mods.dirpyrequalizer.cbdlMethod; + toEdit.dirpyrequalizer.cbdlMethod = mods.dirpyrequalizer.cbdlMethod; } for (int i = 0; i < 6; i++) { if (dirpyrequalizer.mult[i]) { - toEdit.dirpyrequalizer.mult[i] = dontforceSet && options.baBehav[ADDSET_DIRPYREQ] ? toEdit.dirpyrequalizer.mult[i] + mods.dirpyrequalizer.mult[i] : mods.dirpyrequalizer.mult[i]; + toEdit.dirpyrequalizer.mult[i] = dontforceSet && options.baBehav[ADDSET_DIRPYREQ] ? toEdit.dirpyrequalizer.mult[i] + mods.dirpyrequalizer.mult[i] : mods.dirpyrequalizer.mult[i]; } } @@ -3123,93 +3123,95 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng } if (dirpyrequalizer.hueskin) { - toEdit.dirpyrequalizer.hueskin = mods.dirpyrequalizer.hueskin; + toEdit.dirpyrequalizer.hueskin = mods.dirpyrequalizer.hueskin; } -// if (dirpyrequalizer.algo) toEdit.dirpyrequalizer.algo = mods.dirpyrequalizer.algo; +// if (dirpyrequalizer.algo) toEdit.dirpyrequalizer.algo = mods.dirpyrequalizer.algo; if (hsvequalizer.enabled) { toEdit.hsvequalizer.enabled = mods.hsvequalizer.enabled; } if (hsvequalizer.hcurve) { - toEdit.hsvequalizer.hcurve = mods.hsvequalizer.hcurve; + toEdit.hsvequalizer.hcurve = mods.hsvequalizer.hcurve; } if (hsvequalizer.scurve) { - toEdit.hsvequalizer.scurve = mods.hsvequalizer.scurve; + toEdit.hsvequalizer.scurve = mods.hsvequalizer.scurve; } if (hsvequalizer.vcurve) { - toEdit.hsvequalizer.vcurve = mods.hsvequalizer.vcurve; + toEdit.hsvequalizer.vcurve = mods.hsvequalizer.vcurve; } if (filmSimulation.enabled) { - toEdit.filmSimulation.enabled = mods.filmSimulation.enabled; + toEdit.filmSimulation.enabled = mods.filmSimulation.enabled; } if (filmSimulation.clutFilename) { - toEdit.filmSimulation.clutFilename = mods.filmSimulation.clutFilename; + toEdit.filmSimulation.clutFilename = mods.filmSimulation.clutFilename; } if (filmSimulation.strength) { - toEdit.filmSimulation.strength = dontforceSet && options.baBehav[ADDSET_FILMSIMULATION_STRENGTH] ? toEdit.filmSimulation.strength + mods.filmSimulation.strength : mods.filmSimulation.strength; + toEdit.filmSimulation.strength = dontforceSet && options.baBehav[ADDSET_FILMSIMULATION_STRENGTH] ? toEdit.filmSimulation.strength + mods.filmSimulation.strength : mods.filmSimulation.strength; } if (softlight.enabled) { - toEdit.softlight.enabled = mods.softlight.enabled; + toEdit.softlight.enabled = mods.softlight.enabled; } if (softlight.strength) { - toEdit.softlight.strength = dontforceSet && options.baBehav[ADDSET_SOFTLIGHT_STRENGTH] ? toEdit.softlight.strength + mods.softlight.strength : mods.softlight.strength; + toEdit.softlight.strength = dontforceSet && options.baBehav[ADDSET_SOFTLIGHT_STRENGTH] ? toEdit.softlight.strength + mods.softlight.strength : mods.softlight.strength; } if (dehaze.enabled) { - toEdit.dehaze.enabled = mods.dehaze.enabled; + toEdit.dehaze.enabled = mods.dehaze.enabled; } if (dehaze.strength) { - toEdit.dehaze.strength = dontforceSet && options.baBehav[ADDSET_DEHAZE_STRENGTH] ? toEdit.dehaze.strength + mods.dehaze.strength : mods.dehaze.strength; + toEdit.dehaze.strength = dontforceSet && options.baBehav[ADDSET_DEHAZE_STRENGTH] ? toEdit.dehaze.strength + mods.dehaze.strength : mods.dehaze.strength; } if (dehaze.depth) { - toEdit.dehaze.depth = mods.dehaze.depth; + toEdit.dehaze.depth = mods.dehaze.depth; } if (dehaze.showDepthMap) { - toEdit.dehaze.showDepthMap = mods.dehaze.showDepthMap; + toEdit.dehaze.showDepthMap = mods.dehaze.showDepthMap; } if (metadata.mode) { - toEdit.metadata.mode = mods.metadata.mode; + toEdit.metadata.mode = mods.metadata.mode; } if (filmNegative.enabled) { - toEdit.filmNegative.enabled = mods.filmNegative.enabled; + toEdit.filmNegative.enabled = mods.filmNegative.enabled; } if (filmNegative.redExp) { - toEdit.filmNegative.redExp = mods.filmNegative.redExp; + toEdit.filmNegative.redExp = mods.filmNegative.redExp; } if (filmNegative.greenExp) { - toEdit.filmNegative.greenExp = mods.filmNegative.greenExp; + toEdit.filmNegative.greenExp = mods.filmNegative.greenExp; } if (filmNegative.blueExp) { - toEdit.filmNegative.blueExp = mods.filmNegative.blueExp; + toEdit.filmNegative.blueExp = mods.filmNegative.blueExp; } // Exif changes are added to the existing ones - if (exif) + if (exif) { for (procparams::ExifPairs::const_iterator i = mods.exif.begin(); i != mods.exif.end(); ++i) { toEdit.exif[i->first] = i->second; } + } // IPTC changes are added to the existing ones - if (iptc) + if (iptc) { for (procparams::IPTCPairs::const_iterator i = mods.iptc.begin(); i != mods.iptc.end(); ++i) { toEdit.iptc[i->first] = i->second; } + } } bool RAWParamsEdited::BayerSensor::isUnchanged() const @@ -3244,4 +3246,4 @@ bool RetinexParamsEdited::isUnchanged() const bool FilmNegativeParamsEdited::isUnchanged() const { return enabled && redExp && greenExp && blueExp; -} \ No newline at end of file +} diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index ef18e2953..34f9a414d 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -137,7 +137,6 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren //--- filmNegative = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_FILMNEGATIVE")) ); - Gtk::VBox* vboxes[8]; Gtk::HSeparator* hseps[8]; @@ -255,7 +254,6 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren vboxes[7]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); vboxes[7]->pack_start (*filmNegative, Gtk::PACK_SHRINK, 2); - Gtk::VBox* vbCol1 = Gtk::manage (new Gtk::VBox ()); Gtk::VBox* vbCol2 = Gtk::manage (new Gtk::VBox ()); Gtk::VBox* vbCol3 = Gtk::manage (new Gtk::VBox ()); @@ -983,7 +981,6 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param filterPE.filmNegative.blueExp = falsePE.filmNegative.blueExp; } - if (dstPE) { *dstPE = filterPE; } @@ -991,4 +988,3 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param // Apply the filter! filterPE.combine(*dstPP, *srcPP, true); } - diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index bd9720dfd..42dbeb984 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -1025,8 +1025,5 @@ void ToolPanelCoordinator::setEditProvider (EditDataProvider *provider) bool ToolPanelCoordinator::getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, float* newExps) { - if(!ipc) - return false; - - return ipc->getFilmNegativeExponents(spotA.x, spotA.y, spotB.x, spotB.y, newExps); + return ipc && ipc->getFilmNegativeExponents(spotA.x, spotA.y, spotB.x, spotB.y, newExps); } From 80f2b6a00281be746ff6275b9e23f6b1a429b9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Fri, 14 Jun 2019 08:58:04 +0200 Subject: [PATCH 19/42] Replace raw arrays with `std::array<>` --- rtengine/filmnegativeproc.cc | 4 ++-- rtengine/imagesource.h | 3 ++- rtengine/improccoordinator.cc | 2 +- rtengine/improccoordinator.h | 2 +- rtengine/rawimagesource.h | 8 ++++---- rtengine/rtengine.h | 37 +++++++++++++++++++---------------- rtgui/filmnegative.cc | 6 +++--- rtgui/filmnegative.h | 22 ++++++++++----------- rtgui/toolpanelcoord.cc | 2 +- rtgui/toolpanelcoord.h | 2 +- 10 files changed, 46 insertions(+), 42 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index db98fdf02..871b7a1d9 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -82,7 +82,7 @@ float logBase(float base, float num) { return log(num) / log(base); } -bool RawImageSource::getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, float newExps[3]) +bool RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, std::array& newExps) { float clearVals[3], denseVals[3]; @@ -317,4 +317,4 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p } } -} \ No newline at end of file +} diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 0a34b6bc8..bf73b5bb2 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -18,6 +18,7 @@ */ #pragma once +#include #include #include @@ -81,7 +82,7 @@ public: virtual int load (const Glib::ustring &fname) = 0; virtual void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, bool prepareDenoise = true) {}; virtual void filmNegativeProcess (const procparams::FilmNegativeParams ¶ms) {}; - virtual bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, float newExps[3]) { return false; }; + virtual bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams& currentParams, std::array& newExps) { return false; }; virtual void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold) {}; virtual void retinex (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &deh, const procparams::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 procparams::RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) {}; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index fb6250183..6f471eedf 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -1262,7 +1262,7 @@ void ImProcCoordinator::getSpotWB(int x, int y, int rect, double& temp, double& } } -bool ImProcCoordinator::getFilmNegativeExponents(int xA, int yA, int xB, int yB, float* newExps) +bool ImProcCoordinator::getFilmNegativeExponents(int xA, int yA, int xB, int yB, std::array& newExps) { MyMutex::MyLock lock(mProcessing); diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index d10db8d70..fdf74d297 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -269,7 +269,7 @@ public: bool getAutoWB (double& temp, double& green, double equal, double tempBias) override; void getCamWB (double& temp, double& green) override; void getSpotWB (int x, int y, int rectSize, double& temp, double& green) override; - bool getFilmNegativeExponents(int xA, int yA, int xB, int yB, float* newExps) override; + bool getFilmNegativeExponents(int xA, int yA, int xB, int yB, std::array& newExps) override; void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) override; bool getHighQualComputed() override; void setHighQualComputed() override; diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 6e039e7f8..9bfeb0c67 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -16,9 +16,9 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#ifndef _RAWIMAGESOURCE_ -#define _RAWIMAGESOURCE_ +#pragma once +#include #include #include @@ -116,7 +116,7 @@ public: int load(const Glib::ustring &fname, bool firstFrameOnly); void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, bool prepareDenoise = true) override; void filmNegativeProcess (const procparams::FilmNegativeParams ¶ms) override; - bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, float newExps[3]) override; + bool getFilmNegativeExponents (Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, std::array& newExps) override; void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold) override; void retinex (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &deh, const procparams::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) override; void retinexPrepareCurves (const procparams::RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) override; @@ -309,5 +309,5 @@ protected: void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override; }; + } -#endif diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index cc46cfca8..da10d470f 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -16,23 +16,29 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#ifndef _RTENGINE_ -#define _RTENGINE_ +#pragma once -#include "imageformat.h" -#include "rt_math.h" -#include "procevents.h" -#include -#include -#include +#include #include -#include "../rtexif/rtexif.h" -#include "rawmetadatalocation.h" +#include + +#include + +#include + #include "iimage.h" -#include "utils.h" -#include "../rtgui/threadutils.h" -#include "settings.h" +#include "imageformat.h" #include "LUT.h" +#include "procevents.h" +#include "rawmetadatalocation.h" +#include "rt_math.h" +#include "settings.h" +#include "utils.h" + +#include "../rtexif/rtexif.h" + +#include "../rtgui/threadutils.h" + /** * @file * This file contains the main functionality of the RawTherapee engine. @@ -499,7 +505,7 @@ public: virtual bool getAutoWB (double& temp, double& green, double equal, double tempBias) = 0; virtual void getCamWB (double& temp, double& green) = 0; virtual void getSpotWB (int x, int y, int rectSize, double& temp, double& green) = 0; - virtual bool getFilmNegativeExponents(int xA, int yA, int xB, int yB, float* newExps) = 0; + virtual bool getFilmNegativeExponents(int xA, int yA, int xB, int yB, std::array& newExps) = 0; virtual void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) = 0; virtual void saveInputICCReference (const Glib::ustring& fname, bool apply_wb) = 0; @@ -613,6 +619,3 @@ void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl); extern MyMutex* lcmsMutex; } - -#endif - diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 8f1fb5610..72141ecfb 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -281,8 +281,8 @@ bool FilmNegative::button1Pressed(int modifierKey) // User has selected 2 reference gray spots. Calculating new exponents // from channel values and updating parameters. - float newExps[3]; - if(fnp->getFilmNegativeExponents(refSpotCoords[0], refSpotCoords[1], newExps)) { + std::array newExps; + if (fnp->getFilmNegativeExponents(refSpotCoords[0], refSpotCoords[1], newExps)) { disableListener(); redExp->setValue(newExps[0]); greenExp->setValue(newExps[1]); @@ -335,4 +335,4 @@ void FilmNegative::switchOffEditMode () refSpotCoords.clear(); unsubscribe(); spotbutton->set_active(false); -} \ No newline at end of file +} diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h index 5d6c8ce03..b9dc15378 100644 --- a/rtgui/filmnegative.h +++ b/rtgui/filmnegative.h @@ -16,23 +16,25 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#ifndef _NEG_H_ -#define _NEG_H_ +#pragma once + +#include #include -#include "toolpanel.h" -#include "adjuster.h" -#include "guiutils.h" -#include "wbprovider.h" -#include "editcallbacks.h" -#include "../rtengine/procparams.h" +#include "adjuster.h" +#include "editcallbacks.h" +#include "guiutils.h" +#include "toolpanel.h" +#include "wbprovider.h" + +#include "../rtengine/procparams.h" class FilmNegProvider { public: virtual ~FilmNegProvider() = default; - virtual bool getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, float* newExps) = 0; + virtual bool getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, std::array& newExps) = 0; }; class FilmNegative : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public EditSubscriber @@ -89,5 +91,3 @@ public: bool pick1(bool picked) override; }; - -#endif diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 42dbeb984..f7e2991e1 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -1023,7 +1023,7 @@ void ToolPanelCoordinator::setEditProvider (EditDataProvider *provider) } } -bool ToolPanelCoordinator::getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, float* newExps) +bool ToolPanelCoordinator::getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, std::array& newExps) { return ipc && ipc->getFilmNegativeExponents(spotA.x, spotA.y, spotB.x, spotB.y, newExps); } diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 9910f9757..5569861ae 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -292,7 +292,7 @@ public: Glib::ustring GetCurrentImageFilePath() override; // FilmNegProvider interface - bool getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, float* newExps) override; + bool getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, std::array& newExps) override; // rotatelistener interface void straightenRequested () override; From d01f78864c9052963d354a9c0b3cdb60f82e38be Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Fri, 14 Jun 2019 22:14:24 +0200 Subject: [PATCH 20/42] Locked red and blue exponents by default in the GUI, added CheckButton to unlock them. --- rtdata/languages/default | 4 +++- rtgui/filmnegative.cc | 33 +++++++++++++++++++++++++++------ rtgui/filmnegative.h | 4 ++++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 1c6a1acba..36e441015 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1639,9 +1639,11 @@ TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points TP_EXPOS_WHITEPOINT_LABEL;Raw White Points TP_FILMNEGATIVE_BLUE;Blue exponent -TP_FILMNEGATIVE_GREEN;Green exponent +TP_FILMNEGATIVE_GREEN;Green exponent (lead) TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. TP_FILMNEGATIVE_LABEL;Film Negative +TP_FILMNEGATIVE_LOCKCHANNELS;Lock exponent ratios +TP_FILMNEGATIVE_LOCKCHANNELS_TOOLTIP;Unlock to adjust channel exponents independently. This allows to adapt to the color characteristics of different film types. TP_FILMNEGATIVE_PICK;Pick white and black spots TP_FILMNEGATIVE_RED;Red exponent TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 8f1fb5610..72307946b 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -49,6 +49,9 @@ FilmNegative::FilmNegative () : FoldableToolPanel(this, "filmnegative", M("TP_FI greenExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_GREEN"), 2.0); blueExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_BLUE"), 1.72); + redExp->set_sensitive(false); + blueExp->set_sensitive(false); + redRatio = redExp->getValue() / greenExp->getValue(); blueRatio = blueExp->getValue() / greenExp->getValue(); @@ -56,6 +59,10 @@ FilmNegative::FilmNegative () : FoldableToolPanel(this, "filmnegative", M("TP_FI EvFilmNegativeEnabled = m->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_ENABLED"); EvFilmNegativeExponents = m->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_EXPONENTS"); + lockChannels = Gtk::manage (new Gtk::CheckButton (M("TP_FILMNEGATIVE_LOCKCHANNELS"))); + lockChannels->set_tooltip_text(M("TP_FILMNEGATIVE_LOCKCHANNELS_TOOLTIP")); + lockChannels->set_active (true); + spotgrid = Gtk::manage(new Gtk::Grid()); spotgrid->get_style_context()->add_class("grid-spacing"); @@ -86,11 +93,13 @@ FilmNegative::FilmNegative () : FoldableToolPanel(this, "filmnegative", M("TP_FI // spotgrid->attach (*slab, 1, 0, 1, 1); // spotgrid->attach (*wbsizehelper, 2, 0, 1, 1); + pack_start (*lockChannels, Gtk::PACK_SHRINK, 0); pack_start (*redExp, Gtk::PACK_SHRINK, 0); pack_start (*greenExp, Gtk::PACK_SHRINK, 0); pack_start (*blueExp, Gtk::PACK_SHRINK, 0); pack_start (*spotgrid, Gtk::PACK_SHRINK, 0 ); + lockChannels->signal_toggled().connect( sigc::mem_fun(*this, &FilmNegative::lockChannelsToggled) ); spotbutton->signal_toggled().connect( sigc::mem_fun(*this, &FilmNegative::editToggled) ); // spotsize->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::spotSizeChanged) ); @@ -191,6 +200,12 @@ void FilmNegative::editToggled () } } +void FilmNegative::lockChannelsToggled () +{ + bool unlocked = !lockChannels->get_active(); + redExp->set_sensitive(unlocked); + blueExp->set_sensitive(unlocked); +} void FilmNegative::read (const ProcParams* pp, const ParamsEdited* pedited) { @@ -245,12 +260,18 @@ void FilmNegative::setDefaults (const ProcParams* defParams, const ParamsEdited* void FilmNegative::setBatchMode (bool batchMode) { - spotConn.disconnect(); - removeIfThere(this, spotgrid, false); - ToolPanel::setBatchMode (batchMode); - redExp->showEditedCB (); - greenExp->showEditedCB (); - blueExp->showEditedCB (); + if(batchMode) { + spotConn.disconnect(); + lockChannelsConn.disconnect(); + removeIfThere(this, spotgrid, false); + removeIfThere(this, lockChannels, false); + redExp->set_sensitive(true); + blueExp->set_sensitive(true); + ToolPanel::setBatchMode (batchMode); + redExp->showEditedCB (); + greenExp->showEditedCB (); + blueExp->showEditedCB (); + } } bool FilmNegative::mouseOver(int modifierKey) diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h index 5d6c8ce03..1a2262aec 100644 --- a/rtgui/filmnegative.h +++ b/rtgui/filmnegative.h @@ -50,6 +50,9 @@ private: Adjuster* greenExp; Adjuster* blueExp; + Gtk::CheckButton* lockChannels; + sigc::connection lockChannelsConn; + Gtk::Grid* spotgrid; Gtk::ToggleButton* spotbutton; sigc::connection spotConn; @@ -57,6 +60,7 @@ private: double redRatio, blueRatio; void editToggled (); + void lockChannelsToggled (); public: From 54cc02eea971c7002f19b16b1552729ee8acd4e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Mon, 17 Jun 2019 08:03:46 +0200 Subject: [PATCH 21/42] Filmenegative core cleanup --- rtengine/filmnegativeproc.cc | 338 ++++++++++++++++++++-------------- rtengine/rawimage.cc | 2 +- rtengine/rawimage.h | 2 +- rtengine/rawimagesource.h | 1 - rtgui/filmnegative.cc | 343 ++++++++++++++++++----------------- rtgui/filmnegative.h | 80 ++++---- 6 files changed, 422 insertions(+), 344 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index 871b7a1d9..51bd52365 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -1,7 +1,7 @@ /* * This file is part of RawTherapee. * - * Copyright (c) 2004-2010 Gabor Horvath + * Copyright (c) 2019 rom9 * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,15 +19,17 @@ #include #include -#include "rtengine.h" -#include "rawimagesource.h" -#include "mytime.h" -#include "procparams.h" #ifdef _OPENMP #include #endif + +#include "rawimagesource.h" + +#include "mytime.h" #include "opthelper.h" +#include "procparams.h" #include "rt_algo.h" +#include "rtengine.h" //#define BENCHMARK #include "StopWatch.h" @@ -37,168 +39,221 @@ namespace rtengine extern const Settings* settings; -bool RawImageSource::channelsAvg(Coord spotPos, int spotSize, float avgs[3], const FilmNegativeParams ¶ms) +} + +namespace { - avgs[0] = avgs[1] = avgs[2] = 0.f; // Channel averages - if(ri->getSensorType() != ST_BAYER && ri->getSensorType() != ST_FUJI_XTRANS) +bool channelsAvg( + const rtengine::RawImage* ri, + int width, + int height, + array2D& rawData, + rtengine::Coord spotPos, + int spotSize, + const rtengine::procparams::FilmNegativeParams& params, + std::array& avgs +) +{ + avgs = {}; // Channel averages + + if (ri->getSensorType() != rtengine::ST_BAYER && ri->getSensorType() != rtengine::ST_FUJI_XTRANS) { return false; + } - if (settings->verbose) + if (rtengine::settings->verbose) { printf("Spot coord: x=%d y=%d\n", spotPos.x, spotPos.y); + } - int x1 = spotPos.x - spotSize / 2; - int x2 = spotPos.x + spotSize / 2; - int y1 = spotPos.y - spotSize / 2; - int y2 = spotPos.y + spotSize / 2; + const int half_spot_size = spotSize / 2; - if(x1<0 || x2>W || y1<0 || y2>H) + const int& x1 = spotPos.x - half_spot_size; + const int& x2 = spotPos.x + half_spot_size; + const int& y1 = spotPos.y - half_spot_size; + const int& y2 = spotPos.y + half_spot_size; + + if (x1 < 0 || x2 > width || y1 < 0 || y2 > height) { return false; // Spot goes outside bounds, bail out. + } - int pxCount[3] = {0}; // Per-channel sample counts - for(int c=spotPos.x-spotSize; c pxCount = {}; // Per-channel sample counts + for (int c = spotPos.x - spotSize; c < spotPos.x + spotSize; ++c) { + for (int r = spotPos.y - spotSize; r < spotPos.y + spotSize; ++r) { + const int ch = ri->getSensorType() == rtengine::ST_BAYER ? ri->FC(r,c) : ri->XTRANSFC(r,c); - int ch = (ri->getSensorType() == ST_BAYER) ? FC(r,c) : ri->XTRANSFC(r,c); + ++pxCount[ch]; - pxCount[ch]++; // If film negative is currently enabled, undo the effect by elevating to 1/exp, // in order to sample the original, linear value - if(params.enabled) - avgs[ch] += powf(rawData[r][c], -1 / (ch==0 ? params.redExp : ch==1 ? params.greenExp : params.blueExp)); - else + if (params.enabled) { + avgs[ch] += powf(rawData[r][c], -1.f / (ch == 0 ? params.redExp : ch == 1 ? params.greenExp : params.blueExp)); + } else { avgs[ch] += rawData[r][c]; + } } } - for(int ch=0; ch<3; ch++) - avgs[ch] = avgs[ch] / (pxCount[ch]); + for (int ch = 0; ch < 3; ++ch) { + avgs[ch] /= pxCount[ch]; + } return true; } -// Calculate logarithms in arbitrary base -float logBase(float base, float num) { - return log(num) / log(base); } -bool RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, std::array& newExps) +bool rtengine::RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, std::array& newExps) { - float clearVals[3], denseVals[3]; + newExps = { + static_cast(currentParams.redExp), + static_cast(currentParams.greenExp), + static_cast(currentParams.blueExp) + }; - newExps[0] = currentParams.redExp; - newExps[1] = currentParams.greenExp; - newExps[2] = currentParams.blueExp; + constexpr int spotSize = 32; // TODO: Make this configurable? - int spotSize = 32; // TODO : make this confugurable ? Coord spot; + std::array clearVals; + std::array denseVals; + // Sample first spot - transformPosition (spotA.x, spotA.y, tran, spot.x, spot.y); - if(!channelsAvg(spot, spotSize, clearVals, currentParams)) - return false; - - // Sample second spot - transformPosition (spotB.x, spotB.y, tran, spot.x, spot.y); - if(!channelsAvg(spot, spotSize, denseVals, currentParams)) - return false; - - // Detect which one is the dense spot, based on green channel - if(clearVals[1] < denseVals[1]) - std::swap(clearVals, denseVals); - - if (settings->verbose) { - printf("Clear film values: R=%g G=%g B=%g\n", clearVals[0], clearVals[1], clearVals[2]); - printf("Dense film values: R=%g G=%g B=%g\n", denseVals[0], denseVals[1], denseVals[2]); + transformPosition(spotA.x, spotA.y, tran, spot.x, spot.y); + if (!channelsAvg(ri, W, H, rawData, spot, spotSize, currentParams, clearVals)) { + return false; } - float denseGreenRatio = clearVals[1] / denseVals[1]; + // Sample second spot + transformPosition(spotB.x, spotB.y, tran, spot.x, spot.y); + if (!channelsAvg(ri, W, H, rawData, spot, spotSize, currentParams, denseVals)) { + return false; + } + + // Detect which one is the dense spot, based on green channel + if (clearVals[1] < denseVals[1]) { + std::swap(clearVals, denseVals); + } + + if (settings->verbose) { + printf("Clear film values: R=%g G=%g B=%g\n", clearVals[0], clearVals[1], clearVals[2]); + printf("Dense film values: R=%g G=%g B=%g\n", denseVals[0], denseVals[1], denseVals[2]); + } + + const float denseGreenRatio = clearVals[1] / denseVals[1]; + + // Calculate logarithms in arbitrary base + const auto logBase = + [](float base, float num) -> float + { + return std::log(num) / std::log(base); + }; // Calculate exponents for each channel, based on the ratio between the bright and dark values, // compared to the ratio in the reference channel (green) - for(int ch=0; ch<3; ch++) - if(ch==1) + for (int ch = 0; ch < 3; ++ch) { + if (ch == 1) { newExps[ch] = 2.f; // Green is the reference channel - else + } else { newExps[ch] = CLAMP(2.f * logBase(clearVals[ch] / denseVals[ch], denseGreenRatio), 0.3f, 6.f); + } + } - if (settings->verbose) + if (settings->verbose) { printf("New exponents: R=%g G=%g B=%g\n", newExps[0], newExps[1], newExps[2]); + } return true; } -void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams ¶ms) +void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams ¶ms) { // BENCHFUNMICRO - if(!params.enabled) + if (!params.enabled) { return; + } - float exps[3] = { (float)params.redExp, (float)params.greenExp, (float)params.blueExp }; + const std::array exps = { + static_cast(params.redExp), + static_cast(params.greenExp), + static_cast(params.blueExp) + }; - MyTime t1, t2, t3,t4, t5, t6; + MyTime t1, t2, t3,t4, t5; + t1.set(); // Channel vectors to calculate medians - std::vector cvs[3] = { - std::vector(), - std::vector(), - std::vector() - }; + std::array, 3> cvs; // Sample one every 5 pixels, and push the value in the appropriate channel vector. - // Chose an odd step, not multiple of the CFA size, to get a chance to visit each channel. - if(ri->getSensorType() == ST_BAYER) { - for (int row = 0; row < H; row+=5) { - for (int col = 0; col < W; col+=5) { - int c = FC(row, col); // three colors, 0=R, 1=G, 2=B + // Choose an odd step, not a multiple of the CFA size, to get a chance to visit each channel. + if (ri->getSensorType() == ST_BAYER) { + for (int row = 0; row < H; row += 5) { + for (int col = 0; col < W; col += 5) { + const int c = FC(row, col); // three colors: 0=R, 1=G, 2=B cvs[c].push_back(rawData[row][col]); } } - } else if(ri->getSensorType() == ST_FUJI_XTRANS) { - for (int row = 0; row < H; row+=5) { - for (int col = 0; col < W; col+=5) { - int c = ri->XTRANSFC(row, col); // three colors, 0=R, 1=G, 2=B + } + else if (ri->getSensorType() == ST_FUJI_XTRANS) { + for (int row = 0; row < H; row += 5) { + for (int col = 0; col < W; col += 5) { + const int c = ri->XTRANSFC(row, col); // three colors: 0=R, 1=G, 2=B cvs[c].push_back(rawData[row][col]); } } } - const float MAX_OUT_VALUE = 65000.f; + constexpr float MAX_OUT_VALUE = 65000.f; t2.set(); - if (settings->verbose) + + if (settings->verbose) { printf("Median vector fill loop time us: %d\n", t2.etime(t1)); + } - float medians[3]; // Channel median values - float mults[3] = { 1.f }; // Channel normalization multipliers + t2.set(); - for (int c=0; c<3; c++) { + std::array medians; // Channel median values + std::array mults = { + 1.f, + 1.f, + 1.f + }; // Channel normalization multipliers + + for (int c = 0; c < 3; ++c) { // Find median values for each channel - if(cvs[c].size() > 0) { - findMinMaxPercentile(&cvs[c][0], cvs[c].size(), 0.5f, medians[c], 0.5f, medians[c], true); - medians[c] = pow_F(max(medians[c], 1.f), -exps[c]); + if (!cvs[c].empty()) { + findMinMaxPercentile(cvs[c].data(), cvs[c].size(), 0.5f, medians[c], 0.5f, medians[c], true); + medians[c] = pow_F(rtengine::max(medians[c], 1.f), -exps[c]); // Determine the channel multipler so that N times the median becomes 65k. This clips away // the values in the dark border surrounding the negative (due to the film holder, for example), // the reciprocal of which have blown up to stellar values. - mults[c] = MAX_OUT_VALUE / (medians[c] * 24); + mults[c] = MAX_OUT_VALUE / (medians[c] * 24.f); } } t3.set(); + if (settings->verbose) { - printf("Sample count : %lu, %lu, %lu\n", cvs[0].size(), cvs[1].size(), cvs[2].size()); - printf("Medians : %g %g %g\n", medians[0], medians[1], medians[2] ); - printf("Computed multipliers : %g %g %g\n", mults[0], mults[1], mults[2] ); + printf("Sample count: %zu, %zu, %zu\n", cvs[0].size(), cvs[1].size(), cvs[2].size()); + printf("Medians: %g %g %g\n", medians[0], medians[1], medians[2] ); + printf("Computed multipliers: %g %g %g\n", mults[0], mults[1], mults[2] ); printf("Median calc time us: %d\n", t3.etime(t2)); } + t3.set(); + + if (ri->getSensorType() == ST_BAYER) { +#ifdef __SSE2__ + const vfloat onev = F2V(1.f); + const vfloat c65535v = F2V(65535.f); +#endif - if(ri->getSensorType() == ST_BAYER) { #ifdef _OPENMP #pragma omp parallel for schedule(dynamic, 16) #endif - for (int row = 0; row < H; row ++) { + for (int row = 0; row < H; ++row) { int col = 0; // Exponents are expressed as positive in the parameters, so negate them in order // to get the reciprocals. Avoid trouble with zeroes, minimum pixel value is 1. @@ -209,21 +264,24 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p #ifdef __SSE2__ const vfloat expsv = _mm_setr_ps(exps0, exps1, exps0, exps1); const vfloat multsv = _mm_setr_ps(mult0, mult1, mult0, mult1); - const vfloat onev = F2V(1.f); - const vfloat c65535v = F2V(65535.f); - for (; col < W - 3; col+=4) { + for (; col < W - 3; col += 4) { STVFU(rawData[row][col], vminf(multsv * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv), c65535v)); } #endif // __SSE2__ - for (; col < W - 1; col+=2) { - rawData[row][col] = rtengine::min(mult0 * pow_F(max(rawData[row][col], 1.f), exps0), 65535.f); - rawData[row][col + 1] = rtengine::min(mult1 * pow_F(max(rawData[row][col + 1], 1.f), exps1), 65535.f); + for (; col < W - 1; col += 2) { + rawData[row][col] = rtengine::min(mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0), 65535.f); + rawData[row][col + 1] = rtengine::min(mult1 * pow_F(rtengine::max(rawData[row][col + 1], 1.f), exps1), 65535.f); } if (col < W) { - rawData[row][col] = rtengine::min(mult0 * pow_F(max(rawData[row][col], 1.f), exps0), 65535.f); + rawData[row][col] = rtengine::min(mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0), 65535.f); } } - } else if(ri->getSensorType() == ST_FUJI_XTRANS) { + } else if (ri->getSensorType() == ST_FUJI_XTRANS) { +#ifdef __SSE2__ + const vfloat onev = F2V(1.f); + const vfloat c65535v = F2V(65535.f); +#endif + #ifdef _OPENMP #pragma omp parallel for schedule(dynamic, 16) #endif @@ -231,8 +289,22 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p int col = 0; // Exponents are expressed as positive in the parameters, so negate them in order // to get the reciprocals. Avoid trouble with zeroes, minimum pixel value is 1. - const float expsc[6] = {-exps[ri->XTRANSFC(row, 0)], -exps[ri->XTRANSFC(row, 1)], -exps[ri->XTRANSFC(row, 2)], -exps[ri->XTRANSFC(row, 3)], -exps[ri->XTRANSFC(row, 4)], -exps[ri->XTRANSFC(row, 5)]}; - const float multsc[6] = {mults[ri->XTRANSFC(row, 0)], mults[ri->XTRANSFC(row, 1)], mults[ri->XTRANSFC(row, 2)], mults[ri->XTRANSFC(row, 3)], mults[ri->XTRANSFC(row, 4)], mults[ri->XTRANSFC(row, 5)]}; + const std::array expsc = { + -exps[ri->XTRANSFC(row, 0)], + -exps[ri->XTRANSFC(row, 1)], + -exps[ri->XTRANSFC(row, 2)], + -exps[ri->XTRANSFC(row, 3)], + -exps[ri->XTRANSFC(row, 4)], + -exps[ri->XTRANSFC(row, 5)] + }; + const std::array multsc = { + mults[ri->XTRANSFC(row, 0)], + mults[ri->XTRANSFC(row, 1)], + mults[ri->XTRANSFC(row, 2)], + mults[ri->XTRANSFC(row, 3)], + mults[ri->XTRANSFC(row, 4)], + mults[ri->XTRANSFC(row, 5)] + }; #ifdef __SSE2__ const vfloat expsv0 = _mm_setr_ps(expsc[0], expsc[1], expsc[2], expsc[3]); const vfloat expsv1 = _mm_setr_ps(expsc[4], expsc[5], expsc[0], expsc[1]); @@ -240,81 +312,75 @@ void RawImageSource::filmNegativeProcess(const procparams::FilmNegativeParams &p const vfloat multsv0 = _mm_setr_ps(multsc[0], multsc[1], multsc[2], multsc[3]); const vfloat multsv1 = _mm_setr_ps(multsc[4], multsc[5], multsc[0], multsc[1]); const vfloat multsv2 = _mm_setr_ps(multsc[2], multsc[3], multsc[4], multsc[5]); - const vfloat onev = F2V(1.f); - const vfloat c65535v = F2V(65535.f); - for (; col < W - 11; col+=12) { + for (; col < W - 11; col += 12) { STVFU(rawData[row][col], vminf(multsv0 * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv0), c65535v)); STVFU(rawData[row][col + 4], vminf(multsv1 * pow_F(vmaxf(LVFU(rawData[row][col + 4]), onev), expsv1), c65535v)); STVFU(rawData[row][col + 8], vminf(multsv2 * pow_F(vmaxf(LVFU(rawData[row][col + 8]), onev), expsv2), c65535v)); } #endif // __SSE2__ - for (; col < W - 5; col+=6) { + for (; col < W - 5; col += 6) { for (int c = 0; c < 6; ++c) { - rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(max(rawData[row][col + c], 1.f), expsc[c]), 65535.f); + rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]), 65535.f); } } for (int c = 0; col < W; col++, c++) { - rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(max(rawData[row][col + c], 1.f), expsc[c]), 65535.f); + rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]), 65535.f); } } } + t4.set(); + + if (settings->verbose) { + printf("Pow loop time us: %d\n", t4.etime(t3)); + } t4.set(); - if (settings->verbose) - printf("Pow loop time us: %d\n", t4.etime(t3)); - - - t5.set(); PixelsMap bitmapBads(W, H); int totBP = 0; // Hold count of bad pixels to correct - if(ri->getSensorType() == ST_BAYER) { - - + if (ri->getSensorType() == ST_BAYER) { #ifdef _OPENMP #pragma omp parallel for reduction(+:totBP) schedule(dynamic,16) #endif - - for(int i = 0; i < H; i++) - for(int j = 0; j < W; j++) { + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { if (rawData[i][j] >= MAX_OUT_VALUE) { bitmapBads.set(j, i); - totBP++; + ++totBP; } } - - if (totBP > 0) { - interpolateBadPixelsBayer( bitmapBads, rawData ); } - } else if(ri->getSensorType() == ST_FUJI_XTRANS) { - -#ifdef _OPENMP - #pragma omp parallel for reduction(+:totBP) schedule(dynamic,16) -#endif - - for(int i = 0; i < H; i++) - for(int j = 0; j < W; j++) { - if (rawData[i][j] >= MAX_OUT_VALUE) { - bitmapBads.set(j, i); - totBP++; - } - } - if (totBP > 0) { - interpolateBadPixelsXtrans( bitmapBads ); + interpolateBadPixelsBayer(bitmapBads, rawData); } } + else if (ri->getSensorType() == ST_FUJI_XTRANS) { +#ifdef _OPENMP + #pragma omp parallel for reduction(+:totBP) schedule(dynamic,16) +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + if (rawData[i][j] >= MAX_OUT_VALUE) { + bitmapBads.set(j, i); + totBP++; + } + } + } + + if (totBP > 0) { + interpolateBadPixelsXtrans(bitmapBads); + } + } + + t5.set(); - t6.set(); if (settings->verbose) { printf("Bad pixels count: %d\n", totBP); - printf("Bad pixels interpolation time us: %d\n", t6.etime(t5)); + printf("Bad pixels interpolation time us: %d\n", t5.etime(t4)); } } - -} diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index 1fa1630ab..0134d4d16 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -67,7 +67,7 @@ RawImage::~RawImage() } } -eSensorType RawImage::getSensorType() +eSensorType RawImage::getSensorType() const { if (isBayer()) { return ST_BAYER; diff --git a/rtengine/rawimage.h b/rtengine/rawimage.h index 0dabfef0d..4ff6d79c9 100644 --- a/rtengine/rawimage.h +++ b/rtengine/rawimage.h @@ -185,7 +185,7 @@ public: return float_raw_image; } - eSensorType getSensorType(); + eSensorType getSensorType() const; void getRgbCam (float rgbcam[3][4]); void getXtransMatrix ( int xtransMatrix[6][6]); diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 9bfeb0c67..c04da5b66 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -43,7 +43,6 @@ private: static LUTf initInvGrad (); static void colorSpaceConversion_ (Imagefloat* im, const procparams::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); - bool channelsAvg(Coord spotPos, int spotSize, float avgs[3], const FilmNegativeParams ¶ms); protected: MyMutex getImageMutex; // locks getImage diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 72141ecfb..fef4fc6c6 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -1,7 +1,7 @@ /* * This file is part of RawTherapee. * - * Copyright (c) 2004-2010 Gabor Horvath + * Copyright (c) 2019 rom9 * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,52 +16,52 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#include "filmnegative.h" - #include -#include "rtimage.h" -#include "options.h" +#include "filmnegative.h" + #include "editwidgets.h" #include "eventmapper.h" +#include "options.h" +#include "rtimage.h" +#include "../rtengine/procparams.h" -using namespace rtengine; -using namespace rtengine::procparams; - - -FilmNegative::FilmNegative () : FoldableToolPanel(this, "filmnegative", M("TP_FILMNEGATIVE_LABEL"), false, true), EditSubscriber(ET_OBJECTS) +namespace { - auto mkExponentAdjuster = [this](Glib::ustring label, double defaultVal) { - Adjuster *adj = Gtk::manage(new Adjuster (label, 0.3, 6, 0.001, defaultVal)); //exponent - adj->setAdjusterListener (this); - - if (adj->delay < options.adjusterMaxDelay) { - adj->delay = options.adjusterMaxDelay; - } - - adj->show(); - return adj; - }; +Adjuster* createExponentAdjuster(AdjusterListener* listener, const Glib::ustring& label, double defaultVal) +{ + Adjuster* const adj = Gtk::manage(new Adjuster(label, 0.3, 6, 0.001, defaultVal)); // exponent + adj->setAdjusterListener(listener); - redExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_RED"), 2.72); - greenExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_GREEN"), 2.0); - blueExp = mkExponentAdjuster(M("TP_FILMNEGATIVE_BLUE"), 1.72); + if (adj->delay < options.adjusterMaxDelay) { + adj->delay = options.adjusterMaxDelay; + } - redRatio = redExp->getValue() / greenExp->getValue(); - blueRatio = blueExp->getValue() / greenExp->getValue(); + adj->show(); + return adj; +} - auto m = ProcEventMapper::getInstance(); - EvFilmNegativeEnabled = m->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_ENABLED"); - EvFilmNegativeExponents = m->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_EXPONENTS"); +} - - spotgrid = Gtk::manage(new Gtk::Grid()); +FilmNegative::FilmNegative() : + FoldableToolPanel(this, "filmnegative", M("TP_FILMNEGATIVE_LABEL"), false, true), + EditSubscriber(ET_OBJECTS), + evFilmNegativeExponents(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_EXPONENTS")), + evFilmNegativeEnabled(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_ENABLED")), + fnp(nullptr), + redExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_RED"), 2.72)), + greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 2.0)), + blueExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_BLUE"), 1.72)), + spotgrid(Gtk::manage(new Gtk::Grid())), + spotbutton(Gtk::manage(new Gtk::ToggleButton(M("TP_FILMNEGATIVE_PICK")))), + redRatio(redExp->getValue() / greenExp->getValue()), + blueRatio(blueExp->getValue() / greenExp->getValue()) +{ spotgrid->get_style_context()->add_class("grid-spacing"); setExpandAlignProperties(spotgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); - spotbutton = Gtk::manage (new Gtk::ToggleButton (M("TP_FILMNEGATIVE_PICK"))); setExpandAlignProperties(spotbutton, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); spotbutton->get_style_context()->add_class("independent"); spotbutton->set_tooltip_text(M("TP_FILMNEGATIVE_GUESS_TOOLTIP")); @@ -83,120 +83,47 @@ FilmNegative::FilmNegative () : FoldableToolPanel(this, "filmnegative", M("TP_FI // spotsize->append ("4"); spotgrid->attach (*spotbutton, 0, 1, 1, 1); -// spotgrid->attach (*slab, 1, 0, 1, 1); + // spotgrid->attach (*slab, 1, 0, 1, 1); // spotgrid->attach (*wbsizehelper, 2, 0, 1, 1); - pack_start (*redExp, Gtk::PACK_SHRINK, 0); - pack_start (*greenExp, Gtk::PACK_SHRINK, 0); - pack_start (*blueExp, Gtk::PACK_SHRINK, 0); - pack_start (*spotgrid, Gtk::PACK_SHRINK, 0 ); - - spotbutton->signal_toggled().connect( sigc::mem_fun(*this, &FilmNegative::editToggled) ); -// spotsize->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::spotSizeChanged) ); + pack_start(*redExp, Gtk::PACK_SHRINK, 0); + pack_start(*greenExp, Gtk::PACK_SHRINK, 0); + pack_start(*blueExp, Gtk::PACK_SHRINK, 0); + pack_start(*spotgrid, Gtk::PACK_SHRINK, 0); + spotbutton->signal_toggled().connect(sigc::mem_fun(*this, &FilmNegative::editToggled)); + // spotsize->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::spotSizeChanged) ); // Editing geometry; create the spot rectangle - Rectangle *spotRect = new Rectangle(); + Rectangle* const spotRect = new Rectangle(); spotRect->filled = false; - EditSubscriber::visibleGeometry.push_back( spotRect ); + visibleGeometry.push_back(spotRect); // Stick a dummy rectangle over the whole image in mouseOverGeometry. - // This is to make sure the getCursor call is fired everywhere. - Rectangle *imgRect = new Rectangle(); + // This is to make sure the getCursor() call is fired everywhere. + Rectangle* imgRect = new Rectangle(); imgRect->filled = true; - EditSubscriber::mouseOverGeometry.push_back( imgRect ); - + mouseOverGeometry.push_back(imgRect); } FilmNegative::~FilmNegative() { -// idle_register.destroy(); - - for (std::vector::const_iterator i = visibleGeometry.begin(); i != visibleGeometry.end(); ++i) { - delete *i; + for (auto geometry : visibleGeometry) { + delete geometry; } - for (std::vector::const_iterator i = mouseOverGeometry.begin(); i != mouseOverGeometry.end(); ++i) { - delete *i; - } - -} - - - -void FilmNegative::enabledChanged() -{ - if (listener) { - if (get_inconsistent()) { - listener->panelChanged(EvFilmNegativeEnabled, M("GENERAL_UNCHANGED")); - } else if (getEnabled()) { - listener->panelChanged(EvFilmNegativeEnabled, M("GENERAL_ENABLED")); - } else { - listener->panelChanged(EvFilmNegativeEnabled, M("GENERAL_DISABLED")); - } + for (auto geometry : mouseOverGeometry) { + delete geometry; } } - -void FilmNegative::adjusterChanged(Adjuster* a, double newval) +void FilmNegative::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { - if (listener) { - if(a == redExp || a == greenExp || a == blueExp) { - disableListener(); - if(a == greenExp) { - redExp->setValue(a->getValue() * redRatio); - blueExp->setValue(a->getValue() * blueRatio); - } else if(a == redExp) { - redRatio = newval / greenExp->getValue(); - } else if(a == blueExp) { - blueRatio = newval / greenExp->getValue(); - } - enableListener(); + disableListener(); - if(getEnabled()) { - listener->panelChanged (EvFilmNegativeExponents, Glib::ustring::compose ( - "R=%1 ; G=%2 ; B=%3", redExp->getTextValue(), greenExp->getTextValue(), blueExp->getTextValue())); - } - } - } -} - -void FilmNegative::adjusterAutoToggled(Adjuster* a, bool newval) -{ -} - -void FilmNegative::setEditProvider (EditDataProvider* provider) -{ - EditSubscriber::setEditProvider(provider); -} - -void FilmNegative::editToggled () -{ - if (spotbutton->get_active()) { - subscribe(); - - int w, h; - getEditProvider()->getImageSize(w, h); - - // Stick a dummy rectangle over the whole image in mouseOverGeometry. - // This is to make sure the getCursor call is fired everywhere. - const auto imgRect = static_cast(mouseOverGeometry.at(0)); - imgRect->setXYWH(0, 0, w, h); - - } else { - this->refSpotCoords.clear(); - unsubscribe(); - } -} - - -void FilmNegative::read (const ProcParams* pp, const ParamsEdited* pedited) -{ - disableListener (); - - if(pedited) { + if (pedited) { redExp->setEditedState(pedited->filmNegative.redExp ? Edited : UnEdited); greenExp->setEditedState(pedited->filmNegative.greenExp ? Edited : UnEdited); blueExp->setEditedState(pedited->filmNegative.blueExp ? Edited : UnEdited); @@ -208,10 +135,10 @@ void FilmNegative::read (const ProcParams* pp, const ParamsEdited* pedited) greenExp->setValue(pp->filmNegative.greenExp); blueExp->setValue(pp->filmNegative.blueExp); - enableListener (); + enableListener(); } -void FilmNegative::write (ProcParams* pp, ParamsEdited* pedited) +void FilmNegative::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { pp->filmNegative.redExp = redExp->getValue(); pp->filmNegative.greenExp = greenExp->getValue(); @@ -226,37 +153,103 @@ void FilmNegative::write (ProcParams* pp, ParamsEdited* pedited) } } -void FilmNegative::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +void FilmNegative::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { redExp->setValue(defParams->filmNegative.redExp); greenExp->setValue(defParams->filmNegative.greenExp); blueExp->setValue(defParams->filmNegative.blueExp); if (pedited) { - redExp->setDefaultEditedState (pedited->filmNegative.redExp ? Edited : UnEdited); - greenExp->setDefaultEditedState (pedited->filmNegative.greenExp ? Edited : UnEdited); - blueExp->setDefaultEditedState (pedited->filmNegative.blueExp ? Edited : UnEdited); + redExp->setDefaultEditedState(pedited->filmNegative.redExp ? Edited : UnEdited); + greenExp->setDefaultEditedState(pedited->filmNegative.greenExp ? Edited : UnEdited); + blueExp->setDefaultEditedState(pedited->filmNegative.blueExp ? Edited : UnEdited); } else { - redExp->setDefaultEditedState (Irrelevant); - greenExp->setDefaultEditedState (Irrelevant); - blueExp->setDefaultEditedState (Irrelevant); + redExp->setDefaultEditedState(Irrelevant); + greenExp->setDefaultEditedState(Irrelevant); + blueExp->setDefaultEditedState(Irrelevant); } } -void FilmNegative::setBatchMode (bool batchMode) +void FilmNegative::setBatchMode(bool batchMode) { spotConn.disconnect(); removeIfThere(this, spotgrid, false); - ToolPanel::setBatchMode (batchMode); - redExp->showEditedCB (); - greenExp->showEditedCB (); - blueExp->showEditedCB (); + ToolPanel::setBatchMode(batchMode); + redExp->showEditedCB(); + greenExp->showEditedCB(); + blueExp->showEditedCB(); +} + +void FilmNegative::adjusterChanged(Adjuster* a, double newval) +{ + if (listener) { + if (a == redExp || a == greenExp || a == blueExp) { + disableListener(); + if (a == greenExp) { + redExp->setValue(a->getValue() * redRatio); + blueExp->setValue(a->getValue() * blueRatio); + } + else if (a == redExp) { + redRatio = newval / greenExp->getValue(); + } + else if (a == blueExp) { + blueRatio = newval / greenExp->getValue(); + } + enableListener(); + + if (getEnabled()) { + listener->panelChanged( + evFilmNegativeExponents, + Glib::ustring::compose( + "R=%1 ; G=%2 ; B=%3", + redExp->getTextValue(), + greenExp->getTextValue(), + blueExp->getTextValue() + ) + ); + } + } + } +} + +void FilmNegative::adjusterAutoToggled(Adjuster* a, bool newval) +{ +} + +void FilmNegative::enabledChanged() +{ + if (listener) { + if (get_inconsistent()) { + listener->panelChanged(evFilmNegativeEnabled, M("GENERAL_UNCHANGED")); + } + else if (getEnabled()) { + listener->panelChanged(evFilmNegativeEnabled, M("GENERAL_ENABLED")); + } + else { + listener->panelChanged(evFilmNegativeEnabled, M("GENERAL_DISABLED")); + } + } +} + +void FilmNegative::setFilmNegProvider(FilmNegProvider* p) +{ + fnp = p; +} + +void FilmNegative::setEditProvider(EditDataProvider* provider) +{ + EditSubscriber::setEditProvider(provider); +} + +CursorShape FilmNegative::getCursor(int objectID) const +{ + return CSSpotWB; } bool FilmNegative::mouseOver(int modifierKey) { - EditDataProvider *provider = getEditProvider(); - const auto spotRect = static_cast(visibleGeometry.at(0)); + EditDataProvider* const provider = getEditProvider(); + Rectangle* const spotRect = static_cast(visibleGeometry.at(0)); spotRect->setXYWH(provider->posImage.x - 16, provider->posImage.y - 16, 32, 32); return true; @@ -264,20 +257,18 @@ bool FilmNegative::mouseOver(int modifierKey) bool FilmNegative::button1Pressed(int modifierKey) { - EditDataProvider *provider = getEditProvider(); + EditDataProvider* const provider = getEditProvider(); - if(provider) { // debug. remove me + if (provider) { // TODO: Remove me (rom9) printf("x=%d y=%d pv1=%f pv2=%f pv3=%f\n", provider->posImage.x, provider->posImage.y, provider->getPipetteVal1(), provider->getPipetteVal2(), provider->getPipetteVal3()); } EditSubscriber::action = EditSubscriber::Action::NONE; if (listener) { - refSpotCoords.push_back(provider->posImage); - if(refSpotCoords.size() == 2) { - + if (refSpotCoords.size() == 2) { // User has selected 2 reference gray spots. Calculating new exponents // from channel values and updating parameters. @@ -292,8 +283,15 @@ bool FilmNegative::button1Pressed(int modifierKey) enableListener(); if (listener && getEnabled()) { - listener->panelChanged (EvFilmNegativeExponents, Glib::ustring::compose ( - "R=%1 ; G=%2 ; B=%3", redExp->getTextValue(), greenExp->getTextValue(), blueExp->getTextValue())); + listener->panelChanged( + evFilmNegativeExponents, + Glib::ustring::compose( + "R=%1 ; G=%2 ; B=%3", + redExp->getTextValue(), + greenExp->getTextValue(), + blueExp->getTextValue() + ) + ); } } @@ -304,35 +302,50 @@ bool FilmNegative::button1Pressed(int modifierKey) return true; } -bool FilmNegative::button1Released () +bool FilmNegative::button1Released() { - EditDataProvider *provider = getEditProvider(); + EditDataProvider* const provider = getEditProvider(); - if(provider) { // debug. remove me + if (provider) { // TODO: Remove me (rom9) printf("x=%d y=%d pv1=%f pv2=%f pv3=%f\n", provider->posImage.x, provider->posImage.y, provider->getPipetteVal1(), provider->getPipetteVal2(), provider->getPipetteVal3()); } EditSubscriber::action = EditSubscriber::Action::NONE; + return true; } -// TODO remove me ; couldn't make Action::PICKING work -bool FilmNegative::pick1 (bool picked) { - EditDataProvider *provider = getEditProvider(); - if(provider) { // debug. remove me - printf("Picked pick=%d x=%d y=%d pv1=%f pv2=%f pv3=%f\n", picked, provider->posImage.x, provider->posImage.y, provider->getPipetteVal1(), provider->getPipetteVal2(), provider->getPipetteVal3()); - } - return true; -} - -CursorShape FilmNegative::getCursor(int objectID) const -{ - return CSSpotWB; -} - -void FilmNegative::switchOffEditMode () +void FilmNegative::switchOffEditMode() { refSpotCoords.clear(); unsubscribe(); spotbutton->set_active(false); } + +// TODO: Remove me ; couldn't make Action::PICKING work (rom9) +bool FilmNegative::pick1(bool picked) +{ + EditDataProvider* const provider = getEditProvider(); + if (provider) { // TODO: Remove me (rom9) + printf("Picked pick=%d x=%d y=%d pv1=%f pv2=%f pv3=%f\n", picked, provider->posImage.x, provider->posImage.y, provider->getPipetteVal1(), provider->getPipetteVal2(), provider->getPipetteVal3()); + } + return true; +} + +void FilmNegative::editToggled() +{ + if (spotbutton->get_active()) { + subscribe(); + + int w, h; + getEditProvider()->getImageSize(w, h); + + // Stick a dummy rectangle over the whole image in mouseOverGeometry. + // This is to make sure the getCursor() call is fired everywhere. + Rectangle* const imgRect = static_cast(mouseOverGeometry.at(0)); + imgRect->setXYWH(0, 0, w, h); + } else { + refSpotCoords.clear(); + unsubscribe(); + } +} diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h index b9dc15378..31d561127 100644 --- a/rtgui/filmnegative.h +++ b/rtgui/filmnegative.h @@ -1,7 +1,7 @@ /* * This file is part of RawTherapee. * - * Copyright (c) 2004-2010 Gabor Horvath + * Copyright (c) 2019 rom9 * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,66 +28,66 @@ #include "toolpanel.h" #include "wbprovider.h" -#include "../rtengine/procparams.h" +#include "../rtengine/noncopyable.h" class FilmNegProvider { public: virtual ~FilmNegProvider() = default; + virtual bool getFilmNegativeExponents(rtengine::Coord spotA, rtengine::Coord spotB, std::array& newExps) = 0; }; -class FilmNegative : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public EditSubscriber +class FilmNegative : + public rtengine::NonCopyable, + public ToolParamBlock, + public AdjusterListener, + public FoldableToolPanel, + public EditSubscriber { - -private: - rtengine::ProcEvent EvFilmNegativeExponents; - rtengine::ProcEvent EvFilmNegativeEnabled; - - std::vector refSpotCoords; - - FilmNegProvider *fnp; - - Adjuster* redExp; - Adjuster* greenExp; - Adjuster* blueExp; - - Gtk::Grid* spotgrid; - Gtk::ToggleButton* spotbutton; - sigc::connection spotConn; - - double redRatio, blueRatio; - - void editToggled (); - public: + FilmNegative(); + ~FilmNegative() override; - FilmNegative (); - ~FilmNegative () override; + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; + void setBatchMode(bool batchMode) override; - void setFilmNegProvider(FilmNegProvider* p) - { - fnp = p; - }; - - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; - void setBatchMode (bool batchMode) override; - - void adjusterChanged (Adjuster* a, double newval) override; + void adjusterChanged(Adjuster* a, double newval) override; void adjusterAutoToggled(Adjuster* a, bool newval) override; - void spotPressed (); void enabledChanged() override; - void setEditProvider (EditDataProvider* provider) override; + void setFilmNegProvider(FilmNegProvider* p); + + void setEditProvider(EditDataProvider* provider) override; // EditSubscriber interface CursorShape getCursor(int objectID) const override; bool mouseOver(int modifierKey) override; bool button1Pressed(int modifierKey) override; bool button1Released() override; - void switchOffEditMode () override; + void switchOffEditMode() override; bool pick1(bool picked) override; +private: + void editToggled(); + + const rtengine::ProcEvent evFilmNegativeExponents; + const rtengine::ProcEvent evFilmNegativeEnabled; + + std::vector refSpotCoords; + + FilmNegProvider* fnp; + + Adjuster* const redExp; + Adjuster* const greenExp; + Adjuster* const blueExp; + + Gtk::Grid* const spotgrid; + Gtk::ToggleButton* const spotbutton; + sigc::connection spotConn; + + double redRatio; + double blueRatio; }; From 8de581ac39cc4686d50a7908eadf80780fbb0848 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Mon, 17 Jun 2019 21:46:50 +0200 Subject: [PATCH 22/42] Removed old debugging stuff from rtgui/filmnegative.cc --- rtgui/filmnegative.cc | 21 --------------------- rtgui/filmnegative.h | 1 - 2 files changed, 22 deletions(-) diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 0e0f1ee51..8e0e5133f 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -274,10 +274,6 @@ bool FilmNegative::button1Pressed(int modifierKey) { EditDataProvider* const provider = getEditProvider(); - if (provider) { // TODO: Remove me (rom9) - printf("x=%d y=%d pv1=%f pv2=%f pv3=%f\n", provider->posImage.x, provider->posImage.y, provider->getPipetteVal1(), provider->getPipetteVal2(), provider->getPipetteVal3()); - } - EditSubscriber::action = EditSubscriber::Action::NONE; if (listener) { @@ -319,14 +315,7 @@ bool FilmNegative::button1Pressed(int modifierKey) bool FilmNegative::button1Released() { - EditDataProvider* const provider = getEditProvider(); - - if (provider) { // TODO: Remove me (rom9) - printf("x=%d y=%d pv1=%f pv2=%f pv3=%f\n", provider->posImage.x, provider->posImage.y, provider->getPipetteVal1(), provider->getPipetteVal2(), provider->getPipetteVal3()); - } - EditSubscriber::action = EditSubscriber::Action::NONE; - return true; } @@ -337,16 +326,6 @@ void FilmNegative::switchOffEditMode() spotbutton->set_active(false); } -// TODO: Remove me ; couldn't make Action::PICKING work (rom9) -bool FilmNegative::pick1(bool picked) -{ - EditDataProvider* const provider = getEditProvider(); - if (provider) { // TODO: Remove me (rom9) - printf("Picked pick=%d x=%d y=%d pv1=%f pv2=%f pv3=%f\n", picked, provider->posImage.x, provider->posImage.y, provider->getPipetteVal1(), provider->getPipetteVal2(), provider->getPipetteVal3()); - } - return true; -} - void FilmNegative::editToggled() { if (spotbutton->get_active()) { diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h index e29a20103..655217367 100644 --- a/rtgui/filmnegative.h +++ b/rtgui/filmnegative.h @@ -68,7 +68,6 @@ public: bool button1Pressed(int modifierKey) override; bool button1Released() override; void switchOffEditMode() override; - bool pick1(bool picked) override; private: void editToggled(); From 7c0275ca1a034dacb8f130bfffc40e5399a52f7b Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Tue, 18 Jun 2019 13:52:58 +0200 Subject: [PATCH 23/42] Updated copyright notice in new source files --- rtengine/filmnegativeproc.cc | 2 +- rtgui/filmnegative.cc | 2 +- rtgui/filmnegative.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index f367c4368..bd68314e3 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -1,7 +1,7 @@ /* * This file is part of RawTherapee. * - * Copyright (c) 2019 rom9 + * Copyright (c) 2019 Alberto Romei * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 8e0e5133f..b6cb9f1c6 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -1,7 +1,7 @@ /* * This file is part of RawTherapee. * - * Copyright (c) 2019 rom9 + * Copyright (c) 2019 Alberto Romei * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h index 655217367..b21bc23c3 100644 --- a/rtgui/filmnegative.h +++ b/rtgui/filmnegative.h @@ -1,7 +1,7 @@ /* * This file is part of RawTherapee. * - * Copyright (c) 2019 rom9 + * Copyright (c) 2019 Alberto Romei * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From c9c834dc633ac98b17be363b214526125491b691 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Tue, 18 Jun 2019 21:02:53 +0200 Subject: [PATCH 24/42] Very honored to add myself to AUTHORS.txt, as suggested by heckflosse: https://github.com/Beep6581/RawTherapee/pull/5349#pullrequestreview-247409279 --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 15e3e13d4..160869776 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -28,6 +28,7 @@ Development contributors, in last name alphabetical order: Adam Reichold Philip Rinn Jan Rinze + Alberto Romei Ben S. Andrey Skvortsov Fabio Suprani From 03dc855fc73898b5957fdf1d39c26a612d6938f5 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Tue, 18 Jun 2019 21:08:18 +0200 Subject: [PATCH 25/42] Merged cleanup patch proposed by heckflosse, moves exponents negation to a single place. Now it's much easier to read. --- rtengine/filmnegativeproc.cc | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index bd68314e3..f5a231c05 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -172,10 +172,12 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ return; } + // Exponents are expressed as positive in the parameters, so negate them in order + // to get the reciprocals. const std::array exps = { - static_cast(params.redExp), - static_cast(params.greenExp), - static_cast(params.blueExp) + static_cast(-params.redExp), + static_cast(-params.greenExp), + static_cast(-params.blueExp) }; MyTime t1, t2, t3,t4, t5; @@ -244,8 +246,8 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ // Find median values for each channel if (!cvs[c].empty()) { findMinMaxPercentile(cvs[c].data(), cvs[c].size(), 0.5f, medians[c], 0.5f, medians[c], true); - medians[c] = pow_F(rtengine::max(medians[c], 1.f), -exps[c]); - // Determine the channel multipler so that N times the median becomes 65k. This clips away + medians[c] = pow_F(rtengine::max(medians[c], 1.f), exps[c]); + // Determine the channel multiplier so that N times the median becomes 65k. This clips away // the values in the dark border surrounding the negative (due to the film holder, for example), // the reciprocal of which have blown up to stellar values. mults[c] = MAX_OUT_VALUE / (medians[c] * 24.f); @@ -274,10 +276,9 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ #endif for (int row = 0; row < H; ++row) { int col = 0; - // Exponents are expressed as positive in the parameters, so negate them in order - // to get the reciprocals. Avoid trouble with zeroes, minimum pixel value is 1. - const float exps0 = -exps[FC(row, col)]; - const float exps1 = -exps[FC(row, col + 1)]; + // Avoid trouble with zeroes, minimum pixel value is 1. + const float exps0 = exps[FC(row, col)]; + const float exps1 = exps[FC(row, col + 1)]; const float mult0 = mults[FC(row, col)]; const float mult1 = mults[FC(row, col + 1)]; #ifdef __SSE2__ @@ -306,15 +307,14 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ #endif for (int row = 0; row < H; row ++) { int col = 0; - // Exponents are expressed as positive in the parameters, so negate them in order - // to get the reciprocals. Avoid trouble with zeroes, minimum pixel value is 1. + // Avoid trouble with zeroes, minimum pixel value is 1. const std::array expsc = { - -exps[ri->XTRANSFC(row, 0)], - -exps[ri->XTRANSFC(row, 1)], - -exps[ri->XTRANSFC(row, 2)], - -exps[ri->XTRANSFC(row, 3)], - -exps[ri->XTRANSFC(row, 4)], - -exps[ri->XTRANSFC(row, 5)] + exps[ri->XTRANSFC(row, 0)], + exps[ri->XTRANSFC(row, 1)], + exps[ri->XTRANSFC(row, 2)], + exps[ri->XTRANSFC(row, 3)], + exps[ri->XTRANSFC(row, 4)], + exps[ri->XTRANSFC(row, 5)] }; const std::array multsc = { mults[ri->XTRANSFC(row, 0)], From 789edc5bd32c9a604ce71544836d06695b576c49 Mon Sep 17 00:00:00 2001 From: Eric Jiang Date: Tue, 18 Jun 2019 18:02:10 -0700 Subject: [PATCH 26/42] Apply code-cleanup patch from @Floessie See https://github.com/Beep6581/RawTherapee/pull/5325 --- rtengine/imagedata.cc | 73 +++++++++++++++++++++-------------------- rtengine/imagedata.h | 2 +- rtgui/cacheimagedata.cc | 37 +++++++++++++++++---- 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 26fe80f03..faa7ad5ed 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -69,37 +69,40 @@ FramesMetaData* FramesMetaData::fromFile (const Glib::ustring& fname, std::uniqu return new FramesData (fname, std::move(rml), firstFrameOnly); } -FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir) - : frameRootDir(frameRootDir_), iptc(nullptr), time(), timeStamp(), iso_speed(0), aperture(0.), focal_len(0.), focal_len35mm(0.), focus_dist(0.f), - shutter(0.), expcomp(0.), make("Unknown"), model("Unknown"), orientation("Unknown"), rating(0), lens("Unknown"), - sampleFormat(IIOSF_UNKNOWN), isPixelShift(false), isHDR(false) +FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir) : + frameRootDir(frameRootDir_), + iptc(nullptr), + time{}, + timeStamp{}, + iso_speed(0), + aperture(0.), + focal_len(0.), + focal_len35mm(0.), + focus_dist(0.f), + shutter(0.), + expcomp(0.), + make("Unknown"), + model("Unknown"), + orientation("Unknown"), + rating(0), + lens("Unknown"), + sampleFormat(IIOSF_UNKNOWN), + isPixelShift(false), + isHDR(false) { - memset (&time, 0, sizeof(time)); - if (!frameRootDir) { return; } - rtexif::Tag* tag; - rtexif::TagDirectory* newFrameRootDir = frameRootDir; - - memset(&time, 0, sizeof(time)); - timeStamp = 0; - iso_speed = 0; - aperture = 0.0; - focal_len = 0.0; - focal_len35mm = 0.0; - focus_dist = 0.0f; - shutter = 0.0; - expcomp = 0.0; make.clear(); model.clear(); serial.clear(); orientation.clear(); lens.clear(); - rating = 0; - tag = newFrameRootDir->findTag("Make"); + rtexif::TagDirectory* newFrameRootDir = frameRootDir; + + rtexif::Tag* tag = newFrameRootDir->findTag("Make"); if (!tag) { newFrameRootDir = rootDir; tag = newFrameRootDir->findTag("Make"); @@ -198,17 +201,11 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* } char sXMPRating[64]; if (newFrameRootDir->getXMPTagValue("xmp:Rating", sXMPRating)) { - rating = atoi(sXMPRating); - } - // guard against out-of-range values - if (rating > 5) { - rating = 5; - } - // Currently, Rating=-1 is not supported. A value of -1 should mean - // "Rejected" according to the specification. Maybe in the future, Rating=-1 - // sets InTrash=true? - if (rating < 0) { - rating = 0; + // Guard against out-of-range values (<0, >5) + rating = rtengine::max(0, rtengine::min(5, atoi(sXMPRating))); + // Currently, Rating=-1 is not supported. A value of -1 should mean + // "Rejected" according to the specification. Maybe in the future, Rating=-1 + // sets InTrash=true? } tag = newFrameRootDir->findTagUpward("MakerNote"); @@ -1197,15 +1194,21 @@ std::string FramesData::getOrientation(unsigned int frame) const } ); } -int FramesData::getRating (unsigned int frame) const + +int FramesData::getRating(unsigned int frame) const { - return frames.empty() || frame >= frames.size() ? 0 : frames.at(frame)->getRating (); + return getFromFrame( + frames, + frame, + [](const FrameData& frame_data) + { + return frame_data.getRating(); + } + ); } - //------inherited functions--------------// - std::string FramesMetaData::apertureToString (double aperture) { diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index 097a5cc80..d06820296 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -127,7 +127,7 @@ public: std::string getModel (unsigned int frame = 0) const override; std::string getLens (unsigned int frame = 0) const override; std::string getSerialNumber (unsigned int frame = 0) const; - std::string getOrientation (unsigned int frame = 0) const; + std::string getOrientation (unsigned int frame = 0) const override; int getRating (unsigned int frame = 0) const override; }; diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 47318990d..1756f523b 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -24,12 +24,37 @@ #include "../rtengine/procparams.h" -CacheImageData::CacheImageData () - : md5(""), supported(false), format(FT_Invalid), rankOld(-1), inTrashOld(false), recentlySaved(false), - timeValid(false), year(0), month(0), day(0), hour(0), min(0), sec(0), exifValid(false), frameCount(1), - fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), rating(0), isHDR (false), - isPixelShift (false), sensortype(rtengine::ST_NONE), sampleFormat(rtengine::IIOSF_UNKNOWN), - redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), rotate(0), thumbImgType(0) +CacheImageData::CacheImageData() : + supported(false), + format(FT_Invalid), + rankOld(-1), + inTrashOld(false), + recentlySaved(false), + timeValid(false), + year(0), + month(0), + day(0), + hour(0), + min(0), + sec(0), + exifValid(false), + frameCount(1), + fnumber(0.0), + shutter(0.0), + focalLen(0.0), + focalLen35mm(0.0), + focusDist(0.f), + iso(0), + rating(0), + isHDR (false), + isPixelShift (false), + sensortype(rtengine::ST_NONE), + sampleFormat(rtengine::IIOSF_UNKNOWN), + redAWBMul(-1.0), + greenAWBMul(-1.0), + blueAWBMul(-1.0), + rotate(0), + thumbImgType(0) { } From 880a6e125e85977f590de24ec60bbe40710193e9 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Fri, 21 Jun 2019 07:12:42 +0200 Subject: [PATCH 27/42] Added film negative processing in thumbnails, with correct white balance. Calculated channel averages to restore the same initial conditions as RawImageSource, where get_colorsCoeff is called with forceAutoWB = true. Code still needs refinement and cleanup. --- rtengine/rtthumbnail.cc | 72 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 0a74cf8c2..52691475e 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -39,9 +39,12 @@ #include "settings.h" #include "procparams.h" #include +#define BENCHMARK #include "StopWatch.h" #include "median.h" +#include "rt_algo.h" + namespace { @@ -1167,6 +1170,75 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT Imagefloat* baseImg = resizeTo (rwidth, rheight, interp, thumbImg); + if(isRaw && params.filmNegative.enabled) { + StopWatch stop1("Thumbnail film negative", true); + + // Channel exponents + const float rexp = -params.filmNegative.redExp; + const float gexp = -params.filmNegative.greenExp; + const float bexp = -params.filmNegative.blueExp; + + // Need to calculate channel averages, to fake the same conditions + // found in rawimagesource, where get_ColorsCoeff is called with + // forceAutoWB=true. + float rsum = 0.f, gsum = 0.f, bsum = 0.f; + + // Channel vectors to calculate medians + std::vector rv, gv, bv; + + for (int i = 0; i < rheight; i++) { + for (int j = 0; j < rwidth; j++) { + const float r = baseImg->r(i, j); + const float g = baseImg->g(i, j); + const float b = baseImg->b(i, j); + + rsum += r; + gsum += g; + bsum += b; + + rv.push_back(r); + gv.push_back(g); + bv.push_back(b); + } + } + + const float ravg = rsum / (rheight*rwidth); + const float gavg = gsum / (rheight*rwidth); + const float bavg = bsum / (rheight*rwidth); + + // Shifting current WB multipliers, based on channel averages. + rmi /= (gavg/ravg); + // gmi /= (gAvg/gAvg); green chosen as reference channel + bmi /= (gavg/bavg); + + float rmed, gmed, bmed; + findMinMaxPercentile(rv.data(), rv.size(), 0.5f, rmed, 0.5f, rmed, true); + findMinMaxPercentile(gv.data(), gv.size(), 0.5f, gmed, 0.5f, gmed, true); + findMinMaxPercentile(bv.data(), bv.size(), 0.5f, bmed, 0.5f, bmed, true); + + rmed = powf(rmed, rexp); + gmed = powf(gmed, gexp); + bmed = powf(bmed, bexp); + + const float MAX_OUT_VALUE = 65000.f; + const float rmult = (MAX_OUT_VALUE / (rmed * 24)) ; + const float gmult = (MAX_OUT_VALUE / (gmed * 24)) ; + const float bmult = (MAX_OUT_VALUE / (bmed * 24)) ; + + if (settings->verbose) { + printf("Thumbnail channel medians: %g %g %g\n", rmed, gmed, bmed); + printf("Thumbnail computed multipliers: %g %g %g\n", rmult, gmult, bmult); + } + + for (int i = 0; i < rheight; i++) { + for (int j = 0; j < rwidth; j++) { + baseImg->r(i, j) = CLIP(rmult * powf(baseImg->r (i, j), rexp)); + baseImg->g(i, j) = CLIP(gmult * powf(baseImg->g (i, j), gexp)); + baseImg->b(i, j) = CLIP(bmult * powf(baseImg->b (i, j), bexp)); + } + } + } + if (params.coarse.rotate) { baseImg->rotate (params.coarse.rotate); rwidth = baseImg->getWidth(); From 8c6458daff364af5fb8c621009f0ec1fd417a707 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Fri, 21 Jun 2019 20:51:50 +0200 Subject: [PATCH 28/42] Removed "lock channels" CheckButton, it wasn't very useful. Keeping the "(lead)" note on the green channel label, to give a hint that this slider controls the other two as well. --- rtdata/languages/default | 2 -- rtgui/filmnegative.cc | 20 -------------------- rtgui/filmnegative.h | 4 ---- 3 files changed, 26 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 36e441015..79fdc5729 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1642,8 +1642,6 @@ TP_FILMNEGATIVE_BLUE;Blue exponent TP_FILMNEGATIVE_GREEN;Green exponent (lead) TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. TP_FILMNEGATIVE_LABEL;Film Negative -TP_FILMNEGATIVE_LOCKCHANNELS;Lock exponent ratios -TP_FILMNEGATIVE_LOCKCHANNELS_TOOLTIP;Unlock to adjust channel exponents independently. This allows to adapt to the color characteristics of different film types. TP_FILMNEGATIVE_PICK;Pick white and black spots TP_FILMNEGATIVE_RED;Red exponent TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index b6cb9f1c6..36f2e7c34 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -54,18 +54,11 @@ FilmNegative::FilmNegative() : redExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_RED"), 2.72)), greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 2.0)), blueExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_BLUE"), 1.72)), - lockChannels(Gtk::manage(new Gtk::CheckButton(M("TP_FILMNEGATIVE_LOCKCHANNELS")))), spotgrid(Gtk::manage(new Gtk::Grid())), spotbutton(Gtk::manage(new Gtk::ToggleButton(M("TP_FILMNEGATIVE_PICK")))), redRatio(redExp->getValue() / greenExp->getValue()), blueRatio(blueExp->getValue() / greenExp->getValue()) { - redExp->set_sensitive(false); - blueExp->set_sensitive(false); - - lockChannels->set_tooltip_text(M("TP_FILMNEGATIVE_LOCKCHANNELS_TOOLTIP")); - lockChannels->set_active (true); - spotgrid->get_style_context()->add_class("grid-spacing"); setExpandAlignProperties(spotgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); @@ -93,13 +86,11 @@ FilmNegative::FilmNegative() : // spotgrid->attach (*slab, 1, 0, 1, 1); // spotgrid->attach (*wbsizehelper, 2, 0, 1, 1); - pack_start(*lockChannels, Gtk::PACK_SHRINK, 0); pack_start(*redExp, Gtk::PACK_SHRINK, 0); pack_start(*greenExp, Gtk::PACK_SHRINK, 0); pack_start(*blueExp, Gtk::PACK_SHRINK, 0); pack_start(*spotgrid, Gtk::PACK_SHRINK, 0); - lockChannels->signal_toggled().connect(sigc::mem_fun(*this, &FilmNegative::lockChannelsToggled)); spotbutton->signal_toggled().connect(sigc::mem_fun(*this, &FilmNegative::editToggled)); // spotsize->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::spotSizeChanged) ); @@ -183,11 +174,7 @@ void FilmNegative::setBatchMode(bool batchMode) { if (batchMode) { spotConn.disconnect(); - lockChannelsConn.disconnect(); removeIfThere(this, spotgrid, false); - removeIfThere(this, lockChannels, false); - redExp->set_sensitive(true); - blueExp->set_sensitive(true); ToolPanel::setBatchMode(batchMode); redExp->showEditedCB(); greenExp->showEditedCB(); @@ -343,10 +330,3 @@ void FilmNegative::editToggled() unsubscribe(); } } - -void FilmNegative::lockChannelsToggled() -{ - const bool unlocked = !lockChannels->get_active(); - redExp->set_sensitive(unlocked); - blueExp->set_sensitive(unlocked); -} diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h index b21bc23c3..b8aa338c6 100644 --- a/rtgui/filmnegative.h +++ b/rtgui/filmnegative.h @@ -71,7 +71,6 @@ public: private: void editToggled(); - void lockChannelsToggled(); const rtengine::ProcEvent evFilmNegativeExponents; const rtengine::ProcEvent evFilmNegativeEnabled; @@ -84,9 +83,6 @@ private: Adjuster* const greenExp; Adjuster* const blueExp; - Gtk::CheckButton* const lockChannels; - sigc::connection lockChannelsConn; - Gtk::Grid* const spotgrid; Gtk::ToggleButton* const spotbutton; sigc::connection spotConn; From 2fde6e562ad52cff16c098651377d20a0e35b8cd Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Sun, 23 Jun 2019 22:21:24 +0200 Subject: [PATCH 29/42] The "dual-spot" exponents calculation feature now honors the master (green) exponent set by the user, and adjusts red and blue based on the ratios between the new, "guessed" exponents. This way, if the user has chosen a different master exponent than the default, using the feature just alters the color characteristic of the conversion, while keeping the same contrast level. --- rtengine/filmnegativeproc.cc | 4 ++-- rtgui/filmnegative.cc | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index f5a231c05..eed10fdc4 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -151,9 +151,9 @@ bool rtengine::RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D s // compared to the ratio in the reference channel (green) for (int ch = 0; ch < 3; ++ch) { if (ch == 1) { - newExps[ch] = 2.f; // Green is the reference channel + newExps[ch] = 1.f; // Green is the reference channel } else { - newExps[ch] = CLAMP(2.f * logBase(clearVals[ch] / denseVals[ch], denseGreenRatio), 0.3f, 6.f); + newExps[ch] = CLAMP(logBase(clearVals[ch] / denseVals[ch], denseGreenRatio), 0.3f, 6.f); } } diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 36f2e7c34..d84c1bd0a 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -273,11 +273,12 @@ bool FilmNegative::button1Pressed(int modifierKey) std::array newExps; if (fnp->getFilmNegativeExponents(refSpotCoords[0], refSpotCoords[1], newExps)) { disableListener(); - redExp->setValue(newExps[0]); - greenExp->setValue(newExps[1]); - blueExp->setValue(newExps[2]); - redRatio = redExp->getValue() / greenExp->getValue(); - blueRatio = blueExp->getValue() / greenExp->getValue(); + // Leaving green exponent unchanged, setting red and blue exponents based on + // the ratios between newly calculated exponents. + redRatio = newExps[0] / newExps[1]; + blueRatio = newExps[2] / newExps[1]; + redExp->setValue(greenExp->getValue() * redRatio); + blueExp->setValue(greenExp->getValue() * blueRatio); enableListener(); if (listener && getEnabled()) { From 22f6297a5bd09e04482949ad91c847389e3b6b64 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Mon, 24 Jun 2019 21:48:06 +0200 Subject: [PATCH 30/42] Removed clipping check for values above 65535 (reverts commit 9156572). It was just a defensive check to avoid hitting corner cases like this: 1e4f9ac , that is already fixed elsewhere. The check is now causing problems with the dual-spot feature, because after clipping, the formula cannot be undone to get back the original raw values. Since there are no known issues caused by raw values >65k, i'm removing the check until there will be a good reason to re-introduce it. --- rtengine/filmnegativeproc.cc | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index eed10fdc4..6e2f4e37c 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -268,7 +268,6 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ if (ri->getSensorType() == ST_BAYER) { #ifdef __SSE2__ const vfloat onev = F2V(1.f); - const vfloat c65535v = F2V(65535.f); #endif #ifdef _OPENMP @@ -285,21 +284,20 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ const vfloat expsv = _mm_setr_ps(exps0, exps1, exps0, exps1); const vfloat multsv = _mm_setr_ps(mult0, mult1, mult0, mult1); for (; col < W - 3; col += 4) { - STVFU(rawData[row][col], vminf(multsv * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv), c65535v)); + STVFU(rawData[row][col], multsv * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv)); } #endif // __SSE2__ for (; col < W - 1; col += 2) { - rawData[row][col] = rtengine::min(mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0), 65535.f); - rawData[row][col + 1] = rtengine::min(mult1 * pow_F(rtengine::max(rawData[row][col + 1], 1.f), exps1), 65535.f); + rawData[row][col] = mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0); + rawData[row][col + 1] = mult1 * pow_F(rtengine::max(rawData[row][col + 1], 1.f), exps1); } if (col < W) { - rawData[row][col] = rtengine::min(mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0), 65535.f); + rawData[row][col] = mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0); } } } else if (ri->getSensorType() == ST_FUJI_XTRANS) { #ifdef __SSE2__ const vfloat onev = F2V(1.f); - const vfloat c65535v = F2V(65535.f); #endif #ifdef _OPENMP @@ -332,18 +330,18 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ const vfloat multsv1 = _mm_setr_ps(multsc[4], multsc[5], multsc[0], multsc[1]); const vfloat multsv2 = _mm_setr_ps(multsc[2], multsc[3], multsc[4], multsc[5]); for (; col < W - 11; col += 12) { - STVFU(rawData[row][col], vminf(multsv0 * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv0), c65535v)); - STVFU(rawData[row][col + 4], vminf(multsv1 * pow_F(vmaxf(LVFU(rawData[row][col + 4]), onev), expsv1), c65535v)); - STVFU(rawData[row][col + 8], vminf(multsv2 * pow_F(vmaxf(LVFU(rawData[row][col + 8]), onev), expsv2), c65535v)); + STVFU(rawData[row][col], multsv0 * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv0)); + STVFU(rawData[row][col + 4], multsv1 * pow_F(vmaxf(LVFU(rawData[row][col + 4]), onev), expsv1)); + STVFU(rawData[row][col + 8], multsv2 * pow_F(vmaxf(LVFU(rawData[row][col + 8]), onev), expsv2)); } #endif // __SSE2__ for (; col < W - 5; col += 6) { for (int c = 0; c < 6; ++c) { - rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]), 65535.f); + rawData[row][col + c] = multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]); } } for (int c = 0; col < W; col++, c++) { - rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]), 65535.f); + rawData[row][col + c] = multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]); } } } From 157d83d1694754d837f30ce85314806e950b444b Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Wed, 26 Jun 2019 00:14:03 +0200 Subject: [PATCH 31/42] Partially reverting my last commit. When using large exponents, huge raw values could cause segfaults in ImProcFunctions:rgbProc (specifically in shadowToneCurve), and in Amaze demosaic. Re-added the clipping check on raw values, but with a higher threshold. This way, raw clipping is less frequent in highlight areas (so those can be used as spots for exponents calculation), but the threshold is low enough to avoid the segfaults. Not a very clean solution, need to find a better one... --- rtengine/filmnegativeproc.cc | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index 6e2f4e37c..555a47506 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -263,11 +263,14 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ printf("Median calc time us: %d\n", t3.etime(t2)); } + constexpr float CLIP_VAL = 20 * MAX_OUT_VALUE; + t3.set(); if (ri->getSensorType() == ST_BAYER) { #ifdef __SSE2__ const vfloat onev = F2V(1.f); + const vfloat clipv = F2V(CLIP_VAL); #endif #ifdef _OPENMP @@ -284,20 +287,21 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ const vfloat expsv = _mm_setr_ps(exps0, exps1, exps0, exps1); const vfloat multsv = _mm_setr_ps(mult0, mult1, mult0, mult1); for (; col < W - 3; col += 4) { - STVFU(rawData[row][col], multsv * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv)); + STVFU(rawData[row][col], vminf(multsv * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv), clipv)); } #endif // __SSE2__ for (; col < W - 1; col += 2) { - rawData[row][col] = mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0); - rawData[row][col + 1] = mult1 * pow_F(rtengine::max(rawData[row][col + 1], 1.f), exps1); + rawData[row][col] = rtengine::min(mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0), CLIP_VAL); + rawData[row][col + 1] = rtengine::min(mult1 * pow_F(rtengine::max(rawData[row][col + 1], 1.f), exps1), CLIP_VAL); } if (col < W) { - rawData[row][col] = mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0); + rawData[row][col] = rtengine::min(mult0 * pow_F(rtengine::max(rawData[row][col], 1.f), exps0), CLIP_VAL); } } } else if (ri->getSensorType() == ST_FUJI_XTRANS) { #ifdef __SSE2__ const vfloat onev = F2V(1.f); + const vfloat clipv = F2V(CLIP_VAL); #endif #ifdef _OPENMP @@ -330,18 +334,18 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ const vfloat multsv1 = _mm_setr_ps(multsc[4], multsc[5], multsc[0], multsc[1]); const vfloat multsv2 = _mm_setr_ps(multsc[2], multsc[3], multsc[4], multsc[5]); for (; col < W - 11; col += 12) { - STVFU(rawData[row][col], multsv0 * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv0)); - STVFU(rawData[row][col + 4], multsv1 * pow_F(vmaxf(LVFU(rawData[row][col + 4]), onev), expsv1)); - STVFU(rawData[row][col + 8], multsv2 * pow_F(vmaxf(LVFU(rawData[row][col + 8]), onev), expsv2)); + STVFU(rawData[row][col], vminf(multsv0 * pow_F(vmaxf(LVFU(rawData[row][col]), onev), expsv0), clipv)); + STVFU(rawData[row][col + 4], vminf(multsv1 * pow_F(vmaxf(LVFU(rawData[row][col + 4]), onev), expsv1), clipv)); + STVFU(rawData[row][col + 8], vminf(multsv2 * pow_F(vmaxf(LVFU(rawData[row][col + 8]), onev), expsv2), clipv)); } #endif // __SSE2__ for (; col < W - 5; col += 6) { for (int c = 0; c < 6; ++c) { - rawData[row][col + c] = multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]); + rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]), CLIP_VAL); } } for (int c = 0; col < W; col++, c++) { - rawData[row][col + c] = multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]); + rawData[row][col + c] = rtengine::min(multsc[c] * pow_F(rtengine::max(rawData[row][col + c], 1.f), expsc[c]), CLIP_VAL); } } } From 63a6e1b79cc4a6033c2fcb77b74d78857423829b Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Wed, 26 Jun 2019 01:06:48 +0200 Subject: [PATCH 32/42] Changed GUI behaviour so that the first slider sets the reference exponent (green channel), and the other two sliders set the ratio of the red/blue exponent to the reference one. This should be more intuitive, and less confusing when clicking on the reset-to-default slider button. Now the first slider sets the general contrast, while the other two affect the color. Lowered exponent slider max value from 6 to 4 (it was too large to be useful). New sliders are log-scale. --- rtdata/languages/default | 6 +-- rtgui/filmnegative.cc | 87 +++++++++++++++++----------------------- rtgui/filmnegative.h | 7 +--- 3 files changed, 42 insertions(+), 58 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 79fdc5729..63c877bbf 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1638,12 +1638,12 @@ TP_EXPOSURE_TCMODE_STANDARD;Standard TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points TP_EXPOS_WHITEPOINT_LABEL;Raw White Points -TP_FILMNEGATIVE_BLUE;Blue exponent -TP_FILMNEGATIVE_GREEN;Green exponent (lead) +TP_FILMNEGATIVE_BLUE;Blue ratio +TP_FILMNEGATIVE_GREEN;Reference exponent (contrast) TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. TP_FILMNEGATIVE_LABEL;Film Negative TP_FILMNEGATIVE_PICK;Pick white and black spots -TP_FILMNEGATIVE_RED;Red exponent +TP_FILMNEGATIVE_RED;Red ratio TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots TP_FILMSIMULATION_LABEL;Film Simulation TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index d84c1bd0a..129af3034 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -30,11 +30,15 @@ namespace { -Adjuster* createExponentAdjuster(AdjusterListener* listener, const Glib::ustring& label, double defaultVal) +Adjuster* createExponentAdjuster(AdjusterListener* listener, const Glib::ustring& label, double minV, double maxV, double defaultVal, bool log) { - Adjuster* const adj = Gtk::manage(new Adjuster(label, 0.3, 6, 0.001, defaultVal)); // exponent + Adjuster* const adj = Gtk::manage(new Adjuster(label, minV, maxV, 0.001, defaultVal)); // exponent adj->setAdjusterListener(listener); + if (log) { + adj->setLogScale(10, minV, false); + } + if (adj->delay < options.adjusterMaxDelay) { adj->delay = options.adjusterMaxDelay; } @@ -51,13 +55,11 @@ FilmNegative::FilmNegative() : evFilmNegativeExponents(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_EXPONENTS")), evFilmNegativeEnabled(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_ENABLED")), fnp(nullptr), - redExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_RED"), 2.72)), - greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 2.0)), - blueExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_BLUE"), 1.72)), + greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 0.3, 4, 2.0, false)), + redRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_RED"), 0.3, 3, 1.36, true)), + blueRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_BLUE"), 0.3, 3, 0.86, true)), spotgrid(Gtk::manage(new Gtk::Grid())), - spotbutton(Gtk::manage(new Gtk::ToggleButton(M("TP_FILMNEGATIVE_PICK")))), - redRatio(redExp->getValue() / greenExp->getValue()), - blueRatio(blueExp->getValue() / greenExp->getValue()) + spotbutton(Gtk::manage(new Gtk::ToggleButton(M("TP_FILMNEGATIVE_PICK")))) { spotgrid->get_style_context()->add_class("grid-spacing"); setExpandAlignProperties(spotgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); @@ -86,9 +88,9 @@ FilmNegative::FilmNegative() : // spotgrid->attach (*slab, 1, 0, 1, 1); // spotgrid->attach (*wbsizehelper, 2, 0, 1, 1); - pack_start(*redExp, Gtk::PACK_SHRINK, 0); pack_start(*greenExp, Gtk::PACK_SHRINK, 0); - pack_start(*blueExp, Gtk::PACK_SHRINK, 0); + pack_start(*redRatio, Gtk::PACK_SHRINK, 0); + pack_start(*blueRatio, Gtk::PACK_SHRINK, 0); pack_start(*spotgrid, Gtk::PACK_SHRINK, 0); spotbutton->signal_toggled().connect(sigc::mem_fun(*this, &FilmNegative::editToggled)); @@ -124,49 +126,49 @@ void FilmNegative::read(const rtengine::procparams::ProcParams* pp, const Params disableListener(); if (pedited) { - redExp->setEditedState(pedited->filmNegative.redExp ? Edited : UnEdited); + redRatio->setEditedState(pedited->filmNegative.redExp ? Edited : UnEdited); greenExp->setEditedState(pedited->filmNegative.greenExp ? Edited : UnEdited); - blueExp->setEditedState(pedited->filmNegative.blueExp ? Edited : UnEdited); + blueRatio->setEditedState(pedited->filmNegative.blueExp ? Edited : UnEdited); set_inconsistent(multiImage && !pedited->filmNegative.enabled); } setEnabled(pp->filmNegative.enabled); - redExp->setValue(pp->filmNegative.redExp); + redRatio->setValue(pp->filmNegative.redExp / pp->filmNegative.greenExp); greenExp->setValue(pp->filmNegative.greenExp); - blueExp->setValue(pp->filmNegative.blueExp); + blueRatio->setValue(pp->filmNegative.blueExp / pp->filmNegative.greenExp); enableListener(); } void FilmNegative::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->filmNegative.redExp = redExp->getValue(); + pp->filmNegative.redExp = greenExp->getValue() * redRatio->getValue(); pp->filmNegative.greenExp = greenExp->getValue(); - pp->filmNegative.blueExp = blueExp->getValue(); + pp->filmNegative.blueExp = greenExp->getValue() * blueRatio->getValue(); pp->filmNegative.enabled = getEnabled(); if (pedited) { - pedited->filmNegative.redExp = redExp->getEditedState(); + pedited->filmNegative.redExp = greenExp->getEditedState() || redRatio->getEditedState(); pedited->filmNegative.greenExp = greenExp->getEditedState(); - pedited->filmNegative.blueExp = blueExp->getEditedState(); + pedited->filmNegative.blueExp = greenExp->getEditedState() || blueRatio->getEditedState(); pedited->filmNegative.enabled = !get_inconsistent(); } } void FilmNegative::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { - redExp->setValue(defParams->filmNegative.redExp); + redRatio->setValue(defParams->filmNegative.redExp / defParams->filmNegative.greenExp); greenExp->setValue(defParams->filmNegative.greenExp); - blueExp->setValue(defParams->filmNegative.blueExp); + blueRatio->setValue(defParams->filmNegative.blueExp / defParams->filmNegative.greenExp); if (pedited) { - redExp->setDefaultEditedState(pedited->filmNegative.redExp ? Edited : UnEdited); + redRatio->setDefaultEditedState(pedited->filmNegative.redExp ? Edited : UnEdited); greenExp->setDefaultEditedState(pedited->filmNegative.greenExp ? Edited : UnEdited); - blueExp->setDefaultEditedState(pedited->filmNegative.blueExp ? Edited : UnEdited); + blueRatio->setDefaultEditedState(pedited->filmNegative.blueExp ? Edited : UnEdited); } else { - redExp->setDefaultEditedState(Irrelevant); + redRatio->setDefaultEditedState(Irrelevant); greenExp->setDefaultEditedState(Irrelevant); - blueExp->setDefaultEditedState(Irrelevant); + blueRatio->setDefaultEditedState(Irrelevant); } } @@ -176,37 +178,24 @@ void FilmNegative::setBatchMode(bool batchMode) spotConn.disconnect(); removeIfThere(this, spotgrid, false); ToolPanel::setBatchMode(batchMode); - redExp->showEditedCB(); + redRatio->showEditedCB(); greenExp->showEditedCB(); - blueExp->showEditedCB(); + blueRatio->showEditedCB(); } } void FilmNegative::adjusterChanged(Adjuster* a, double newval) { if (listener) { - if (a == redExp || a == greenExp || a == blueExp) { - disableListener(); - if (a == greenExp) { - redExp->setValue(a->getValue() * redRatio); - blueExp->setValue(a->getValue() * blueRatio); - } - else if (a == redExp) { - redRatio = newval / greenExp->getValue(); - } - else if (a == blueExp) { - blueRatio = newval / greenExp->getValue(); - } - enableListener(); - + if (a == redRatio || a == greenExp || a == blueRatio) { if (getEnabled()) { listener->panelChanged( evFilmNegativeExponents, Glib::ustring::compose( "R=%1 ; G=%2 ; B=%3", - redExp->getTextValue(), - greenExp->getTextValue(), - blueExp->getTextValue() + greenExp->getValue() * redRatio->getValue(), + greenExp->getValue(), + greenExp->getValue() * blueRatio->getValue() ) ); } @@ -275,10 +264,8 @@ bool FilmNegative::button1Pressed(int modifierKey) disableListener(); // Leaving green exponent unchanged, setting red and blue exponents based on // the ratios between newly calculated exponents. - redRatio = newExps[0] / newExps[1]; - blueRatio = newExps[2] / newExps[1]; - redExp->setValue(greenExp->getValue() * redRatio); - blueExp->setValue(greenExp->getValue() * blueRatio); + redRatio->setValue(newExps[0] / newExps[1]); + blueRatio->setValue(newExps[2] / newExps[1]); enableListener(); if (listener && getEnabled()) { @@ -286,9 +273,9 @@ bool FilmNegative::button1Pressed(int modifierKey) evFilmNegativeExponents, Glib::ustring::compose( "R=%1 ; G=%2 ; B=%3", - redExp->getTextValue(), - greenExp->getTextValue(), - blueExp->getTextValue() + greenExp->getValue() * redRatio->getValue(), + greenExp->getValue(), + greenExp->getValue() * blueRatio->getValue() ) ); } diff --git a/rtgui/filmnegative.h b/rtgui/filmnegative.h index b8aa338c6..7de1bd56a 100644 --- a/rtgui/filmnegative.h +++ b/rtgui/filmnegative.h @@ -79,14 +79,11 @@ private: FilmNegProvider* fnp; - Adjuster* const redExp; Adjuster* const greenExp; - Adjuster* const blueExp; + Adjuster* const redRatio; + Adjuster* const blueRatio; Gtk::Grid* const spotgrid; Gtk::ToggleButton* const spotbutton; sigc::connection spotConn; - - double redRatio; - double blueRatio; }; From a3004bb2b8be6242b927a048d3f68a77456e80fc Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Thu, 27 Jun 2019 22:03:59 +0200 Subject: [PATCH 33/42] Added SSE2 optimization in film negative thumbnail processing. --- rtengine/rtthumbnail.cc | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 52691475e..7e4544a0d 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1229,12 +1229,33 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT printf("Thumbnail channel medians: %g %g %g\n", rmed, gmed, bmed); printf("Thumbnail computed multipliers: %g %g %g\n", rmult, gmult, bmult); } - + +#ifdef __SSE2__ + const vfloat clipv = F2V(MAXVALF); + const vfloat rexpv = F2V(rexp); + const vfloat gexpv = F2V(gexp); + const vfloat bexpv = F2V(bexp); + const vfloat rmultv = F2V(rmult); + const vfloat gmultv = F2V(gmult); + const vfloat bmultv = F2V(bmult); +#endif + for (int i = 0; i < rheight; i++) { - for (int j = 0; j < rwidth; j++) { - baseImg->r(i, j) = CLIP(rmult * powf(baseImg->r (i, j), rexp)); - baseImg->g(i, j) = CLIP(gmult * powf(baseImg->g (i, j), gexp)); - baseImg->b(i, j) = CLIP(bmult * powf(baseImg->b (i, j), bexp)); + float *rline = baseImg->r(i); + float *gline = baseImg->g(i); + float *bline = baseImg->b(i); + int j = 0; +#ifdef __SSE2__ + for (; j < rwidth - 3; j +=4) { + STVFU(rline[j], vminf(rmultv * pow_F(LVFU(rline[j]), rexpv), clipv)); + STVFU(gline[j], vminf(gmultv * pow_F(LVFU(gline[j]), gexpv), clipv)); + STVFU(bline[j], vminf(bmultv * pow_F(LVFU(bline[j]), bexpv), clipv)); + } +#endif + for (; j < rwidth; ++j) { + rline[j] = CLIP(rmult * powf(rline[j], rexp)); + gline[j] = CLIP(gmult * powf(gline[j], gexp)); + bline[j] = CLIP(bmult * powf(bline[j], bexp)); } } } From 938fc63dd0b25200cd4732c10aaa4ab2b51b718e Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Thu, 27 Jun 2019 23:01:51 +0200 Subject: [PATCH 34/42] Replaced `powf` calls with the optimized `pow_F` macro (which also works for the non-SSE2 case). --- rtengine/rtthumbnail.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 7e4544a0d..60052f783 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1253,9 +1253,9 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT } #endif for (; j < rwidth; ++j) { - rline[j] = CLIP(rmult * powf(rline[j], rexp)); - gline[j] = CLIP(gmult * powf(gline[j], gexp)); - bline[j] = CLIP(bmult * powf(bline[j], bexp)); + rline[j] = CLIP(rmult * pow_F(rline[j], rexp)); + gline[j] = CLIP(gmult * pow_F(gline[j], gexp)); + bline[j] = CLIP(bmult * pow_F(bline[j], bexp)); } } } From d7bab9ba9f7981b3e1710f88ec25df9200c5e11d Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Fri, 28 Jun 2019 20:44:40 +0200 Subject: [PATCH 35/42] Changed `channelsAverage()` to sample values from the original data in the RawImage instance, taking into account black levels. This lets me completely revert my awful commit 22f6297a5 and clip values to 65535, as it should be to avoid trouble downstream. --- rtengine/filmnegativeproc.cc | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index 555a47506..4abe32b86 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -49,6 +49,7 @@ bool channelsAvg( int width, int height, array2D& rawData, + const float* cblacksom, rtengine::Coord spotPos, int spotSize, const rtengine::procparams::FilmNegativeParams& params, @@ -83,13 +84,9 @@ bool channelsAvg( ++pxCount[ch]; - // If film negative is currently enabled, undo the effect by elevating to 1/exp, - // in order to sample the original, linear value - if (params.enabled) { - avgs[ch] += powf(rawData[r][c], -1.f / (ch == 0 ? params.redExp : ch == 1 ? params.greenExp : params.blueExp)); - } else { - avgs[ch] += rawData[r][c]; - } + // Sample the original unprocessed values from RawImage, subtracting black levels. + // Scaling is irrelevant, as we are only interested in the ratio between two spots. + avgs[ch] += ri->data[r][c] - cblacksom[ch]; } } @@ -118,13 +115,13 @@ bool rtengine::RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D s // Sample first spot transformPosition(spotA.x, spotA.y, tran, spot.x, spot.y); - if (!channelsAvg(ri, W, H, rawData, spot, spotSize, currentParams, clearVals)) { + if (!channelsAvg(ri, W, H, rawData, cblacksom, spot, spotSize, currentParams, clearVals)) { return false; } // Sample second spot transformPosition(spotB.x, spotB.y, tran, spot.x, spot.y); - if (!channelsAvg(ri, W, H, rawData, spot, spotSize, currentParams, denseVals)) { + if (!channelsAvg(ri, W, H, rawData, cblacksom, spot, spotSize, currentParams, denseVals)) { return false; } @@ -263,7 +260,7 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ printf("Median calc time us: %d\n", t3.etime(t2)); } - constexpr float CLIP_VAL = 20 * MAX_OUT_VALUE; + constexpr float CLIP_VAL = 65535.f; t3.set(); From 4e09fd4f212efd3e8b0606302745beb1ef42d066 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Fri, 28 Jun 2019 21:29:06 +0200 Subject: [PATCH 36/42] Changed master exponent default from 2.0 to 1.5; it was too large for high-contrast negatives. Set all sliders as log-scale, centered at 1.0, so that reasonable values can be fine-tuned more easily. --- rtengine/filmnegativeproc.cc | 2 +- rtengine/procparams.cc | 6 +++--- rtgui/filmnegative.cc | 15 ++++++--------- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index 4abe32b86..f3cca1245 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -150,7 +150,7 @@ bool rtengine::RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D s if (ch == 1) { newExps[ch] = 1.f; // Green is the reference channel } else { - newExps[ch] = CLAMP(logBase(clearVals[ch] / denseVals[ch], denseGreenRatio), 0.3f, 6.f); + newExps[ch] = CLAMP(logBase(clearVals[ch] / denseVals[ch], denseGreenRatio), 0.3f, 4.f); } } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 4ed97f767..b35faca94 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2736,9 +2736,9 @@ bool MetaDataParams::operator!=(const MetaDataParams &other) const FilmNegativeParams::FilmNegativeParams() : enabled(false), - redExp(2.72), - greenExp(2.0), - blueExp(1.72) + redExp(2.04), + greenExp(1.5), + blueExp(1.29) { } diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 129af3034..0e6ec9e8f 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -30,14 +30,11 @@ namespace { -Adjuster* createExponentAdjuster(AdjusterListener* listener, const Glib::ustring& label, double minV, double maxV, double defaultVal, bool log) +Adjuster* createExponentAdjuster(AdjusterListener* listener, const Glib::ustring& label, double minV, double maxV, double defaultVal) { - Adjuster* const adj = Gtk::manage(new Adjuster(label, minV, maxV, 0.001, defaultVal)); // exponent + Adjuster* const adj = Gtk::manage(new Adjuster(label, minV, maxV, 0.001, defaultVal)); adj->setAdjusterListener(listener); - - if (log) { - adj->setLogScale(10, minV, false); - } + adj->setLogScale(6, 1, true); if (adj->delay < options.adjusterMaxDelay) { adj->delay = options.adjusterMaxDelay; @@ -55,9 +52,9 @@ FilmNegative::FilmNegative() : evFilmNegativeExponents(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_EXPONENTS")), evFilmNegativeEnabled(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_ENABLED")), fnp(nullptr), - greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 0.3, 4, 2.0, false)), - redRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_RED"), 0.3, 3, 1.36, true)), - blueRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_BLUE"), 0.3, 3, 0.86, true)), + greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 0.3, 4, 1.5)), + redRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_RED"), 0.3, 3, 1.36)), + blueRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_BLUE"), 0.3, 3, 0.86)), spotgrid(Gtk::manage(new Gtk::Grid())), spotbutton(Gtk::manage(new Gtk::ToggleButton(M("TP_FILMNEGATIVE_PICK")))) { From 536bbf95aad6a0c6e989aef36773ec14378a5fbd Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Fri, 28 Jun 2019 22:17:28 +0200 Subject: [PATCH 37/42] Added comments to clarify the difference between default exponents in procparams and default ratios in the GUI sliders. --- rtgui/filmnegative.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 0e6ec9e8f..4956968e3 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -52,9 +52,9 @@ FilmNegative::FilmNegative() : evFilmNegativeExponents(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_EXPONENTS")), evFilmNegativeEnabled(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_ENABLED")), fnp(nullptr), - greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 0.3, 4, 1.5)), - redRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_RED"), 0.3, 3, 1.36)), - blueRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_BLUE"), 0.3, 3, 0.86)), + greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 0.3, 4, 1.5)), // master exponent (green channel) + redRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_RED"), 0.3, 3, (2.04 / 1.5))), // ratio of red exponent to master exponent + blueRatio(createExponentAdjuster(this, M("TP_FILMNEGATIVE_BLUE"), 0.3, 3, (1.29 / 1.5))), // ratio of blue exponent to master exponent spotgrid(Gtk::manage(new Gtk::Grid())), spotbutton(Gtk::manage(new Gtk::ToggleButton(M("TP_FILMNEGATIVE_PICK")))) { From 0920f6dfe8d5656429ef36147cf356dd9e491a12 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Fri, 28 Jun 2019 22:51:22 +0200 Subject: [PATCH 38/42] rawData is not needed anymore in channelsAvg after commit d7bab9ba --- rtengine/filmnegativeproc.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index f3cca1245..db5705a3c 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -48,7 +48,6 @@ bool channelsAvg( const rtengine::RawImage* ri, int width, int height, - array2D& rawData, const float* cblacksom, rtengine::Coord spotPos, int spotSize, @@ -115,13 +114,13 @@ bool rtengine::RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D s // Sample first spot transformPosition(spotA.x, spotA.y, tran, spot.x, spot.y); - if (!channelsAvg(ri, W, H, rawData, cblacksom, spot, spotSize, currentParams, clearVals)) { + if (!channelsAvg(ri, W, H, cblacksom, spot, spotSize, currentParams, clearVals)) { return false; } // Sample second spot transformPosition(spotB.x, spotB.y, tran, spot.x, spot.y); - if (!channelsAvg(ri, W, H, rawData, cblacksom, spot, spotSize, currentParams, denseVals)) { + if (!channelsAvg(ri, W, H, cblacksom, spot, spotSize, currentParams, denseVals)) { return false; } From 41e5899f97bd7055f6ba957c490aeb8d2005c5a0 Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Fri, 28 Jun 2019 22:54:32 +0200 Subject: [PATCH 39/42] Moved film negative thumbnail processing to own compilation unit --- rtengine/CMakeLists.txt | 1 + rtengine/filmnegativethumb.cc | 139 ++++++++++++++++++++++++++++++++++ rtengine/rtthumbnail.cc | 91 +--------------------- rtengine/rtthumbnail.h | 2 + 4 files changed, 143 insertions(+), 90 deletions(-) create mode 100644 rtengine/filmnegativethumb.cc diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 9ac09fbcc..c5c8afa82 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -62,6 +62,7 @@ set(RTENGINESOURCEFILES fast_demo.cc ffmanager.cc filmnegativeproc.cc + filmnegativethumb.cc flatcurves.cc gauss.cc green_equil_RT.cc diff --git a/rtengine/filmnegativethumb.cc b/rtengine/filmnegativethumb.cc new file mode 100644 index 000000000..8889915e6 --- /dev/null +++ b/rtengine/filmnegativethumb.cc @@ -0,0 +1,139 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2019 Alberto Romei + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include +#include + +#ifdef _OPENMP +#include +#endif + +#include "rtengine.h" +#include "rtthumbnail.h" + +#include "mytime.h" +#include "opthelper.h" +#include "procparams.h" +#include "rt_algo.h" +#include "rtengine.h" +#include "settings.h" +#include "procparams.h" +#define BENCHMARK +#include "StopWatch.h" + +namespace rtengine +{ + +extern const Settings* settings; + +} + +void rtengine::Thumbnail::processFilmNegative( + const procparams::ProcParams ¶ms, + const Imagefloat* baseImg, + const int rwidth, const int rheight, + float &rmi, float &gmi, float &bmi +) { + StopWatch stop1("Thumbnail film negative", true); + + // Channel exponents + const float rexp = -params.filmNegative.redExp; + const float gexp = -params.filmNegative.greenExp; + const float bexp = -params.filmNegative.blueExp; + + // Need to calculate channel averages, to fake the same conditions + // found in rawimagesource, where get_ColorsCoeff is called with + // forceAutoWB=true. + float rsum = 0.f, gsum = 0.f, bsum = 0.f; + + // Channel vectors to calculate medians + std::vector rv, gv, bv; + + for (int i = 0; i < rheight; i++) { + for (int j = 0; j < rwidth; j++) { + const float r = baseImg->r(i, j); + const float g = baseImg->g(i, j); + const float b = baseImg->b(i, j); + + rsum += r; + gsum += g; + bsum += b; + + rv.push_back(r); + gv.push_back(g); + bv.push_back(b); + } + } + + const float ravg = rsum / (rheight*rwidth); + const float gavg = gsum / (rheight*rwidth); + const float bavg = bsum / (rheight*rwidth); + + // Shifting current WB multipliers, based on channel averages. + rmi /= (gavg/ravg); + // gmi /= (gAvg/gAvg); green chosen as reference channel + bmi /= (gavg/bavg); + + float rmed, gmed, bmed; + findMinMaxPercentile(rv.data(), rv.size(), 0.5f, rmed, 0.5f, rmed, true); + findMinMaxPercentile(gv.data(), gv.size(), 0.5f, gmed, 0.5f, gmed, true); + findMinMaxPercentile(bv.data(), bv.size(), 0.5f, bmed, 0.5f, bmed, true); + + rmed = powf(rmed, rexp); + gmed = powf(gmed, gexp); + bmed = powf(bmed, bexp); + + const float MAX_OUT_VALUE = 65000.f; + const float rmult = (MAX_OUT_VALUE / (rmed * 24)) ; + const float gmult = (MAX_OUT_VALUE / (gmed * 24)) ; + const float bmult = (MAX_OUT_VALUE / (bmed * 24)) ; + + if (settings->verbose) { + printf("Thumbnail channel medians: %g %g %g\n", rmed, gmed, bmed); + printf("Thumbnail computed multipliers: %g %g %g\n", rmult, gmult, bmult); + } + +#ifdef __SSE2__ + const vfloat clipv = F2V(MAXVALF); + const vfloat rexpv = F2V(rexp); + const vfloat gexpv = F2V(gexp); + const vfloat bexpv = F2V(bexp); + const vfloat rmultv = F2V(rmult); + const vfloat gmultv = F2V(gmult); + const vfloat bmultv = F2V(bmult); +#endif + + for (int i = 0; i < rheight; i++) { + float *rline = baseImg->r(i); + float *gline = baseImg->g(i); + float *bline = baseImg->b(i); + int j = 0; +#ifdef __SSE2__ + for (; j < rwidth - 3; j +=4) { + STVFU(rline[j], vminf(rmultv * pow_F(LVFU(rline[j]), rexpv), clipv)); + STVFU(gline[j], vminf(gmultv * pow_F(LVFU(gline[j]), gexpv), clipv)); + STVFU(bline[j], vminf(bmultv * pow_F(LVFU(bline[j]), bexpv), clipv)); + } +#endif + for (; j < rwidth; ++j) { + rline[j] = CLIP(rmult * pow_F(rline[j], rexp)); + gline[j] = CLIP(gmult * pow_F(gline[j], gexp)); + bline[j] = CLIP(bmult * pow_F(bline[j], bexp)); + } + } +} \ No newline at end of file diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 60052f783..4b0baa685 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -39,12 +39,9 @@ #include "settings.h" #include "procparams.h" #include -#define BENCHMARK #include "StopWatch.h" #include "median.h" -#include "rt_algo.h" - namespace { @@ -1171,93 +1168,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT Imagefloat* baseImg = resizeTo (rwidth, rheight, interp, thumbImg); if(isRaw && params.filmNegative.enabled) { - StopWatch stop1("Thumbnail film negative", true); - - // Channel exponents - const float rexp = -params.filmNegative.redExp; - const float gexp = -params.filmNegative.greenExp; - const float bexp = -params.filmNegative.blueExp; - - // Need to calculate channel averages, to fake the same conditions - // found in rawimagesource, where get_ColorsCoeff is called with - // forceAutoWB=true. - float rsum = 0.f, gsum = 0.f, bsum = 0.f; - - // Channel vectors to calculate medians - std::vector rv, gv, bv; - - for (int i = 0; i < rheight; i++) { - for (int j = 0; j < rwidth; j++) { - const float r = baseImg->r(i, j); - const float g = baseImg->g(i, j); - const float b = baseImg->b(i, j); - - rsum += r; - gsum += g; - bsum += b; - - rv.push_back(r); - gv.push_back(g); - bv.push_back(b); - } - } - - const float ravg = rsum / (rheight*rwidth); - const float gavg = gsum / (rheight*rwidth); - const float bavg = bsum / (rheight*rwidth); - - // Shifting current WB multipliers, based on channel averages. - rmi /= (gavg/ravg); - // gmi /= (gAvg/gAvg); green chosen as reference channel - bmi /= (gavg/bavg); - - float rmed, gmed, bmed; - findMinMaxPercentile(rv.data(), rv.size(), 0.5f, rmed, 0.5f, rmed, true); - findMinMaxPercentile(gv.data(), gv.size(), 0.5f, gmed, 0.5f, gmed, true); - findMinMaxPercentile(bv.data(), bv.size(), 0.5f, bmed, 0.5f, bmed, true); - - rmed = powf(rmed, rexp); - gmed = powf(gmed, gexp); - bmed = powf(bmed, bexp); - - const float MAX_OUT_VALUE = 65000.f; - const float rmult = (MAX_OUT_VALUE / (rmed * 24)) ; - const float gmult = (MAX_OUT_VALUE / (gmed * 24)) ; - const float bmult = (MAX_OUT_VALUE / (bmed * 24)) ; - - if (settings->verbose) { - printf("Thumbnail channel medians: %g %g %g\n", rmed, gmed, bmed); - printf("Thumbnail computed multipliers: %g %g %g\n", rmult, gmult, bmult); - } - -#ifdef __SSE2__ - const vfloat clipv = F2V(MAXVALF); - const vfloat rexpv = F2V(rexp); - const vfloat gexpv = F2V(gexp); - const vfloat bexpv = F2V(bexp); - const vfloat rmultv = F2V(rmult); - const vfloat gmultv = F2V(gmult); - const vfloat bmultv = F2V(bmult); -#endif - - for (int i = 0; i < rheight; i++) { - float *rline = baseImg->r(i); - float *gline = baseImg->g(i); - float *bline = baseImg->b(i); - int j = 0; -#ifdef __SSE2__ - for (; j < rwidth - 3; j +=4) { - STVFU(rline[j], vminf(rmultv * pow_F(LVFU(rline[j]), rexpv), clipv)); - STVFU(gline[j], vminf(gmultv * pow_F(LVFU(gline[j]), gexpv), clipv)); - STVFU(bline[j], vminf(bmultv * pow_F(LVFU(bline[j]), bexpv), clipv)); - } -#endif - for (; j < rwidth; ++j) { - rline[j] = CLIP(rmult * pow_F(rline[j], rexp)); - gline[j] = CLIP(gmult * pow_F(gline[j], gexp)); - bline[j] = CLIP(bmult * pow_F(bline[j], bexp)); - } - } + processFilmNegative(params, baseImg, rwidth, rheight, rmi, gmi, bmi); } if (params.coarse.rotate) { diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index df33b892d..09a0510eb 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -68,6 +68,8 @@ class Thumbnail bool gammaCorrected; double colorMatrix[3][3]; + void processFilmNegative(const procparams::ProcParams& params, const Imagefloat* baseImg, int rwidth, int rheight, float &rmi, float &gmi, float &bmi); + public: bool isRaw; From b4c109f275beaf33d624c9ac7a4ea42cb480d41b Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Sat, 29 Jun 2019 16:06:40 +0200 Subject: [PATCH 40/42] ProcParams now contain red and blue ratios, to be aligned with values in the GUI. --- rtdata/languages/Catala | 6 +-- rtdata/languages/Chinese (Simplified) | 6 +-- rtdata/languages/Deutsch | 6 +-- rtdata/languages/English (UK) | 6 +-- rtdata/languages/English (US) | 6 +-- rtdata/languages/Italiano | 6 +-- rtdata/languages/Magyar | 6 +-- rtdata/languages/Nederlands | 6 +-- rtdata/languages/Polish | 6 +-- rtdata/languages/Portugues (Brasil) | 6 +-- rtdata/languages/Russian | 6 +-- rtdata/languages/Serbian (Cyrilic Characters) | 6 +-- rtdata/languages/Swedish | 6 +-- rtdata/languages/default | 2 +- rtengine/filmnegativeproc.cc | 8 ++-- rtengine/filmnegativethumb.cc | 12 +----- rtengine/procparams.cc | 16 ++++---- rtengine/procparams.h | 4 +- rtgui/filmnegative.cc | 38 +++++++++---------- rtgui/paramsedited.cc | 18 ++++----- rtgui/paramsedited.h | 4 +- rtgui/partialpastedlg.cc | 4 +- 22 files changed, 88 insertions(+), 96 deletions(-) diff --git a/rtdata/languages/Catala b/rtdata/languages/Catala index f9bcf25b2..a6b104be2 100644 --- a/rtdata/languages/Catala +++ b/rtdata/languages/Catala @@ -1315,7 +1315,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1853,12 +1853,12 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points -!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified) index 78807ddd4..9f0e4b365 100644 --- a/rtdata/languages/Chinese (Simplified) +++ b/rtdata/languages/Chinese (Simplified) @@ -1362,7 +1362,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1800,12 +1800,12 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points -!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index fd2d0d07a..e3aa6ea44 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -2365,11 +2365,11 @@ ZOOMPANEL_ZOOMOUT;Herauszoomen\nTaste: - !!!!!!!!!!!!!!!!!!!!!!!!! !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed -!TP_FILMNEGATIVE_BLUE;Blue exponent +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index 24bffbb0a..677dc1818 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -839,7 +839,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1667,12 +1667,12 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points -!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index 5dad9591a..7d2c5ff43 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -749,7 +749,7 @@ !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1638,12 +1638,12 @@ !TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points -!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano index 98d86b69d..2390c0d81 100644 --- a/rtdata/languages/Italiano +++ b/rtdata/languages/Italiano @@ -1540,7 +1540,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1905,12 +1905,12 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points -!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? diff --git a/rtdata/languages/Magyar b/rtdata/languages/Magyar index 7aa5b30c3..c3272133a 100644 --- a/rtdata/languages/Magyar +++ b/rtdata/languages/Magyar @@ -1249,7 +1249,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1818,12 +1818,12 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Weighted Standard !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points -!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands index 508f06384..179ba9b3f 100644 --- a/rtdata/languages/Nederlands +++ b/rtdata/languages/Nederlands @@ -2037,7 +2037,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -2232,12 +2232,12 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !TP_EXPOSURE_CLAMPOOG;Clip out-of-gamut colors !TP_EXPOSURE_HISTMATCHING;Auto-Matched Tone Curve !TP_EXPOSURE_HISTMATCHING_TOOLTIP;Automatically adjust sliders and curves (except exposure compensation) to match the look of the embedded JPEG thumbnail. -!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_ICM_WORKING_TRC;Tone response curve: !TP_ICM_WORKING_TRC_CUSTOM;Custom diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish index e35f583ff..daca63dd6 100644 --- a/rtdata/languages/Polish +++ b/rtdata/languages/Polish @@ -1622,7 +1622,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1931,12 +1931,12 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_EXPOSURE_HISTMATCHING_TOOLTIP;Automatically adjust sliders and curves (except exposure compensation) to match the look of the embedded JPEG thumbnail. !TP_EXPOSURE_TCMODE_LUMINANCE;Luminance !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual -!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_ICM_APPLYBASELINEEXPOSUREOFFSET;Baseline exposure diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil) index 0bafe632f..0a9f4fe89 100644 --- a/rtdata/languages/Portugues (Brasil) +++ b/rtdata/languages/Portugues (Brasil) @@ -2259,7 +2259,7 @@ ZOOMPANEL_ZOOMOUT;Menos Zoom\nAtalho: - !HISTORY_MSG_COLORTONING_LABREGION_OFFSET;CT - region offset !HISTORY_MSG_COLORTONING_LABREGION_POWER;CT - region power !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !MAIN_FRAME_PLACES_DEL;Remove !PREFERENCES_APPEARANCE_PSEUDOHIDPI;Pseudo-HiDPI mode !PREFERENCES_CACHECLEAR_SAFETY;Only files in the cache are cleared. Processing profiles stored alongside the source images are not touched. @@ -2273,12 +2273,12 @@ ZOOMPANEL_ZOOMOUT;Menos Zoom\nAtalho: - !TP_COLORTONING_LABREGION_OFFSET;Offset !TP_COLORTONING_LABREGION_POWER;Power !TP_CROP_PPI;PPI -!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected !TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian index 9e43f1098..dd4c501d7 100644 --- a/rtdata/languages/Russian +++ b/rtdata/languages/Russian @@ -1707,7 +1707,7 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D !HISTORY_MSG_ICM_OUTPUT_TYPE;Output - Type @@ -1976,12 +1976,12 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !TP_DISTORTION_AUTO_TIP;Automatically corrects lens distortion in raw files by matching it against the embedded JPEG image if one exists and has had its lens disortion auto-corrected by the camera. !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points -!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? !TP_FLATFIELD_CLIPCONTROL;Clip control diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters) index ce1452821..966213d1d 100644 --- a/rtdata/languages/Serbian (Cyrilic Characters) +++ b/rtdata/languages/Serbian (Cyrilic Characters) @@ -1515,7 +1515,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -1904,12 +1904,12 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual !TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points !TP_EXPOS_WHITEPOINT_LABEL;Raw White Points -!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FILMSIMULATION_LABEL;Film Simulation !TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now? diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish index cd3b9b3fc..4fb3e301b 100644 --- a/rtdata/languages/Swedish +++ b/rtdata/languages/Swedish @@ -1864,7 +1864,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold !HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold !HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -!HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +!HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values !HISTORY_MSG_HISTMATCHING;Auto-matched tone curve !HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries !HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D @@ -2119,12 +2119,12 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !TP_EXPOSURE_CLAMPOOG;Clip out-of-gamut colors !TP_EXPOSURE_HISTMATCHING;Auto-Matched Tone Curve !TP_EXPOSURE_HISTMATCHING_TOOLTIP;Automatically adjust sliders and curves (except exposure compensation) to match the look of the embedded JPEG thumbnail. -!TP_FILMNEGATIVE_BLUE;Blue exponent +!TP_FILMNEGATIVE_BLUE;Blue ratio !TP_FILMNEGATIVE_GREEN;Green exponent !TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking 2 neutral reference spots in the image; one white (light gray) and one black (dark gray).\nThe order does not matter. The exponents will be updated after the second spot is picked. !TP_FILMNEGATIVE_LABEL;Film Negative !TP_FILMNEGATIVE_PICK;Pick white and black spots -!TP_FILMNEGATIVE_RED;Red exponent +!TP_FILMNEGATIVE_RED;Red ratio !TP_FILMNEGATIVE_REF_SPOTS;Film negative reference spots !TP_FLATFIELD_CLIPCONTROL;Clip control !TP_FLATFIELD_CLIPCONTROL_TOOLTIP;Clip control avoids clipped highlights caused by applying the flat field. If there are already clipped highlights before applying the flat field, clip control can lead to color cast. diff --git a/rtdata/languages/default b/rtdata/languages/default index 63c877bbf..d5e3b13fa 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -748,7 +748,7 @@ HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative -HISTORY_MSG_FILMNEGATIVE_EXPONENTS;Film negative exponents changed +HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values HISTORY_MSG_HISTMATCHING;Auto-matched tone curve HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries HISTORY_MSG_ICM_OUTPUT_TEMP;Output - ICC-v4 illuminant D diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc index db5705a3c..58d87d103 100644 --- a/rtengine/filmnegativeproc.cc +++ b/rtengine/filmnegativeproc.cc @@ -101,9 +101,9 @@ bool channelsAvg( bool rtengine::RawImageSource::getFilmNegativeExponents(Coord2D spotA, Coord2D spotB, int tran, const FilmNegativeParams ¤tParams, std::array& newExps) { newExps = { - static_cast(currentParams.redExp), + static_cast(currentParams.redRatio * currentParams.greenExp), static_cast(currentParams.greenExp), - static_cast(currentParams.blueExp) + static_cast(currentParams.blueRatio * currentParams.greenExp) }; constexpr int spotSize = 32; // TODO: Make this configurable? @@ -171,9 +171,9 @@ void rtengine::RawImageSource::filmNegativeProcess(const procparams::FilmNegativ // Exponents are expressed as positive in the parameters, so negate them in order // to get the reciprocals. const std::array exps = { - static_cast(-params.redExp), + static_cast(-params.redRatio * params.greenExp), static_cast(-params.greenExp), - static_cast(-params.blueExp) + static_cast(-params.blueRatio * params.greenExp) }; MyTime t1, t2, t3,t4, t5; diff --git a/rtengine/filmnegativethumb.cc b/rtengine/filmnegativethumb.cc index 8889915e6..610781872 100644 --- a/rtengine/filmnegativethumb.cc +++ b/rtengine/filmnegativethumb.cc @@ -17,18 +17,10 @@ * along with RawTherapee. If not, see . */ #include -#include - -#ifdef _OPENMP -#include -#endif #include "rtengine.h" #include "rtthumbnail.h" - -#include "mytime.h" #include "opthelper.h" -#include "procparams.h" #include "rt_algo.h" #include "rtengine.h" #include "settings.h" @@ -52,9 +44,9 @@ void rtengine::Thumbnail::processFilmNegative( StopWatch stop1("Thumbnail film negative", true); // Channel exponents - const float rexp = -params.filmNegative.redExp; + const float rexp = -params.filmNegative.redRatio * params.filmNegative.greenExp; const float gexp = -params.filmNegative.greenExp; - const float bexp = -params.filmNegative.blueExp; + const float bexp = -params.filmNegative.blueRatio * params.filmNegative.greenExp; // Need to calculate channel averages, to fake the same conditions // found in rawimagesource, where get_ColorsCoeff is called with diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index b35faca94..45c71b03a 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2736,9 +2736,9 @@ bool MetaDataParams::operator!=(const MetaDataParams &other) const FilmNegativeParams::FilmNegativeParams() : enabled(false), - redExp(2.04), + redRatio(1.36), greenExp(1.5), - blueExp(1.29) + blueRatio(0.86) { } @@ -2746,9 +2746,9 @@ bool FilmNegativeParams::operator ==(const FilmNegativeParams& other) const { return enabled == other.enabled - && redExp == other.redExp + && redRatio == other.redRatio && greenExp == other.greenExp - && blueExp == other.blueExp; + && blueRatio == other.blueRatio; } bool FilmNegativeParams::operator !=(const FilmNegativeParams& other) const @@ -3589,9 +3589,9 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo // Film negative saveToKeyfile(!pedited || pedited->filmNegative.enabled, "Film Negative", "Enabled", filmNegative.enabled, keyFile); - saveToKeyfile(!pedited || pedited->filmNegative.redExp, "Film Negative", "RedExponent", filmNegative.redExp, keyFile); + saveToKeyfile(!pedited || pedited->filmNegative.redRatio, "Film Negative", "RedRatio", filmNegative.redRatio, keyFile); saveToKeyfile(!pedited || pedited->filmNegative.greenExp, "Film Negative", "GreenExponent", filmNegative.greenExp, keyFile); - saveToKeyfile(!pedited || pedited->filmNegative.blueExp, "Film Negative", "BlueExponent", filmNegative.blueExp, keyFile); + saveToKeyfile(!pedited || pedited->filmNegative.blueRatio, "Film Negative", "BlueRatio", filmNegative.blueRatio, keyFile); // EXIF change list if (!pedited || pedited->exif) { @@ -5138,9 +5138,9 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_group("Film Negative")) { assignFromKeyfile(keyFile, "Film Negative", "Enabled", pedited, filmNegative.enabled, pedited->filmNegative.enabled); - assignFromKeyfile(keyFile, "Film Negative", "RedExponent", pedited, filmNegative.redExp, pedited->filmNegative.redExp); + assignFromKeyfile(keyFile, "Film Negative", "RedRatio", pedited, filmNegative.redRatio, pedited->filmNegative.redRatio); assignFromKeyfile(keyFile, "Film Negative", "GreenExponent", pedited, filmNegative.greenExp, pedited->filmNegative.greenExp); - assignFromKeyfile(keyFile, "Film Negative", "BlueExponent", pedited, filmNegative.blueExp, pedited->filmNegative.blueExp); + assignFromKeyfile(keyFile, "Film Negative", "BlueRatio", pedited, filmNegative.blueRatio, pedited->filmNegative.blueRatio); } if (keyFile.has_group("MetaData")) { diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 2af018035..46eb530bc 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1501,9 +1501,9 @@ struct RAWParams { */ struct FilmNegativeParams { bool enabled; - double redExp; + double redRatio; double greenExp; - double blueExp; + double blueRatio; FilmNegativeParams(); diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc index 4956968e3..598c9463a 100644 --- a/rtgui/filmnegative.cc +++ b/rtgui/filmnegative.cc @@ -49,7 +49,7 @@ Adjuster* createExponentAdjuster(AdjusterListener* listener, const Glib::ustring FilmNegative::FilmNegative() : FoldableToolPanel(this, "filmnegative", M("TP_FILMNEGATIVE_LABEL"), false, true), EditSubscriber(ET_OBJECTS), - evFilmNegativeExponents(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_EXPONENTS")), + evFilmNegativeExponents(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_VALUES")), evFilmNegativeEnabled(ProcEventMapper::getInstance()->newEvent(FIRST, "HISTORY_MSG_FILMNEGATIVE_ENABLED")), fnp(nullptr), greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 0.3, 4, 1.5)), // master exponent (green channel) @@ -123,45 +123,45 @@ void FilmNegative::read(const rtengine::procparams::ProcParams* pp, const Params disableListener(); if (pedited) { - redRatio->setEditedState(pedited->filmNegative.redExp ? Edited : UnEdited); + redRatio->setEditedState(pedited->filmNegative.redRatio ? Edited : UnEdited); greenExp->setEditedState(pedited->filmNegative.greenExp ? Edited : UnEdited); - blueRatio->setEditedState(pedited->filmNegative.blueExp ? Edited : UnEdited); + blueRatio->setEditedState(pedited->filmNegative.blueRatio ? Edited : UnEdited); set_inconsistent(multiImage && !pedited->filmNegative.enabled); } setEnabled(pp->filmNegative.enabled); - redRatio->setValue(pp->filmNegative.redExp / pp->filmNegative.greenExp); + redRatio->setValue(pp->filmNegative.redRatio); greenExp->setValue(pp->filmNegative.greenExp); - blueRatio->setValue(pp->filmNegative.blueExp / pp->filmNegative.greenExp); + blueRatio->setValue(pp->filmNegative.blueRatio); enableListener(); } void FilmNegative::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->filmNegative.redExp = greenExp->getValue() * redRatio->getValue(); + pp->filmNegative.redRatio = redRatio->getValue(); pp->filmNegative.greenExp = greenExp->getValue(); - pp->filmNegative.blueExp = greenExp->getValue() * blueRatio->getValue(); + pp->filmNegative.blueRatio = blueRatio->getValue(); pp->filmNegative.enabled = getEnabled(); if (pedited) { - pedited->filmNegative.redExp = greenExp->getEditedState() || redRatio->getEditedState(); + pedited->filmNegative.redRatio = redRatio->getEditedState(); pedited->filmNegative.greenExp = greenExp->getEditedState(); - pedited->filmNegative.blueExp = greenExp->getEditedState() || blueRatio->getEditedState(); + pedited->filmNegative.blueRatio = blueRatio->getEditedState(); pedited->filmNegative.enabled = !get_inconsistent(); } } void FilmNegative::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { - redRatio->setValue(defParams->filmNegative.redExp / defParams->filmNegative.greenExp); + redRatio->setValue(defParams->filmNegative.redRatio); greenExp->setValue(defParams->filmNegative.greenExp); - blueRatio->setValue(defParams->filmNegative.blueExp / defParams->filmNegative.greenExp); + blueRatio->setValue(defParams->filmNegative.blueRatio); if (pedited) { - redRatio->setDefaultEditedState(pedited->filmNegative.redExp ? Edited : UnEdited); + redRatio->setDefaultEditedState(pedited->filmNegative.redRatio ? Edited : UnEdited); greenExp->setDefaultEditedState(pedited->filmNegative.greenExp ? Edited : UnEdited); - blueRatio->setDefaultEditedState(pedited->filmNegative.blueExp ? Edited : UnEdited); + blueRatio->setDefaultEditedState(pedited->filmNegative.blueRatio ? Edited : UnEdited); } else { redRatio->setDefaultEditedState(Irrelevant); greenExp->setDefaultEditedState(Irrelevant); @@ -189,10 +189,10 @@ void FilmNegative::adjusterChanged(Adjuster* a, double newval) listener->panelChanged( evFilmNegativeExponents, Glib::ustring::compose( - "R=%1 ; G=%2 ; B=%3", - greenExp->getValue() * redRatio->getValue(), + "Ref=%1 ; R=%2 ; B=%3", greenExp->getValue(), - greenExp->getValue() * blueRatio->getValue() + redRatio->getValue(), + blueRatio->getValue() ) ); } @@ -269,10 +269,10 @@ bool FilmNegative::button1Pressed(int modifierKey) listener->panelChanged( evFilmNegativeExponents, Glib::ustring::compose( - "R=%1 ; G=%2 ; B=%3", - greenExp->getValue() * redRatio->getValue(), + "Ref=%1 ; R=%2 ; B=%3", greenExp->getValue(), - greenExp->getValue() * blueRatio->getValue() + redRatio->getValue(), + blueRatio->getValue() ) ); } diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 7d52d309a..952b08161 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -581,9 +581,9 @@ void ParamsEdited::set(bool v) dehaze.depth = v; metadata.mode = v; filmNegative.enabled = v; - filmNegative.redExp = v; + filmNegative.redRatio = v; filmNegative.greenExp = v; - filmNegative.blueExp = v; + filmNegative.blueRatio = v; exif = v; iptc = v; @@ -1147,9 +1147,9 @@ void ParamsEdited::initFrom(const std::vector& dehaze.depth = dehaze.depth && p.dehaze.depth == other.dehaze.depth; metadata.mode = metadata.mode && p.metadata.mode == other.metadata.mode; filmNegative.enabled = filmNegative.enabled && p.filmNegative.enabled == other.filmNegative.enabled; - filmNegative.redExp = filmNegative.redExp && p.filmNegative.redExp == other.filmNegative.redExp; + filmNegative.redRatio = filmNegative.redRatio && p.filmNegative.redRatio == other.filmNegative.redRatio; filmNegative.greenExp = filmNegative.greenExp && p.filmNegative.greenExp == other.filmNegative.greenExp; - filmNegative.blueExp = filmNegative.blueExp && p.filmNegative.blueExp == other.filmNegative.blueExp; + filmNegative.blueRatio = filmNegative.blueRatio && p.filmNegative.blueRatio == other.filmNegative.blueRatio; // How the hell can we handle that??? // exif = exif && p.exif==other.exif @@ -3187,16 +3187,16 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.filmNegative.enabled = mods.filmNegative.enabled; } - if (filmNegative.redExp) { - toEdit.filmNegative.redExp = mods.filmNegative.redExp; + if (filmNegative.redRatio) { + toEdit.filmNegative.redRatio = mods.filmNegative.redRatio; } if (filmNegative.greenExp) { toEdit.filmNegative.greenExp = mods.filmNegative.greenExp; } - if (filmNegative.blueExp) { - toEdit.filmNegative.blueExp = mods.filmNegative.blueExp; + if (filmNegative.blueRatio) { + toEdit.filmNegative.blueRatio = mods.filmNegative.blueRatio; } // Exif changes are added to the existing ones @@ -3245,5 +3245,5 @@ bool RetinexParamsEdited::isUnchanged() const bool FilmNegativeParamsEdited::isUnchanged() const { - return enabled && redExp && greenExp && blueExp; + return enabled && redRatio && greenExp && blueRatio; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 57e6f2cdd..08a41fc7a 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -668,9 +668,9 @@ struct MetaDataParamsEdited { struct FilmNegativeParamsEdited { bool enabled; - bool redExp; + bool redRatio; bool greenExp; - bool blueExp; + bool blueRatio; bool isUnchanged() const; }; diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index 34f9a414d..52adcfbf7 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -976,9 +976,9 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param if (!filmNegative->get_active ()) { filterPE.filmNegative.enabled = falsePE.filmNegative.enabled; - filterPE.filmNegative.redExp = falsePE.filmNegative.redExp; + filterPE.filmNegative.redRatio = falsePE.filmNegative.redRatio; filterPE.filmNegative.greenExp = falsePE.filmNegative.greenExp; - filterPE.filmNegative.blueExp = falsePE.filmNegative.blueExp; + filterPE.filmNegative.blueRatio = falsePE.filmNegative.blueRatio; } if (dstPE) { From 85aacaddf285c7c8eb4cb60f4085457103e8e71e Mon Sep 17 00:00:00 2001 From: rom9 <4711834+rom9@users.noreply.github.com> Date: Wed, 17 Jul 2019 00:53:36 +0200 Subject: [PATCH 41/42] Minor whitespace fix --- rtengine/rtthumbnail.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 4b0baa685..2a35176e6 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1167,7 +1167,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT Imagefloat* baseImg = resizeTo (rwidth, rheight, interp, thumbImg); - if(isRaw && params.filmNegative.enabled) { + if (isRaw && params.filmNegative.enabled) { processFilmNegative(params, baseImg, rwidth, rheight, rmi, gmi, bmi); } From cd597ec3865a9e2df224a52ef9a5d1cb4179d54c Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Wed, 17 Jul 2019 12:13:48 +0200 Subject: [PATCH 42/42] raw crop for Sony ILCE-7RM4 (Sony A7R IV) --- rtengine/camconst.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 97a14f66e..894414f8a 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -2437,6 +2437,11 @@ Camera constants: "pdaf_offset" : 31 }, + { // Quality C, + "make_model": "Sony ILCE-7RM4", + "raw_crop": [ 0, 0, 9568, 0 ] // full raw frame 9600x6376 - 32 rightmost columns are garbage + }, + { // Quality B, color matrix copied from a7rm2 "make_model": "Sony ILCE-9", "dcraw_matrix": [ 6389,-1703,-378,-4562,12265,2587,-670,1489,6550 ], // DNG_v9.12 D65