From 91dc97eafb929ab3b658b854847dbe553feaae29 Mon Sep 17 00:00:00 2001 From: Andy Dodd Date: Sun, 17 Mar 2024 09:49:42 -0400 Subject: [PATCH 01/39] Fix regression with demosaiced DNGs caused by 831a9bbd Uses a new function checkRawDataDimensions as suggested/written by @Lawrence37 to verify that image dimensions are correct. Fixes #6996 --- rtengine/rawimagesource.cc | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 8149c0464..03823644b 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -742,9 +742,19 @@ void RawImageSource::getWBMults(const ColorTemp &ctemp, const RAWParams &raw, st autoGainComp = camInitialGain / initialGain; } +bool checkRawDataDimensions(const array2D &rawData, const RawImage &rawImage, int width, int height) +{ + const int colors = (rawImage.getSensorType() == rtengine::ST_BAYER || + rawImage.getSensorType() == rtengine::ST_FUJI_XTRANS || + rawImage.get_colors() == 1) + ? 1 + : 3; + return rawData.getHeight() == height && rawData.getWidth() == colors * width; +} + void RawImageSource::getImage(const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw) { - assert(rawData.getHeight() == H && rawData.getWidth() == W); + assert(checkRawDataDimensions(rawData, *ri, W, H)); MyMutex::MyLock lock(getImageMutex); @@ -1747,7 +1757,7 @@ void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lens void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &contrastThreshold, bool cache) { - assert(rawData.getHeight() == H && rawData.getWidth() == W); + assert(checkRawDataDimensions(rawData, *ri, W, H)); MyTime t1, t2; t1.set(); @@ -3842,7 +3852,7 @@ void RawImageSource::hlRecovery(const std::string &method, float* red, float* gr void RawImageSource::getAutoExpHistogram(LUTu & histogram, int& histcompr) { - assert(rawData.getHeight() == H && rawData.getWidth() == W); + assert(checkRawDataDimensions(rawData, *ri, W, H)); // BENCHFUN histcompr = 3; @@ -7487,7 +7497,7 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int void RawImageSource::getAutoWBMultipliersitc(bool extra, double & tempref, double & greenref, double & tempitc, double & greenitc, float &temp0, float &delta, int &bia, int &dread, int &kcam, int &nocam, float &studgood, float &minchrom, int &kmin, float &minhist, float &maxhist, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double & rm, double & gm, double & bm, const WBParams & wbpar, const ColorManagementParams & cmp, const RAWParams & raw, const ToneCurveParams &hrp) { - assert(rawData.getHeight() == H && rawData.getWidth() == W); + assert(checkRawDataDimensions(rawData, *ri, W, H)); // BENCHFUN constexpr double clipHigh = 64000.0; @@ -7713,7 +7723,7 @@ void RawImageSource::getAutoWBMultipliersitc(bool extra, double & tempref, doubl void RawImageSource::getAutoWBMultipliers(double &rm, double &gm, double &bm) { - assert(rawData.getHeight() == H && rawData.getWidth() == W); + assert(checkRawDataDimensions(rawData, *ri, W, H)); // BENCHFUN constexpr double clipHigh = 64000.0; @@ -7931,7 +7941,7 @@ void RawImageSource::getAutoWBMultipliers(double &rm, double &gm, double &bm) ColorTemp RawImageSource::getSpotWB(std::vector &red, std::vector &green, std::vector &blue, int tran, double equal, StandardObserver observer) { - assert(rawData.getHeight() == H && rawData.getWidth() == W); + assert(checkRawDataDimensions(rawData, *ri, W, H)); int x; int y; @@ -8271,7 +8281,7 @@ void RawImageSource::init() void RawImageSource::getRawValues(int x, int y, int rotate, int &R, int &G, int &B) { - if (rawData.getWidth() != W || rawData.getHeight() != H || d1x) { // Nikon D1x has special sensor. We just skip it + if (!checkRawDataDimensions(rawData, *ri, W, H) || d1x) { // Nikon D1x has special sensor. We just skip it R = G = B = 0; return; } @@ -8319,7 +8329,7 @@ bool RawImageSource::isGainMapSupported() const void RawImageSource::applyDngGainMap(const float black[4], const std::vector &gainMaps) { - assert(rawData.getHeight() == H && rawData.getWidth() == W); + assert(checkRawDataDimensions(rawData, *ri, W, H)); // now we can apply each gain map to raw_data array2D mvals[2][2]; From 068420da605a57e60ba9b021a6c1f1009d39b1f7 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Thu, 2 May 2024 22:12:44 -0700 Subject: [PATCH 02/39] Use camera crop factor to select Lensfun lens --- rtengine/rtlensfun.cc | 75 +++++++++++++++++++++++++++++++++++++------ rtengine/rtlensfun.h | 2 +- rtgui/lensprofile.cc | 6 ++-- 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/rtengine/rtlensfun.cc b/rtengine/rtlensfun.cc index fc5bb0017..df518c133 100644 --- a/rtengine/rtlensfun.cc +++ b/rtengine/rtlensfun.cc @@ -25,6 +25,61 @@ #include "rtlensfun.h" #include "settings.h" + +namespace +{ + +bool isCStringIn(const char *str, const char *const *list) +{ + for (auto element_ptr = list; *element_ptr; element_ptr++) { + if (!strcmp(str, *element_ptr)) { + return true; + } + } + return false; +} + +bool isNextLensCropFactorBetter(const lfLens *current_lens, const lfCamera *camera, float next_lens_crop_factor) +{ + if (!current_lens) { + // No current lens, so next lens's crop factor is + // automatically better. + return true; + } + + const float current_lens_crop_factor = current_lens->CropFactor; + + if (!camera) { + // Favor the smaller crop factor for maximum coverage. + return current_lens_crop_factor > next_lens_crop_factor; + } + + const float camera_crop_factor = camera->CropFactor; + + if (current_lens_crop_factor > camera_crop_factor) { + // Current lens's data does not cover the entire camera + // sensor. Any lens's data with a smaller crop factor is + // better. + return current_lens->CropFactor > next_lens_crop_factor; + } + + // Current lens's data covers the entire camera sensor. A lens + // with data from a larger crop factor will be more precise, but + // also must not be larger than the camera sensor's crop factor + // to maintain full coverage. + return current_lens->CropFactor < next_lens_crop_factor && + next_lens_crop_factor <= camera_crop_factor; +} + +bool isNextLensBetter(const lfCamera *camera, const lfLens *current_lens, const lfLens &next_lens, const Glib::ustring &lens_name, const Glib::ustring &next_lens_name) +{ + return isNextLensCropFactorBetter(current_lens, camera, next_lens.CropFactor) && + lens_name == next_lens_name && + (!camera || isCStringIn(camera->Mount, next_lens.Mounts)); +} + +} // namespace + namespace rtengine { @@ -460,20 +515,25 @@ LFCamera LFDatabase::findCamera(const Glib::ustring &make, const Glib::ustring & } -LFLens LFDatabase::findLens(const LFCamera &camera, const Glib::ustring &name) const +LFLens LFDatabase::findLens(const LFCamera &camera, const Glib::ustring &name, bool autoMatch) const { LFLens ret; if (data_ && !name.empty()) { MyMutex::MyLock lock(lfDBMutex); - if (!camera.data_) { + if (!autoMatch) { // Only the lens name provided. Try to find exact match by name. LFLens candidate; + LFLens bestCandidate; + for (auto lens_list = data_->GetLenses(); lens_list[0]; lens_list++) { candidate.data_ = lens_list[0]; - if (name == candidate.getLens()) { - return candidate; + if (isNextLensBetter(camera.data_, bestCandidate.data_, *(candidate.data_), name, candidate.getLens())) { + bestCandidate.data_ = candidate.data_; } } + if (bestCandidate.data_) { + return bestCandidate; + } } auto found = data_->FindLenses(camera.data_, nullptr, name.c_str()); for (size_t pos = 0; !found && pos < name.size(); ) { @@ -562,12 +622,7 @@ std::unique_ptr LFDatabase::findModifier( } const LFCamera c = findCamera(make, model, lensProf.lfAutoMatch()); - const LFLens l = findLens( - lensProf.lfAutoMatch() - ? c - : LFCamera(), - lens - ); + const LFLens l = findLens(c, lens, lensProf.lfAutoMatch()); bool swap_xy = false; if (rawRotationDeg >= 0) { diff --git a/rtengine/rtlensfun.h b/rtengine/rtlensfun.h index bcce77f34..1d941246f 100644 --- a/rtengine/rtlensfun.h +++ b/rtengine/rtlensfun.h @@ -121,7 +121,7 @@ public: std::vector getCameras() const; std::vector getLenses() const; LFCamera findCamera(const Glib::ustring &make, const Glib::ustring &model, bool autoMatch) const; - LFLens findLens(const LFCamera &camera, const Glib::ustring &name) const; + LFLens findLens(const LFCamera &camera, const Glib::ustring &name, bool autoMatch) const; std::unique_ptr findModifier( const procparams::LensProfParams &lensProf, diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 0e17b3f40..5f42a1cde 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -251,7 +251,7 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa if (pp->lensProf.lfAutoMatch()) { if (metadata) { - const LFLens l = db->findLens(c, metadata->getLens()); + const LFLens l = db->findLens(c, metadata->getLens(), true); setLensfunLens(l.getLens()); } } else if (pp->lensProf.lfManual()) { @@ -522,7 +522,7 @@ void LensProfilePanel::onCorrModeChanged(const Gtk::RadioButton* rbChanged) } else if (metadata) { const LFDatabase* const db = LFDatabase::getInstance(); const LFCamera c = db->findCamera(metadata->getMake(), metadata->getModel(), true); - const LFLens l = db->findLens(c, metadata->getLens()); + const LFLens l = db->findLens(c, metadata->getLens(), true); setLensfunCamera(c.getMake(), c.getModel()); setLensfunLens(l.getLens()); } @@ -808,7 +808,7 @@ void LensProfilePanel::updateLensfunWarning() return; } - const LFLens l = db->findLens(LFCamera(), (*itl)[lf->lensfunModelLens.lens]); + const LFLens l = db->findLens(c, (*itl)[lf->lensfunModelLens.lens], false); const float lenscrop = l.getCropFactor(); const float camcrop = c.getCropFactor(); From 324f488f5b0a6b5ce841e0f780f5cd595b1d34bf Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sat, 1 Jun 2024 18:59:42 -0700 Subject: [PATCH 03/39] Fix jpg file not writable after save Use a unique_ptr to automatically close the jpg file after. --- rtengine/imageio.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index f096213dc..85afb08ea 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -480,7 +480,11 @@ int ImageIO::loadJPEGFromMemory (const char* buffer, int bufsize) int ImageIO::loadJPEG (const Glib::ustring &fname) { - FILE *file = g_fopen(fname.c_str (), "rb"); + std::unique_ptr file( + g_fopen(fname.c_str(), "rb"), + [](FILE *f) { + fclose(f); + }); if (!file) { return IMIO_CANNOTREADFILE; @@ -491,7 +495,7 @@ int ImageIO::loadJPEG (const Glib::ustring &fname) cinfo.err = my_jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); - my_jpeg_stdio_src (&cinfo, file); + my_jpeg_stdio_src (&cinfo, file.get()); #if defined( _WIN32 ) && defined( __x86_64__ ) && !defined(__clang__) if ( __builtin_setjmp((reinterpret_cast(cinfo.src))->error_jmp_buf) == 0 ) { @@ -553,7 +557,7 @@ int ImageIO::loadJPEG (const Glib::ustring &fname) jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); - fclose(file); + file.reset(); if (pl) { pl->setProgressStr ("PROGRESSBAR_READY"); From 5d75c44287aa5d6452ff74447fbe1c7063bf79d8 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 2 Jun 2024 17:38:36 -0700 Subject: [PATCH 04/39] Add Fujifilm X-H2S color matrix and raw crop --- rtengine/camconst.json | 5 +++++ rtengine/dcraw.cc | 2 ++ 2 files changed, 7 insertions(+) diff --git a/rtengine/camconst.json b/rtengine/camconst.json index b80d776b8..65e57929a 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -1539,6 +1539,11 @@ Camera constants: "ranges": { "white": 3838 } }, + { // Quality B + "make_model": [ "Fujifilm X-H2S" ], + "raw_crop": [ 0, 5, 6264, 4176 ] + }, + { // Quality B "make_model": [ "FUJIFILM X-T10", "FUJIFILM X-E2" ], "dcraw_matrix": [ 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 ], // DNG D65 diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index cfb949b86..cef0e9fff 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -8463,6 +8463,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, { "Fujifilm X-H1", 0, 0, { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, + { "Fujifilm X-H2S", 0, 0, + { 12836, -5909, -1032, -3087, 11132, 2236, -35, 872, 5330 } }, { "Fujifilm X-M1", 0, 0, { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } }, { "Fujifilm X-S1", 0, 0, From 29f4f37cdb114e86e7e8d8ee5a34f126bf10905d Mon Sep 17 00:00:00 2001 From: xiota Date: Mon, 10 Jun 2024 04:23:19 +0000 Subject: [PATCH 05/39] Enable extensions that are missing from config --- rtdata/options/options.lin | 4 ++-- rtdata/options/options.osx | 4 ++-- rtdata/options/options.win | 4 ++-- rtgui/options.cc | 29 +++++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/rtdata/options/options.lin b/rtdata/options/options.lin index 2a96c6997..18cb01901 100644 --- a/rtdata/options/options.lin +++ b/rtdata/options/options.lin @@ -12,8 +12,8 @@ MultiUser=true [File Browser] # Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include) -ParseExtensions=3fr;arw;arq;cr2;cr3;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;jxl;kdc;mef;mos;mrw;nef;nrw;orf;ori;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; -ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;1;1;1;1;1;1;1;1;1;1;1; +ParseExtensions= +ParseExtensionsEnabled= [Output] PathTemplate=%p1/converted/%f diff --git a/rtdata/options/options.osx b/rtdata/options/options.osx index eff9cd8d9..8d954529f 100644 --- a/rtdata/options/options.osx +++ b/rtdata/options/options.osx @@ -13,8 +13,8 @@ UseSystemTheme=false [File Browser] # Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include) -ParseExtensions=3fr;arw;arq;cr2;cr3;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;jxl;kdc;mef;mos;mrw;nef;nrw;orf;ori;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; -ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;1;1;1;1;1;1;1;1;1;1;1; +ParseExtensions= +ParseExtensionsEnabled= [Output] PathTemplate=%p1/converted/%f diff --git a/rtdata/options/options.win b/rtdata/options/options.win index e3f43343e..a88cc3db2 100644 --- a/rtdata/options/options.win +++ b/rtdata/options/options.win @@ -14,8 +14,8 @@ UseSystemTheme=false [File Browser] # Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include) -ParseExtensions=3fr;arw;arq;cr2;cr3;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;jxl;kdc;mef;mos;mrw;nef;nrw;orf;ori;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; -ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;1;1;1;1;1;1;1;1;1;1;1; +ParseExtensions= +ParseExtensionsEnabled= [Output] PathTemplate=%p1/converted/%f diff --git a/rtgui/options.cc b/rtgui/options.cc index c96febe86..643012dfe 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -1268,6 +1268,35 @@ void Options::readFromFile(Glib::ustring fname) } } + // check and add extensions that are missing from config + static const std::vector extensions_known = { + "3fr", "arw", "arq", "cr2", "cr3", "crf", "crw", "dcr", "dng", + "fff", "iiq", "jpg", "jpeg", "jxl", "kdc", "mef", "mos", "mrw", + "nef", "nrw", "orf", "ori", "pef", "png", "raf", "raw", "rw2", + "rwl", "rwz", "sr2", "srf", "srw", "tif", "tiff", "x3f"}; + + std::map extensions_checked; + + if (parseExtensions.size() == parseExtensionsEnabled.size()) { + for (auto i = 0; i < parseExtensions.size(); ++i) { + extensions_checked[parseExtensions[i]] = parseExtensionsEnabled[i]; + } + } + + parseExtensions.clear(); + parseExtensionsEnabled.clear(); + + for (auto const &i : extensions_known) { + if (extensions_checked.count(i) == 0) { + extensions_checked[i] = 1; + } + } + + for (auto const &x : extensions_checked) { + parseExtensions.emplace_back(x.first); + parseExtensionsEnabled.emplace_back(x.second); + } + if (keyFile.has_key("File Browser", "ThumbnailArrangement")) { fbArrangement = keyFile.get_integer("File Browser", "ThumbnailArrangement"); } From 8503d5323e5b05dc79c583d59de395e4d1544714 Mon Sep 17 00:00:00 2001 From: xiota Date: Mon, 10 Jun 2024 13:46:17 +0000 Subject: [PATCH 06/39] Fix whitespace/formatting --- rtgui/options.cc | 16 ++++++++-------- rtgui/options.h | 6 +++--- rtgui/preferences.cc | 13 +++++++------ 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/rtgui/options.cc b/rtgui/options.cc index 643012dfe..af40595aa 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -471,7 +471,7 @@ void Options::setDefaults() curvebboxpos = 1; complexity = 2; spotmet = 0; - + inspectorWindow = false; zoomOnScroll = true; prevdemo = PD_Sidecar; @@ -580,8 +580,8 @@ void Options::setDefaults() rtSettings.darkFramesPath = ""; rtSettings.flatFieldsPath = ""; - rtSettings.cameraProfilesPath = ""; - rtSettings.lensProfilesPath = ""; + rtSettings.cameraProfilesPath = ""; + rtSettings.lensProfilesPath = ""; #ifdef _WIN32 const gchar* sysRoot = g_getenv("SystemRoot"); // Returns e.g. "c:\Windows" @@ -673,8 +673,8 @@ void Options::setDefaults() lastIccDir = rtSettings.iccDirectory; lastDarkframeDir = rtSettings.darkFramesPath; lastFlatfieldDir = rtSettings.flatFieldsPath; - lastCameraProfilesDir = rtSettings.cameraProfilesPath; - lastLensProfilesDir = rtSettings.lensProfilesPath; + lastCameraProfilesDir = rtSettings.cameraProfilesPath; + lastLensProfilesDir = rtSettings.lensProfilesPath; // rtSettings.bw_complementary = true; // There is no reasonable default for curves. We can still suppose that they will take place // in a subdirectory of the user's own ProcParams presets, i.e. in a subdirectory @@ -816,7 +816,7 @@ void Options::readFromFile(Glib::ustring fname) rtSettings.cameraProfilesPath = keyFile.get_string("General", "CameraProfilesPath"); } - if (keyFile.has_key("General", "LensProfilesPath")) { + if (keyFile.has_key("General", "LensProfilesPath")) { rtSettings.lensProfilesPath = keyFile.get_string("General", "LensProfilesPath"); } @@ -2424,8 +2424,8 @@ void Options::saveToFile(Glib::ustring fname) keyFile.set_string("General", "Version", RTVERSION); keyFile.set_string("General", "DarkFramesPath", rtSettings.darkFramesPath); keyFile.set_string("General", "FlatFieldsPath", rtSettings.flatFieldsPath); - keyFile.set_string("General", "CameraProfilesPath", rtSettings.cameraProfilesPath); - keyFile.set_string("General", "LensProfilesPath", rtSettings.lensProfilesPath); + keyFile.set_string("General", "CameraProfilesPath", rtSettings.cameraProfilesPath); + keyFile.set_string("General", "LensProfilesPath", rtSettings.lensProfilesPath); keyFile.set_boolean("General", "Verbose", rtSettings.verbose); keyFile.set_integer("General", "Cropsleep", rtSettings.cropsleep); keyFile.set_double("General", "Reduchigh", rtSettings.reduchigh); diff --git a/rtgui/options.h b/rtgui/options.h index b2221e844..38f4fe896 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -331,7 +331,7 @@ public: bool overwriteOutputFile; int complexity; int spotmet; - + bool inspectorWindow; // open inspector in separate window bool zoomOnScroll; // translate scroll events to zoom @@ -472,8 +472,8 @@ public: Glib::ustring lastIccDir; Glib::ustring lastDarkframeDir; Glib::ustring lastFlatfieldDir; - Glib::ustring lastCameraProfilesDir; - Glib::ustring lastLensProfilesDir; + Glib::ustring lastCameraProfilesDir; + Glib::ustring lastLensProfilesDir; Glib::ustring lastRgbCurvesDir; Glib::ustring lastLabCurvesDir; Glib::ustring lastRetinexDir; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index d92080af8..04a9ece60 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -656,7 +656,7 @@ Gtk::Widget* Preferences::getImageProcessingPanel () Gtk::Grid* dirgrid = Gtk::manage(new Gtk::Grid()); setExpandAlignProperties(dirgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); - // Dark Frames Dir + // Dark Frames Dir Gtk::Label *dfLab = Gtk::manage(new Gtk::Label(M("PREFERENCES_DIRDARKFRAMES") + ":")); setExpandAlignProperties(dfLab, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); darkFrameDir = Gtk::manage(new MyFileChooserButton(M("PREFERENCES_DIRDARKFRAMES"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER)); @@ -705,7 +705,7 @@ Gtk::Widget* Preferences::getImageProcessingPanel () dirgrid->attach_next_to(*cameraProfilesDirLabel, *clutsDirLabel, Gtk::POS_BOTTOM, 1, 1); dirgrid->attach_next_to(*cameraProfilesDir, *cameraProfilesDirLabel, Gtk::POS_RIGHT, 1, 1); - //Lens Profiles Dir + //Lens Profiles Dir Gtk::Label *lensProfilesDirLabel = Gtk::manage(new Gtk::Label(M("PREFERENCES_LENSPROFILESDIR") + ":")); lensProfilesDirLabel->set_tooltip_text(M("PREFERENCES_LENSPROFILESDIR_TOOLTIP")); setExpandAlignProperties(lensProfilesDirLabel, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER); @@ -1111,7 +1111,7 @@ Gtk::Widget* Preferences::getGeneralPanel() workflowGrid->attach_next_to(*curveBBoxPosL, *flayoutlab, Gtk::POS_BOTTOM, 1, 1); workflowGrid->attach_next_to(*curveBBoxPosC, *editorLayout, Gtk::POS_BOTTOM, 1, 1); workflowGrid->attach_next_to(*curveBBoxPosRestartL, *lNextStart, Gtk::POS_BOTTOM, 1, 1); - + curveBBoxPosS = Gtk::manage(new Gtk::ComboBoxText()); setExpandAlignProperties(curveBBoxPosS, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE); @@ -2013,8 +2013,8 @@ void Preferences::storePreferences() moptions.curvebboxpos = curveBBoxPosC->get_active_row_number(); moptions.complexity = complexitylocal->get_active_row_number(); - moptions.spotmet = spotlocal->get_active_row_number(); - + moptions.spotmet = spotlocal->get_active_row_number(); + moptions.inspectorWindow = inspectorWindowCB->get_active(); moptions.zoomOnScroll = zoomOnScrollCB->get_active(); moptions.histogramPosition = ckbHistogramPositionLeft->get_active() ? 1 : 2; @@ -2673,10 +2673,11 @@ void Preferences::addExtPressed() Gtk::TreeNodeChildren c = extensionModel->children(); - for (size_t i = 0; i < c.size(); i++) + for (size_t i = 0; i < c.size(); i++) { if (c[i][extensionColumns.ext] == extension->get_text()) { return; } + } Gtk::TreeRow row = * (extensionModel->append()); From 7f7e808b9c07d6da896af462a8ab63146735fd74 Mon Sep 17 00:00:00 2001 From: xiota Date: Mon, 10 Jun 2024 14:03:41 +0000 Subject: [PATCH 07/39] Don't allow deleting known extensions --- rtgui/options.cc | 18 ++++++------------ rtgui/options.h | 7 +++++++ rtgui/preferences.cc | 23 ++++++++++++++++++++++- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/rtgui/options.cc b/rtgui/options.cc index af40595aa..a6756d37d 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -1269,30 +1269,24 @@ void Options::readFromFile(Glib::ustring fname) } // check and add extensions that are missing from config - static const std::vector extensions_known = { - "3fr", "arw", "arq", "cr2", "cr3", "crf", "crw", "dcr", "dng", - "fff", "iiq", "jpg", "jpeg", "jxl", "kdc", "mef", "mos", "mrw", - "nef", "nrw", "orf", "ori", "pef", "png", "raf", "raw", "rw2", - "rwl", "rwz", "sr2", "srf", "srw", "tif", "tiff", "x3f"}; - - std::map extensions_checked; + std::map checkedExtensions; if (parseExtensions.size() == parseExtensionsEnabled.size()) { for (auto i = 0; i < parseExtensions.size(); ++i) { - extensions_checked[parseExtensions[i]] = parseExtensionsEnabled[i]; + checkedExtensions[parseExtensions[i]] = parseExtensionsEnabled[i]; } } parseExtensions.clear(); parseExtensionsEnabled.clear(); - for (auto const &i : extensions_known) { - if (extensions_checked.count(i) == 0) { - extensions_checked[i] = 1; + for (auto const &i : knownExtensions) { + if (checkedExtensions.count(i) == 0) { + checkedExtensions[i] = 1; } } - for (auto const &x : extensions_checked) { + for (auto const &x : checkedExtensions) { parseExtensions.emplace_back(x.first); parseExtensionsEnabled.emplace_back(x.second); } diff --git a/rtgui/options.h b/rtgui/options.h index 38f4fe896..6a2b0c35d 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -310,6 +310,13 @@ public: int maxThumbnailWidth; std::size_t maxCacheEntries; int thumbInterp; // 0: nearest, 1: bilinear + + std::vector knownExtensions = { + "3fr", "arw", "arq", "cr2", "cr3", "crf", "crw", "dcr", "dng", + "fff", "iiq", "jpg", "jpeg", "jxl", "kdc", "mef", "mos", "mrw", + "nef", "nrw", "orf", "ori", "pef", "png", "raf", "raw", "rw2", + "rwl", "rwz", "sr2", "srf", "srw", "tif", "tiff", "x3f"}; + std::vector parseExtensions; // List containing all extensions type std::vector parseExtensionsEnabled; // List of bool to retain extension or not std::vector parsedExtensions; // List containing all retained extensions (lowercase) diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 04a9ece60..97bfb92b6 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -2687,8 +2687,29 @@ void Preferences::addExtPressed() void Preferences::delExtPressed() { + const Glib::RefPtr selection = extensions->get_selection(); - extensionModel->erase(extensions->get_selection()->get_selected()); + if (!selection) { + return; + } + + const Gtk::TreeModel::iterator selected = selection->get_selected(); + + if (!selected) { + return; + } + + bool delOkay = true; + for (auto const &x : moptions.knownExtensions) { + if (x == (*selected)[extensionColumns.ext]) { + delOkay = false; + break; + } + } + + if (delOkay) { + extensionModel->erase(selected); + } } void Preferences::moveExtUpPressed() From 02e8d3f33c9cd6cd97d09f8cf9453a096b449408 Mon Sep 17 00:00:00 2001 From: xiota Date: Sun, 16 Jun 2024 02:30:40 +0000 Subject: [PATCH 08/39] Change order of image/raw loading to generate thumbnails --- rtgui/thumbnail.cc | 58 +++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 228592a70..f5098ae6d 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -248,44 +248,44 @@ void Thumbnail::_generateThumbnailImage() cfs.exifValid = false; cfs.timeValid = false; - // RAW works like this: - // 1. if we are here it's because we aren't in the cache so load the JPG - // image out of the RAW. Mark as "quick". - // 2. if we don't find that then just grab the real image. - bool quick = false; - - rtengine::eSensorType sensorType = rtengine::ST_NONE; - - if (initial_ && options.internalThumbIfUntouched) { - quick = true; - tpp = rtengine::Thumbnail::loadQuickFromRaw(fname, sensorType, tw, th, 1, TRUE); - } - - if (!tpp) { - quick = false; - tpp = rtengine::Thumbnail::loadFromRaw(fname, sensorType, tw, th, 1, pparams->wb.equal, pparams->wb.observer, TRUE, &(pparams->raw)); - } - - cfs.sensortype = sensorType; + // this will load formats supported by imagio (jpg, png, jxl, and tiff) + tpp = rtengine::Thumbnail::loadFromImage(fname, tw, th, -1, pparams->wb.equal, pparams->wb.observer); if (tpp) { - cfs.format = FT_Raw; - cfs.thumbImgType = quick ? CacheImageData::QUICK_THUMBNAIL : CacheImageData::FULL_THUMBNAIL; + cfs.format = FT_Custom; infoFromImage(fname); - - if (!quick) { - cfs.width = tpp->full_width; - cfs.height = tpp->full_height; - } } if (!tpp) { - // this will load formats supported by imagio (jpg, png, jxl, and tiff) - tpp = rtengine::Thumbnail::loadFromImage(fname, tw, th, -1, pparams->wb.equal, pparams->wb.observer); + // RAW works like this: + // 1. if we are here it's because we aren't in the cache so load the JPG + // image out of the RAW. Mark as "quick". + // 2. if we don't find that then just grab the real image. + bool quick = false; + + rtengine::eSensorType sensorType = rtengine::ST_NONE; + + if (initial_ && options.internalThumbIfUntouched) { + quick = true; + tpp = rtengine::Thumbnail::loadQuickFromRaw(fname, sensorType, tw, th, 1, TRUE); + } + + if (!tpp) { + quick = false; + tpp = rtengine::Thumbnail::loadFromRaw(fname, sensorType, tw, th, 1, pparams->wb.equal, pparams->wb.observer, TRUE, &(pparams->raw)); + } + + cfs.sensortype = sensorType; if (tpp) { - cfs.format = FT_Custom; + cfs.format = FT_Raw; + cfs.thumbImgType = quick ? CacheImageData::QUICK_THUMBNAIL : CacheImageData::FULL_THUMBNAIL; infoFromImage(fname); + + if (!quick) { + cfs.width = tpp->full_width; + cfs.height = tpp->full_height; + } } } From 3b2990dd78424cda3a57434fc405646cac138ced Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Tue, 11 Jun 2024 17:55:10 -0700 Subject: [PATCH 09/39] Add/update dcraw constants from LibRaw Add or update adobe_coeff constants from LibRaw public snapshot 202403. --- rtengine/dcraw.cc | 481 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 474 insertions(+), 7 deletions(-) diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index cfb949b86..3358dc91b 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -8113,6 +8113,12 @@ void CLASS adobe_coeff (const char *make, const char *model) { 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } }, { "Apple QuickTake", 0, 0, /* DJC */ { 21392,-5653,-3353,2406,8010,-415,7166,1427,2078 } }, + { "Broadcom RPi IMX219", 66, 0x3ff, + { 5302,1083,-728,-5320,14112,1699,-863,2371,5136 } }, /* LibRaw */ // From LibRaw + { "Broadcom RPi OV5647", 16, 0x3ff, + { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } }, /* DJC */ // From LibRaw + { "Broadcom Pi", 16, 0x3ff, + { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } }, /* DJC */ // From LibRaw { "Canon EOS D2000", 0, 0, { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, { "Canon EOS D6000", 0, 0, @@ -8151,6 +8157,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } }, { "Canon EOS 50D", 0, 0x3d93, { 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } }, + { "Canon EOS 250D", 0, 0, + { 9079,-1923,-1236,-4677,12454,2492,-922,2319,5565 } }, // From LibRaw { "Canon EOS 60D", 0, 0x2ff7, { 6719,-994,-925,-4408,12426,2211,-887,2129,6051 } }, { "Canon EOS 70D", 0, 0x3bc7, @@ -8161,6 +8169,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 7457,-671,-937,-4849,12495,2643,-1213,2354,5492 } }, { "Canon EOS 100D", 0, 0x350f, { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } }, + { "Canon EOS 250D", 0, 0, + { 9079,-1923,-1236,-4677,12454,2492,-922,2319,5565 } }, // From LibRaw { "Canon EOS 200D", 0, 0, { 7377,-742,-998,-4235,11981,2549,-673,1918,5538 } }, { "Canon EOS 300D", 0, 0xfa0, @@ -8185,8 +8195,14 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } }, { "Canon EOS 760D", 0, 0x350f, { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } }, + { "Canon EOS 850D", 0, 0, + { 9079,-1923,-1236,-4677,12454,2492,-922,2319,5565}}, // From LibRaw { "Canon EOS 800D", 0, 0, { 6970,-512,-968,-4425,12161,2553,-739,1982,5601 } }, + { "EOS 850D", 0, 0, + { 9079,-1923,-1236,-4677,12454,2492,-922,2319,5565}}, // From LibRaw + { "Canon EOS 90D", 0, 0, + { 11498, -3759, -1516, -5073, 12954, 2349, -892, 1867, 6118}}, // From LibRaw { "Canon EOS 1000D", 0, 0xe43, { 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } }, { "Canon EOS 1100D", 0, 0x3510, @@ -8199,12 +8215,46 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, { "Canon EOS 3000D", 0, 0, { 6939,-1016,-866,-4428,12473,2177,-1175,2178,6162 } }, + { "Canon EOS RP", 0, 0, + { 8608,-2097,-1178,-5425,13265,2383,-1149,2238,5680 } }, // From LibRaw + { "Canon EOS R3", 0, 0, + { 9423,-2839,-1195,-4532,12377,2415,-483,1374,5276 } }, // From LibRaw + { "Canon EOS R50", 0, 0, + { 9269, -2012, -1107, -3990, 11762, 2527, -569, 2093, 4913 } }, // From LibRaw + { "Canon EOS R100", 0, 0, + { 8230, -1515, -1032, -4179, 12005, 2454, -649, 2076, 4711 } }, // From LibRaw + { "Canon EOS R5", 0, 0, + { 9766,-2953,-1254,-4276,12116,2433,-437,1336,5131 } }, // From LibRaw + { "Canon EOS R6 Mark II", 0, 0, + { 9539, -2795, -1224, -4175, 11998, 2458, -465, 1755,6048 } }, // From LibRaw + { "Canon EOS R6", 0, 0, + { 8293,-1611,-1132,-4759,12711,2275,-1013,2415,5509 } }, // From LibRaw + { "Canon EOS R7", 0, 0, + { 10424, -3138, -1300, -4221, 11938, 2584, -547, 1658, 6183 } }, // From LibRaw + { "Canon EOS R8", 0, 0, + { 9539, -2795, -1224, -4175, 11998, 2458, -465, 1755, 6048 } }, // From LibRaw + { "Canon EOS R10", 0, 0, + { 9269, -2012, -1107, -3990, 11762, 2527, -569, 2093, 4913 } }, // From LibRaw + { "Canon EOS Ra", 0, 0, + { 22880,-11531,-2223,-2034,10469,1809, 316,1401,5769 } }, // From LibRaw + { "Canon EOS R", 0, 0, + { 8293,-1789,-1094,-5025,12925,2327,-1199,2769,6108 } }, // v.2 // From LibRaw + { "Canon EOS M6 Mark II", 0, 0, + { 11498,-3759,-1516,-5073,12954,2349,-892,1867,6118 } }, // From LibRaw { "Canon EOS M6", 0, 0, { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, + { "Canon EOS M50 Mark II", 0, 0, + { 10463,-2173,-1437,-4856,12635,2482,-1216,2915,7237 } }, // From LibRaw + { "Canon EOS M50", 0, 0, + { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, // From LibRaw { "Canon EOS M5", 0, 0, /* also M50 */ { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, { "Canon EOS M3", 0, 0, { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } }, + { "Canon EOS M200", 0, 0, + { 10463,-2173,-1437,-4856,12635,2482,-1216,2915,7237 } }, // From LibRaw + { "Canon EOS M2", 0, 0, + { 6400,-480,-888,-5294,13416,2047,-1296,2203,6137 } }, // From LibRaw { "Canon EOS M100", 0, 0, { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, { "Canon EOS M10", 0, 0, @@ -8227,6 +8277,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } }, { "Canon EOS-1D C", 0, 0x3c4e, { 6847,-614,-1014,-4669,12737,2139,-1197,2488,6846 } }, + { "Canon EOS-1D X Mark III", 0, 0, + { 8971, -2022, -1242, -5405, 13249, 2380, -1280, 2483, 6072}}, // From LibRaw { "Canon EOS-1D X Mark II", 0, 0, { 7596,-978,-967,-4808,12571,2503,-1398,2567,5752 } }, { "Canon EOS-1D X", 0, 0x3c4e, @@ -8235,12 +8287,16 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } }, { "Canon EOS C500", 853, 0, /* DJC */ { 17851,-10604,922,-7425,16662,763,-3660,3636,22278 } }, + { "Canon PowerShot 600", 0, 0, + { -3822,10019,1311,4085,-157,3386,-5341,10829,4812,-1969,10969,1126 } }, // From LibRaw { "Canon PowerShot A530", 0, 0, { 0 } }, /* don't want the A5 matrix */ { "Canon PowerShot A50", 0, 0, { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } }, { "Canon PowerShot A5", 0, 0, { -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } }, + { "Canon PowerShot D10", 127, 0, + { 14052,-5229,-1156,-1325,9420,2252,-498,1957,4116 } }, /* DJC */ // From LibRaw { "Canon PowerShot G10", 0, 0, { 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } }, { "Canon PowerShot G11", 0, 0, @@ -8253,6 +8309,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8020,-2687,-682,-3704,11879,2052,-965,1921,5556 } }, { "Canon PowerShot G1 X Mark III", 0, 0, { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, + { "Canon PowerShot G1 X Mark II", 0, 0, + { 7378,-1255,-1043,-4088,12251,2048,-876,1946,5805 } }, // From LibRaw { "Canon PowerShot G1 X", 0, 0, { 7378,-1255,-1043,-4088,12251,2048,-876,1946,5805 } }, { "Canon PowerShot G1", 0, 0, @@ -8263,12 +8321,18 @@ void CLASS adobe_coeff (const char *make, const char *model) { 9701,-3857,-921,-3149,11537,1817,-786,1817,5147 } }, { "Canon PowerShot G3", 0, 0, { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } }, + { "Canon PowerShot G5 X Mark II",0, 0, + { 11629, -5713, -914, -2706, 11090, 1842, -206, 1225, 5515 } }, // From LibRaw { "Canon PowerShot G5 X", 0, 0, { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } }, { "Canon PowerShot G5", 0, 0, { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } }, { "Canon PowerShot G6", 0, 0, { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } }, + { "Canon PowerShot G7 X Mark III", 0, 0, + { 11629, -5713, -914, -2706, 11090, 1842, -206, 1225, 5515 } }, // From LibRaw + { "Canon PowerShot G7 X Mark II", 0, 0, + { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } }, // From LibRaw { "Canon PowerShot G7 X", 0, 0, { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } }, { "Canon PowerShot G9 X Mark II", 0, 0, @@ -8305,14 +8369,24 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8039,-2643,-654,-3783,11230,2930,-206,690,4194 } }, { "Canon PowerShot S120", 0, 0, { 6961,-1685,-695,-4625,12945,1836,-1114,2152,5518 } }, + { "Canon PowerShot SD300", 0, 0, + { 6526,-1720,-1075,-1390,5945,602,-90,820,2380 } }, // CHDK // From LibRaw { "Canon PowerShot SX1 IS", 0, 0, { 6578,-259,-502,-5974,13030,3309,-308,1058,4970 } }, + { "Canon PowerShot SX20 IS", 0, 0, + { 8275,-2904,-1260,-128,5305,505,51,481,2450 } }, // CHDK // From LibRaw + { "Canon PowerShot SX30 IS", 0, 0, + { 13014,-4698,-1026,-2001,9615,2386,-164,1423,3759 } }, // CHDK // From LibRaw { "Canon PowerShot SX50 HS", 0, 0, { 12432,-4753,-1247,-2110,10691,1629,-412,1623,4926 } }, { "Canon PowerShot SX60 HS", 0, 0, { 13161,-5451,-1344,-1989,10654,1531,-47,1271,4955 } }, + { "Canon PowerShot SX70 HS", 0, 0, + { 18285,-8907,-1951,-1845,10688,1323,364,1101,5139 } }, // From LibRaw { "Canon PowerShot A3300", 0, 0, /* DJC */ { 10826,-3654,-1023,-3215,11310,1906,0,999,4960 } }, + { "Canon PowerShot A460", 0, 0, + { 6493,-2338,-885,-1589,5934,697,-445,1368,2543 } }, // CHDK // From LibRaw { "Canon PowerShot A470", 0, 0, /* DJC */ { 12513,-4407,-1242,-2680,10276,2405,-878,2215,4734 } }, { "Canon PowerShot A610", 0, 0, /* DJC */ @@ -8327,14 +8401,24 @@ void CLASS adobe_coeff (const char *make, const char *model) { 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } }, { "Canon PowerShot A720", 0, 0, /* DJC */ { 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } }, + { "Canon PowerShot S2 IS", 0, 0, + { 5477,-1435,-992,-1868,6639,510,-58,792,2670 } }, // CHDK // From LibRaw { "Canon PowerShot S3 IS", 0, 0, /* DJC */ { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } }, { "Canon PowerShot SX110 IS", 0, 0, /* DJC */ { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } }, + { "Canon PowerShot SX120 IS", 0, 0, + { 7286,-2242,-1047,41,4401,457,269,684,1864 } }, // CHDK // From LibRaw { "Canon PowerShot SX220", 0, 0, /* DJC */ { 13898,-5076,-1447,-1405,10109,1297,-244,1860,3687 } }, + { "Canon PowerShot SX710 HS", 0, 0, + { 13161,-5451,-1344,-1989,10654,1531,-47,1271,4955 } }, // From LibRaw { "Canon IXUS 160", 0, 0, /* DJC */ { 11657,-3781,-1136,-3544,11262,2283,-160,1219,4700 } }, + { "Casio EX-F1", 0, 0, + { 9084,-2016,-848,-6711,14351,2570,-1059,1725,6135 } }, // From LibRaw + { "Casio EX-FH100", 0, 0, + { 12771,-4179,-1558,-2149,10938,1375,-453,1751,4494 } }, // From LibRaw { "Casio EX-S20", 0, 0, /* DJC */ { 11634,-3924,-1128,-4968,12954,2015,-1588,2648,7206 } }, { "Casio EX-Z750", 0, 0, /* DJC */ @@ -8353,6 +8437,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } }, { "Epson R-D1", 0, 0, { 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } }, + { "Fujifilm DBP for GX680", 128, 0x0fff, + { 12741,-4916,-1420,-8510,16791,1715,-1767,2302,7771 } }, /* temp, copy from S2Pro */ // From LibRaw { "Fujifilm E550", 0, 0, { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } }, { "Fujifilm E900", 0, 0, @@ -8365,9 +8451,15 @@ void CLASS adobe_coeff (const char *make, const char *model) { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, { "Fujifilm F7", 0, 0, { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } }, + { "Fujifilm F810", 0, 0, + { 11044,-3888,-1120,-7248,15167,2208,-1531,2276,8069 } }, // From LibRaw { "Fujifilm F8", 0, 0, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, - { "Fujifilm GFX 50S", 0, 0, + { "Fujifilm GFX 100 II", 0, 0, + { 12806,-5779,-1110,-3546,11507,2318,-177,996,5715 } }, // From LibRaw + { "Fujifilm GFX 100", 0, 0, // same CMs: "GFX 100", "GFX 100S"/"GFX100S", "GFX 100 IR" + { 16212,-8423,-1583,-4336,12583,1937,-195,726,6199 } }, // From LibRaw + { "Fujifilm GFX 50", 0, 0, // same CMs: "GFX 50S", "GFX 50R", "GFX 50S II" { 11756,-4754,-874,-3056,11045,2305,-381,1457,6006 } }, { "Fujifilm S100FS", 514, 0, { 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } }, @@ -8411,7 +8503,7 @@ void CLASS adobe_coeff (const char *make, const char *model) { 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } }, { "Fujifilm IS Pro", 0, 0, { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } }, - { "Fujifilm HS10 HS11", 0, 0xf68, + { "Fujifilm HS10", 0, 0xf68, { 12440,-3954,-1183,-1123,9674,1708,-83,1614,4086 } }, { "Fujifilm HS2", 0, 0xfef, { 13690,-5358,-1474,-3369,11600,1998,-132,1554,4395 } }, @@ -8427,6 +8519,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } }, { "Fujifilm X100T", 0, 0, { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } }, + { "Fujifilm X100V", 0, 0, + { 13426,-6334,-1177,-4244,12136,2371,580,1303,5980 } }, // From LibRaw { "Fujifilm X100", 0, 0, { 12161,-4457,-1069,-5034,12874,2400,-795,1724,6904 } }, { "Fujifilm X10", 0, 0, @@ -8441,6 +8535,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } }, { "Fujifilm X-Pro2", 0, 0, { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, + { "Fujifilm X-Pro3", 0, 0, + { 13426,-6334,-1177,-4244,12136,2371,580,1303,5980 } }, // From LibRaw { "Fujifilm X-A10", 0, 0, { 11540,-4999,-991,-2949,10963,2278,-382,1049,5605 } }, { "Fujifilm X-A20", 0, 0, @@ -8453,6 +8549,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 12407,-5222,-1086,-2971,11116,2120,-294,1029,5284 } }, { "Fujifilm X-A5", 0, 0, { 11673,-4760,-1041,-3988,12058,2166,-771,1417,5569 } }, + { "Fujifilm X-A7", 0, 0, + { 15055,-7391,-1274,-4062,12071,2238,-610,1217,6147 } }, // From LibRaw { "Fujifilm X-E1", 0, 0, { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } }, { "Fujifilm X-E2S", 0, 0, @@ -8461,22 +8559,123 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } }, { "Fujifilm X-E3", 0, 0, { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, + { "Fujifilm X-E4", 0, 0, + { 13426, -6334, -1177, -4244, 12136, 2371, -580, 1303, 5980 } }, // From LibRaw { "Fujifilm X-H1", 0, 0, { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, + { "Fujifilm X-H2S", 0, 0, + { 12836, -5909, -1032, -3087, 11132, 2236, -35, 872, 5330 } }, // From LibRaw + { "Fujifilm X-H2", 0, 0, + { 11809, -5358, -1141, -4248, 12164, 2343, -514, 1097, 5848 } }, // From LibRaw { "Fujifilm X-M1", 0, 0, { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } }, + { "Fujifilm X-S20", 0, 0, + { 12836, -5909, -1032, -3087, 11132, 2236, -35, 872, 5330 } }, // From LibRaw + { "Fujifilm X-S10", 0, 0, + { 13426,-6334,-1177,-4244,12136,2371,-580,1303,5980 } }, // From LibRaw { "Fujifilm X-S1", 0, 0, { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } }, + { "Fujifilm X-T100", 0, 0, + { 11673,-4760,-1041,-3988,12058,2166,-771,1417,5569 } }, // From LibRaw { "Fujifilm X-T1", 0, 0, /* also X-T10 */ { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } }, + { "Fujifilm X-T200", 0, 0, + { 15055,-7391,-1274,-4062,12071,2238,-610,1217,6147 } }, // From LibRaw { "Fujifilm X-T2", 0, 0, /* also X-T20 */ { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, + { "Fujifilm X-T3", 0, 0, // same CMs: X-T3, X-T30, "X-T30 II" + { 13426,-6334,-1177,-4244,12136,2371,580,1303,5980 } }, // v.2 // From LibRaw + { "Fujifilm X-T4", 0, 0, + { 13426,-6334,-1177,-4244,12136,2371,580,1303,5980 } }, // From LibRaw + { "Fujifilm X-T5", 0, 0, + { 11809, -5358, -1141, -4248, 12164, 2343, -514, 1097, 5848 } }, // From LibRaw + { "Fujifilm XF10", 0, 0, + { 11673,-4760,-1041,-3988,12058,2166,-771,1417,5569 } }, // From LibRaw { "Fujifilm XF1", 0, 0, { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } }, { "Fujifilm XQ", 0, 0, /* XQ1 and XQ2 */ { 9252,-2704,-1064,-5893,14265,1717,-1101,2341,4349 } }, + { "GITUP G3DUO", 130, 62000, + { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, // From LibRaw + { "GITUP GIT2P", 4160, 0, + { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, // From LibRaw + { "GITUP GIT2", 3200, 0, + { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, // From LibRaw { "GoPro HERO5 Black", 0, 0, { 10344,-4210,-620,-2315,10625,1948,93,1058,5541 } }, + { "Hasselblad L1D-20c", 0, 0, + { 7310, -2746, -646, -2991, 10847, 2469, 163, 585, 6324}}, // From LibRaw +// TODO: These Hasselblad camera names are from LibRaw. dcraw names are different. +// { "Hasselblad 16-Uncoated-3FR", 0, 0, +// { 8519, -3260, -280, -5081, 13459, 1738, -1449, 2960, 7809}}, +// { "Hasselblad 16-Uncoated-FFF", 0, 0, +// { 8068, -2959, -108, -5788, 13608, 2389, -1002, 2237, 8162}}, +// { "Hasselblad 16-Uncoated", 0, 0, +// { 8519, -3260, -280, -5081, 13459, 1738, -1449, 2960, 7809}}, +// { "Hasselblad 22-Uncoated-3FR", 0, 0, +// { 8523, -3257, -280, -5078, 13458, 1743, -1449, 2961, 7809}}, +// { "Hasselblad 22-Uncoated-FFF", 0, 0, +// { 8068, -2959, -108, -5788, 13608, 2389, -1002, 2237, 8162}}, +// { "Hasselblad 22-Uncoated", 0, 0, +// { 8519, -3260, -280, -5081, 13459, 1738, -1449, 2960, 7809}}, +// { "Hasselblad 31-Uncoated-FFF", 0, 0, +// { 5155, -1201, 200, -5841, 13197, 2950, -1101, 2317, 6988}}, +// { "Hasselblad 31-Uncoated", 0, 0, +// { 5458, -1448, 145, -4479, 12338, 2401, -1659, 3086, 6710}}, +// { "Hasselblad 39-Uncoated-3FR", 0, 0, +// { 3904, -100, 262, -4318, 12407, 2128, -1598, 3594, 6233}}, +// { "Hasselblad 39-Uncoated-FFF", 0, 0, +// { 4739, -932, 295, -4829, 12220, 2952, -1027, 2341, 7083}}, +// { "Hasselblad 39-Uncoated", 0, 0, +// { 3894, -110, 287, -4672, 12610, 2295, -2092, 4100, 6196}}, +// { "Hasselblad 39-Coated-3FR", 0, 0, +// { 5427, -1147, 173, -3834, 12073, 1969, -1444, 3320, 5621}}, +// { "Hasselblad 39-Coated-FFF", 0, 0, +// { 5323, -1233, 399, -4926, 12362, 2894, -856, 2471, 5961}}, +// { "Hasselblad 39-Coated", 0, 0, +// { 3857, 452, -46, -6008, 14477, 1596, -2627, 4481, 5718}}, +// { "Hasselblad 40-Coated5-3FR", 0, 0, +// { 7014, -2067, -540, -4821, 13016, 1980, -1663, 3089, 6940}}, +// { "Hasselblad 40-Coated5-FFF", 0, 0, +// { 5963, -1357, -172, -5439, 12762, 3007, -964, 2222, 7172}}, +// { "Hasselblad 40-Coated5", 0, 0, +// { 6159, -1402, -177, -5439, 12762, 3007, -955, 2200, 7104}}, +// { "Hasselblad 40-Coated-3FR", 0, 0, +// { 6550, -1681, -399, -4626, 12598, 2257, -1807, 3354, 6486}}, +// { "Hasselblad 40-Coated-FFF", 0, 0, +// { 6041, -1375, -174, -5439, 10000, 3007, -930, 2145, 6923}}, +// { "Hasselblad 40-Coated", 0, 0, +// { 6159, -1402, -177, -5439, 12762, 3007, -955, 2200, 7104}}, +// { "Hasselblad 50-Coated5-3FR", 0, 0, +// { 5707, -693, -382, -4285, 12669, 1773, -1615, 3519, 5410}}, +// { "Hasselblad 50-Coated5-FFF", 0, 0, +// { 5263, -612, 39, -4950, 12426, 2843, -935, 2423, 5941}}, +// { "Hasselblad 50-Coated5", 0, 0, +// { 5656, -659, -346, -3923, 12306, 1791, -1602, 3509, 5442}}, +// { "Hasselblad 50-Coated-3FR", 0, 0, +// { 5656, -659, -346, -3923, 12305, 1790, -1602, 3509, 5442}}, +// { "Hasselblad 50-Coated-FFF", 0, 0, +// { 5280, -614, 39, -4950, 12426, 2843, -939, 2434, 5968}}, +// { "Hasselblad 50-Coated", 0, 0, +// { 5656, -659, -346, -3923, 12306, 1791, -1602, 3509, 5442}}, +// { "Hasselblad 50-15-Coated5-II-3FR", 0, 0, +// { 10887, -6152, 1034, -3564, 12412, 4224, 63, 626, 10123}}, +// { "Hasselblad 50-15-Coated5-II-FFF", 0, 0, +// { 4932, -835, 141, -4878, 11868, 3437, -1138, 1961, 7067}}, +// { "Hasselblad 50-15-Coated5-II", 0, 0, +// { 8737, -4937, 830, -2860, 9961, 3390, 51, 502, 8124}}, +// { "Hasselblad 50-15-Coated5", 0, 0, +// { 4932,-835,141,-4878,11868,3437,-1138,1961,7067 } }, +// { "Hasselblad 60-Coated-3FR", 0, 0, +// { 9296, 336, -1088, -6442, 14323, 2289, -1433, 2942, 5756}}, +// { "Hasselblad 60-Coated", 0, 0, +// { 9662, -684, -279, -4903, 12293, 2950, -344, 1669, 6024}}, +// { "Hasselblad 100-17-Coated5", 0, 0, +// { 5110, -1357, -308, -5573, 12835, 3077, -1279, 2025, 7010}}, +// { "Hasselblad 100-20-Coated6", 0, 0, +// { 6468,-1899,-545,-4526,12267,2542,-388,1276,6096 } }, + { "HTC One A9", 64, 1023, + { 101,-20,-2,-11,145,41,-24,1,56 } }, /* this is FM1 transposed */ // From LibRaw { "Imacon Ixpress", 0, 0, /* DJC */ { 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } }, { "Kodak NC2000", 0, 0, @@ -8487,11 +8686,11 @@ void CLASS adobe_coeff (const char *make, const char *model) { 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } }, { "Kodak DCS420", 0, 0, { 10868,-1852,-644,-1537,11083,484,2343,628,2216 } }, - { "Kodak DCS460", 0, 0, + { "Kodak DCS46", 0, 0, // same CM as EOSDCS1 and DCS465 DB { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } }, { "Kodak EOSDCS1", 0, 0, { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } }, - { "Kodak EOSDCS3B", 0, 0, + { "Kodak EOSDCS3", 0, 0, { 9898,-2700,-940,-2478,12219,206,1985,634,1031 } }, { "Kodak DCS520C", 178, 0, { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } }, @@ -8517,6 +8716,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } }, { "Kodak ProBack", 0, 0, { 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } }, + { "Kodak PIXPRO AZ901", 0, 0, // dng + { 21875, -8006, -2558, 634, 8194, 1104, 1535, 951, 6969}}, // From LibRaw { "Kodak P712", 0, 0, { 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } }, { "Kodak P850", 0, 0xf7c, @@ -8531,16 +8732,62 @@ void CLASS adobe_coeff (const char *make, const char *model) { 11749,-4048,-1309,-1867,10572,1489,-138,1449,4522 } }, { "Kodak EASYSHARE Z1015", 0, 0xef1, { 11265,-4286,-992,-4694,12343,2647,-1090,1523,5447 } }, + { "Leaf AFi 54S", 0, 0, + { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}}, // From LibRaw + { "Leaf AFi 65S", 0, 0, + { 7914, 1414, -1190, -8776, 16582, 2280, -2811, 4605, 5562}}, // From LibRaw + { "Leaf AFi 75S", 0, 0, + { 7914, 1414, -1190, -8776, 16582, 2280, -2811, 4605, 5562}}, // From LibRaw { "Leaf CMost", 0, 0, { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } }, + { "Leaf Credo 40", 0, 0, + { 8035, 435, -962, -6001, 13872, 2320, -1159, 3065, 5434}}, // From LibRaw + { "Leaf Credo 50", 0, 0, // emb + { 10325, 845, -604, -4113, 13385, 481, -1791, 4163, 6924}}, // From LibRaw + { "Leaf Credo 60", 0, 0, + { 8035, 435, -962, -6001, 13872, 2320, -1159, 3065, 5434}}, // From LibRaw + { "Leaf Credo 80", 0, 0, + { 6294, 686, -712, -5435, 13417, 2211, -1006, 2435, 5042}}, // From LibRaw + { "Leaf Valeo 11", 0, 0, + { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}}, // From LibRaw + { "Leaf Valeo 17", 0, 0, + { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}}, // From LibRaw + { "Leaf Valeo 22", 0, 0, + { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}}, // From LibRaw { "Leaf Valeo 6", 0, 0, { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } }, + { "Leaf AFi-II 7", 0, 0, + { 7691,-108,-339,-6185,13627,2833,-2046,3899,5952 } }, // From LibRaw + { "Leaf AFi-II 10", 0, 0, + { 6719,1147,-148,-6929,14061,3176,-1781,3343,5424 } }, // From LibRaw + { "Leaf Aptus 17", 0, 0, + { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}}, // From LibRaw + { "Leaf Aptus 22", 0, 0, + { 8236, 1746, -1313, -8251, 15953, 2428, -3672, 5786, 5771}}, // From LibRaw { "Leaf Aptus 54S", 0, 0, { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } }, + { "Leaf Aptus 65S", 0, 0, + { 7914, 1414, -1190, -8776, 16582, 2280, -2811, 4605, 5562}}, // From LibRaw { "Leaf Aptus 65", 0, 0, { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, + { "Leaf Aptus 75S", 0, 0, + { 7914, 1414, -1190, -8776, 16582, 2280, -2811, 4605, 5562}}, // From LibRaw { "Leaf Aptus 75", 0, 0, { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, + { "Leaf Aptus-II 5", 0, 0, + { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, // From LibRaw + { "Leaf Aptus-II 6", 0, 0, + { 7989,-113,-352,-6185,13627,2833,-2028,3866,5901 } }, // From LibRaw + { "Leaf Aptus-II 7", 0, 0, + { 8209,-116,-362,-6185,13627,2833,-1962,3740,5709 } }, // From LibRaw + { "Leaf Aptus-II 8", 0, 0, + { 7361,1257,-163,-6929,14061,3176,-1839,3454,5603 } }, // From LibRaw + { "Leaf Aptus-II 10R", 0, 0, + { 7167,1224,-158,-6929,14061,3176,-1826,3429,5562 } }, // From LibRaw + { "Leaf Aptus-II 10", 0, 0, + { 7527,1285,-166,-6929,14061,3176,-1995,3747,6077 } }, // From LibRaw + { "Leaf Aptus-II 12", 0, 0, + { 7361,1257,-163,-6929,14061,3176,-1695,3182,5162 } }, // From LibRaw { "Leaf", 0, 0, { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } }, { "Mamiya ZD", 0, 0, @@ -8551,6 +8798,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } }, { "Minolta DiMAGE 7Hi", 0, 0xf7d, { 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 } }, + { "Minolta DiMAGE 7i", 0, 0xf7d, + { 11050,-3791,-1199,-7875,15585,2434,-2797,3359,7560 } }, // From LibRaw { "Minolta DiMAGE 7", 0, 0xf7d, { 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } }, { "Minolta DiMAGE A1", 0, 0xf8b, @@ -8591,6 +8840,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } }, { "Nikon D3400", 0, 0, { 6988,-1384,-714,-5631,13410,2447,-1485,2204,7318 } }, + { "Nikon D3500", 0, 0, + { 8821,-2938,-785,-4178,12142,2287,-824,1651,6860 } }, // From LibRaw { "Nikon D300", 0, 0, { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } }, { "Nikon D3X", 0, 0, @@ -8633,6 +8884,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } }, { "Nikon D60", 0, 0, { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } }, + { "Nikon D6", 0, 0, + { 9028,-3423,-1035,-6321,14265,2217,-1013,1683,6928 } }, // From LibRaw { "Nikon D7000", 0, 0, { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, { "Nikon D7100", 0, 0, @@ -8641,6 +8894,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, { "Nikon D7500", 0, 0, { 8813,-3210,-1036,-4703,12868,2021,-1054,1940,6129 } }, + { "Nikon D780", 0, 0, + { 9943,-3269,-839,-5323,13269,2259,-1198,2083,7557 } }, // From LibRaw { "Nikon D750", 0, 0, { 9020,-2890,-715,-4535,12436,2348,-934,1919,7086 } }, { "Nikon D700", 0, 0, @@ -8649,6 +8904,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, { "Nikon D850", 0, 0, { 10405,-3755,-1270,-5461,13787,1793,-1040,2015,6785 } }, + { "Nikon D810A", 0, 0, + { 11973,-5685,-888,-1965,10326,1901,-115,1123,7169 } }, // From LibRaw { "Nikon D810", 0, 0, { 9369,-3195,-791,-4488,12430,2301,-893,1796,6872 } }, { "Nikon D800", 0, 0, @@ -8687,6 +8944,24 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, { "Nikon E8800", 0, 0, { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } }, + { "Nikon Z 30", 0, 0, + { 10339,-3822,-890,-4183,12023,2436,-671,1638,7049 } }, // From LibRaw + { "Nikon Z 50", 0, 0, + { 11640,-4829,-1079,-5107,13006,2325,-972,1711,7380 } }, // From LibRaw + { "Nikon Z 5", 0, 0, + { 8695,-2558,-648,-5015,12711,2575,-1279,2215,7514 } }, // From LibRaw + { "Nikon Z 6", 0, 0, + { 9943,-3269,-839,-5323,13269,2259,-1198,2083,7557 } }, // 'Z 6'(v.2) // From LibRaw, 'Z 6_2' + { "Nikon Z 7", 0, 0, + { 13705,-6004,-1400,-5464,13568,2062,-940,1706,7618 } }, // 'Z 7'(v.2), 'Z 7_2' // From LibRaw + { "Nikon Z 8", 0, 0, + {11423,-4564,-1123,-4816,12895,2119,-210,1061,7282 } }, // From LibRaw + { "Nikon Z 9", 0, 0, + { 13389,-6049,-1441,-4544,12757,1969,229,498,7390 } }, // From LibRaw + { "Nikon Z fc", 0, 0, + { 11640,-4829,-1079,-5107,13006,2325,-972,1711,7380 } }, // From LibRaw + { "Nikon COOLPIX A1000", 0, 0, + { 10601,-3487,-1127,-2931,11443,1676,-587,1740,5278 } }, // From LibRaw { "Nikon COOLPIX A", 0, 0, { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, { "Nikon COOLPIX B700", 200, 0, @@ -8695,6 +8970,10 @@ void CLASS adobe_coeff (const char *make, const char *model) { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, { "Nikon COOLPIX P340", 200, 0, { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, + { "Nikon Coolpix P950", 0, 0, + { 13307, -5641, -1290, -2048, 10581, 1689, -64, 1222, 5176}}, // From LibRaw + { "Nikon COOLPIX P1000", 0, 0, + { 14294,-6116,-1333,-1628,10219,1637,-14,1158,5022 } }, // From LibRaw { "Nikon COOLPIX P6000", 0, 0, { 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } }, { "Nikon COOLPIX P7000", 0, 0, @@ -8775,6 +9054,10 @@ void CLASS adobe_coeff (const char *make, const char *model) { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } }, { "Olympus E-P5", 0, 0, { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, + { "Olympus E-P7", 0, 0, + { 9476,-3182,-765,-2613,10958,1893,-449,1315,5268 } }, // From LibRaw + { "Olympus E-PL10", 0, 0, + { 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 } }, // From LibRaw { "Olympus E-PL1s", 0, 0, { 11409,-3872,-1393,-4572,12757,2003,-709,1810,7415 } }, { "Olympus E-PL1", 0, 0, @@ -8797,12 +9080,20 @@ void CLASS adobe_coeff (const char *make, const char *model) { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } }, { "Olympus E-PM2", 0, 0, { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, + { "Olympus E-M10MarkIV", 0, 0, + { 9476,-3182,-765,-2613,10958,1893,-449,1315,5268 } }, // From LibRaw { "Olympus E-M10", 0, 0, /* also E-M10 Mark II & III */ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, + { "Olympus E-M1X", 0, 0, + { 11896,-5110,-1076,-3181,11378,2048,-519,1224,5166 } }, // From LibRaw + { "Olympus E-M1MarkIII", 0, 0, + { 11896,-5110,-1076,-3181,11378,2048,-519,1224,5166 } }, // From LibRaw { "Olympus E-M1Mark II", 0, 0, { 9383,-3170,-763,-2457,10702,2020,-384,1236,5552 } }, { "Olympus E-M1", 0, 0, { 7687,-1984,-606,-4327,11928,2721,-1381,2339,6452 } }, + { "Olympus E-M5MarkIII", 0, 0, + { 11896,-5110,-1076,-3181,11378,2048,-519,1224,5166 } }, // From LibRaw { "Olympus E-M5MarkII", 0, 0, { 9422,-3258,-711,-2655,10898,2015,-512,1354,5512 } }, { "Olympus E-M5", 0, 0xfe1, @@ -8824,13 +9115,15 @@ void CLASS adobe_coeff (const char *make, const char *model) { 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } }, { "Olympus SP560UZ", 0, 0xff9, { 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } }, + { "Olympus SP565UZ", 0, 0, + { 11856,-4469,-1159,-4814,12368,2756,-993,1779,5589 } }, // From LibRaw { "Olympus SP570UZ", 0, 0, { 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } }, { "Olympus STYLUS1", 0, 0, { 8360,-2420,-880,-3928,12353,1739,-1381,2416,5173 } }, { "Olympus TG-4", 0, 0, { 11426,-4159,-1126,-2066,10678,1593,-120,1327,4998 } }, - { "Olympus TG-5", 0, 0, + { "Olympus TG-", 0, 0, // same CMs: TG-5, TG-6 { 10899,-3833,-1082,-2112,10736,1575,-267,1452,5269 } }, { "Olympus XZ-10", 0, 0, { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } }, @@ -8840,6 +9133,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } }, { "OM Digital Solutions OM-1", 0, 0, { 9488, -3984, -714, -2887, 10945, 2229, -137, 960, 5786 } }, // From LibRaw + { "OM Digital Solutions OM-5", 0, 0, + { 11896, -5110, -1076, -3181, 11378, 2048, -519, 1224, 5166 } }, // From LibRaw { "OmniVision", 0, 0, /* DJC */ { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } }, { "Pentax *ist DL2", 0, 0, @@ -8852,6 +9147,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } }, { "Pentax *ist D", 0, 0, { 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } }, + { "Pentax K-01", 0, 0, + { 8134,-2728,-645,-4365,11987,2694,-838,1509,6498 } }, // From LibRaw { "Pentax K10D", 0, 0, { 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } }, { "Pentax K1", 0, 0, @@ -8872,10 +9169,16 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8596,-2981,-639,-4202,12046,2431,-685,1424,6122 } }, { "Pentax K-30", 0, 0, { 8710,-2632,-1167,-3995,12301,1881,-981,1719,6535 } }, + { "Pentax K-3 Mark III", 0, 0, + { 9251, -3817, -1069, -4627, 12667, 2175, -798, 1660, 5633 } }, // From LibRaw { "Pentax K-3 II", 0, 0, { 8626,-2607,-1155,-3995,12301,1881,-1039,1822,6925 } }, { "Pentax K-3", 0, 0, { 7415,-2052,-721,-5186,12788,2682,-1446,2157,6773 } }, + { "Pentax K-500", 0, 0, + { 8109,-2740,-608,-4593,12175,2731,-1006,1515,6545 } }, // From LibRaw + { "Pentax K-50", 0, 0, + { 8109,-2740,-608,-4593,12175,2731,-1006,1515,6545 } }, // From LibRaw { "Pentax K-5 II", 0, 0, { 8170,-2725,-639,-4440,12017,2744,-771,1465,6599 } }, { "Pentax K-5", 0, 0, @@ -8892,8 +9195,18 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8617,-3228,-1034,-4674,12821,2044,-803,1577,5728 } }, { "Pentax Q-S1", 0, 0, { 12995,-5593,-1107,-1879,10139,2027,-64,1233,4919 } }, + { "Pentax Q7", 0, 0, + { 10901,-3938,-1025,-2743,11210,1738,-823,1805,5344 } }, // From LibRaw + { "Pentax Q10", 0, 0, + { 11562,-4183,-1172,-2357,10919,1641,-582,1726,5112 } }, // From LibRaw + { "Pentax Q", 0, 0, + { 11731,-4169,-1267,-2015,10727,1473,-217,1492,4870 } }, // From LibRaw + { "Pentax MX-1", 0, 0, + { 9296,-3146,-888,-2860,11287,1783,-618,1698,5151 } }, // From LibRaw { "Pentax 645D", 0, 0x3e00, { 10646,-3593,-1158,-3329,11699,1831,-667,2874,6287 } }, + { "Pentax 645Z", 0, 0, + { 9519,-3591,-664,-4074,11725,2671,-624,1501,6653 } }, // From LibRaw { "Panasonic DMC-CM1", 15, 0, { 8770,-3194,-820,-2871,11281,1803,-513,1552,4434 } }, { "Panasonic DC-FZ80", 0, 0, @@ -8932,6 +9245,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, { "Leica DIGILUX 2", 0, 0, { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } }, + { "Panasonic DC-LX100M2", 15, 0, + { 8585,-3127,-833,-4005,12250,1953,-650,1494,4862 } }, // v.2 // From LibRaw { "Panasonic DMC-LX100", 15, 0, { 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 } }, { "Leica D-LUX (Typ 109)", 15, 0, @@ -8962,6 +9277,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } }, { "Panasonic DMC-LX9", 15, 0, { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, + { "Panasonic DC-FZ10002", 15, 0, + { 9803,-4185,-992,-4066,12578,1628,-838,1824,5288 } }, // From LibRaw { "Panasonic DMC-FZ1000", 15, 0, { 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 } }, { "Leica V-LUX (Typ 114)", 15, 0, @@ -8996,12 +9313,26 @@ void CLASS adobe_coeff (const char *make, const char *model) { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, { "Panasonic DMC-G8", 15, 0xfff, /* G8, G80, G81, G85 */ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, + { "Panasonic DC-S1R", 0, 0, + { 11822,-5321,-1249,-5958,15114,766,-614,1264,7043 } }, // From LibRaw + { "Panasonic DC-S1H", 0, 0, + { 9397,-3719,-805,-5425,13326,2309,-972,1715,6034 } }, // From LibRaw + { "Panasonic DC-S1", 0, 0, + { 9744,-3905,-779,-4899,12807,2324,-798,1630,5827 } }, // From LibRaw { "Panasonic DC-S5M2", 0, 0, /* DC-S5M2, DC-S5M2X */ { 10308,-4206,-783,-4088,12102,2229,-125,1051,5912 } }, + { "Panasonic DC-S5", 0, 0, + { 9744,-3905,-779,-4899,12807,2324,-798,1630,5827 } }, // From LibRaw + { "Panasonic DC-G99", 15, 0, + { 9657,-3963,-748,-3361,11378,2258,-568,1415,5158 } }, // From LibRaw + { "Panasonic DC-G100", 15, 0, + { 8370,-2869,-710,-3389,11372,2298,-640,1599,4887 } }, // From LibRaw { "Panasonic DC-G9M2", 0, 0, { 8325,-3456,-623,-4330,12089,2528,-860,2646,5984 } }, { "Panasonic DC-G9", 15, 0xfff, { 7685,-2375,-634,-3687,11700,2249,-748,1546,5111 } }, + { "Panasonic DC-GF10", 15, 0, + { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, // From LibRaw { "Panasonic DMC-GF1", 15, 0xf92, { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } }, { "Panasonic DMC-GF2", 15, 0xfff, @@ -9062,28 +9393,74 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } }, { "Panasonic DMC-ZS70", 15, 0, { 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 } }, + { "Panasonic DMC-ZS80", 15, 0, + { 12194,-5340,-1329,-3035,11394,1858,-50,1418,5219 } }, // From LibRaw { "Leica S (Typ 007)", 0, 0, { 6063,-2234,-231,-5210,13787,1500,-1043,2866,6997 } }, + { "Leica X2", 0, 0, + { 8336,-2853,-699,-4425,11989,2760,-954,1625,6396 } }, // From LibRaw + { "Leica X1", 0, 0, + { 9055,-2611,-666,-4906,12652,2519,-555,1384,7417 } }, // From LibRaw { "Leica X", 0, 0, /* X and X-U, both (Typ 113) */ { 7712,-2059,-653,-3882,11494,2726,-710,1332,5958 } }, { "Leica Q (Typ 116)", 0, 0, { 11865,-4523,-1441,-5423,14458,935,-1587,2687,4830 } }, + { "Leica Q2", 0, 0, + { 12312,-5440,-1307,-6408,15499,824,-1075,1677,7220 } }, // From LibRaw { "Leica M (Typ 262)", 0, 0, { 6653,-1486,-611,-4221,13303,929,-881,2416,7226 } }, + { "Leica M (Typ 2", 0, 0, // same CMs: "M (Typ 240)", "M-D (Typ 262)" + { 7199,-2140,-712,-4005,13327,649,-810,2521,6673 } }, // From LibRaw { "Leica SL (Typ 601)", 0, 0, { 11865,-4523,-1441,-5423,14458,935,-1587,2687,4830 } }, + { "Leica S2", 0, 0, + { 5627,-721,-447,-4423,12456,2192,-1048,2948,7379 } }, // From LibRaw + { "Leica S3", 0, 0, + { 5092,-1630,-470,-6313,14297,2170,-1603,3135,5982 } }, // From LibRaw + { "Leica S", 0, 0, // same CMs: "S-E (Typ 006)", "S (Typ 006)" + { 5749,-1072,-382,-4274,12432,2048,-1166,3104,7105 } }, // From LibRaw { "Leica TL2", 0, 0, { 5836,-1626,-647,-5384,13326,2261,-1207,2129,5861 } }, { "Leica TL", 0, 0, { 5463,-988,-364,-4634,12036,2946,-766,1389,6522 } }, + { "Leica T", 0, 0, // same CMs: TL, "T (Typ 701)" + { 6295,-1679,-475,-5586,13046,2837,-1410,1889,7075 } }, // From LibRaw { "Leica CL", 0, 0, { 7414,-2393,-840,-5127,13180,2138,-1585,2468,5064 } }, + { "Leica M8", 0, 0, + { 7675,-2196,-305,-5860,14119,1856,-2425,4006,6578 } }, // From LibRaw + { "Leica M9", 0, 0, + { 6687,-1751,-291,-3556,11373,2492,-548,2204,7146 } }, // From LibRaw { "Leica M10", 0, 0, { 8249,-2849,-620,-5415,14756,565,-957,3074,6517 } }, { "Phase One H 20", 0, 0, /* DJC */ { 1313,1855,-109,-6715,15908,808,-327,1840,6020 } }, { "Phase One H 25", 0, 0, { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } }, + { "Phase One IQ140", 0, 0, + { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, // From LibRaw + { "Phase One IQ150", 0, 0, + {10325,845,-604,-4113,13385,481,-1791,4163,6924}}, /* temp */ /* emb // From LibRaw */ + { "Phase One IQ160", 0, 0, + { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, // From LibRaw + { "Phase One IQ180", 0, 0, + { 6294,686,-712,-5435,13417,2211,-1006,2435,5042 } }, // From LibRaw + { "Phase One IQ250",0, 0, + {10325,845,-604,-4113,13385,481,-1791,4163,6924}}, /* emb */ // From LibRaw + { "Phase One IQ260", 0, 0, + { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, // From LibRaw + { "Phase One IQ280", 0, 0, + { 6294,686,-712,-5435,13417,2211,-1006,2435,5042 } }, // From LibRaw + { "Phase One IQ3 100MP", 0, 0, + { 10999,354,-742,-4590,13342,937,-1060,2166,8120} }, /* emb */ // From LibRaw + { "Phase One IQ3 50MP", 0, 0, + {10058,1079,-587,-4135,12903,944,-916,2726,7480}}, /* emb */ // From LibRaw + { "Phase One IQ3 60MP", 0, 0, + { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, // From LibRaw + { "Phase One IQ3 80MP", 0, 0, + { 6294,686,-712,-5435,13417,2211,-1006,2435,5042 } }, // From LibRaw + { "Phase One P21", 0, 0, + { 6516,-2050,-507,-8217,16703,1479,-3492,4741,8489 } }, // From LibRaw { "Phase One P 2", 0, 0, { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } }, { "Phase One P 30", 0, 0, @@ -9096,20 +9473,60 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, { "Photron BC2-HD", 0, 0, /* DJC */ { 14603,-4122,-528,-1810,9794,2017,-297,2763,5936 } }, + { "Polaroid x530", 0, 0, + { 13458,-2556,-510,-5444,15081,205,0,0,12120 } }, // From LibRaw { "Red One", 704, 0xffff, /* DJC */ { 21014,-7891,-2613,-3056,12201,856,-2203,5125,8042 } }, + { "Ricoh S10 24-72mm F2.5-4.4 VC", 0, 0, + { 10531,-4043,-878,-2038,10270,2052,-107,895,4577 } }, // From LibRaw + { "Ricoh GR A12 50mm F2.5 MACRO", 0, 0, + { 8849,-2560,-689,-5092,12831,2520,-507,1280,7104 } }, // From LibRaw + { "Ricoh GR DIGITAL 2", 0, 0, + { 8846,-2704,-729,-5265,12708,2871,-1471,1955,6218 } }, // From LibRaw + { "Ricoh GR DIGITAL 3", 0, 0, + { 8170,-2496,-655,-5147,13056,2312,-1367,1859,5265 } }, // From LibRaw + { "Ricoh GR DIGITAL 4", 0, 0, + { 8771,-3151,-837,-3097,11015,2389,-703,1343,4924 } }, // From LibRaw + { "Ricoh GR III", 0, 0, + { 6127,-1777,-585,-5913,13699,2428,-1088,1780,6017 } }, // From LibRaw { "Ricoh GR II", 0, 0, { 4630,-834,-423,-4977,12805,2417,-638,1467,6115 } }, { "Ricoh GR", 0, 0, { 3708,-543,-160,-5381,12254,3556,-1471,1929,8234 } }, + { "Ricoh GX200", 0, 0, + { 8040,-2368,-626,-4659,12543,2363,-1125,1581,5660 } }, // From LibRaw + { "Ricoh GXR Mount A12", 0, 0, + { 7834,-2182,-739,-5453,13409,2241,-952,2005,6620 } }, // From LibRaw + { "Ricoh GXR A12 50mm", 0, 0, + { 8849,-2560,-689,-5092,12831,2520,-507,1280,7104 } }, // From LibRaw + { "Ricoh GXR A12 28mm", 0, 0, + { 10228,-3159,-933,-5304,13158,2371,-943,1873,6685 } }, // From LibRaw + { "Ricoh GXR A16", 0, 0, + { 7837,-2538,-730,-4370,12184,2461,-868,1648,5830 } }, // From LibRaw + { "Ricoh GXR P10", 0, 0, + { 13168,-5128,-1663,-3006,11569,1611,-373,1244,4907 } }, // From LibRaw + { "Ricoh GXR S10", 0, 0, + { 8963,-2926,-754,-4881,12921,2164,-1464,1944,4901 } }, // From LibRaw { "Samsung EX1", 0, 0x3e00, { 8898,-2498,-994,-3144,11328,2066,-760,1381,4576 } }, { "Samsung EX2F", 0, 0x7ff, { 10648,-3897,-1055,-2022,10573,1668,-492,1611,4742 } }, { "Samsung EK-GN120", 0, 0, { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, + { "Samsung Galaxy S6", 0, 0, // same CMs: "Galaxy S6", "Galaxy S6 Edge" + { 13699,-5767,-1384,-4449,13879,499,-467,1691,5892 } }, // From LibRaw + { "Samsung Galaxy S7", 0, 0, // same CMs: "Galaxy S7", "Galaxy S7 Edge" + { 9927,-3704,-1024,-3935,12758,1257,-389,1512,4993 } }, // From LibRaw + { "Samsung Galaxy S8", 0, 0, // same CMs: "Galaxy S8", "Galaxy S8+" + { 9927,-3704,-1024,-3935,12758,1257,-389,1512,4993 } }, // From LibRaw + { "Samsung Galaxy S9", 0, 0, // same CMs: "Galaxy S9", "Galaxy S9+" + { 13292,-6142,-1268,-4095,12890,1283,-557,1930,5163 } }, // From LibRaw + { "Samsung Galaxy Note 9 Rear Camera", 0, 0, + { 13292,-6142,-1268,-4095,12890,1283,-557,1930,5163 } }, // From LibRaw { "Samsung NX mini", 0, 0, { 5222,-1196,-550,-6540,14649,2009,-1666,2819,5657 } }, + { "Samsung NX U", 0, 0, + { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, // From LibRaw { "Samsung NX3300", 0, 0, { 8060,-2933,-761,-4504,12890,1762,-630,1489,5227 } }, { "Samsung NX3000", 0, 0, @@ -9136,6 +9553,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 10686,-4042,-1052,-3595,13238,276,-464,1259,5931 } }, { "Samsung WB2000", 0, 0xfff, { 12093,-3557,-1155,-1000,9534,1733,-22,1787,4576 } }, + { "Samsung WB5000", 0, 0, + { 7675, -2195, -305, -5860, 14118, 1857, -2425, 4007, 6578}}, // From LibRaw { "Samsung GX-1", 0, 0, { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, { "Samsung GX20", 0, 0, /* copied from Pentax K20D */ @@ -9150,6 +9569,20 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } }, { "Sony DSC-V3", 0, 0, { 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } }, + { "Sony DSC-HX9", 200, 0, // same CMs: DSC-HX95, DSC-HX99. RT: BL divided by 4 + { 13076,-5686,-1481,-4027,12851,1251,-167,725,4937 } }, // From LibRaw + { "Sony ZV-1", 200, 0, // same CMs: ZV-1, ZV-1B, ZV-1M2. RT: BL divided by 4 + { 8280,-2987,-703,-3531,11645,2133,-550,1542,5312 } }, // From LibRaw + { "Sony ZV-E10", 0, 0, + { 6355,-2067,-490,-3653,11542,2400,-406,1258,5506 } }, // From LibRaw + { "Sony ZV-E1", 0, 0, + { 6912,-2127,-469,-4470,12175,2587,-398,1478,6492 } }, // From LibRaw + { "Sony DSC-RX100M7", 0, 0, + {10315, -4390, -937, -4859, 12734, 2365, -734, 1537, 5997 } }, // From LibRaw + { "Sony DSC-RX100M6", 0, 0, + { 7325,-2321,-596,-3494,11674,2055,-668,1562,5031 } }, // From LibRaw + { "Sony DSC-RX100M5A", 0, 0, + { 11176,-4700,-965,-4004,12184,2032,-763,1726,5876 } }, // From LibRaw { "Sony DSC-RX100M", 0, 0, /* M2, M3, M4, and M5 */ { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } }, { "Sony DSC-RX100", 0, 0, @@ -9160,6 +9593,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6679,-1825,-745,-5047,13256,1953,-1580,2422,5183 } }, { "Sony DSC-RX1RM2", 0, 0, { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } }, + { "Sony DSC-RX1R", 0, 0, + { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, // From LibRaw { "Sony DSC-RX1", 0, 0, { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, { "Sony DSC-RX0", 200, 0, @@ -9200,28 +9635,56 @@ void CLASS adobe_coeff (const char *make, const char *model) { 5991,-1732,-443,-4100,11989,2381,-704,1467,5992 } }, { "Sony ILCA-99M2", 0, 0, { 6660,-1918,-471,-4613,12398,2485,-649,1433,6447 } }, + { "Sony ILCE-1", 0, 0, + { 8161, -2947, -739, -4811, 12668, 2389, -437, 1229, 6524}}, // From LibRaw + { "Sony ILCE-6100", 0, 0, + { 7657,-2847,-607,-4083,11966,2389,-684,1418,5844 } }, // From LibRaw + { "Sony ILCE-6300", 0, 0, + { 5973,-1695,-419,-3826,11797,2293,-639,1398,5789 } }, + { "Sony ILCE-6400", 0, 0, + { 7657,-2847,-607,-4083,11966,2389,-684,1418,5844 } }, // From LibRaw + { "Sony ILCE-6500", 0, 0, + { 5973,-1695,-419,-3826,11797,2293,-639,1398,5789 } }, + { "Sony ILCE-6600", 0, 0, + { 7657,-2847,-607,-4083,11966,2389,-684,1418,5844 } }, // From LibRaw { "Sony ILCE-6700", 0, 0, { 6972,-2408,-600,-4330,12101,2515,-388,1277,5847 } }, - { "Sony ILCE-6", 0, 0, /* 6300, 6500 */ - { 5973,-1695,-419,-3826,11797,2293,-639,1398,5789 } }, { "Sony ILCE-7M2", 0, 0, { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } }, { "Sony ILCE-7M3", 0, 0, { 7374,-2389,-551,-5435,13162,2519,-1006,1795,6552 } }, + { "Sony ILCE-7M4", 0, 0, + { 7460,-2365,-588,-5687,13442,2474,-624,1156,6584 } }, // From LibRaw + { "Sony ILCE-7SM3", 0, 0, + { 6912,-2127,-469,-4470,12175,2587,-398,1478,6492 } }, // From LibRaw { "Sony ILCE-7S", 0, 0, /* also ILCE-7SM2 */ { 5838,-1430,-246,-3497,11477,2297,-748,1885,5778 } }, + { "Sony ILCE-7RM5", 0, 0, + { 8200, -2976, -719, -4296, 12053, 2532, -429, 1282, 5774 } }, // From LibRaw + { "Sony ILCE-7RM4", 0, 0, // same CMs: ILCE-7RM4, ILCE-7RM4A + { 7662, -2686,-660,-5240, 12965,2530, -796, 1508, 6167 } }, // From LibRaw { "Sony ILCE-7RM3", 0, 0, { 6640,-1847,-503,-5238,13010,2474,-993,1673,6527 } }, { "Sony ILCE-7RM2", 0, 0, { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } }, { "Sony ILCE-7R", 0, 0, { 4913,-541,-202,-6130,13513,2906,-1564,2151,7183 } }, + { "Sony ILCE-7CR", 0, 0, + { 8200,-2976,-719,-4296,12053,2532,-429,1282,5774 } }, // temp // From LibRaw + { "Sony ILCE-7CM2", 0, 0, + { 7460,-2365,-588,-5687,13442,2474,-624,1156,6584 } }, // temp // From LibRaw + { "Sony ILCE-7C", 0, 0, + { 7374,-2389,-551,-5435,13162,2519,-1006,1795,6552 } }, // From LibRaw { "Sony ILCE-7", 0, 0, { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } }, { "Sony ILCE-9", 0, 0, { 6389,-1703,-378,-4562,12265,2587,-670,1489,6550 } }, { "Sony ILCE", 0, 0, /* 3000, 5000, 5100, 6000, and QX1 */ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, + { "Sony ILME-FX30", 0, 0, + { 6972, -2408, -600, -4330, 12101, 2515, -388, 1277, 5847 } }, // From LibRaw + { "Sony ILME-FX3", 0, 0, + { 6912, -2127, -469, -4470, 12175, 2587, -398, 1478, 6492 } }, // From LibRaw { "Sony NEX-5N", 0, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony NEX-5R", 0, 0, @@ -9242,6 +9705,10 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, { "Sony NEX-7", 0, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, + { "Sony NEX-VG30", 0, 0, + { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, // From LibRaw + { "Sony NEX-VG900", 0, 0, + { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, // From LibRaw { "Sony NEX", 0, 0, /* NEX-C3, NEX-F3 */ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony SLT-A33", 0, 0, From a1c6ce5dd2b34df5a55e0073aef5b07deaab4280 Mon Sep 17 00:00:00 2001 From: Desmis Date: Sun, 16 Jun 2024 07:35:50 +0200 Subject: [PATCH 10/39] Selective editing - adds the feather slider for each Graduated Filter (#7079) * Feather GF color and vibrance * Feather exposure * Graduated filer feather wavelet * Graduated filter feather log * Graduated filter Cam16 feather * Change history msg * GF shadows highlight feather * GF mask common feather * Move feather settings in settings mask * Change history msg * Change label feather * Change 2 labels --- rtdata/languages/default | 18 ++++++++--- rtengine/iplocallab.cc | 43 ++++++++++++++++++++++++-- rtengine/procparams.cc | 34 ++++++++++++++++++++- rtengine/procparams.h | 8 +++++ rtgui/controlspotpanel.cc | 5 ++-- rtgui/locallabtools.cc | 63 +++++++++++++++++++++++++++++++++++++-- rtgui/locallabtools.h | 16 ++++++++++ rtgui/locallabtools2.cc | 60 +++++++++++++++++++++++++++++++++++++ rtgui/paramsedited.cc | 58 ++++++++++++++++++++++++++++++++++- rtgui/paramsedited.h | 8 +++++ 10 files changed, 300 insertions(+), 13 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 75d060dec..f8f7cf114 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1068,7 +1068,7 @@ HISTORY_MSG_829;Local - SH gradient angle HISTORY_MSG_830;Local - Color gradient strength L HISTORY_MSG_831;Local - Color gradient angle HISTORY_MSG_832;Local - Color gradient strength C -HISTORY_MSG_833;Local - TG - Feather gradient +HISTORY_MSG_833;Local - Mask gradient feather HISTORY_MSG_834;Local - Color gradient strength H HISTORY_MSG_835;Local - Vib gradient strength L HISTORY_MSG_836;Local - Vib gradient angle @@ -1502,6 +1502,15 @@ HISTORY_MSG_LOCAL_CIEMASK_STRU;Local Cie mask structure HISTORY_MSG_LOCAL_CIEMASK_STRU_TOOL;Local Cie mask structure as tool HISTORY_MSG_LOCAL_CIEMASK_WLC;Local CIECAM mask wavelet Lc HISTORY_MSG_LOCAL_CIEMASK_WLEV;Local CIECAM mask wavelet levels +HISTORY_MSG_LOCAL_FEATHERCOL;Local Color gradient feather +HISTORY_MSG_LOCAL_FEATHEREXE;Local Exp gradient feather +HISTORY_MSG_LOCAL_FEATHERVIB;Local Vib gradient feather +HISTORY_MSG_LOCAL_FEATHERWAV;Local Wav gradient feather +HISTORY_MSG_LOCAL_FEATHERLOG;Local Log gradient feather +HISTORY_MSG_LOCAL_FEATHERCIE;Local CIECAM gradient feather +HISTORY_MSG_LOCAL_FEATHERSH;Local SH gradient feather +HISTORY_MSG_LOCAL_FEATHERMAS;Local Mask common gradient feather + HISTORY_MSG_LOCAL_LOG_BLACKS;Local Log - Blacks distribution HISTORY_MSG_LOCAL_LOG_COMPR;Local Log - Compress brightness HISTORY_MSG_LOCAL_LOG_SAT;Local Log - Saturation control @@ -2929,7 +2938,7 @@ TP_LOCALLAB_CHRRT;Chroma TP_LOCALLAB_CIE;Color appearance (Cam16 & JzCzHz) TP_LOCALLAB_CIE_SMOOTH_NONE;None TP_LOCALLAB_CIE_SMOOTH_EV;Ev based -TP_LOCALLAB_CIE_SMOOTHFRAME;Highlight attenuation & Levels +TP_LOCALLAB_CIE_SMOOTHFRAME;Highlight Attenuation & Levels TP_LOCALLAB_CIE_SMOOTH_GAMMA;Slope based TP_LOCALLAB_CIE_SMOOTH_GAMMA ROLLOFF;Gamma based TP_LOCALLAB_CIE_SMOOTH_LEVELS;Levels @@ -3089,7 +3098,8 @@ TP_LOCALLAB_FATLEVEL;Sigma TP_LOCALLAB_FATSAT;Saturation control TP_LOCALLAB_FATSHFRA;Dynamic Range Compression Mask Æ’ TP_LOCALLAB_FEATH_TOOLTIP;Gradient width as a percentage of the Spot diagonal\nUsed by all graduated filters in all tools.\nNo action if a graduated filter hasn't been activated. -TP_LOCALLAB_FEATVALUE;Feather gradient (Grad. Filters) +TP_LOCALLAB_FEATVALUE;Feather gradient +TP_LOCALLAB_FEATVALUE_MASK;Feather gradient (Grad. Filters Mask) TP_LOCALLAB_FFTCOL_MASK;FFTW Æ’ TP_LOCALLAB_FFTMASK_TOOLTIP;Use a Fourier transform for better quality (increased processing time and memory requirements). TP_LOCALLAB_FFTW;Æ’ - Use Fast Fourier Transform @@ -3566,7 +3576,7 @@ TP_LOCALLAB_SLOPESMOOTHR;Red balance (Slope) TP_LOCALLAB_SLOPESMOOTHG;Green balance (Slope) TP_LOCALLAB_SLOPESMOOTHB;Blue balance (Slope) TP_LOCALLAB_SLOSH;Slope -TP_LOCALLAB_SMOOTHCIE;Highlight attenuation +TP_LOCALLAB_SMOOTHCIE;Highlight Attenuation TP_LOCALLAB_SMOOTHCIE_LUM;Luminosity mode TP_LOCALLAB_SMOOTHCIE_SCA;Scale Yb Scene TP_LOCALLAB_SMOOTHCIE_YB;Scale Yb Viewing diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index 1d03f7adc..9cf83d9cb 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -501,19 +501,25 @@ struct local_params { float angmaexp; float str_mas; float ang_mas; + float feather_mas; float strexp; float angexp; + float featherexp; float strSH; float angSH; + float featherSH; float strcol; float strcolab; float strcolh; float angcol; + float feathcol; float strvib; float strvibab; float strvibh; float angvib; + float feathervib; float angwav; + float featherwav; float strwav; float blendmaL; float radmaL; @@ -529,6 +535,7 @@ struct local_params { float basew; float anglog; + float featherlog; float strlog; float softradiusexp; float softradiuscol; @@ -804,6 +811,7 @@ struct local_params { float detailcie; float strgradcie; float anggradcie; + float feathercie; bool satcie; bool satlog; int sensilog; @@ -1367,22 +1375,29 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall float angmaskexpo = ((float) locallab.spots.at(sp).angmaskexp); float strmask = ((float) locallab.spots.at(sp).str_mask); float angmask = ((float) locallab.spots.at(sp).ang_mask); + float feathermask = ((float) locallab.spots.at(sp).feather_mask); float strexpo = ((float) locallab.spots.at(sp).strexp); float angexpo = ((float) locallab.spots.at(sp).angexp); + float featherexpo = ((float) locallab.spots.at(sp).featherexp); float strSH = ((float) locallab.spots.at(sp).strSH); float angSH = ((float) locallab.spots.at(sp).angSH); + float featherSH = ((float) locallab.spots.at(sp).featherSH); float strcol = ((float) locallab.spots.at(sp).strcol); float strcolab = ((float) locallab.spots.at(sp).strcolab); float strcolh = ((float) locallab.spots.at(sp).strcolh); float angcol = ((float) locallab.spots.at(sp).angcol); + float feathcol = ((float) locallab.spots.at(sp).feathercol); float strvib = ((float) locallab.spots.at(sp).strvib); float strvibab = ((float) locallab.spots.at(sp).strvibab); float strvibh = ((float) locallab.spots.at(sp).strvibh); float angvib = ((float) locallab.spots.at(sp).angvib); + float feathervib = ((float) locallab.spots.at(sp).feathervib); float strwav = ((float) locallab.spots.at(sp).strwav); float angwav = ((float) locallab.spots.at(sp).angwav); + float featherwav = ((float) locallab.spots.at(sp).featherwav); float strlog = ((float) locallab.spots.at(sp).strlog); float anglog = ((float) locallab.spots.at(sp).anglog); + float featherlog = ((float) locallab.spots.at(sp).featherlog); float softradiusexpo = ((float) locallab.spots.at(sp).softradiusexp); float softradiuscolor = ((float) locallab.spots.at(sp).softradiuscol); float softradiusreti = ((float) locallab.spots.at(sp).softradiusret); @@ -1515,6 +1530,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall float contciemask = (float) locallab.spots.at(sp).contcie; float strgradcie = ((float) locallab.spots.at(sp).strgradcie); float anggradcie = ((float) locallab.spots.at(sp).anggradcie); + float feathercie = ((float) locallab.spots.at(sp).feathercie); lp.comprlo = locallab.spots.at(sp).comprlog; lp.comprlocie = locallab.spots.at(sp).comprcie; @@ -1550,23 +1566,30 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.angmaexp = angmaskexpo; lp.str_mas = strmask; lp.ang_mas = angmask; + lp.feather_mas = feathermask; lp.strexp = strexpo; lp.angexp = angexpo; + lp.featherexp = featherexpo; lp.strSH = strSH; lp.angSH = angSH; + lp.featherSH = featherSH; lp.strcol = strcol; lp.strcolab = strcolab; lp.strcolh = strcolh; lp.angcol = angcol; + lp.feathcol = feathcol; lp.strvib = strvib; lp.strvibab = strvibab; lp.strvibh = strvibh; lp.angvib = angvib; + lp.feathervib = feathervib; lp.strwav = strwav; lp.angwav = angwav; + lp.featherwav = featherwav; lp.strlog = strlog; lp.anglog = anglog; + lp.featherlog = featherlog; lp.softradiusexp = softradiusexpo; lp.softradiuscol = softradiuscolor; lp.softradiusret = softradiusreti; @@ -1779,6 +1802,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.contciemask = 0.01f * contciemask; lp.strgradcie = strgradcie; lp.anggradcie = anggradcie; + lp.feathercie = feathercie; lp.blendmacie = blendmaskcie; lp.radmacie = radmaskcie; @@ -5621,19 +5645,24 @@ void calclocalGradientParams(const struct local_params& lp, struct grad_params& int h = bfh; float stops = 0.f; float angs = 0.f; + double varfeath = 0.25; //0.01f * lp.feath; if (indic == 0) { stops = -lp.strmaexp; angs = lp.angmaexp; + varfeath = 0.01f * lp.feath;//for all masks when present } else if (indic == 1) { stops = lp.strexp; angs = lp.angexp; + varfeath = 0.01f * lp.featherexp; } else if (indic == 2) { stops = lp.strSH; angs = lp.angSH; + varfeath = 0.01f * lp.featherSH; } else if (indic == 3) { stops = lp.strcol; angs = lp.angcol; + varfeath = 0.01f * lp.feathcol; } else if (indic == 4) { float redu = 1.f; @@ -5645,41 +5674,49 @@ void calclocalGradientParams(const struct local_params& lp, struct grad_params& stops = redu * lp.strcolab; angs = lp.angcol; + varfeath = 0.01f * lp.feathcol; } else if (indic == 5) { stops = lp.strcolab; angs = lp.angcol; + varfeath = 0.01f * lp.feathcol; } else if (indic == 6) { stops = lp.strcolh; angs = lp.angcol; + varfeath = 0.01f * lp.feathcol; } else if (indic == 7) { stops = lp.strvib; angs = lp.angvib; + varfeath = 0.01f * lp.feathervib; } else if (indic == 8) { float redu = 1.f; - if (lp.strvibab > 0.f) { redu = 0.7f; } else { redu = 0.5f; } - stops = redu * lp.strvibab; angs = lp.angvib; + varfeath = 0.01f * lp.feathervib; } else if (indic == 9) { stops = lp.strvibh; angs = lp.angvib; + varfeath = 0.01f * lp.feathervib; } else if (indic == 10) { stops = std::fabs(lp.strwav); angs = lp.angwav; + varfeath = 0.01f * lp.featherwav; } else if (indic == 11) { stops = lp.strlog; angs = lp.anglog; + varfeath = 0.01f * lp.featherlog; } else if (indic == 12) { stops = -lp.str_mas; angs = lp.ang_mas; + varfeath = 0.01f * lp.feather_mas; } else if (indic == 15) { stops = lp.strgradcie; angs = lp.anggradcie; + varfeath = 0.01f * lp.feathercie; } @@ -5687,7 +5724,7 @@ void calclocalGradientParams(const struct local_params& lp, struct grad_params& double gradient_center_x = LIM01((lp.xc - xstart) / bfw); double gradient_center_y = LIM01((lp.yc - ystart) / bfh); double gradient_angle = static_cast(angs) / 180.0 * rtengine::RT_PI; - double varfeath = 0.01f * lp.feath; + // double varfeath = 0.01f * lp.feath; //printf("xstart=%f ysta=%f lpxc=%f lpyc=%f stop=%f bb=%f cc=%f ang=%f ff=%d gg=%d\n", xstart, ystart, lp.xc, lp.yc, gradient_stops, gradient_center_x, gradient_center_y, gradient_angle, w, h); diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 9d759a723..1ba92c366 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -3044,6 +3044,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : strcolab(0.), strcolh(0.), angcol(0.), + feathercol(25.), blurcolde(5), blurcol(0.2), contcol(0.), @@ -3286,6 +3287,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : gamex(1.), strexp(0.), angexp(0.), + featherexp(25.), excurve{ static_cast(DCT_NURBS), 0.0, @@ -3436,6 +3438,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : blurSHde(5), strSH(0.), angSH(0.), + featherSH(25.), inverssh(false), chromaskSH(0.0), gammaskSH(1.0), @@ -3531,6 +3534,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : strvibab(0.0), strvibh(0.0), angvib(0.0), + feathervib(25.0), Lmaskvibcurve{ static_cast(DCT_NURBS), 0.0, @@ -3975,6 +3979,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : sigmalc2(1.0), strwav(0.0), angwav(0.0), + featherwav(25.0), strengthw(0.0), sigmaed(1.0), radiusw(15.0), @@ -4259,6 +4264,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : baselog(2.), strlog(0.0), anglog(0.0), + featherlog(25.0), CCmaskcurveL{ static_cast(FCT_MinMaxCPoints), 0.0, @@ -4386,6 +4392,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : shadmask(0.0), str_mask(0), ang_mask(0), + feather_mask(25), HHhmask_curve{ static_cast(FCT_MinMaxCPoints), 0.0, @@ -4669,6 +4676,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : surroundcie("Average"), strgradcie(0.), anggradcie(0.), + feathercie(25.), enacieMask(false), enacieMaskall(false), CCmaskciecurve{ @@ -4912,6 +4920,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && strcolab == other.strcolab && strcolh == other.strcolh && angcol == other.angcol + && feathercol == other.feathercol && blurcolde == other.blurcolde && blurcol == other.blurcol && contcol == other.contcol @@ -4974,6 +4983,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && gamex == other.gamex && strexp == other.strexp && angexp == other.angexp + && featherexp == other.featherexp && excurve == other.excurve && norm == other.norm && inversex == other.inversex @@ -5037,6 +5047,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && blurSHde == other.blurSHde && strSH == other.strSH && angSH == other.angSH + && featherSH == other.featherSH && inverssh == other.inverssh && chromaskSH == other.chromaskSH && gammaskSH == other.gammaskSH @@ -5082,6 +5093,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && strvibab == other.strvibab && strvibh == other.strvibh && angvib == other.angvib + && feathervib == other.feathervib && Lmaskvibcurve == other.Lmaskvibcurve && recothresv == other.recothresv && lowthresv == other.lowthresv @@ -5298,6 +5310,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && sigmalc2 == other.sigmalc2 && strwav == other.strwav && angwav == other.angwav + && featherwav == other.featherwav && strengthw == other.strengthw && sigmaed == other.sigmaed && radiusw == other.radiusw @@ -5412,6 +5425,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && surround == other.surround && strlog == other.strlog && anglog == other.anglog + && featherlog == other.featherlog && CCmaskcurveL == other.CCmaskcurveL && LLmaskcurveL == other.LLmaskcurveL && HHmaskcurveL == other.HHmaskcurveL @@ -5450,6 +5464,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && shadmask == other.shadmask && str_mask == other.str_mask && ang_mask == other.ang_mask + && feather_mask == other.feather_mask && HHhmask_curve == other.HHhmask_curve && Lmask_curve == other.Lmask_curve && LLmask_curvewav == other.LLmask_curvewav @@ -5584,6 +5599,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && detailcie == other.detailcie && strgradcie == other.strgradcie && anggradcie == other.anggradcie + && feathercie == other.feathercie && surroundcie == other.surroundcie && enacieMask == other.enacieMask && enacieMaskall == other.enacieMaskall @@ -6856,6 +6872,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || spot_edited->strcolab, "Locallab", "Strcolab_" + index_str, spot.strcolab, keyFile); saveToKeyfile(!pedited || spot_edited->strcolh, "Locallab", "Strcolh_" + index_str, spot.strcolh, keyFile); saveToKeyfile(!pedited || spot_edited->angcol, "Locallab", "Angcol_" + index_str, spot.angcol, keyFile); + saveToKeyfile(!pedited || spot_edited->feathercol, "Locallab", "Feathercol_" + index_str, spot.feathercol, keyFile); saveToKeyfile(!pedited || spot_edited->blurcolde, "Locallab", "Blurcolde_" + index_str, spot.blurcolde, keyFile); saveToKeyfile(!pedited || spot_edited->blurcol, "Locallab", "Blurcol_" + index_str, spot.blurcol, keyFile); saveToKeyfile(!pedited || spot_edited->contcol, "Locallab", "Contcol_" + index_str, spot.contcol, keyFile); @@ -6919,6 +6936,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || spot_edited->gamex, "Locallab", "Gamex_" + index_str, spot.gamex, keyFile); saveToKeyfile(!pedited || spot_edited->strexp, "Locallab", "Strexp_" + index_str, spot.strexp, keyFile); saveToKeyfile(!pedited || spot_edited->angexp, "Locallab", "Angexp_" + index_str, spot.angexp, keyFile); + saveToKeyfile(!pedited || spot_edited->featherexp, "Locallab", "Featherexp_" + index_str, spot.featherexp, keyFile); saveToKeyfile(!pedited || spot_edited->excurve, "Locallab", "ExCurve_" + index_str, spot.excurve, keyFile); saveToKeyfile(!pedited || spot_edited->norm, "Locallab", "Norm_" + index_str, spot.norm, keyFile); saveToKeyfile(!pedited || spot_edited->inversex, "Locallab", "Inversex_" + index_str, spot.inversex, keyFile); @@ -6979,6 +6997,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || spot_edited->blurSHde, "Locallab", "BlurSHde_" + index_str, spot.blurSHde, keyFile); saveToKeyfile(!pedited || spot_edited->strSH, "Locallab", "StrSH_" + index_str, spot.strSH, keyFile); saveToKeyfile(!pedited || spot_edited->angSH, "Locallab", "AngSH_" + index_str, spot.angSH, keyFile); + saveToKeyfile(!pedited || spot_edited->featherSH, "Locallab", "FeatherSH_" + index_str, spot.featherSH, keyFile); saveToKeyfile(!pedited || spot_edited->inverssh, "Locallab", "Inverssh_" + index_str, spot.inverssh, keyFile); saveToKeyfile(!pedited || spot_edited->chromaskSH, "Locallab", "ChromaskSH_" + index_str, spot.chromaskSH, keyFile); saveToKeyfile(!pedited || spot_edited->gammaskSH, "Locallab", "GammaskSH_" + index_str, spot.gammaskSH, keyFile); @@ -7024,6 +7043,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || spot_edited->strvibab, "Locallab", "Strvibab_" + index_str, spot.strvibab, keyFile); saveToKeyfile(!pedited || spot_edited->strvibh, "Locallab", "Strvibh_" + index_str, spot.strvibh, keyFile); saveToKeyfile(!pedited || spot_edited->angvib, "Locallab", "Angvib_" + index_str, spot.angvib, keyFile); + saveToKeyfile(!pedited || spot_edited->angvib, "Locallab", "Feathervib_" + index_str, spot.feathervib, keyFile); saveToKeyfile(!pedited || spot_edited->Lmaskvibcurve, "Locallab", "LmaskvibCurve_" + index_str, spot.Lmaskvibcurve, keyFile); saveToKeyfile(!pedited || spot_edited->recothresv, "Locallab", "Recothresv_" + index_str, spot.recothresv, keyFile); saveToKeyfile(!pedited || spot_edited->lowthresv, "Locallab", "Lowthresv_" + index_str, spot.lowthresv, keyFile); @@ -7246,6 +7266,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || spot_edited->sigmalc2, "Locallab", "Sigmalc2_" + index_str, spot.sigmalc2, keyFile); saveToKeyfile(!pedited || spot_edited->strwav, "Locallab", "Strwav_" + index_str, spot.strwav, keyFile); saveToKeyfile(!pedited || spot_edited->angwav, "Locallab", "Angwav_" + index_str, spot.angwav, keyFile); + saveToKeyfile(!pedited || spot_edited->featherwav, "Locallab", "Featherwav_" + index_str, spot.featherwav, keyFile); saveToKeyfile(!pedited || spot_edited->strengthw, "Locallab", "Strengthw_" + index_str, spot.strengthw, keyFile); saveToKeyfile(!pedited || spot_edited->sigmaed, "Locallab", "Sigmaed_" + index_str, spot.sigmaed, keyFile); saveToKeyfile(!pedited || spot_edited->radiusw, "Locallab", "Radiusw_" + index_str, spot.radiusw, keyFile); @@ -7358,6 +7379,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || spot_edited->surround, "Locallab", "Surround_" + index_str, spot.surround, keyFile); saveToKeyfile(!pedited || spot_edited->strlog, "Locallab", "Strlog_" + index_str, spot.strlog, keyFile); saveToKeyfile(!pedited || spot_edited->anglog, "Locallab", "Anglog_" + index_str, spot.anglog, keyFile); + saveToKeyfile(!pedited || spot_edited->featherlog, "Locallab", "Featherlog_" + index_str, spot.featherlog, keyFile); saveToKeyfile(!pedited || spot_edited->CCmaskcurveL, "Locallab", "CCmaskCurveL_" + index_str, spot.CCmaskcurveL, keyFile); saveToKeyfile(!pedited || spot_edited->LLmaskcurveL, "Locallab", "LLmaskCurveL_" + index_str, spot.LLmaskcurveL, keyFile); saveToKeyfile(!pedited || spot_edited->HHmaskcurveL, "Locallab", "HHmaskCurveL_" + index_str, spot.HHmaskcurveL, keyFile); @@ -7397,6 +7419,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || spot_edited->shadmask, "Locallab", "Shadmask_" + index_str, spot.shadmask, keyFile); saveToKeyfile(!pedited || spot_edited->str_mask, "Locallab", "Str_mask_" + index_str, spot.str_mask, keyFile); saveToKeyfile(!pedited || spot_edited->ang_mask, "Locallab", "Ang_mask_" + index_str, spot.ang_mask, keyFile); + saveToKeyfile(!pedited || spot_edited->feather_mask, "Locallab", "Feather_mask_" + index_str, spot.feather_mask, keyFile); saveToKeyfile(!pedited || spot_edited->HHhmask_curve, "Locallab", "HHhmask_Curve_" + index_str, spot.HHhmask_curve, keyFile); saveToKeyfile(!pedited || spot_edited->Lmask_curve, "Locallab", "Lmask_Curve_" + index_str, spot.Lmask_curve, keyFile); saveToKeyfile(!pedited || spot_edited->LLmask_curvewav, "Locallab", "LLmask_Curvewav_" + index_str, spot.LLmask_curvewav, keyFile); @@ -7534,6 +7557,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || spot_edited->detailcie, "Locallab", "Detailcie_" + index_str, spot.detailcie, keyFile); saveToKeyfile(!pedited || spot_edited->strgradcie, "Locallab", "Strgradcie_" + index_str, spot.strgradcie, keyFile); saveToKeyfile(!pedited || spot_edited->anggradcie, "Locallab", "Anggradcie_" + index_str, spot.anggradcie, keyFile); + saveToKeyfile(!pedited || spot_edited->feathercie, "Locallab", "Feathercie_" + index_str, spot.feathercie, keyFile); saveToKeyfile(!pedited || spot_edited->surroundcie, "Locallab", "Surroundcie_" + index_str, spot.surroundcie, keyFile); saveToKeyfile(!pedited || spot_edited->enacieMask, "Locallab", "EnacieMask_" + index_str, spot.enacieMask, keyFile); saveToKeyfile(!pedited || spot_edited->enacieMaskall, "Locallab", "EnacieMaskall_" + index_str, spot.enacieMaskall, keyFile); @@ -9126,6 +9150,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Strcolab_" + index_str, spot.strcolab, spotEdited.strcolab); assignFromKeyfile(keyFile, "Locallab", "Strcolh_" + index_str, spot.strcolh, spotEdited.strcolh); assignFromKeyfile(keyFile, "Locallab", "Angcol_" + index_str, spot.angcol, spotEdited.angcol); + assignFromKeyfile(keyFile, "Locallab", "Fetahercol_" + index_str, spot.feathercol, spotEdited.feathercol); assignFromKeyfile(keyFile, "Locallab", "Blurcolde_" + index_str, spot.blurcolde, spotEdited.blurcolde); assignFromKeyfile(keyFile, "Locallab", "Blurcol_" + index_str, spot.blurcol, spotEdited.blurcol); assignFromKeyfile(keyFile, "Locallab", "Contcol_" + index_str, spot.contcol, spotEdited.contcol); @@ -9202,6 +9227,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Gamex_" + index_str, spot.gamex, spotEdited.gamex); assignFromKeyfile(keyFile, "Locallab", "Strexp_" + index_str, spot.strexp, spotEdited.strexp); assignFromKeyfile(keyFile, "Locallab", "Angexp_" + index_str, spot.angexp, spotEdited.angexp); + assignFromKeyfile(keyFile, "Locallab", "Featherexp_" + index_str, spot.featherexp, spotEdited.featherexp); assignFromKeyfile(keyFile, "Locallab", "ExCurve_" + index_str, spot.excurve, spotEdited.excurve); assignFromKeyfile(keyFile, "Locallab", "Norm_" + index_str, spot.norm, spotEdited.norm); assignFromKeyfile(keyFile, "Locallab", "Inversex_" + index_str, spot.inversex, spotEdited.inversex); @@ -9266,6 +9292,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "BlurSHde_" + index_str, spot.blurSHde, spotEdited.blurSHde); assignFromKeyfile(keyFile, "Locallab", "StrSH_" + index_str, spot.strSH, spotEdited.strSH); assignFromKeyfile(keyFile, "Locallab", "AngSH_" + index_str, spot.angSH, spotEdited.angSH); + assignFromKeyfile(keyFile, "Locallab", "FeatherSH_" + index_str, spot.featherSH, spotEdited.featherSH); assignFromKeyfile(keyFile, "Locallab", "Inverssh_" + index_str, spot.inverssh, spotEdited.inverssh); assignFromKeyfile(keyFile, "Locallab", "ChromaskSH_" + index_str, spot.chromaskSH, spotEdited.chromaskSH); assignFromKeyfile(keyFile, "Locallab", "GammaskSH_" + index_str, spot.gammaskSH, spotEdited.gammaskSH); @@ -9325,6 +9352,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Strvibab_" + index_str, spot.strvibab, spotEdited.strvibab); assignFromKeyfile(keyFile, "Locallab", "Strvibh_" + index_str, spot.strvibh, spotEdited.strvibh); assignFromKeyfile(keyFile, "Locallab", "Angvib_" + index_str, spot.angvib, spotEdited.angvib); + assignFromKeyfile(keyFile, "Locallab", "Feathervib_" + index_str, spot.feathervib, spotEdited.feathervib); assignFromKeyfile(keyFile, "Locallab", "LmaskvibCurve_" + index_str, spot.Lmaskvibcurve, spotEdited.Lmaskvibcurve); assignFromKeyfile(keyFile, "Locallab", "Recothresv_" + index_str, spot.recothresv, spotEdited.recothresv); assignFromKeyfile(keyFile, "Locallab", "Lowthresv_" + index_str, spot.lowthresv, spotEdited.lowthresv); @@ -9574,6 +9602,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Sigmalc2_" + index_str, spot.sigmalc2, spotEdited.sigmalc2); assignFromKeyfile(keyFile, "Locallab", "Strwav_" + index_str, spot.strwav, spotEdited.strwav); assignFromKeyfile(keyFile, "Locallab", "Angwav_" + index_str, spot.angwav, spotEdited.angwav); + assignFromKeyfile(keyFile, "Locallab", "Featherwav_" + index_str, spot.featherwav, spotEdited.featherwav); assignFromKeyfile(keyFile, "Locallab", "Strengthw_" + index_str, spot.strengthw, spotEdited.strengthw); assignFromKeyfile(keyFile, "Locallab", "Sigmaed_" + index_str, spot.sigmaed, spotEdited.sigmaed); assignFromKeyfile(keyFile, "Locallab", "Radiusw_" + index_str, spot.radiusw, spotEdited.radiusw); @@ -9703,6 +9732,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Surround_" + index_str, spot.surround, spotEdited.surround); assignFromKeyfile(keyFile, "Locallab", "Strlog_" + index_str, spot.strlog, spotEdited.strlog); assignFromKeyfile(keyFile, "Locallab", "Anglog_" + index_str, spot.anglog, spotEdited.anglog); + assignFromKeyfile(keyFile, "Locallab", "Featherlog_" + index_str, spot.featherlog, spotEdited.featherlog); assignFromKeyfile(keyFile, "Locallab", "CCmaskCurveL_" + index_str, spot.CCmaskcurveL, spotEdited.CCmaskcurveL); assignFromKeyfile(keyFile, "Locallab", "LLmaskCurveL_" + index_str, spot.LLmaskcurveL, spotEdited.LLmaskcurveL); assignFromKeyfile(keyFile, "Locallab", "HHmaskCurveL_" + index_str, spot.HHmaskcurveL, spotEdited.HHmaskcurveL); @@ -9740,6 +9770,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Shadmask_" + index_str, spot.shadmask, spotEdited.shadmask); assignFromKeyfile(keyFile, "Locallab", "Str_mask_" + index_str, spot.str_mask, spotEdited.str_mask); assignFromKeyfile(keyFile, "Locallab", "Ang_mask_" + index_str, spot.ang_mask, spotEdited.ang_mask); + assignFromKeyfile(keyFile, "Locallab", "Feather_mask_" + index_str, spot.feather_mask, spotEdited.feather_mask); assignFromKeyfile(keyFile, "Locallab", "HHhmask_Curve_" + index_str, spot.HHhmask_curve, spotEdited.HHhmask_curve); assignFromKeyfile(keyFile, "Locallab", "Lmask_Curve_" + index_str, spot.Lmask_curve, spotEdited.Lmask_curve); assignFromKeyfile(keyFile, "Locallab", "LLmask_Curvewav_" + index_str, spot.LLmask_curvewav, spotEdited.LLmask_curvewav); @@ -9902,7 +9933,8 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Surroundcie_" + index_str, spot.surroundcie, spotEdited.surroundcie); assignFromKeyfile(keyFile, "Locallab", "Strgradcie_" + index_str, spot.strgradcie, spotEdited.strgradcie); assignFromKeyfile(keyFile, "Locallab", "Anggradcie_" + index_str, spot.anggradcie, spotEdited.anggradcie); - + assignFromKeyfile(keyFile, "Locallab", "Feathercie_" + index_str, spot.feathercie, spotEdited.feathercie); + assignFromKeyfile(keyFile, "Locallab", "EnacieMask_" + index_str, spot.enacieMask, spotEdited.enacieMask); assignFromKeyfile(keyFile, "Locallab", "EnacieMaskall_" + index_str, spot.enacieMaskall, spotEdited.enacieMaskall); assignFromKeyfile(keyFile, "Locallab", "CCmaskcieCurve_" + index_str, spot.CCmaskciecurve, spotEdited.CCmaskciecurve); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index d1cad0a5d..d71c3d172 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1122,6 +1122,7 @@ struct LocallabParams { double strcolab; double strcolh; double angcol; + double feathercol; int blurcolde; double blurcol; double contcol; @@ -1184,6 +1185,7 @@ struct LocallabParams { double gamex; double strexp; double angexp; + double featherexp; std::vector excurve; bool norm; bool inversex; @@ -1239,6 +1241,7 @@ struct LocallabParams { int blurSHde; double strSH; double angSH; + double featherSH; bool inverssh; double chromaskSH; double gammaskSH; @@ -1284,6 +1287,7 @@ struct LocallabParams { double strvibab; double strvibh; double angvib; + double feathervib; std::vector Lmaskvibcurve; double recothresv; double lowthresv; @@ -1500,6 +1504,7 @@ struct LocallabParams { double sigmalc2; double strwav; double angwav; + double featherwav; double strengthw; double sigmaed; double radiusw; @@ -1606,6 +1611,7 @@ struct LocallabParams { double baselog; double strlog; double anglog; + double featherlog; std::vector CCmaskcurveL; std::vector LLmaskcurveL; std::vector HHmaskcurveL; @@ -1644,6 +1650,7 @@ struct LocallabParams { double shadmask; int str_mask; int ang_mask; + int feather_mask; std::vector HHhmask_curve; std::vector Lmask_curve; std::vector LLmask_curvewav; @@ -1780,6 +1787,7 @@ struct LocallabParams { Glib::ustring surroundcie; double strgradcie; double anggradcie; + double feathercie; bool enacieMask; bool enacieMaskall; std::vector CCmaskciecurve; diff --git a/rtgui/controlspotpanel.cc b/rtgui/controlspotpanel.cc index 8588f6057..783f253c7 100644 --- a/rtgui/controlspotpanel.cc +++ b/rtgui/controlspotpanel.cc @@ -70,7 +70,7 @@ ControlSpotPanel::ControlSpotPanel(): transit_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_TRANSITVALUE"), 2., 100., 0.1, 60.))), transitweak_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_TRANSITWEAK"), 0.5, 25.0, 0.1, 1.0))), transitgrad_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_TRANSITGRAD"), -1.0, 1.0, 0.01, 0.0))), - feather_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FEATVALUE"), 10., 100., 0.1, 25.))), + feather_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FEATVALUE_MASK"), 10., 100., 0.1, 25.))), struc_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_THRES"), 1.0, 12.0, 0.1, 4.0))), thresh_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_THRESDELTAE"), 0.0, 15.0, 0.1, 2.0))), iter_(Gtk::manage(new Adjuster(M("TP_LOCALLAB_PROXI"), 0.2, 10.0, 0.1, 2.0))), @@ -351,7 +351,7 @@ ControlSpotPanel::ControlSpotPanel(): transitBox->pack_start(*transit_); transitBox->pack_start(*transitweak_); transitBox->pack_start(*transitgrad_); - transitBox->pack_start(*feather_); + //transitBox->pack_start(*feather_); expTransGrad_->add(*transitBox, false); pack_start(*expTransGrad_, false, false); @@ -504,6 +504,7 @@ ControlSpotPanel::ControlSpotPanel(): maskBox->pack_start(*deltae_); maskBox->pack_start(*scopemask_); maskBox->pack_start(*denoichmask_); + maskBox->pack_start(*feather_); // maskBox->pack_start(*shortc_); maskBox->pack_start(*lumask_); // maskBox->pack_start(*savrest_); diff --git a/rtgui/locallabtools.cc b/rtgui/locallabtools.cc index fd4ed22be..4c68b004e 100644 --- a/rtgui/locallabtools.cc +++ b/rtgui/locallabtools.cc @@ -476,6 +476,7 @@ LocallabColor::LocallabColor(): strcolab(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTRCHRO"), -6., 6., 0.05, 0.))), strcolh(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTRHUE"), -6., 6., 0.05, 0.))), angcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), + feathercol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FEATVALUE"), 10., 100., 0.1, 25.))), expcurvcol(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPCURV")))), labqualcurv(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_QUALCURV_METHOD") + ":"))), qualitycurveMethod(Gtk::manage(new MyComboBoxText())), @@ -541,8 +542,9 @@ LocallabColor::LocallabColor(): csThresholdcol(Gtk::manage(new ThresholdAdjuster(M("TP_LOCALLAB_CSTHRESHOLDBLUR"), 0, 9, 0, 0, 6, 5, 0, false))) { auto m = ProcEventMapper::getInstance(); + //rtengine::ProcEvent EvlocallabenacieMaskall; + Evlocallabfeathercol = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_FEATHERCOL"); Evlocallabpreviewcol = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_PREVIEWCOL"); - set_orientation(Gtk::ORIENTATION_VERTICAL); float R, G, B; @@ -609,6 +611,7 @@ LocallabColor::LocallabColor(): strcolh->set_tooltip_text(M("TP_LOCALLAB_GRADSTRHUE_TOOLTIP")); angcol->setAdjusterListener(this); + feathercol->setAdjusterListener(this); setExpandAlignProperties(expcurvcol, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); @@ -879,6 +882,7 @@ LocallabColor::LocallabColor(): gradcolBox->pack_start(*strcolab); gradcolBox->pack_start(*strcolh); gradcolBox->pack_start(*angcol); + gradcolBox->pack_start(*feathercol); expgradcol->add(*gradcolBox, false); pack_start(*expgradcol, false, false); ToolParamBlock* const curvBox = Gtk::manage(new ToolParamBlock()); @@ -1291,6 +1295,7 @@ void LocallabColor::read(const rtengine::procparams::ProcParams* pp, const Param strcolab->setValue(spot.strcolab); strcolh->setValue(spot.strcolh); angcol->setValue(spot.angcol); + feathercol->setValue(spot.feathercol); if (spot.qualitycurveMethod == "none") { qualitycurveMethod->set_active(0); @@ -1472,6 +1477,7 @@ void LocallabColor::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pe spot.strcolab = strcolab->getValue(); spot.strcolh = strcolh->getValue(); spot.angcol = angcol->getValue(); + spot.feathercol = feathercol->getValue(); spot.recothresc = recothresc->getValue(); spot.lowthresc = lowthresc->getValue(); @@ -1626,6 +1632,7 @@ void LocallabColor::setDefaults(const rtengine::procparams::ProcParams* defParam strcolab->setDefault(defSpot.strcolab); strcolh->setDefault(defSpot.strcolh); angcol->setDefault(defSpot.angcol); + feathercol->setDefault(defSpot.feathercol); mercol->setDefault(defSpot.mercol); opacol->setDefault(defSpot.opacol); conthrcol->setDefault(defSpot.conthrcol); @@ -1786,6 +1793,13 @@ void LocallabColor::adjusterChanged(Adjuster* a, double newval) } } + if (a == feathercol) { + if (listener) { + listener->panelChanged(Evlocallabfeathercol, + feathercol->getTextValue() + " (" + escapeHtmlChars(getSpotName()) + ")"); + } + } + if (a == mercol) { if (listener) { listener->panelChanged(Evlocallabmercol, @@ -2147,6 +2161,7 @@ void LocallabColor::convertParamToSimple() softradiuscol->setValue(defSpot.softradiuscol); strcol->setValue(defSpot.strcol); angcol->setValue(defSpot.angcol); + feathercol->setValue(defSpot.feathercol); gamc->setValue(defSpot.gamc); if (defSpot.qualitycurveMethod == "none") { @@ -2706,6 +2721,7 @@ LocallabExposure::LocallabExposure(): expgradexp(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPGRAD")))), strexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -4., 4., 0.05, 0.))), angexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), + featherexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FEATVALUE"), 10., 100., 0.1, 25.))), softradiusexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.5, 0.))), inversex(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))), expmaskexp(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWE")))), @@ -2737,6 +2753,7 @@ LocallabExposure::LocallabExposure(): const LocallabParams::LocallabSpot defSpot; auto m = ProcEventMapper::getInstance(); Evlocallabpreviewexe = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_PREVIEWEXE"); + Evlocallabfeatherexp = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_FEATHEREXE"); // Parameter Exposure specific widgets expMethod->append(M("TP_LOCALLAB_STD")); @@ -2811,6 +2828,7 @@ LocallabExposure::LocallabExposure(): angexp->setAdjusterListener(this); angexp->set_tooltip_text(M("TP_LOCALLAB_GRADANG_TOOLTIP")); + featherexp->setAdjusterListener(this); softradiusexp->setLogScale(10, 0); softradiusexp->setAdjusterListener(this); @@ -2954,6 +2972,7 @@ LocallabExposure::LocallabExposure(): ToolParamBlock* const gradBox = Gtk::manage(new ToolParamBlock()); gradBox->pack_start(*strexp); gradBox->pack_start(*angexp); + gradBox->pack_start(*featherexp); expgradexp->add(*gradBox, false); pack_start(*expgradexp); pack_start(*softradiusexp); @@ -3272,6 +3291,7 @@ void LocallabExposure::read(const rtengine::procparams::ProcParams* pp, const Pa shapeexpos->setCurve(spot.excurve); strexp->setValue(spot.strexp); angexp->setValue(spot.angexp); + featherexp->setValue(spot.featherexp); softradiusexp->setValue(spot.softradiusexp); norm->set_active(spot.norm); fatsatur->set_active(spot.fatsatur); @@ -3363,6 +3383,7 @@ void LocallabExposure::write(rtengine::procparams::ProcParams* pp, ParamsEdited* spot.excurve = shapeexpos->getCurve(); spot.strexp = strexp->getValue(); spot.angexp = angexp->getValue(); + spot.featherexp = featherexp->getValue(); spot.softradiusexp = softradiusexp->getValue(); spot.inversex = inversex->get_active(); spot.norm = norm->get_active(); @@ -3416,6 +3437,7 @@ void LocallabExposure::setDefaults(const rtengine::procparams::ProcParams* defPa expchroma->setDefault((double)defSpot.expchroma); strexp->setDefault(defSpot.strexp); angexp->setDefault(defSpot.angexp); + featherexp->setDefault(defSpot.featherexp); softradiusexp->setDefault(defSpot.softradiusexp); blendmaskexp->setDefault((double)defSpot.blendmaskexp); radmaskexp->setDefault(defSpot.radmaskexp); @@ -3640,6 +3662,13 @@ void LocallabExposure::adjusterChanged(Adjuster* a, double newval) } } + if (a == featherexp) { + if (listener) { + listener->panelChanged(Evlocallabfeatherexp, + featherexp->getTextValue() + " (" + escapeHtmlChars(getSpotName()) + ")"); + } + } + if (a == softradiusexp) { if (listener) { listener->panelChanged(Evlocallabsoftradiusexp, @@ -3796,6 +3825,7 @@ void LocallabExposure::convertParamToSimple() // Set hidden specific GUI widgets in Simple mode to default spot values strexp->setValue(defSpot.strexp); angexp->setValue(defSpot.angexp); + featherexp->setValue(defSpot.featherexp); softradiusexp->setValue(defSpot.softradiusexp); enaExpMask->set_active(defSpot.enaExpMask); enaExpMaskaft->set_active(defSpot.enaExpMaskaft); @@ -4240,6 +4270,7 @@ LocallabShadow::LocallabShadow(): expgradsh(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPGRAD")))), strSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -4., 4., 0.05, 0.))), angSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), + featherSH(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FEATVALUE"), 10., 100., 0.1, 25.))), inverssh(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))), expmasksh(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWS")))), showmaskSHMethod(Gtk::manage(new MyComboBoxText())), @@ -4265,6 +4296,7 @@ LocallabShadow::LocallabShadow(): { auto m = ProcEventMapper::getInstance(); Evlocallabpreviewsh = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_PREVIEWSH"); + EvlocallabfeatherSH = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_FEATHERSH"); set_orientation(Gtk::ORIENTATION_VERTICAL); @@ -4316,6 +4348,7 @@ LocallabShadow::LocallabShadow(): angSH->setAdjusterListener(this); angSH->set_tooltip_text(M("TP_LOCALLAB_GRADANG_TOOLTIP")); + featherSH->setAdjusterListener(this); inversshConn = inverssh->signal_toggled().connect(sigc::mem_fun(*this, &LocallabShadow::inversshChanged)); inverssh->set_tooltip_text(M("TP_LOCALLAB_INVERS_TOOLTIP")); @@ -4427,6 +4460,7 @@ LocallabShadow::LocallabShadow(): ToolParamBlock* const gradSHBox = Gtk::manage(new ToolParamBlock()); gradSHBox->pack_start(*strSH); gradSHBox->pack_start(*angSH); + gradSHBox->pack_start(*featherSH); expgradsh->add(*gradSHBox, false); pack_start(*expgradsh); // pack_start(*inverssh); @@ -4718,6 +4752,7 @@ void LocallabShadow::read(const rtengine::procparams::ProcParams* pp, const Para sloSH->setValue(spot.sloSH); strSH->setValue(spot.strSH); angSH->setValue(spot.angSH); + featherSH->setValue(spot.featherSH); inverssh->set_active(spot.inverssh); enaSHMask->set_active(spot.enaSHMask); CCmaskSHshape->setCurve(spot.CCmaskSHcurve); @@ -4784,6 +4819,7 @@ void LocallabShadow::write(rtengine::procparams::ProcParams* pp, ParamsEdited* p spot.sloSH = sloSH->getValue(); spot.strSH = strSH->getValue(); spot.angSH = angSH->getValue(); + spot.featherSH = featherSH->getValue(); spot.inverssh = inverssh->get_active(); spot.enaSHMask = enaSHMask->get_active(); spot.LLmaskSHcurve = LLmaskSHshape->getCurve(); @@ -4833,6 +4869,7 @@ void LocallabShadow::setDefaults(const rtengine::procparams::ProcParams* defPara sloSH->setDefault(defSpot.sloSH); strSH->setDefault(defSpot.strSH); angSH->setDefault(defSpot.angSH); + featherSH->setDefault(defSpot.featherSH); blendmaskSH->setDefault((double)defSpot.blendmaskSH); radmaskSH->setDefault(defSpot.radmaskSH); lapmaskSH->setDefault(defSpot.lapmaskSH); @@ -4994,6 +5031,13 @@ void LocallabShadow::adjusterChanged(Adjuster* a, double newval) } } + if (a == featherSH) { + if (listener) { + listener->panelChanged(EvlocallabfeatherSH, + featherSH->getTextValue() + " (" + escapeHtmlChars(getSpotName()) + ")"); + } + } + if (a == blendmaskSH) { if (listener) { listener->panelChanged(EvlocallabblendmaskSH, @@ -5133,6 +5177,7 @@ void LocallabShadow::convertParamToSimple() sloSH->setValue(defSpot.sloSH); strSH->setValue(defSpot.strSH); angSH->setValue(defSpot.angSH); + featherSH->setValue(defSpot.featherSH); showmaskSHMethod->set_active(0); showmaskSHMethodinv->set_active(0); enaSHMask->set_active(defSpot.enaSHMask); @@ -5450,6 +5495,7 @@ LocallabVibrance::LocallabVibrance(): strvibab(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTRCHRO"), -4., 4., 0.05, 0.))), strvibh(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTRHUE2"), -6., 6., 0.05, 0.))), angvib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), + feathervib(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FEATVALUE"), 10., 100., 0.1, 25.))), expmaskvib(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWVI")))), showmaskvibMethod(Gtk::manage(new MyComboBoxText())), enavibMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), @@ -5469,7 +5515,7 @@ LocallabVibrance::LocallabVibrance(): { auto m = ProcEventMapper::getInstance(); Evlocallabpreviewvib = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_PREVIEWVIB"); - + Evlocallabfeathervib = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_FEATHERVIB"); set_orientation(Gtk::ORIENTATION_VERTICAL); float R, G, B; @@ -5533,6 +5579,7 @@ LocallabVibrance::LocallabVibrance(): angvib->set_tooltip_text(M("TP_LOCALLAB_GRADANG_TOOLTIP")); angvib->setAdjusterListener(this); + feathervib->setAdjusterListener(this); previewvib->set_active(false); previewvibConn = previewvib->signal_clicked().connect( @@ -5620,6 +5667,7 @@ LocallabVibrance::LocallabVibrance(): gradvibBox->pack_start(*strvibab); gradvibBox->pack_start(*strvibh); gradvibBox->pack_start(*angvib); + gradvibBox->pack_start(*feathervib); expgradvib->add(*gradvibBox, false); pack_start(*expgradvib); ToolParamBlock* const maskvibBox = Gtk::manage(new ToolParamBlock()); @@ -5872,6 +5920,7 @@ void LocallabVibrance::read(const rtengine::procparams::ProcParams* pp, const Pa strvibab->setValue(spot.strvibab); strvibh->setValue(spot.strvibh); angvib->setValue(spot.angvib); + feathervib->setValue(spot.feathervib); enavibMask->set_active(spot.enavibMask); CCmaskvibshape->setCurve(spot.CCmaskvibcurve); LLmaskvibshape->setCurve(spot.LLmaskvibcurve); @@ -5926,6 +5975,7 @@ void LocallabVibrance::write(rtengine::procparams::ProcParams* pp, ParamsEdited* spot.strvibab = strvibab->getValue(); spot.strvibh = strvibh->getValue(); spot.angvib = angvib->getValue(); + spot.feathervib = feathervib->getValue(); spot.enavibMask = enavibMask->get_active(); spot.CCmaskvibcurve = CCmaskvibshape->getCurve(); spot.LLmaskvibcurve = LLmaskvibshape->getCurve(); @@ -5964,6 +6014,7 @@ void LocallabVibrance::setDefaults(const rtengine::procparams::ProcParams* defPa strvibab->setDefault(defSpot.strvibab); strvibh->setDefault(defSpot.strvibh); angvib->setDefault(defSpot.angvib); + feathervib->setDefault(defSpot.feathervib); blendmaskvib->setDefault((double)defSpot.blendmaskvib); radmaskvib->setDefault(defSpot.radmaskvib); lapmaskvib->setDefault(defSpot.lapmaskvib); @@ -6079,6 +6130,13 @@ void LocallabVibrance::adjusterChanged(Adjuster* a, double newval) } } + if (a == feathervib) { + if (listener) { + listener->panelChanged(Evlocallabfeathervib, + feathervib->getTextValue() + " (" + escapeHtmlChars(getSpotName()) + ")"); + } + } + if (a == blendmaskvib) { if (listener) { listener->panelChanged(Evlocallabblendmaskvi, @@ -6277,6 +6335,7 @@ void LocallabVibrance::convertParamToSimple() // Set hidden specific GUI widgets in Simple mode to default spot values strvib->setValue(defSpot.strvib); angvib->setValue(defSpot.angvib); + feathervib->setValue(defSpot.feathervib); showmaskvibMethod->set_active(0); enavibMask->set_active(defSpot.enavibMask); // CCmaskvibshape->setCurve(defSpot.CCmaskvibcurve); diff --git a/rtgui/locallabtools.h b/rtgui/locallabtools.h index 17f9bd5cb..828615ba3 100644 --- a/rtgui/locallabtools.h +++ b/rtgui/locallabtools.h @@ -123,6 +123,14 @@ protected: rtengine::ProcEvent Evlocallabstrgradcie; rtengine::ProcEvent Evlocallabdetailciejz; rtengine::ProcEvent EvlocallabenacieMaskall; + rtengine::ProcEvent Evlocallabfeathercol; + rtengine::ProcEvent Evlocallabfeathervib; + rtengine::ProcEvent Evlocallabfeatherexp; + rtengine::ProcEvent Evlocallabfeatherwav; + rtengine::ProcEvent Evlocallabfeatherlog; + rtengine::ProcEvent Evlocallabfeathercie; + rtengine::ProcEvent EvlocallabfeatherSH; + rtengine::ProcEvent Evlocallabfeather_mask; // LocallabTool parameters bool needMode; bool isLocActivated; @@ -278,6 +286,7 @@ private: Adjuster* const strcolab; Adjuster* const strcolh; Adjuster* const angcol; + Adjuster* const feathercol; MyExpander* const expcurvcol; Gtk::Label* const labqualcurv; MyComboBoxText* const qualitycurveMethod; @@ -451,6 +460,7 @@ private: MyExpander* const expgradexp; Adjuster* const strexp; Adjuster* const angexp; + Adjuster* const featherexp; Adjuster* const softradiusexp; Gtk::CheckButton* const inversex; MyExpander* const expmaskexp; @@ -559,6 +569,7 @@ private: MyExpander* const expgradsh; Adjuster* const strSH; Adjuster* const angSH; + Adjuster* const featherSH; Gtk::CheckButton* const inverssh; MyExpander* const expmasksh; MyComboBoxText* const showmaskSHMethod; @@ -661,6 +672,7 @@ private: Adjuster* const strvibab; Adjuster* const strvibh; Adjuster* const angvib; + Adjuster* const feathervib; MyExpander* const expmaskvib; MyComboBoxText* const showmaskvibMethod; Gtk::CheckButton* const enavibMask; @@ -1240,6 +1252,7 @@ private: Adjuster* const sigmalc2; Adjuster* const strwav; Adjuster* const angwav; + Adjuster* const featherwav; Gtk::CheckButton* const wavedg; Adjuster* const strengthw; Adjuster* const sigmaed; @@ -1506,6 +1519,7 @@ private: Gtk::Frame* const gradlogFrame; Adjuster* const strlog; Adjuster* const anglog; + Adjuster* const featherlog; MyExpander* const expmaskL; MyComboBoxText* const showmaskLMethod; Gtk::CheckButton* const enaLMask; @@ -1613,6 +1627,7 @@ private: ThresholdAdjuster* const csThresholdmask; Gtk::Frame* const gradFramemask; Adjuster* const str_mask; + Adjuster* const feather_mask; Adjuster* const ang_mask; sigc::connection showmask_MethodConn, previewmasConn, enamaskConn, toolmaskConn, fftmaskConn; @@ -1866,6 +1881,7 @@ private: MyExpander* const expgradcie; Adjuster* const strgradcie; Adjuster* const anggradcie; + Adjuster* const feathercie; MyExpander* const exprecovcie; Gtk::Label* const maskusablecie; diff --git a/rtgui/locallabtools2.cc b/rtgui/locallabtools2.cc index af09224b5..b13148cd1 100644 --- a/rtgui/locallabtools2.cc +++ b/rtgui/locallabtools2.cc @@ -2534,6 +2534,7 @@ LocallabContrast::LocallabContrast(): sigmalc2(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SIGMAWAV"), 0.2, 2.5, 0.01, 1.))), strwav(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -4.0, 4.0, 0.05, 0.))), angwav(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), + featherwav(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FEATVALUE"), 10., 100., 0.1, 25.))), wavedg(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_EDGFRA")))), strengthw(Gtk::manage(new Adjuster(M("TP_WAVELET_EDVAL"), 0., 100.0, 0.5, 0.))), sigmaed(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SIGMAWAV"), 0.2, 2.5, 0.01, 1.))), @@ -2602,6 +2603,7 @@ LocallabContrast::LocallabContrast(): { auto m = ProcEventMapper::getInstance(); Evlocallabpreviewlc = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_PREVIEWLC"); + Evlocallabfeatherwav = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_FEATHERWAV"); set_orientation(Gtk::ORIENTATION_VERTICAL); @@ -2708,6 +2710,7 @@ LocallabContrast::LocallabContrast(): strwav->setAdjusterListener(this); angwav->setAdjusterListener(this); + featherwav->setAdjusterListener(this); wavedgConn = wavedg->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::wavedgChanged)); @@ -2949,6 +2952,7 @@ LocallabContrast::LocallabContrast(): gradwavBox->pack_start(*sigmalc2); gradwavBox->pack_start(*strwav); gradwavBox->pack_start(*angwav); + gradwavBox->pack_start(*featherwav); gradwavFrame->add(*gradwavBox); blurcontBox->pack_start(*gradwavFrame); Gtk::Frame* const edgFrame = Gtk::manage(new Gtk::Frame()); @@ -3400,6 +3404,7 @@ void LocallabContrast::read(const rtengine::procparams::ProcParams* pp, const Pa sigmalc2->setValue(spot.sigmalc2); strwav->setValue(spot.strwav); angwav->setValue(spot.angwav); + featherwav->setValue(spot.featherwav); wavedg->set_active(spot.wavedg); strengthw->setValue(spot.strengthw); sigmaed->setValue(spot.sigmaed); @@ -3525,6 +3530,7 @@ void LocallabContrast::write(rtengine::procparams::ProcParams* pp, ParamsEdited* spot.sigmalc2 = sigmalc2->getValue(); spot.strwav = strwav->getValue(); spot.angwav = angwav->getValue(); + spot.featherwav = featherwav->getValue(); spot.wavedg = wavedg->get_active(); spot.strengthw = strengthw->getValue(); spot.sigmaed = sigmaed->getValue(); @@ -3627,6 +3633,7 @@ void LocallabContrast::setDefaults(const rtengine::procparams::ProcParams* defPa sigmalc2->setDefault(defSpot.sigmalc2); strwav->setDefault(defSpot.strwav); angwav->setDefault(defSpot.angwav); + featherwav->setDefault(defSpot.featherwav); strengthw->setDefault(defSpot.strengthw); sigmaed->setDefault(defSpot.sigmaed); gradw->setDefault(defSpot.gradw); @@ -3825,6 +3832,13 @@ void LocallabContrast::adjusterChanged(Adjuster* a, double newval) } } + if (a == featherwav) { + if (listener) { + listener->panelChanged(Evlocallabfeatherwav, + featherwav->getTextValue() + " (" + escapeHtmlChars(getSpotName()) + ")"); + } + } + if (a == strengthw) { if (listener) { listener->panelChanged(Evlocallabstrengthw, @@ -4146,6 +4160,7 @@ void LocallabContrast::convertParamToNormal() sigmalc2->setValue(defSpot.sigmalc2); strwav->setValue(defSpot.strwav); angwav->setValue(defSpot.angwav); + featherwav->setValue(defSpot.featherwav); wavedg->set_active(defSpot.wavedg); strengthw->setValue(defSpot.strengthw); sigmaed->setValue(defSpot.sigmaed); @@ -5516,6 +5531,7 @@ LocallabLog::LocallabLog(): gradlogFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_GRADLOGFRA")))), strlog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -2.0, 2.0, 0.05, 0.))), anglog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), + featherlog(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FEATVALUE"), 10., 100., 0.1, 25.))), expmaskL(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOWC")))), showmaskLMethod(Gtk::manage(new MyComboBoxText())), enaLMask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK")))), @@ -5539,6 +5555,7 @@ LocallabLog::LocallabLog(): Evlocallabcomprlog = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_LOG_COMPR"); Evlocallabstrelog = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_LOG_STRE"); Evlocallabsatlog = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_LOG_SAT"); + Evlocallabfeatherlog = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_FEATHERLOG"); set_orientation(Gtk::ORIENTATION_VERTICAL); @@ -5619,6 +5636,7 @@ LocallabLog::LocallabLog(): strlog->setAdjusterListener(this); anglog->setAdjusterListener(this); + featherlog->setAdjusterListener(this); surHBox->set_spacing(2); surHBox->set_tooltip_markup(M("TP_LOCALLAB_LOGSURSOUR_TOOLTIP")); @@ -5788,6 +5806,7 @@ LocallabLog::LocallabLog(): ToolParamBlock* const gradlogBox = Gtk::manage(new ToolParamBlock()); gradlogBox->pack_start(*strlog); gradlogBox->pack_start(*anglog); + gradlogBox->pack_start(*featherlog); gradlogFrame->add(*gradlogBox); pack_start(*gradlogFrame); } @@ -6101,6 +6120,7 @@ void LocallabLog::read(const rtengine::procparams::ProcParams* pp, const ParamsE sensilog->setValue((double)spot.sensilog); strlog->setValue(spot.strlog); anglog->setValue(spot.anglog); + featherlog->setValue(spot.featherlog); CCmaskshapeL->setCurve(spot.CCmaskcurveL); LLmaskshapeL->setCurve(spot.LLmaskcurveL); HHmaskshapeL->setCurve(spot.HHmaskcurveL); @@ -6168,6 +6188,7 @@ void LocallabLog::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedi spot.sensilog = sensilog->getIntValue(); spot.strlog = strlog->getValue(); spot.anglog = anglog->getValue(); + spot.featherlog = featherlog->getValue(); spot.CCmaskcurveL = CCmaskshapeL->getCurve(); spot.LLmaskcurveL = LLmaskshapeL->getCurve(); spot.HHmaskcurveL = HHmaskshapeL->getCurve(); @@ -6354,6 +6375,7 @@ void LocallabLog::convertParamToSimple() sursour->set_active(0); strlog->setValue(defSpot.strlog); anglog->setValue(defSpot.anglog); + featherlog->setValue(defSpot.featherlog); enaLMask->set_active(false); showmaskLMethod->set_active(0); recothresl->setValue(defSpot.recothresl); @@ -6476,6 +6498,7 @@ void LocallabLog::setDefaults(const rtengine::procparams::ProcParams* defParams, sensilog->setDefault((double)defSpot.sensilog); strlog->setDefault(defSpot.strlog); anglog->setDefault(defSpot.anglog); + featherlog->setDefault(defSpot.featherlog); blendmaskL->setDefault(defSpot.blendmaskL); radmaskL->setDefault(defSpot.radmaskL); chromaskL->setDefault(defSpot.chromaskL); @@ -6699,6 +6722,13 @@ void LocallabLog::adjusterChanged(Adjuster* a, double newval) } } + if (a == featherlog) { + if (listener) { + listener->panelChanged(Evlocallabfeatherlog, + featherlog->getTextValue() + " (" + escapeHtmlChars(getSpotName()) + ")"); + } + } + if (a == blendmaskL) { if (listener) { listener->panelChanged(EvLocallabblendmaskL, @@ -7011,11 +7041,13 @@ LocallabMask::LocallabMask(): csThresholdmask(Gtk::manage(new ThresholdAdjuster(M("TP_LOCALLAB_CSTHRESHOLDBLUR"), 0, 9, 0, 0, 6, 5, 0, false))), gradFramemask(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_GRADFRA")))), str_mask(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -2., 2., 0.05, 0.))), + feather_mask(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FEATVALUE"), 10., 100., 0.1, 25.))), ang_mask(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180., 180., 0.1, 0.))) { auto m = ProcEventMapper::getInstance(); Evlocallabpreviewmas = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_PREVIEWMAS"); + Evlocallabfeather_mask = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_FEATHERMAS"); set_orientation(Gtk::ORIENTATION_VERTICAL); @@ -7125,6 +7157,7 @@ LocallabMask::LocallabMask(): ang_mask->setAdjusterListener(this); ang_mask->set_tooltip_text(M("TP_LOCALLAB_GRADANG_TOOLTIP")); + feather_mask->setAdjusterListener(this); // Add Common mask specific widgets to GUI pack_start(*sensimask); @@ -7160,6 +7193,7 @@ LocallabMask::LocallabMask(): ToolParamBlock* const gradmaskBox = Gtk::manage(new ToolParamBlock()); gradmaskBox->pack_start(*str_mask); gradmaskBox->pack_start(*ang_mask); + gradmaskBox->pack_start(*feather_mask); gradFramemask->add(*gradmaskBox); toolmaskBox->pack_start(*gradFramemask, Gtk::PACK_SHRINK, 0); toolmaskFrame->add(*toolmaskBox); @@ -7375,6 +7409,7 @@ void LocallabMask::read(const rtengine::procparams::ProcParams* pp, const Params csThresholdmask->setValue(spot.csthresholdmask); str_mask->setValue((double)spot.str_mask); ang_mask->setValue((double)spot.ang_mask); + feather_mask->setValue((double)spot.feather_mask); } // Enable all listeners @@ -7422,6 +7457,7 @@ void LocallabMask::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped spot.csthresholdmask = csThresholdmask->getValue(); spot.str_mask = str_mask->getIntValue(); spot.ang_mask = ang_mask->getIntValue(); + spot.feather_mask = feather_mask->getIntValue(); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -7451,6 +7487,7 @@ void LocallabMask::setDefaults(const rtengine::procparams::ProcParams* defParams csThresholdmask->setDefault(defSpot.csthresholdmask); str_mask->setDefault((double)defSpot.str_mask); ang_mask->setDefault((double)defSpot.ang_mask); + feather_mask->setDefault((double)defSpot.feather_mask); } // Note: No need to manage pedited as batch mode is deactivated for Locallab @@ -7565,6 +7602,13 @@ void LocallabMask::adjusterChanged(Adjuster* a, double newval) } } + if (a == feather_mask) { + if (listener) { + listener->panelChanged(Evlocallabfeather_mask, + feather_mask->getTextValue() + " (" + escapeHtmlChars(getSpotName()) + ")"); + } + } + } } @@ -7700,6 +7744,7 @@ void LocallabMask::convertParamToNormal() csThresholdmask->setValue(defSpot.csthresholdmask); str_mask->setValue((double)defSpot.str_mask); ang_mask->setValue((double)defSpot.ang_mask); + feather_mask->setValue((double)defSpot.feather_mask); // Enable all listeners enableListener(); @@ -8067,6 +8112,7 @@ Locallabcie::Locallabcie(): expgradcie(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_EXPGRAD")))), strgradcie(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADSTR"), -4., 4., 0.05, 0.))), anggradcie(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GRADANG"), -180, 180, 0.1, 0.))), + feathercie(Gtk::manage(new Adjuster(M("TP_LOCALLAB_FEATVALUE"), 10., 100., 0.1, 25.))), exprecovcie(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_DENOI2_EXP")))), maskusablecie(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_MASKUSABLE")))), @@ -8167,6 +8213,7 @@ Locallabcie::Locallabcie(): Evlocallabdetailciejz = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_CIE_DETAILJZ"); EvlocallabenacieMaskall = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_CIE_ENAMASKALL"); Evlocallabsmoothciemet = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_CIE_SMOOTHMET"); + Evlocallabfeathercie = m->newEvent(AUTOEXP, "HISTORY_MSG_LOCAL_FEATHERCIE"); set_orientation(Gtk::ORIENTATION_VERTICAL); @@ -8984,9 +9031,11 @@ Locallabcie::Locallabcie(): strgradcie->setAdjusterListener(this); anggradcie->setAdjusterListener(this); + feathercie->setAdjusterListener(this); ToolParamBlock* const cieBoxgrad = Gtk::manage(new ToolParamBlock()); cieBoxgrad->pack_start(*strgradcie); cieBoxgrad->pack_start(*anggradcie); + cieBoxgrad->pack_start(*feathercie); expgradcie->add(*cieBoxgrad, false); pack_start(*expgradcie, false, false); @@ -9875,6 +9924,7 @@ void Locallabcie::read(const rtengine::procparams::ProcParams* pp, const ParamsE strgradcie->setValue((double)spot.strgradcie); anggradcie->setValue((double)spot.anggradcie); + feathercie->setValue((double)spot.feathercie); enacieMask->set_active(spot.enacieMask); enacieMaskall->set_active(spot.enacieMaskall); @@ -10178,6 +10228,7 @@ void Locallabcie::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedi spot.detailcie = detailcie->getValue(); spot.strgradcie = strgradcie->getValue(); spot.anggradcie = anggradcie->getValue(); + spot.feathercie = feathercie->getValue(); spot.enacieMask = enacieMask->get_active(); spot.enacieMaskall = enacieMaskall->get_active(); @@ -11886,6 +11937,7 @@ void Locallabcie::convertParamToSimple() enacieMaskall->set_active(defSpot.enacieMaskall); strgradcie->setValue(defSpot.strgradcie); anggradcie->setValue(defSpot.anggradcie); + feathercie->setValue(defSpot.feathercie); refi->setValue(defSpot.refi); modecie->set_active(0); primMethod->set_active(0);//Prophoto @@ -12050,6 +12102,7 @@ void Locallabcie::setDefaults(const rtengine::procparams::ProcParams* defParams, // detailcie->setDefault(defSpot.detailcie); strgradcie->setDefault((double)defSpot.strgradcie); anggradcie->setDefault((double)defSpot.anggradcie); + feathercie->setDefault((double)defSpot.feathercie); blendmaskcie->setDefault((double)defSpot.blendmaskcie); radmaskcie->setDefault(defSpot.radmaskcie); chromaskcie->setDefault(defSpot.chromaskcie); @@ -12758,6 +12811,13 @@ void Locallabcie::adjusterChanged(Adjuster* a, double newval) } } + if (a == feathercie) { + if (listener) { + listener->panelChanged(Evlocallabfeathercie, + feathercie->getTextValue() + spName); + } + } + if (a == blendmaskcie) { if (listener) { listener->panelChanged(Evlocallabblendmaskcie, diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 66ea3f9aa..81b6b34d8 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -1185,6 +1185,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).strcolab = locallab.spots.at(j).strcolab && pSpot.strcolab == otherSpot.strcolab; locallab.spots.at(j).strcolh = locallab.spots.at(j).strcolh && pSpot.strcolh == otherSpot.strcolh; locallab.spots.at(j).angcol = locallab.spots.at(j).angcol && pSpot.angcol == otherSpot.angcol; + locallab.spots.at(j).feathercol = locallab.spots.at(j).feathercol && pSpot.feathercol == otherSpot.feathercol; locallab.spots.at(j).blurcolde = locallab.spots.at(j).blurcolde && pSpot.blurcolde == otherSpot.blurcolde; locallab.spots.at(j).blurcol = locallab.spots.at(j).blurcol && pSpot.blurcol == otherSpot.blurcol; locallab.spots.at(j).contcol = locallab.spots.at(j).contcol && pSpot.contcol == otherSpot.contcol; @@ -1247,6 +1248,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).blurexpde = locallab.spots.at(j).blurexpde && pSpot.blurexpde == otherSpot.blurexpde; locallab.spots.at(j).strexp = locallab.spots.at(j).strexp && pSpot.strexp == otherSpot.strexp; locallab.spots.at(j).angexp = locallab.spots.at(j).angexp && pSpot.angexp == otherSpot.angexp; + locallab.spots.at(j).featherexp = locallab.spots.at(j).featherexp && pSpot.featherexp == otherSpot.featherexp; locallab.spots.at(j).excurve = locallab.spots.at(j).excurve && pSpot.excurve == otherSpot.excurve; locallab.spots.at(j).norm = locallab.spots.at(j).norm && pSpot.norm == otherSpot.norm; locallab.spots.at(j).inversex = locallab.spots.at(j).inversex && pSpot.inversex == otherSpot.inversex; @@ -1306,6 +1308,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).blurSHde = locallab.spots.at(j).blurSHde && pSpot.blurSHde == otherSpot.blurSHde; locallab.spots.at(j).strSH = locallab.spots.at(j).strSH && pSpot.strSH == otherSpot.strSH; locallab.spots.at(j).angSH = locallab.spots.at(j).angSH && pSpot.angSH == otherSpot.angSH; + locallab.spots.at(j).featherSH = locallab.spots.at(j).featherSH && pSpot.featherSH == otherSpot.featherSH; locallab.spots.at(j).inverssh = locallab.spots.at(j).inverssh && pSpot.inverssh == otherSpot.inverssh; locallab.spots.at(j).chromaskSH = locallab.spots.at(j).chromaskSH && pSpot.chromaskSH == otherSpot.chromaskSH; locallab.spots.at(j).gammaskSH = locallab.spots.at(j).gammaskSH && pSpot.gammaskSH == otherSpot.gammaskSH; @@ -1351,6 +1354,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).strvibab = locallab.spots.at(j).strvibab && pSpot.strvibab == otherSpot.strvibab; locallab.spots.at(j).strvibh = locallab.spots.at(j).strvibh && pSpot.strvibh == otherSpot.strvibh; locallab.spots.at(j).angvib = locallab.spots.at(j).angvib && pSpot.angvib == otherSpot.angvib; + locallab.spots.at(j).feathervib = locallab.spots.at(j).feathervib && pSpot.feathervib == otherSpot.feathervib; locallab.spots.at(j).Lmaskvibcurve = locallab.spots.at(j).Lmaskvibcurve && pSpot.Lmaskvibcurve == otherSpot.Lmaskvibcurve; locallab.spots.at(j).recothresv = locallab.spots.at(j).recothresv && pSpot.recothresv == otherSpot.recothresv; locallab.spots.at(j).lowthresv = locallab.spots.at(j).lowthresv && pSpot.lowthresv == otherSpot.lowthresv; @@ -1567,6 +1571,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).sigmalc2 = locallab.spots.at(j).sigmalc2 && pSpot.sigmalc2 == otherSpot.sigmalc2; locallab.spots.at(j).strwav = locallab.spots.at(j).strwav && pSpot.strwav == otherSpot.strwav; locallab.spots.at(j).angwav = locallab.spots.at(j).angwav && pSpot.angwav == otherSpot.angwav; + locallab.spots.at(j).featherwav = locallab.spots.at(j).featherwav && pSpot.featherwav == otherSpot.featherwav; locallab.spots.at(j).strengthw = locallab.spots.at(j).strengthw && pSpot.strengthw == otherSpot.strengthw; locallab.spots.at(j).sigmaed = locallab.spots.at(j).sigmaed && pSpot.sigmaed == otherSpot.sigmaed; locallab.spots.at(j).radiusw = locallab.spots.at(j).radiusw && pSpot.radiusw == otherSpot.radiusw; @@ -1678,6 +1683,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).baselog = locallab.spots.at(j).baselog && pSpot.baselog == otherSpot.baselog; locallab.spots.at(j).strlog = locallab.spots.at(j).strlog && pSpot.strlog == otherSpot.strlog; locallab.spots.at(j).anglog = locallab.spots.at(j).anglog && pSpot.anglog == otherSpot.anglog; + locallab.spots.at(j).featherlog = locallab.spots.at(j).featherlog && pSpot.featherlog == otherSpot.featherlog; locallab.spots.at(j).CCmaskcurveL = locallab.spots.at(j).CCmaskcurveL && pSpot.CCmaskcurveL == otherSpot.CCmaskcurveL; locallab.spots.at(j).LLmaskcurveL = locallab.spots.at(j).LLmaskcurveL && pSpot.LLmaskcurveL == otherSpot.LLmaskcurveL; locallab.spots.at(j).HHmaskcurveL = locallab.spots.at(j).HHmaskcurveL && pSpot.HHmaskcurveL == otherSpot.HHmaskcurveL; @@ -1716,6 +1722,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).shadmask = locallab.spots.at(j).shadmask && pSpot.shadmask == otherSpot.shadmask; locallab.spots.at(j).str_mask = locallab.spots.at(j).str_mask && pSpot.str_mask == otherSpot.str_mask; locallab.spots.at(j).ang_mask = locallab.spots.at(j).ang_mask && pSpot.ang_mask == otherSpot.ang_mask; + locallab.spots.at(j).feather_mask = locallab.spots.at(j).feather_mask && pSpot.feather_mask == otherSpot.feather_mask; locallab.spots.at(j).HHhmask_curve = locallab.spots.at(j).HHhmask_curve && pSpot.HHhmask_curve == otherSpot.HHhmask_curve; locallab.spots.at(j).Lmask_curve = locallab.spots.at(j).Lmask_curve && pSpot.Lmask_curve == otherSpot.Lmask_curve; locallab.spots.at(j).LLmask_curvewav = locallab.spots.at(j).LLmask_curvewav && pSpot.LLmask_curvewav == otherSpot.LLmask_curvewav; @@ -1848,7 +1855,8 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).strgradcie = locallab.spots.at(j).strgradcie && pSpot.strgradcie == otherSpot.strgradcie; locallab.spots.at(j).anggradcie = locallab.spots.at(j).anggradcie && pSpot.anggradcie == otherSpot.anggradcie; - + locallab.spots.at(j).feathercie = locallab.spots.at(j).feathercie && pSpot.feathercie == otherSpot.feathercie; + locallab.spots.at(j).enacieMask = locallab.spots.at(j).enacieMask && pSpot.enacieMask == otherSpot.enacieMask; locallab.spots.at(j).enacieMaskall = locallab.spots.at(j).enacieMaskall && pSpot.enacieMaskall == otherSpot.enacieMaskall; locallab.spots.at(j).CCmaskciecurve = locallab.spots.at(j).CCmaskciecurve && pSpot.CCmaskciecurve == otherSpot.CCmaskciecurve; @@ -3832,6 +3840,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).angcol = mods.locallab.spots.at(i).angcol; } + if (locallab.spots.at(i).feathercol) { + toEdit.locallab.spots.at(i).feathercol = mods.locallab.spots.at(i).feathercol; + } + if (locallab.spots.at(i).blurcolde) { toEdit.locallab.spots.at(i).blurcolde = mods.locallab.spots.at(i).blurcolde; } @@ -4081,6 +4093,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).angexp = mods.locallab.spots.at(i).angexp; } + if (locallab.spots.at(i).featherexp) { + toEdit.locallab.spots.at(i).featherexp = mods.locallab.spots.at(i).featherexp; + } + if (locallab.spots.at(i).excurve) { toEdit.locallab.spots.at(i).excurve = mods.locallab.spots.at(i).excurve; } @@ -4300,6 +4316,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).angSH = mods.locallab.spots.at(i).angSH; } + if (locallab.spots.at(i).featherSH) { + toEdit.locallab.spots.at(i).featherSH = mods.locallab.spots.at(i).featherSH; + } + if (locallab.spots.at(i).inverssh) { toEdit.locallab.spots.at(i).inverssh = mods.locallab.spots.at(i).inverssh; } @@ -4477,6 +4497,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).angvib = mods.locallab.spots.at(i).angvib; } + if (locallab.spots.at(i).feathervib) { + toEdit.locallab.spots.at(i).feathervib = mods.locallab.spots.at(i).feathervib; + } + if (locallab.spots.at(i).Lmaskvibcurve) { toEdit.locallab.spots.at(i).Lmaskvibcurve = mods.locallab.spots.at(i).Lmaskvibcurve; } @@ -5325,6 +5349,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).angwav = mods.locallab.spots.at(i).angwav; } + if (locallab.spots.at(i).featherwav) { + toEdit.locallab.spots.at(i).featherwav = mods.locallab.spots.at(i).featherwav; + } + if (locallab.spots.at(i).strengthw) { toEdit.locallab.spots.at(i).strengthw = mods.locallab.spots.at(i).strengthw; } @@ -5749,6 +5777,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).anglog = mods.locallab.spots.at(i).anglog; } + if (locallab.spots.at(i).featherlog) { + toEdit.locallab.spots.at(i).featherlog = mods.locallab.spots.at(i).featherlog; + } + if (locallab.spots.at(i).CCmaskcurveL) { toEdit.locallab.spots.at(i).CCmaskcurveL = mods.locallab.spots.at(i).CCmaskcurveL; } @@ -5890,6 +5922,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).ang_mask = mods.locallab.spots.at(i).ang_mask; } + if (locallab.spots.at(i).feather_mask) { + toEdit.locallab.spots.at(i).feather_mask = mods.locallab.spots.at(i).feather_mask; + } + if (locallab.spots.at(i).HHhmask_curve) { toEdit.locallab.spots.at(i).HHhmask_curve = mods.locallab.spots.at(i).HHhmask_curve; } @@ -6423,6 +6459,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).anggradcie = mods.locallab.spots.at(i).anggradcie; } + if (locallab.spots.at(i).feathercie) { + toEdit.locallab.spots.at(i).feathercie = mods.locallab.spots.at(i).feathercie; + } + if (locallab.spots.at(i).enacieMask) { toEdit.locallab.spots.at(i).enacieMask = mods.locallab.spots.at(i).enacieMask; } @@ -7938,6 +7978,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : strcolab(v), strcolh(v), angcol(v), + feathercol(v), blurcolde(v), blurcol(v), contcol(v), @@ -8000,6 +8041,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : blurexpde(v), strexp(v), angexp(v), + featherexp(v), excurve(v), norm(v), inversex(v), @@ -8055,6 +8097,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : blurSHde(v), strSH(v), angSH(v), + featherSH(v), inverssh(v), chromaskSH(v), gammaskSH(v), @@ -8100,6 +8143,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : strvibab(v), strvibh(v), angvib(v), + feathervib(v), Lmaskvibcurve(v), recothresv(v), lowthresv(v), @@ -8316,6 +8360,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : sigmalc2(v), strwav(v), angwav(v), + featherwav(v), strengthw(v), sigmaed(v), radiusw(v), @@ -8422,6 +8467,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : baselog(v), strlog(v), anglog(v), + featherlog(v), CCmaskcurveL(v), LLmaskcurveL(v), HHmaskcurveL(v), @@ -8459,6 +8505,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : shadmask(v), str_mask(v), ang_mask(v), + feather_mask(v), HHhmask_curve(v), Lmask_curve(v), LLmask_curvewav(v), @@ -8588,6 +8635,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : surroundcie(v), strgradcie(v), anggradcie(v), + feathercie(v), enacieMask(v), enacieMaskall(v), CCmaskciecurve(v), @@ -8690,6 +8738,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) strcolab = v; strcolh = v; angcol = v; + feathercol = v; blurcolde = v; blurcol = v; contcol = v; @@ -8752,6 +8801,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) blurexpde = v; strexp = v; angexp = v; + featherexp = v; excurve = v; norm = v; inversex = v; @@ -8811,6 +8861,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) blurSHde = v; strSH = v; angSH = v; + featherSH = v; inverssh = v; chromaskSH = v; gammaskSH = v; @@ -8856,6 +8907,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) strvibab = v; strvibh = v; angvib = v; + feathervib = v; Lmaskvibcurve = v; recothresv = v; lowthresv = v; @@ -9071,6 +9123,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) sigmalc2 = v; strwav = v; angwav = v; + featherwav = v; strengthw = v; sigmaed = v; radiusw = v; @@ -9181,6 +9234,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) baselog = v; strlog = v; anglog = v; + featherlog = v; CCmaskcurveL = v; LLmaskcurveL = v; HHmaskcurveL = v; @@ -9218,6 +9272,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) shadmask = v; str_mask = v; ang_mask = v; + feather_mask = v; HHhmask_curve = v; Lmask_curve = v; LLmask_curvewav = v; @@ -9346,6 +9401,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) detailcie = v; surroundcie = v; anggradcie = v; + feathercie = v; strgradcie = v; enacieMask = v; enacieMaskall = v; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 27f9ac9cc..bc617612c 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -476,6 +476,7 @@ public: bool strcolab; bool strcolh; bool angcol; + bool feathercol; bool blurcolde; bool blurcol; bool contcol; @@ -538,6 +539,7 @@ public: bool blurexpde; bool strexp; bool angexp; + bool featherexp; bool excurve; bool norm; bool inversex; @@ -593,6 +595,7 @@ public: bool blurSHde; bool strSH; bool angSH; + bool featherSH; bool inverssh; bool chromaskSH; bool gammaskSH; @@ -638,6 +641,7 @@ public: bool strvibab; bool strvibh; bool angvib; + bool feathervib; bool Lmaskvibcurve; bool recothresv; bool lowthresv; @@ -854,6 +858,7 @@ public: bool sigmalc2; bool strwav; bool angwav; + bool featherwav; bool strengthw; bool sigmaed; bool radiusw; @@ -960,6 +965,7 @@ public: bool baselog; bool strlog; bool anglog; + bool featherlog; bool CCmaskcurveL; bool LLmaskcurveL; bool HHmaskcurveL; @@ -997,6 +1003,7 @@ public: bool shadmask; bool str_mask; bool ang_mask; + bool feather_mask; bool HHhmask_curve; bool Lmask_curve; bool LLmask_curvewav; @@ -1127,6 +1134,7 @@ public: bool surroundcie; bool strgradcie; bool anggradcie; + bool feathercie; bool enacieMask; bool enacieMaskall; From c478c7caa32cbb0b2ec9b8d65e588d4d91123b8b Mon Sep 17 00:00:00 2001 From: Lawrence37 <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 16 Jun 2024 10:47:04 -0700 Subject: [PATCH 11/39] Remove Itanium architecture support for Windows --- UpdateInfo.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UpdateInfo.cmake b/UpdateInfo.cmake index b0c2bdff6..350adc071 100644 --- a/UpdateInfo.cmake +++ b/UpdateInfo.cmake @@ -100,15 +100,15 @@ if(WIN32) if(BIT_DEPTH EQUAL 4) set(BUILD_BIT_DEPTH 32) # 32 bits builds has to be installable on 64 bits system, to support WinXP/64. - set(ARCHITECTURE_ALLOWED "x86 x64 ia64") + set(ARCHITECTURE_ALLOWED "x86 x64") # installing in 32 bits mode even on 64 bits OS and architecture set(INSTALL_MODE "") elseif(BIT_DEPTH EQUAL 8) set(BUILD_BIT_DEPTH 64) # Restricting the 64 bits builds to 64 bits systems only - set(ARCHITECTURE_ALLOWED "x64 ia64 arm64") + set(ARCHITECTURE_ALLOWED "x64 arm64") # installing in 64 bits mode for all 64 bits processors, even for itanium architecture - set(INSTALL_MODE "x64 ia64 arm64") + set(INSTALL_MODE "x64 arm64") endif() # set part of the output archive name set(SYSTEM_NAME "WinVista") From 3433741bb6df4849003def58503411f0f0d5e9ff Mon Sep 17 00:00:00 2001 From: Lawrence37 <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 16 Jun 2024 15:33:46 -0700 Subject: [PATCH 12/39] Mention capture sharpening in contrast mask tool-tip Closes #7087. --- rtdata/languages/default | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index f8f7cf114..5ef480ce4 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1793,7 +1793,7 @@ MAIN_TOOLTIP_PREVIEWFOCUSMASK;Preview the focus mask.\nShortcut: Shift MAIN_TOOLTIP_PREVIEWG;Preview the green channel.\nShortcut: g MAIN_TOOLTIP_PREVIEWL;Preview the luminosity.\nShortcut: v\n\n0.299*R + 0.587*G + 0.114*B MAIN_TOOLTIP_PREVIEWR;Preview the red channel.\nShortcut: r -MAIN_TOOLTIP_PREVIEWSHARPMASK;Preview the sharpening contrast mask.\nShortcut: p\n\nOnly works when sharpening is enabled and zoom >= 100%. +MAIN_TOOLTIP_PREVIEWSHARPMASK;Preview the sharpening contrast mask.\nShortcut: p\n\nOnly works when sharpening is enabled and zoom >= 100%, or when capture sharpening is enabled. MAIN_TOOLTIP_QINFO;Quick info on the image.\nShortcut: i MAIN_TOOLTIP_SHOWHIDELP1;Show/Hide the left panel.\nShortcut: l MAIN_TOOLTIP_SHOWHIDERP1;Show/Hide the right panel.\nShortcut: Alt-l From 89de9792480b239fe7b5f5bbb584019c0ce7e1c9 Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 16 Jun 2024 16:41:55 -0700 Subject: [PATCH 13/39] Add Nikon Z f color matrix --- rtengine/camconst.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rtengine/camconst.json b/rtengine/camconst.json index b80d776b8..00fc2cf5d 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -2101,6 +2101,11 @@ Camera constants: "pdaf_pattern": [285, 297, 309, 321, 333, 345, 357, 369, 381, 393, 405, 417, 429, 441, 453, 465, 477, 489, 501, 513, 525, 537, 549, 561, 573, 585, 597, 609, 621, 633, 645, 657, 669, 681, 693, 705, 717, 729, 741, 753, 765, 777, 789, 801, 813, 825, 837, 849, 861, 873, 885, 897, 909, 921, 933, 945, 957, 969, 981, 993, 1005, 1017, 1029, 1041, 1053, 1065, 1077, 1089, 1101, 1113, 1125, 1137, 1149, 1161, 1173, 1185, 1197, 1209, 1221, 1233, 1245, 1257, 1269, 1281, 1293, 1305, 1317, 1329, 1341, 1353, 1365, 1377, 1389, 1401, 1413, 1425, 1437, 1449, 1461, 1473, 1485, 1497, 1509, 1521, 1533, 1545, 1557, 1569, 1581, 1593, 1605, 1617, 1629, 1641, 1653, 1665, 1677, 1689, 1701, 1713, 1725, 1737, 1749, 1761, 1773, 1785, 1797, 1809, 1821, 1833, 1845, 1857, 1869, 1881, 1893, 1905, 1917, 1929, 1941, 1953, 1965, 1977, 1989, 2001, 2013, 2025, 2037, 2049, 2061, 2073, 2085, 2097, 2109, 2121, 2133, 2145, 2157, 2169, 2181, 2193, 2205, 2217, 2229, 2241, 2253, 2265, 2277, 2289, 2301, 2313, 2325, 2337, 2349, 2361, 2373, 2385, 2397, 2409, 2421, 2433, 2445, 2457, 2469, 2481, 2493, 2505, 2517, 2529, 2541, 2553, 2565, 2577, 2589, 2601, 2613, 2625, 2637, 2649, 2661, 2673, 2685, 2697, 2709, 2721, 2733, 2745, 2757, 2769, 2781, 2793, 2805, 2817, 2829, 2841, 2853, 2865, 2877, 2889, 2901, 2913, 2925, 2937, 2949, 2961, 2973, 2985, 2997, 3009, 3021, 3033, 3045, 3057, 3069, 3081, 3093, 3105, 3117, 3129, 3141, 3153, 3165, 3177, 3189, 3201, 3213, 3225, 3237, 3249, 3261, 3273, 3285, 3297, 3309, 3321, 3333, 3345, 3357, 3369, 3381, 3393, 3405, 3417, 3429, 3441] }, + { // Quality C + "make_model" : "Nikon Z f", + "dcraw_matrix" : [ 11607, -4491, -977, -4522, 12460, 2304, -458, 1519, 7616 ] // DNG v16.1 + }, + { // Quality B, 16Mp and 64Mp raw frames "make_model": "OLYMPUS E-M5MarkII", "dcraw_matrix": [ 9422,-3258,-711,-2655,10898,2015,-512,1354,5512 ], // DNG_v8.8 D65 From cffba6c3b065a3d537107875d98ab527484d014d Mon Sep 17 00:00:00 2001 From: xiota Date: Mon, 17 Jun 2024 02:15:19 +0000 Subject: [PATCH 14/39] Move add-extension panel to top of frame --- rtgui/preferences.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 97bfb92b6..54e0c6725 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -1552,9 +1552,9 @@ Gtk::Widget* Preferences::getFileBrowserPanel() frmnu->add (*menuGrid); - Gtk::Frame* fre = Gtk::manage(new Gtk::Frame(M("PREFERENCES_PARSEDEXT"))); Gtk::Box* vbre = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL)); + Gtk::Box* hb0 = Gtk::manage(new Gtk::Box()); Gtk::Label* elab = Gtk::manage (new Gtk::Label (M("PREFERENCES_PARSEDEXTADD") + ":", Gtk::ALIGN_START)); hb0->pack_start(*elab, Gtk::PACK_SHRINK, 4); @@ -1582,6 +1582,7 @@ Gtk::Widget* Preferences::getFileBrowserPanel() hb0->pack_end(*moveExtUp, Gtk::PACK_SHRINK, 4); hb0->pack_end(*delExt, Gtk::PACK_SHRINK, 4); hb0->pack_end(*addExt, Gtk::PACK_SHRINK, 4); + extensions = Gtk::manage(new Gtk::TreeView()); Gtk::ScrolledWindow* hscrollw = Gtk::manage(new Gtk::ScrolledWindow()); hscrollw->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); @@ -1591,8 +1592,9 @@ Gtk::Widget* Preferences::getFileBrowserPanel() extensions->append_column_editable("Enabled", extensionColumns.enabled); extensions->append_column("Extension", extensionColumns.ext); extensions->set_headers_visible(false); - vbre->pack_start(*hscrollw); + vbre->pack_start(*hb0, Gtk::PACK_SHRINK, 4); + vbre->pack_start(*hscrollw); fre->add(*vbre); @@ -2679,7 +2681,7 @@ void Preferences::addExtPressed() } } - Gtk::TreeRow row = * (extensionModel->append()); + Gtk::TreeRow row = * (extensionModel->prepend()); row[extensionColumns.enabled] = true; row[extensionColumns.ext] = extension->get_text(); From 6eb191c5e5e55044c357a0c27869c7bf2c744277 Mon Sep 17 00:00:00 2001 From: xiota Date: Mon, 17 Jun 2024 01:25:06 +0000 Subject: [PATCH 15/39] Disable addExt/delExt buttons based on context --- rtgui/preferences.cc | 81 +++++++++++++++++++++++++++++--------------- rtgui/preferences.h | 2 ++ 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 54e0c6725..94dc68e65 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -1566,8 +1566,10 @@ Gtk::Widget* Preferences::getFileBrowserPanel() delExt = Gtk::manage(new Gtk::Button()); moveExtUp = Gtk::manage(new Gtk::Button()); moveExtDown = Gtk::manage(new Gtk::Button()); - addExt->set_tooltip_text(M("PREFERENCES_PARSEDEXTADDHINT")); - delExt->set_tooltip_text(M("PREFERENCES_PARSEDEXTDELHINT")); + addExt->set_sensitive(false); + delExt->set_sensitive(false); + addExt->set_tooltip_markup(M("PREFERENCES_PARSEDEXTADDHINT")); + delExt->set_tooltip_markup(M("PREFERENCES_PARSEDEXTDELHINT")); moveExtUp->set_tooltip_text(M("PREFERENCES_PARSEDEXTUPHINT")); moveExtDown->set_tooltip_text(M("PREFERENCES_PARSEDEXTDOWNHINT")); Gtk::Image* addExtImg = Gtk::manage ( new RTImage ("add-small", Gtk::ICON_SIZE_BUTTON) ); @@ -1672,11 +1674,14 @@ Gtk::Widget* Preferences::getFileBrowserPanel() vbFileBrowser->pack_start (*hb6, Gtk::PACK_SHRINK, 4); + extensions->signal_cursor_changed().connect(sigc::mem_fun(*this, &Preferences::extensionsChanged)); + extension->signal_changed().connect(sigc::mem_fun(*this, &Preferences::extensionChanged)); + addExt->signal_clicked().connect(sigc::mem_fun(*this, &Preferences::addExtPressed)); delExt->signal_clicked().connect(sigc::mem_fun(*this, &Preferences::delExtPressed)); moveExtUp->signal_clicked().connect(sigc::mem_fun(*this, &Preferences::moveExtUpPressed)); moveExtDown->signal_clicked().connect(sigc::mem_fun(*this, &Preferences::moveExtDownPressed)); - extension->signal_activate().connect(sigc::mem_fun(*this, &Preferences::addExtPressed)); + clearThumbsBtn->signal_clicked().connect ( sigc::mem_fun (*this, &Preferences::clearThumbImagesPressed) ); if (moptions.saveParamsCache) { clearProfilesBtn->signal_clicked().connect(sigc::mem_fun(*this, &Preferences::clearProfilesPressed)); @@ -2670,9 +2675,50 @@ void Preferences::workflowUpdate() } } +void Preferences::extensionsChanged() +{ + const Glib::RefPtr selection = extensions->get_selection(); + if (!selection) { + delExt->set_sensitive(false); + return; + } + + const Gtk::TreeModel::iterator selected = selection->get_selected(); + if (!selected) { + delExt->set_sensitive(false); + return; + } + + bool delOkay = true; + for (auto const &x : moptions.knownExtensions) { + if (x == (*selected)[extensionColumns.ext]) { + delOkay = false; + break; + } + } + delExt->set_sensitive(delOkay); +} + +void Preferences::extensionChanged() +{ + if (extension->get_text()[0] == '\0') { + addExt->set_sensitive(false); + return; + } + + Gtk::TreeNodeChildren c = extensionModel->children(); + for (size_t i = 0; i < c.size(); i++) { + if (c[i][extensionColumns.ext] == extension->get_text()) { + addExt->set_sensitive(false); + return; + } + } + + addExt->set_sensitive(true); +} + void Preferences::addExtPressed() { - Gtk::TreeNodeChildren c = extensionModel->children(); for (size_t i = 0; i < c.size(); i++) { @@ -2685,33 +2731,14 @@ void Preferences::addExtPressed() row[extensionColumns.enabled] = true; row[extensionColumns.ext] = extension->get_text(); + + extension->set_text(""); + addExt->set_sensitive(false); } void Preferences::delExtPressed() { - const Glib::RefPtr selection = extensions->get_selection(); - - if (!selection) { - return; - } - - const Gtk::TreeModel::iterator selected = selection->get_selected(); - - if (!selected) { - return; - } - - bool delOkay = true; - for (auto const &x : moptions.knownExtensions) { - if (x == (*selected)[extensionColumns.ext]) { - delOkay = false; - break; - } - } - - if (delOkay) { - extensionModel->erase(selected); - } + extensionModel->erase(extensions->get_selection()->get_selected()); } void Preferences::moveExtUpPressed() diff --git a/rtgui/preferences.h b/rtgui/preferences.h index e01ec85c0..b98a8a306 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -323,6 +323,8 @@ public: void observer10Toggled (); void selectStartupDir (); + void extensionsChanged (); + void extensionChanged (); void addExtPressed (); void delExtPressed (); void moveExtUpPressed (); From 51277dc7d2521a306ae4314cc3e1dc0deedb315e Mon Sep 17 00:00:00 2001 From: Lawrence Lee <45837045+Lawrence37@users.noreply.github.com> Date: Sun, 23 Jun 2024 12:40:51 -0700 Subject: [PATCH 16/39] Move function into anonymous namespace --- rtengine/rawimagesource.cc | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 03823644b..63969a21c 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -420,6 +420,16 @@ void transLineD1x(const float* const red, const float* const green, const float* } } +bool checkRawDataDimensions(const array2D &rawData, const rtengine::RawImage &rawImage, int width, int height) +{ + const int colors = (rawImage.getSensorType() == rtengine::ST_BAYER || + rawImage.getSensorType() == rtengine::ST_FUJI_XTRANS || + rawImage.get_colors() == 1) + ? 1 + : 3; + return rawData.getHeight() == height && rawData.getWidth() == colors * width; +} + } @@ -742,16 +752,6 @@ void RawImageSource::getWBMults(const ColorTemp &ctemp, const RAWParams &raw, st autoGainComp = camInitialGain / initialGain; } -bool checkRawDataDimensions(const array2D &rawData, const RawImage &rawImage, int width, int height) -{ - const int colors = (rawImage.getSensorType() == rtengine::ST_BAYER || - rawImage.getSensorType() == rtengine::ST_FUJI_XTRANS || - rawImage.get_colors() == 1) - ? 1 - : 3; - return rawData.getHeight() == height && rawData.getWidth() == colors * width; -} - void RawImageSource::getImage(const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw) { assert(checkRawDataDimensions(rawData, *ri, W, H)); From 082207eb6033c0c413b5f654998aab66d3d03b38 Mon Sep 17 00:00:00 2001 From: Richard E Barber Date: Tue, 25 Jun 2024 17:21:18 -0700 Subject: [PATCH 17/39] macOS CI: update libomp library to current --- .github/workflows/macos.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 3a0f27483..60bee53aa 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -25,7 +25,7 @@ jobs: mkdir build date +%s > build/stamp brew uninstall --ignore-dependencies libtiff - brew install libtiff gtk+3 gtkmm3 gtk-mac-integration adwaita-icon-theme libsigc++@2 little-cms2 libiptcdata fftw lensfun expat pkgconfig llvm shared-mime-info exiv2 jpeg-xl | tee -a depslog + brew install libtiff gtk+3 gtkmm3 gtk-mac-integration adwaita-icon-theme libsigc++@2 little-cms2 libiptcdata fftw lensfun expat pkgconfig llvm shared-mime-info exiv2 jpeg-xl libomp | tee -a depslog date -u echo "----====Pourage====----" cat depslog | grep Pouring @@ -69,7 +69,6 @@ jobs: -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \ -DOSX_CONTINUOUS=ON \ .. - curl -L https://github.com/Homebrew/homebrew-core/raw/679923b4eb48a8dc7ecc1f05d06063cd79b3fc00/Formula/libomp.rb -o libomp.rb && brew install --formula libomp.rb zsh -c 'echo "Configured in $(printf "%0.2f" $(($[$(date +%s)-$(cat configstamp)]/$((60.))))) minutes"' - name: Compile RawTherapee run: | From 5a8f048e8aa94ad8c0b537347f92ad3147027bab Mon Sep 17 00:00:00 2001 From: Richard E Barber Date: Tue, 25 Jun 2024 17:25:53 -0700 Subject: [PATCH 18/39] mac: bundle libjxl_cms --- tools/osx/macosx_bundle.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/osx/macosx_bundle.sh b/tools/osx/macosx_bundle.sh index bd0dcf3e1..83689d45b 100644 --- a/tools/osx/macosx_bundle.sh +++ b/tools/osx/macosx_bundle.sh @@ -220,6 +220,9 @@ ModifyInstallNames 2>&1 # Copy libpng16 to the app bundle cp ${LOCAL_PREFIX}/lib/libpng16.16.dylib "${CONTENTS}/Frameworks/libpng16.16.dylib" +# Copy libjxl_cms to the app bundle +cp ${LOCAL_PREFIX}/lib/libjxl_cms.0.10.dylib "${CONTENTS}/Frameworks/libjxl_cms.0.10.dylib" + # Copy graphite to Frameworks cp ${LOCAL_PREFIX}/lib/libgraphite2.3.dylib "${CONTENTS}/Frameworks" From 893c4a153e56e251b614bab67b6dbe966772d106 Mon Sep 17 00:00:00 2001 From: Richard E Barber Date: Tue, 25 Jun 2024 18:00:40 -0700 Subject: [PATCH 19/39] macOS CI: point to new location of libomp --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 60bee53aa..1188ae017 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -63,7 +63,7 @@ jobs: -DOpenMP_CXX_FLAGS="${C_FLAGS}" \ -DOpenMP_C_LIB_NAMES=libomp \ -DOpenMP_CXX_LIB_NAMES=libomp \ - -DOpenMP_libomp_LIBRARY=/usr/local/lib/libomp.dylib \ + -DOpenMP_libomp_LIBRARY=/usr/local/opt/libomp/lib/libomp.dylib \ -DCMAKE_AR=/usr/bin/ar \ -DCMAKE_RANLIB=/usr/bin/ranlib \ -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \ From df607d5e0418b769d43b0952c68b96ecdcdddbe5 Mon Sep 17 00:00:00 2001 From: Richard E Barber Date: Tue, 25 Jun 2024 18:07:07 -0700 Subject: [PATCH 20/39] macOS CI: point linker to opt/libomp --- .github/workflows/macos.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 1188ae017..307236fcf 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -35,7 +35,7 @@ jobs: CMAKE_CXX_STANDARD: 11 PKG_CONFIG_PATH: /usr/local/opt/libtiff/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig:/usr/local/opt/expat/lib/pkgconfig RAW_THERAPEE_MAJOR: '5' - RAW_THERAPEE_MINOR: '8' + RAW_THERAPEE_MINOR: '10' C_FLAGS: > -arch x86_64 -mtune=generic -Xpreprocessor -fopenmp /usr/local/lib/libomp.dylib -I/usr/local/include -I/usr/local/opt/gdk-pixbuf/include -I/usr/local/opt/libiconv/include -I/usr/local/opt/libxml2/include -I/usr/local/opt/expat/include -I/usr/local/opt/libtiff/include run: | @@ -48,7 +48,7 @@ jobs: cmake \ -DCMAKE_BUILD_TYPE="Release" \ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ - -DCMAKE_EXE_LINKER_FLAGS="-L. -L/usr/local/lib -Wl,-rpath -Wl,/usr/local/lib -L/usr/local/opt/gdk-pixbuf/lib -L/usr/local/opt/libiconv/lib -L/usr/local/opt/libffi/lib -L/usr/local/opt/libffi/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/expat/lib" \ + -DCMAKE_EXE_LINKER_FLAGS="-L. -L/usr/local/lib -Wl,-rpath -Wl,/usr/local/lib -L/usr/local/opt/gdk-pixbuf/lib -L/usr/local/opt/libiconv/lib -L/usr/local/opt/libomp/lib -L/usr/local/opt/libffi/lib -L/usr/local/opt/libffi/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/expat/lib" \ -DCACHE_NAME_SUFFIX="${RAW_THERAPEE_MAJOR}.${RAW_THERAPEE_MINOR}-${REF}" \ -DPROC_TARGET_NUMBER="1" \ -DPROC_LABEL="generic processor" \ From 688f9696286c4e4a7c72deb64d6bda4c7af60e6f Mon Sep 17 00:00:00 2001 From: Richard E Barber Date: Tue, 25 Jun 2024 18:11:34 -0700 Subject: [PATCH 21/39] macOS CI: also point cflags to opt/libomp --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 307236fcf..ef27c6dcb 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -37,7 +37,7 @@ jobs: RAW_THERAPEE_MAJOR: '5' RAW_THERAPEE_MINOR: '10' C_FLAGS: > - -arch x86_64 -mtune=generic -Xpreprocessor -fopenmp /usr/local/lib/libomp.dylib -I/usr/local/include -I/usr/local/opt/gdk-pixbuf/include -I/usr/local/opt/libiconv/include -I/usr/local/opt/libxml2/include -I/usr/local/opt/expat/include -I/usr/local/opt/libtiff/include + -arch x86_64 -mtune=generic -Xpreprocessor -fopenmp /usr/local/opt/libomp/lib/libomp.dylib -I/usr/local/include -I/usr/local/opt/gdk-pixbuf/include -I/usr/local/opt/libiconv/include -I/usr/local/opt/libxml2/include -I/usr/local/opt/expat/include -I/usr/local/opt/libtiff/include run: | # GITHUB_REF is the ref that triggered the build, like # refs/heads/new-feature - the next line parses that to REF: the branch From 1235cb202008630a41677ccaea0bb9f941e2b993 Mon Sep 17 00:00:00 2001 From: Richard E Barber Date: Tue, 25 Jun 2024 18:16:04 -0700 Subject: [PATCH 22/39] macOS CI: add include to cflags --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index ef27c6dcb..fd2928a58 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -37,7 +37,7 @@ jobs: RAW_THERAPEE_MAJOR: '5' RAW_THERAPEE_MINOR: '10' C_FLAGS: > - -arch x86_64 -mtune=generic -Xpreprocessor -fopenmp /usr/local/opt/libomp/lib/libomp.dylib -I/usr/local/include -I/usr/local/opt/gdk-pixbuf/include -I/usr/local/opt/libiconv/include -I/usr/local/opt/libxml2/include -I/usr/local/opt/expat/include -I/usr/local/opt/libtiff/include + -arch x86_64 -mtune=generic -Xpreprocessor -fopenmp /usr/local/opt/libomp/lib/libomp.dylib -I/usr/local/opt/libomp/include -I/usr/local/include -I/usr/local/opt/gdk-pixbuf/include -I/usr/local/opt/libiconv/include -I/usr/local/opt/libxml2/include -I/usr/local/opt/expat/include -I/usr/local/opt/libtiff/include run: | # GITHUB_REF is the ref that triggered the build, like # refs/heads/new-feature - the next line parses that to REF: the branch From b673154531bd3582f25cdb2fb5fd3b468f8d5324 Mon Sep 17 00:00:00 2001 From: Daniel Martinez Date: Tue, 17 May 2022 23:03:55 -0400 Subject: [PATCH 23/39] Support more ARQ files, 4 and 16 Shot ARQ from ILCE-1 --- rtengine/dcraw.cc | 7 ++++--- rtengine/pixelshift.cc | 36 ++++++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 3358dc91b..7131eabf4 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -6590,9 +6590,10 @@ int CLASS parse_tiff_ifd (int base) break; case 258: /* BitsPerSample */ case 61443: - tiff_ifd[ifd].samples = len & 7; + if(!tiff_ifd[ifd].samples || tag != 258) + tiff_ifd[ifd].samples = len & 7; if ((tiff_ifd[ifd].bps = getint(type)) > 32) - tiff_ifd[ifd].bps = 8; + tiff_ifd[ifd].bps = 8; if (tiff_bps < tiff_ifd[ifd].bps) tiff_bps = tiff_ifd[ifd].bps; break; @@ -7288,7 +7289,7 @@ void CLASS apply_tiff() load_raw = &CLASS olympus_load_raw; // ------- RT ------- if (!strncmp(make,"SONY",4) && - (!strncmp(model,"ILCE-7RM3",9) || !strncmp(model,"ILCE-7RM4",9)) && + (!strncmp(model,"ILCE-7RM3",9) || !strncmp(model,"ILCE-7RM4",9) || !strncmp(model,"ILCE-1",6)) && tiff_samples == 4 && tiff_ifd[raw].bytes == raw_width*raw_height*tiff_samples*2) { load_raw = &CLASS sony_arq_load_raw; diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc index 8088e2e9c..2df07f074 100644 --- a/rtengine/pixelshift.cc +++ b/rtengine/pixelshift.cc @@ -592,6 +592,7 @@ BENCHFUN static const float ePerIsoILCE7RM3 = 0.8f; + //TODO: Add data for ILCE-7RM4, and ILCE-1 if(plistener) { plistener->setProgressStr(Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), M("TP_RAW_PIXELSHIFT"))); plistener->setProgress(0.0); @@ -610,18 +611,29 @@ BENCHFUN int nReadIndex = static_cast(round(log2(idata->getISOSpeed() / 100.f) * 3.f)); - if(model.find("K-3") != string::npos) { - nRead = nReadK3II[nReadIndex]; - eperIsoModel = ePerIsoK3II; - } else if(model.find("K-1") != string::npos) { // this also matches K-1 Mark II - nRead = nReadK1[nReadIndex]; - eperIsoModel = ePerIsoK1; - } else if(model.find("ILCE-7RM3") != string::npos) { - nRead = nReadILCE7RM3[nReadIndex]; - eperIsoModel = ePerIsoILCE7RM3; - } else { // as long as we don't have values for Pentax KP, we use the values from K-70 - nRead = nReadK70[nReadIndex]; - eperIsoModel = ePerIsoK70; + if(make.find("Sony") != string::npos) { + if(model.find("ILCE-7RM3") != string::npos) { + nRead = nReadILCE7RM3[nReadIndex]; + eperIsoModel = ePerIsoILCE7RM3; + /* TODO: When we have data for missing ILCE-7RM4, and ILCE-1, add it here + } else if(model.find("ILCE-7RM4") != string::npos) { + } else if(model.find("ILCE-1") != string::npos) { + */ + } else { // default to ILCE-7RM3 for Sony cameras without data + nRead = nReadILCE7RM3[nReadIndex]; + eperIsoModel = ePerIsoILCE7RM3; + } + } else { // Pentax + if(model.find("K-3") != string::npos) { + nRead = nReadK3II[nReadIndex]; + eperIsoModel = ePerIsoK3II; + } else if(model.find("K-1") != string::npos) { // this also matches K-1 Mark II + nRead = nReadK1[nReadIndex]; + eperIsoModel = ePerIsoK1; + } else { // as long as we don't have values for Pentax KP, we use the values from K-70 + nRead = nReadK70[nReadIndex]; + eperIsoModel = ePerIsoK70; + } } eperIsoModel *= pow(2.f, eperIso - 1.f); From 88160bd8b858256260253546b5b014f7b9991259 Mon Sep 17 00:00:00 2001 From: xiota Date: Sun, 30 Jun 2024 02:53:49 +0000 Subject: [PATCH 24/39] Update PREFERENCES_PARSEDEXTDELHINT (default/English) --- rtdata/languages/English (UK) | 2 +- rtdata/languages/English (US) | 2 +- rtdata/languages/default | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index 37ccdc48f..5d22fa61f 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -2154,7 +2154,7 @@ TP_WBALANCE_PATCHLABEL_TOOLTIP;Display number of read colours (max=237).\nDispla !PREFERENCES_PARSEDEXT;Parsed Extensions !PREFERENCES_PARSEDEXTADD;Add extension !PREFERENCES_PARSEDEXTADDHINT;Add entered extension to the list. -!PREFERENCES_PARSEDEXTDELHINT;Delete selected extension from the list. +!PREFERENCES_PARSEDEXTDELHINT;Delete selected extension from the list.\nPredefined extensions cannot be deleted. !PREFERENCES_PARSEDEXTDOWNHINT;Move selected extension down in the list. !PREFERENCES_PARSEDEXTUPHINT;Move selected extension up in the list. !PREFERENCES_PERFORMANCE_MEASURE;Measure diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index 079713ac1..4cd01622a 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -1971,7 +1971,7 @@ !PREFERENCES_PARSEDEXT;Parsed Extensions !PREFERENCES_PARSEDEXTADD;Add extension !PREFERENCES_PARSEDEXTADDHINT;Add entered extension to the list. -!PREFERENCES_PARSEDEXTDELHINT;Delete selected extension from the list. +!PREFERENCES_PARSEDEXTDELHINT;Delete selected extension from the list.\nPredefined extensions cannot be deleted. !PREFERENCES_PARSEDEXTDOWNHINT;Move selected extension down in the list. !PREFERENCES_PARSEDEXTUPHINT;Move selected extension up in the list. !PREFERENCES_PERFORMANCE_MEASURE;Measure diff --git a/rtdata/languages/default b/rtdata/languages/default index 75d060dec..7a4c8aea7 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -2038,7 +2038,7 @@ PREFERENCES_PANFACTORLABEL;Pan rate amplification PREFERENCES_PARSEDEXT;Parsed Extensions PREFERENCES_PARSEDEXTADD;Add extension PREFERENCES_PARSEDEXTADDHINT;Add entered extension to the list. -PREFERENCES_PARSEDEXTDELHINT;Delete selected extension from the list. +PREFERENCES_PARSEDEXTDELHINT;Delete selected extension from the list.\nPredefined extensions cannot be deleted. PREFERENCES_PARSEDEXTDOWNHINT;Move selected extension down in the list. PREFERENCES_PARSEDEXTUPHINT;Move selected extension up in the list. PREFERENCES_PERFORMANCE_MEASURE;Measure From 7168870d695d887e65c4bf595843d1170b542ea7 Mon Sep 17 00:00:00 2001 From: xiota Date: Sun, 30 Jun 2024 02:55:30 +0000 Subject: [PATCH 25/39] Improve empty string check --- rtgui/preferences.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 94dc68e65..f6f80a2d3 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -2701,7 +2701,7 @@ void Preferences::extensionsChanged() void Preferences::extensionChanged() { - if (extension->get_text()[0] == '\0') { + if (extension->get_text().empty()) { addExt->set_sensitive(false); return; } From 819b65af7fc0b6b62d598681b8a5b47103d73068 Mon Sep 17 00:00:00 2001 From: Desmis Date: Sun, 30 Jun 2024 07:47:55 +0200 Subject: [PATCH 26/39] Keep values scope from 5.10 Selective Editing - for color & light - shadow/highlight - vibrance #7102 (#7107) * ppversion 351 and keep valus scope for color and light shadow-highligt vibrance * Change comment in ppversion.h * Change procparams for colorscope pp<351 * Remove not used isset --- rtengine/improccoordinator.cc | 16 ++++++++++------ rtengine/procparams.cc | 29 ++++++++++++++++++++++++++--- rtgui/ppversion.h | 4 +++- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 46dd7bc29..127c65248 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -1170,9 +1170,11 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) if (params->locallab.spots.at(sp).equilret && params->locallab.spots.at(sp).expreti) { savenormreti.reset(new LabImage(*oprevl, true)); } - if(params->locallab.spots.at(sp).colorscope != 30) {//compatibility with old method in controlspotpanel to change scope - default value 30 - scopefp[sp]= params->locallab.spots.at(sp).colorscope; - } + + // if(params->locallab.spots.at(sp).colorscope != 30) {//compatibility with old method in controlspotpanel to change scope - default value 30 + // scopefp[sp]= params->locallab.spots.at(sp).colorscope; + // } + // Set local curves of current spot to LUT locRETgainCurve.Set(params->locallab.spots.at(sp).localTgaincurve); locRETtransCurve.Set(params->locallab.spots.at(sp).localTtranscurve); @@ -1587,7 +1589,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) bool islog = params->locallab.spots.at(sp).explog; bool ismas = params->locallab.spots.at(sp).expmask; bool iscie = params->locallab.spots.at(sp).expcie; - bool isset = iscolor || issh || isvib; + // bool isset = iscolor || issh || isvib; //set select spot settings LocallabListener::locallabsetLC locsetlc; @@ -1615,13 +1617,15 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) locallListener->cieChanged(locallcielc,params->locallab.selspot); } locallListener->sigChanged(locallciesig,params->locallab.selspot); - if(params->locallab.spots.at(sp).colorscope != 30) {//compatibility with old method in controlspotpanel + /* + if(params->locallab.spots.at(sp).colorscope != 0) {//compatibility with old method in controlspotpanel locallListener->scopeChangedcol(scopefp[sp], params->locallab.selspot, iscolor); locallListener->scopeChangedsh(scopefp[sp], params->locallab.selspot, issh); locallListener->scopeChangedvib(scopefp[sp], params->locallab.selspot, isvib); locallListener->scopeChangedset(scopefp[sp], params->locallab.selspot, isset); - params->locallab.spots.at(sp).colorscope = 30; + //params->locallab.spots.at(sp).colorscope = 30; } + */ // if (mainfp[sp] >= 0) {//minimize call to idle register //used by Global fullimage. locallListener->maiChanged(locallsetlc,params->locallab.selspot); diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 1ba92c366..d5cad43c9 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -9144,7 +9144,16 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "labgridAHighmerg_" + index_str, spot.labgridAHighmerg, spotEdited.labgridAHighmerg); assignFromKeyfile(keyFile, "Locallab", "labgridBHighmerg_" + index_str, spot.labgridBHighmerg, spotEdited.labgridBHighmerg); assignFromKeyfile(keyFile, "Locallab", "Strengthgrid_" + index_str, spot.strengthgrid, spotEdited.strengthgrid); - assignFromKeyfile(keyFile, "Locallab", "Sensi_" + index_str, spot.sensi, spotEdited.sensi); + assignFromKeyfile(keyFile, "Locallab", "Colorscope_" + index_str, spot.colorscope, spotEdited.colorscope); + + if (ppVersion <= 350) { + if (keyFile.has_key("Locallab", "Colorscope_" + index_str)) { + spot.sensi = keyFile.get_integer("Locallab", "Colorscope_" + index_str); + spotEdited.sensi = true; + } + } else { + assignFromKeyfile(keyFile, "Locallab", "Sensi_" + index_str, spot.sensi, spotEdited.sensi); + } assignFromKeyfile(keyFile, "Locallab", "Structcol_" + index_str, spot.structcol, spotEdited.structcol); assignFromKeyfile(keyFile, "Locallab", "Strcol_" + index_str, spot.strcol, spotEdited.strcol); assignFromKeyfile(keyFile, "Locallab", "Strcolab_" + index_str, spot.strcolab, spotEdited.strcolab); @@ -9282,7 +9291,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "shadows_" + index_str, spot.shadows, spotEdited.shadows); assignFromKeyfile(keyFile, "Locallab", "s_tonalwidth_" + index_str, spot.s_tonalwidth, spotEdited.s_tonalwidth); assignFromKeyfile(keyFile, "Locallab", "sh_radius_" + index_str, spot.sh_radius, spotEdited.sh_radius); - assignFromKeyfile(keyFile, "Locallab", "sensihs_" + index_str, spot.sensihs, spotEdited.sensihs); + if (ppVersion <= 350) { + if (keyFile.has_key("Locallab", "Colorscope_" + index_str)) { + spot.sensihs = keyFile.get_integer("Locallab", "Colorscope_" + index_str); + spotEdited.sensihs = true; + } + } else { + assignFromKeyfile(keyFile, "Locallab", "sensihs_" + index_str, spot.sensihs, spotEdited.sensihs); + } assignFromKeyfile(keyFile, "Locallab", "EnaSHMask_" + index_str, spot.enaSHMask, spotEdited.enaSHMask); assignFromKeyfile(keyFile, "Locallab", "CCmaskSHCurve_" + index_str, spot.CCmaskSHcurve, spotEdited.CCmaskSHcurve); assignFromKeyfile(keyFile, "Locallab", "LLmaskSHCurve_" + index_str, spot.LLmaskSHcurve, spotEdited.LLmaskSHcurve); @@ -9336,7 +9352,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "ProtectSkins_" + index_str, spot.protectskins, spotEdited.protectskins); assignFromKeyfile(keyFile, "Locallab", "AvoidColorShift_" + index_str, spot.avoidcolorshift, spotEdited.avoidcolorshift); assignFromKeyfile(keyFile, "Locallab", "PastSatTog_" + index_str, spot.pastsattog, spotEdited.pastsattog); - assignFromKeyfile(keyFile, "Locallab", "Sensiv_" + index_str, spot.sensiv, spotEdited.sensiv); + if (ppVersion <= 350) { + if (keyFile.has_key("Locallab", "Colorscope_" + index_str)) { + spot.sensiv = keyFile.get_integer("Locallab", "Colorscope_" + index_str); + spotEdited.sensiv = true; + } + } else { + assignFromKeyfile(keyFile, "Locallab", "Sensiv_" + index_str, spot.sensiv, spotEdited.sensiv); + } assignFromKeyfile(keyFile, "Locallab", "SkinTonesCurve_" + index_str, spot.skintonescurve, spotEdited.skintonescurve); assignFromKeyfile(keyFile, "Locallab", "CCmaskvibCurve_" + index_str, spot.CCmaskvibcurve, spotEdited.CCmaskvibcurve); assignFromKeyfile(keyFile, "Locallab", "LLmaskvibCurve_" + index_str, spot.LLmaskvibcurve, spotEdited.LLmaskvibcurve); diff --git a/rtgui/ppversion.h b/rtgui/ppversion.h index f2455699c..6b7909edf 100644 --- a/rtgui/ppversion.h +++ b/rtgui/ppversion.h @@ -1,11 +1,13 @@ #pragma once // This number has to be incremented whenever the PP3 file format is modified or the behaviour of a tool changes -#define PPVERSION 350 +#define PPVERSION 351 #define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified /* Log of version changes + 351 2024-06-19 + take into account Global in selective editing 350 2023-03-05 introduced white balance standard observer 349 2020-10-29 From 89c90774af8df5cc1f37fc556a286b2603b9318e Mon Sep 17 00:00:00 2001 From: Desmis Date: Mon, 1 Jul 2024 09:35:33 +0200 Subject: [PATCH 27/39] Selective Editing - compatibility 5.10 - Feather - Log encoding (#7120) * Fixed pp3 from 5.10 feather and ciecam log encoding * Fixed 2 wrong typo feather in procparams.cc * Fixed 2 wrong typo feather in procparams.cc * Remove unused line in procparams --- rtengine/procparams.cc | 86 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 9 deletions(-) diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index d5cad43c9..b868a7627 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -9159,7 +9159,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Strcolab_" + index_str, spot.strcolab, spotEdited.strcolab); assignFromKeyfile(keyFile, "Locallab", "Strcolh_" + index_str, spot.strcolh, spotEdited.strcolh); assignFromKeyfile(keyFile, "Locallab", "Angcol_" + index_str, spot.angcol, spotEdited.angcol); - assignFromKeyfile(keyFile, "Locallab", "Fetahercol_" + index_str, spot.feathercol, spotEdited.feathercol); + if (ppVersion <= 350) { + if (keyFile.has_key("Locallab", "Feather_" + index_str)) { + spot.feathercol = keyFile.get_integer("Locallab", "Feather_" + index_str); + spotEdited.feathercol = true; + } + } else { + assignFromKeyfile(keyFile, "Locallab", "Feathercol_" + index_str, spot.feathercol, spotEdited.feathercol); + } assignFromKeyfile(keyFile, "Locallab", "Blurcolde_" + index_str, spot.blurcolde, spotEdited.blurcolde); assignFromKeyfile(keyFile, "Locallab", "Blurcol_" + index_str, spot.blurcol, spotEdited.blurcol); assignFromKeyfile(keyFile, "Locallab", "Contcol_" + index_str, spot.contcol, spotEdited.contcol); @@ -9236,7 +9243,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Gamex_" + index_str, spot.gamex, spotEdited.gamex); assignFromKeyfile(keyFile, "Locallab", "Strexp_" + index_str, spot.strexp, spotEdited.strexp); assignFromKeyfile(keyFile, "Locallab", "Angexp_" + index_str, spot.angexp, spotEdited.angexp); - assignFromKeyfile(keyFile, "Locallab", "Featherexp_" + index_str, spot.featherexp, spotEdited.featherexp); + if (ppVersion <= 350) { + if (keyFile.has_key("Locallab", "Feather_" + index_str)) { + spot.featherexp = keyFile.get_integer("Locallab", "Feather_" + index_str); + spotEdited.featherexp = true; + } + } else { + assignFromKeyfile(keyFile, "Locallab", "Featherexp_" + index_str, spot.featherexp, spotEdited.featherexp); + } assignFromKeyfile(keyFile, "Locallab", "ExCurve_" + index_str, spot.excurve, spotEdited.excurve); assignFromKeyfile(keyFile, "Locallab", "Norm_" + index_str, spot.norm, spotEdited.norm); assignFromKeyfile(keyFile, "Locallab", "Inversex_" + index_str, spot.inversex, spotEdited.inversex); @@ -9308,7 +9322,15 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "BlurSHde_" + index_str, spot.blurSHde, spotEdited.blurSHde); assignFromKeyfile(keyFile, "Locallab", "StrSH_" + index_str, spot.strSH, spotEdited.strSH); assignFromKeyfile(keyFile, "Locallab", "AngSH_" + index_str, spot.angSH, spotEdited.angSH); - assignFromKeyfile(keyFile, "Locallab", "FeatherSH_" + index_str, spot.featherSH, spotEdited.featherSH); + if (ppVersion <= 350) { + if (keyFile.has_key("Locallab", "Feather_" + index_str)) { + spot.featherSH = keyFile.get_integer("Locallab", "Feather_" + index_str); + spotEdited.featherSH = true; + } + } else { + assignFromKeyfile(keyFile, "Locallab", "FeatherSH_" + index_str, spot.featherSH, spotEdited.featherSH); + } + assignFromKeyfile(keyFile, "Locallab", "Inverssh_" + index_str, spot.inverssh, spotEdited.inverssh); assignFromKeyfile(keyFile, "Locallab", "ChromaskSH_" + index_str, spot.chromaskSH, spotEdited.chromaskSH); assignFromKeyfile(keyFile, "Locallab", "GammaskSH_" + index_str, spot.gammaskSH, spotEdited.gammaskSH); @@ -9375,7 +9397,15 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Strvibab_" + index_str, spot.strvibab, spotEdited.strvibab); assignFromKeyfile(keyFile, "Locallab", "Strvibh_" + index_str, spot.strvibh, spotEdited.strvibh); assignFromKeyfile(keyFile, "Locallab", "Angvib_" + index_str, spot.angvib, spotEdited.angvib); - assignFromKeyfile(keyFile, "Locallab", "Feathervib_" + index_str, spot.feathervib, spotEdited.feathervib); + if (ppVersion <= 350) { + if (keyFile.has_key("Locallab", "Feather_" + index_str)) { + spot.feathervib = keyFile.get_integer("Locallab", "Feather_" + index_str); + spotEdited.feathervib = true; + } + } else { + assignFromKeyfile(keyFile, "Locallab", "Feathervib_" + index_str, spot.feathervib, spotEdited.feathervib); + } + assignFromKeyfile(keyFile, "Locallab", "LmaskvibCurve_" + index_str, spot.Lmaskvibcurve, spotEdited.Lmaskvibcurve); assignFromKeyfile(keyFile, "Locallab", "Recothresv_" + index_str, spot.recothresv, spotEdited.recothresv); assignFromKeyfile(keyFile, "Locallab", "Lowthresv_" + index_str, spot.lowthresv, spotEdited.lowthresv); @@ -9625,7 +9655,15 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Sigmalc2_" + index_str, spot.sigmalc2, spotEdited.sigmalc2); assignFromKeyfile(keyFile, "Locallab", "Strwav_" + index_str, spot.strwav, spotEdited.strwav); assignFromKeyfile(keyFile, "Locallab", "Angwav_" + index_str, spot.angwav, spotEdited.angwav); - assignFromKeyfile(keyFile, "Locallab", "Featherwav_" + index_str, spot.featherwav, spotEdited.featherwav); + if (ppVersion <= 350) { + if (keyFile.has_key("Locallab", "Feather_" + index_str)) { + spot.featherwav = keyFile.get_integer("Locallab", "Feather_" + index_str); + spotEdited.featherwav = true; + } + } else { + assignFromKeyfile(keyFile, "Locallab", "Featherwav_" + index_str, spot.featherwav, spotEdited.featherwav); + } + assignFromKeyfile(keyFile, "Locallab", "Strengthw_" + index_str, spot.strengthw, spotEdited.strengthw); assignFromKeyfile(keyFile, "Locallab", "Sigmaed_" + index_str, spot.sigmaed, spotEdited.sigmaed); assignFromKeyfile(keyFile, "Locallab", "Radiusw_" + index_str, spot.radiusw, spotEdited.radiusw); @@ -9740,7 +9778,15 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "AutoGray_" + index_str, spot.Autogray, spotEdited.Autogray); assignFromKeyfile(keyFile, "Locallab", "Fullimage_" + index_str, spot.fullimage, spotEdited.fullimage); assignFromKeyfile(keyFile, "Locallab", "Repart_" + index_str, spot.repar, spotEdited.repar); - assignFromKeyfile(keyFile, "Locallab", "Ciecam_" + index_str, spot.ciecam, spotEdited.ciecam); + if (ppVersion <= 350) {//issue 7114 + if (keyFile.has_key("Locallab", "Ciecam_" + index_str)) { + spot.ciecam = true; + spotEdited.ciecam = true; + } + } else { + assignFromKeyfile(keyFile, "Locallab", "Ciecam_" + index_str, spot.ciecam, spotEdited.ciecam); + } + assignFromKeyfile(keyFile, "Locallab", "Satlog_" + index_str, spot.satlog, spotEdited.satlog); assignFromKeyfile(keyFile, "Locallab", "BlackEv_" + index_str, spot.blackEv, spotEdited.blackEv); assignFromKeyfile(keyFile, "Locallab", "WhiteEv_" + index_str, spot.whiteEv, spotEdited.whiteEv); @@ -9755,7 +9801,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Surround_" + index_str, spot.surround, spotEdited.surround); assignFromKeyfile(keyFile, "Locallab", "Strlog_" + index_str, spot.strlog, spotEdited.strlog); assignFromKeyfile(keyFile, "Locallab", "Anglog_" + index_str, spot.anglog, spotEdited.anglog); - assignFromKeyfile(keyFile, "Locallab", "Featherlog_" + index_str, spot.featherlog, spotEdited.featherlog); + if (ppVersion <= 350) { + if (keyFile.has_key("Locallab", "Feather_" + index_str)) { + spot.featherlog = keyFile.get_integer("Locallab", "Feather_" + index_str); + spotEdited.featherlog = true; + } + } else { + assignFromKeyfile(keyFile, "Locallab", "Featherlog_" + index_str, spot.featherlog, spotEdited.featherlog); + } assignFromKeyfile(keyFile, "Locallab", "CCmaskCurveL_" + index_str, spot.CCmaskcurveL, spotEdited.CCmaskcurveL); assignFromKeyfile(keyFile, "Locallab", "LLmaskCurveL_" + index_str, spot.LLmaskcurveL, spotEdited.LLmaskcurveL); assignFromKeyfile(keyFile, "Locallab", "HHmaskCurveL_" + index_str, spot.HHmaskcurveL, spotEdited.HHmaskcurveL); @@ -9793,7 +9846,15 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Shadmask_" + index_str, spot.shadmask, spotEdited.shadmask); assignFromKeyfile(keyFile, "Locallab", "Str_mask_" + index_str, spot.str_mask, spotEdited.str_mask); assignFromKeyfile(keyFile, "Locallab", "Ang_mask_" + index_str, spot.ang_mask, spotEdited.ang_mask); - assignFromKeyfile(keyFile, "Locallab", "Feather_mask_" + index_str, spot.feather_mask, spotEdited.feather_mask); + if (ppVersion <= 350) { + if (keyFile.has_key("Locallab", "Feather_" + index_str)) { + spot.feather_mask = keyFile.get_integer("Locallab", "Feather_" + index_str); + spotEdited.feather_mask = true; + } + } else { + assignFromKeyfile(keyFile, "Locallab", "Feather_mask_" + index_str, spot.feather_mask, spotEdited.feather_mask); + } + assignFromKeyfile(keyFile, "Locallab", "HHhmask_Curve_" + index_str, spot.HHhmask_curve, spotEdited.HHhmask_curve); assignFromKeyfile(keyFile, "Locallab", "Lmask_Curve_" + index_str, spot.Lmask_curve, spotEdited.Lmask_curve); assignFromKeyfile(keyFile, "Locallab", "LLmask_Curvewav_" + index_str, spot.LLmask_curvewav, spotEdited.LLmask_curvewav); @@ -9956,7 +10017,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Surroundcie_" + index_str, spot.surroundcie, spotEdited.surroundcie); assignFromKeyfile(keyFile, "Locallab", "Strgradcie_" + index_str, spot.strgradcie, spotEdited.strgradcie); assignFromKeyfile(keyFile, "Locallab", "Anggradcie_" + index_str, spot.anggradcie, spotEdited.anggradcie); - assignFromKeyfile(keyFile, "Locallab", "Feathercie_" + index_str, spot.feathercie, spotEdited.feathercie); + if (ppVersion <= 350) { + if (keyFile.has_key("Locallab", "Feather_" + index_str)) { + spot.feathercie = keyFile.get_integer("Locallab", "Feather_" + index_str); + spotEdited.feathercie = true; + } + } else { + assignFromKeyfile(keyFile, "Locallab", "Feathercie_" + index_str, spot.feathercie, spotEdited.feathercie); + } assignFromKeyfile(keyFile, "Locallab", "EnacieMask_" + index_str, spot.enacieMask, spotEdited.enacieMask); assignFromKeyfile(keyFile, "Locallab", "EnacieMaskall_" + index_str, spot.enacieMaskall, spotEdited.enacieMaskall); From 363f3cc2a65fa5c3d96ed519247eb073b9f9cd20 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Sat, 15 Jun 2024 09:04:22 +0200 Subject: [PATCH 28/39] iptransform: correct profile based distortion/CA before rotation Like perspective correction also rotation correction should be applied after distortion/CA correction. --- rtengine/iptransform.cc | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 3d384ee62..d62a87199 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -515,14 +515,14 @@ bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, break; } - if (pLCPMap && params->lensProf.useDist) { - pLCPMap->correctDistortion(x_d, y_d, w2, h2); - } - // rotate double Dx = x_d * cost - y_d * sint; double Dy = x_d * sint + y_d * cost; + if (pLCPMap && params->lensProf.useDist) { + pLCPMap->correctDistortion(Dx, Dy, w2, h2); + } + // distortion correction double s = 1; @@ -700,7 +700,7 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, } } transformGeneral(highQuality, original, dest, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap.get(), useOriginalBuffer); - + if (highQuality && dest != transformed) { transformLCPCAOnly(dest, transformed, cx, cy, pLCPMap.get(), useOriginalBuffer); } @@ -1240,25 +1240,25 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I break; } - if (enableLCPDist) { - pLCPMap->correctDistortion(x_d, y_d, w2, h2); - } - // rotate - const double Dxc = x_d * cost - y_d * sint; - const double Dyc = x_d * sint + y_d * cost; + double Dxr = x_d * cost - y_d * sint; + double Dyr = x_d * sint + y_d * cost; + + if (enableLCPDist) { + pLCPMap->correctDistortion(Dxr, Dyr, w2, h2); + } // distortion correction double s = 1.0; if (enableDistortion) { - const double r = sqrt(Dxc * Dxc + Dyc * Dyc) / maxRadius; + const double r = sqrt(Dxr * Dxr + Dyr * Dyr) / maxRadius; s = 1.0 - distAmount + distAmount * r; } for (int c = 0; c < (enableCA ? 3 : 1); ++c) { - double Dx = Dxc * (s + chDist[c]); - double Dy = Dyc * (s + chDist[c]); + double Dx = Dxr * (s + chDist[c]); + double Dy = Dyr * (s + chDist[c]); // de-center Dx += w2; @@ -1386,7 +1386,7 @@ void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *trans for (int c = 0; c < 3; c++) { double Dx = x; double Dy = y; - + pLCPMap->correctCA(Dx, Dy, cx, cy, c); // Extract integer and fractions of coordinates @@ -1522,4 +1522,3 @@ bool ImProcFunctions::needsTransform (int oW, int oH, int rawRotationDeg, const } - From 55fd4b975e48141e73e068c8332a46caba5755d1 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Thu, 13 Jun 2024 09:34:14 +0200 Subject: [PATCH 29/39] iptransform: move profile based CA with and after distortion Doing profile based CA as the really first correction in a separate steps is probably not useful. Additionally many lens profile (lensfun) and future one provide functions to do them in a single step with better precision while other just provide a single step that does both (i.e. DNG WarpRectilinear). For the above reasons this patch removes the additional pass for CA correction. This will also improve the perfomance due to less work. --- rtengine/iptransform.cc | 136 +++++++++------------------------------- 1 file changed, 29 insertions(+), 107 deletions(-) diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index d62a87199..757d3d54c 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -420,7 +420,6 @@ homogeneous::Matrix perspectiveMatrix(double camera_focal_length, double bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef, const LensCorrection *pLCPMap) const { - enum PerspType { NONE, SIMPLE, CAMERA_BASED }; const PerspType perspectiveType = needsPerspective() ? ( (params->perspective.method == "camera_based") ? @@ -686,24 +685,8 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, highQuality = false; } else { highQuality = true; - // agriggio: CA correction via the lens profile has to be - // performed before separately from the the other transformations - // (except for the coarse rotation/flipping). In order to not - // change the code too much, I simply introduced a new mode - // TRANSFORM_HIGH_QUALITY_CA, which applies *only* profile-based - // CA correction. So, the correction in this case occurs in two - // steps, using an intermediate temporary image. There's room for - // optimization of course... - if (pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable()) { - tmpimg.reset(new Imagefloat(transformed->getWidth(), transformed->getHeight())); - dest = tmpimg.get(); - } } transformGeneral(highQuality, original, dest, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap.get(), useOriginalBuffer); - - if (highQuality && dest != transformed) { - transformLCPCAOnly(dest, transformed, cx, cy, pLCPMap.get(), useOriginalBuffer); - } } } @@ -1095,7 +1078,9 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I // set up stuff, depending on the mode we are enum PerspType { NONE, SIMPLE, CAMERA_BASED }; const bool enableLCPDist = pLCPMap && params->lensProf.useDist; + const bool enableLCPCA = pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable(); const bool enableCA = highQuality && needsCA(); + const bool doCACorrection = enableCA || enableLCPCA; const bool enableGradient = needsGradient(); const bool enablePCVignetting = needsPCVignetting(); const bool enableVignetting = needsVignetting(); @@ -1241,24 +1226,32 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I } // rotate - double Dxr = x_d * cost - y_d * sint; - double Dyr = x_d * sint + y_d * cost; + const double Dxr = x_d * cost - y_d * sint; + const double Dyr = x_d * sint + y_d * cost; - if (enableLCPDist) { - pLCPMap->correctDistortion(Dxr, Dyr, w2, h2); - } + for (int c = 0; c < (doCACorrection ? 3 : 1); ++c) { + double Dx = Dxr; + double Dy = Dyr; - // distortion correction - double s = 1.0; + if (enableLCPCA) { + pLCPMap->correctCA(Dx, Dy, w2, h2, c); + } - if (enableDistortion) { - const double r = sqrt(Dxr * Dxr + Dyr * Dyr) / maxRadius; - s = 1.0 - distAmount + distAmount * r; - } + if (enableLCPDist) { + pLCPMap->correctDistortion(Dx, Dy, w2, h2); + } - for (int c = 0; c < (enableCA ? 3 : 1); ++c) { - double Dx = Dxr * (s + chDist[c]); - double Dy = Dyr * (s + chDist[c]); + // distortion correction + double s = 1.0; + + if (enableDistortion) { + const double r = sqrt(Dx * Dx + Dy * Dy) / maxRadius; + s = 1.0 - distAmount + distAmount * r; + } + + // CA correction + Dx *= s + chDist[c]; + Dy *= s + chDist[c]; // de-center Dx += w2; @@ -1305,13 +1298,13 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I transformed->g(y, x) = vignmul * (original->g(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g(yc, xc + 1) * Dx * (1.0 - Dy) + original->g(yc + 1, xc) * (1.0 - Dx) * Dy + original->g(yc + 1, xc + 1) * Dx * Dy); transformed->b(y, x) = vignmul * (original->b(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b(yc, xc + 1) * Dx * (1.0 - Dy) + original->b(yc + 1, xc) * (1.0 - Dx) * Dy + original->b(yc + 1, xc + 1) * Dx * Dy); } else if (!useLog) { - if (enableCA) { + if (doCACorrection) { interpolateTransformChannelsCubic(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], vignmul); } else { interpolateTransformCubic(original, xc - 1, yc - 1, Dx, Dy, transformed->r(y, x), transformed->g(y, x), transformed->b(y, x), vignmul); } } else { - if (enableCA) { + if (doCACorrection) { interpolateTransformChannelsCubicLog(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], vignmul); } else { interpolateTransformCubicLog(original, xc - 1, yc - 1, Dx, Dy, transformed->r(y, x), transformed->g(y, x), transformed->b(y, x), vignmul); @@ -1325,7 +1318,7 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I const int x2 = LIM(xc + 1, 0, original->getWidth() - 1); if (useLog) { - if (enableCA) { + if (doCACorrection) { chTrans[c][y][x] = vignmul * xexpf(chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); } else { transformed->r(y, x) = vignmul * xexpf(original->r(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->r(y1, x2) * Dx * (1.0 - Dy) + original->r(y2, x1) * (1.0 - Dx) * Dy + original->r(y2, x2) * Dx * Dy); @@ -1333,7 +1326,7 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I transformed->b(y, x) = vignmul * xexpf(original->b(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->b(y1, x2) * Dx * (1.0 - Dy) + original->b(y2, x1) * (1.0 - Dx) * Dy + original->b(y2, x2) * Dx * Dy); } } else { - if (enableCA) { + if (doCACorrection) { chTrans[c][y][x] = vignmul * (chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); } else { transformed->r(y, x) = vignmul * (original->r(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->r(y1, x2) * Dx * (1.0 - Dy) + original->r(y2, x1) * (1.0 - Dx) * Dy + original->r(y2, x2) * Dx * Dy); @@ -1343,7 +1336,7 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I } } } else { - if (enableCA) { + if (doCACorrection) { // not valid (source pixel x,y not inside source image, etc.) chTrans[c][y][x] = 0; } else { @@ -1357,77 +1350,6 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I } } - -void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap, bool useOriginalBuffer) -{ - assert(pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable()); - const bool useLog = params->commonTrans.method == "log"; - - float** chTrans[3] = {transformed->r.ptrs, transformed->g.ptrs, transformed->b.ptrs}; - - std::unique_ptr tempLog; - if (useLog) { - if (!useOriginalBuffer) { - tempLog.reset(new Imagefloat(original->getWidth(), original->getHeight())); - logEncode(original, tempLog.get(), multiThread); - original = tempLog.get(); - } else { - logEncode(original, original, multiThread); - } - } - float** chOrig[3] = {original->r.ptrs, original->g.ptrs, original->b.ptrs}; - -#ifdef _OPENMP - #pragma omp parallel for if (multiThread) -#endif - - for (int y = 0; y < transformed->getHeight(); y++) { - for (int x = 0; x < transformed->getWidth(); x++) { - for (int c = 0; c < 3; c++) { - double Dx = x; - double Dy = y; - - pLCPMap->correctCA(Dx, Dy, cx, cy, c); - - // Extract integer and fractions of coordinates - int xc = (int)Dx; - Dx -= (double)xc; - int yc = (int)Dy; - Dy -= (double)yc; - - // Convert only valid pixels - if (yc >= 0 && yc < original->getHeight() && xc >= 0 && xc < original->getWidth()) { - - // multiplier for vignetting correction - if (yc > 0 && yc < original->getHeight() - 2 && xc > 0 && xc < original->getWidth() - 2) { - // all interpolation pixels inside image - if (!useLog) { - interpolateTransformChannelsCubic(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], 1.0); - } else { - interpolateTransformChannelsCubicLog(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], 1.0); - } - } else { - // edge pixels - int y1 = LIM (yc, 0, original->getHeight() - 1); - int y2 = LIM (yc + 1, 0, original->getHeight() - 1); - int x1 = LIM (xc, 0, original->getWidth() - 1); - int x2 = LIM (xc + 1, 0, original->getWidth() - 1); - if (!useLog) { - chTrans[c][y][x] = (chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); - } else { - chTrans[c][y][x] = xexpf(chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); - } - } - } else { - // not valid (source pixel x,y not inside source image, etc.) - chTrans[c][y][x] = 0; - } - } - } - } -} - - double ImProcFunctions::getTransformAutoFill (int oW, int oH, const LensCorrection *pLCPMap) const { if (!needsCA() && !needsDistortion() && !needsRotation() && !needsPerspective() && (!params->lensProf.useDist || pLCPMap == nullptr)) { From dc0e23c82c4ebedd901fb66593702ae3fb6df724 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Thu, 13 Jun 2024 20:02:15 +0200 Subject: [PATCH 30/39] iptransform: apply distortion and CA correction in a single pass Some lens profile methods provides a way to correct distortion and CA in a single step. When available, applying distortion and CA correction when both enabled in a single pass is more precise (see lensfun ApplySubpixelGeometryDistortion doc) since it's usually how the profile is done. Instead applying the CA correction in a step after distortion correction could lead to a bit different (also if not always visible) correction. This is also required for future lens correction methods (like DNG WarpRectilinear or corrections based on vendor metadata) that provides only merged distortion and CA correction in a single pass. --- rtengine/iptransform.cc | 10 +++++----- rtengine/lcp.cc | 6 ++++++ rtengine/lcp.h | 3 +++ rtengine/rtlensfun.cc | 30 +++++++++++++++++++++++++++--- rtengine/rtlensfun.h | 1 + 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 757d3d54c..08ee9a4a0 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -1233,12 +1233,12 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I double Dx = Dxr; double Dy = Dyr; - if (enableLCPCA) { - pLCPMap->correctCA(Dx, Dy, w2, h2, c); - } - - if (enableLCPDist) { + if (enableLCPDist && enableLCPCA) { + pLCPMap->correctDistortionAndCA(Dx, Dy, w2, h2, c); + } else if (enableLCPDist) { pLCPMap->correctDistortion(Dx, Dy, w2, h2); + } else if (enableLCPCA) { + pLCPMap->correctCA(Dx, Dy, w2, h2, c); } // distortion correction diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index 7507bbb11..ba96147dc 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -990,6 +990,12 @@ bool rtengine::LCPMapper::isCACorrectionAvailable() const return enableCA; } +void rtengine::LCPMapper::correctDistortionAndCA(double &x, double &y, int cx, int cy, int channel) const +{ + correctDistortion(x, y, cx, cy); + correctCA(x, y, cx, cy, channel); +} + void rtengine::LCPMapper::correctDistortion(double &x, double &y, int cx, int cy) const { x += cx; diff --git a/rtengine/lcp.h b/rtengine/lcp.h index b59cc84c6..97cdd0890 100644 --- a/rtengine/lcp.h +++ b/rtengine/lcp.h @@ -166,6 +166,8 @@ private: class LensCorrection { public: virtual ~LensCorrection() {} + + virtual void correctDistortionAndCA(double &x, double &y, int cx, int cy, int channel) const = 0; virtual void correctDistortion(double &x, double &y, int cx, int cy) const = 0; virtual bool isCACorrectionAvailable() const = 0; virtual void correctCA(double &x, double &y, int cx, int cy, int channel) const = 0; @@ -194,6 +196,7 @@ public: ); + void correctDistortionAndCA(double &x, double &y, int cx, int cy, int channel) const override; void correctDistortion(double &x, double &y, int cx, int cy) const override; bool isCACorrectionAvailable() const override; void correctCA(double& x, double& y, int cx, int cy, int channel) const override; diff --git a/rtengine/rtlensfun.cc b/rtengine/rtlensfun.cc index 08010f50f..505346ad0 100644 --- a/rtengine/rtlensfun.cc +++ b/rtengine/rtlensfun.cc @@ -125,7 +125,6 @@ void LFModifier::correctDistortion(double &x, double &y, int cx, int cy) const } } - bool LFModifier::isCACorrectionAvailable() const { return (flags_ & LF_MODIFY_TCA); @@ -141,7 +140,7 @@ void LFModifier::correctCA(double &x, double &y, int cx, int cy, int channel) co // channels. We could consider caching the info to speed this up x += cx; y += cy; - + float pos[6]; if (swap_xy_) { std::swap(x, y); @@ -156,6 +155,31 @@ void LFModifier::correctCA(double &x, double &y, int cx, int cy, int channel) co y -= cy; } +void LFModifier::correctDistortionAndCA(double &x, double &y, int cx, int cy, int channel) const +{ + assert(channel >= 0 && channel <= 2); + + // RT currently applies the CA correction per channel, whereas + // lensfun applies it to all the three channels simultaneously. This means + // we do the work 3 times, because each time we discard 2 of the 3 + // channels. We could consider caching the info to speed this up + x += cx; + y += cy; + + float pos[6]; + if (swap_xy_) { + std::swap(x, y); + } + data_->ApplySubpixelGeometryDistortion(x, y, 1, 1, pos); // This is thread-safe + x = pos[2*channel]; + y = pos[2*channel+1]; + if (swap_xy_) { + std::swap(x, y); + } + x -= cx; + y -= cy; +} + #ifdef _OPENMP void LFModifier::processVignette(int width, int height, float** rawData) const { @@ -396,7 +420,7 @@ bool LFDatabase::init(const Glib::ustring &dbdir) if (settings->verbose) { std::cout << (ok ? "OK" : "FAIL") << std::endl; } - + return ok; } diff --git a/rtengine/rtlensfun.h b/rtengine/rtlensfun.h index 1d941246f..39ca67ec2 100644 --- a/rtengine/rtlensfun.h +++ b/rtengine/rtlensfun.h @@ -53,6 +53,7 @@ public: explicit operator bool() const; + void correctDistortionAndCA(double &x, double &y, int cx, int cy, int channel) const override; void correctDistortion(double &x, double &y, int cx, int cy) const override; bool isCACorrectionAvailable() const override; void correctCA(double &x, double &y, int cx, int cy, int channel) const override; From b98fa4285720ccc1caeb475904af03c9649d4a79 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Thu, 13 Jun 2024 20:03:07 +0200 Subject: [PATCH 31/39] lens profile: report availability of distortion and vignetting Beside CA, report also distortion and vignetting availability. Rename is${CORRECTION}Available methods to has${CORRECTION}. --- rtengine/iptransform.cc | 6 +++--- rtengine/lcp.cc | 14 +++++++++++++- rtengine/lcp.h | 10 ++++++++-- rtengine/rtlensfun.cc | 20 +++++++++++++++----- rtengine/rtlensfun.h | 5 ++++- 5 files changed, 43 insertions(+), 12 deletions(-) diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 08ee9a4a0..468507385 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -518,7 +518,7 @@ bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, double Dx = x_d * cost - y_d * sint; double Dy = x_d * sint + y_d * cost; - if (pLCPMap && params->lensProf.useDist) { + if (pLCPMap && params->lensProf.useDist && pLCPMap->hasDistortionCorrection()) { pLCPMap->correctDistortion(Dx, Dy, w2, h2); } @@ -1077,8 +1077,8 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I // set up stuff, depending on the mode we are enum PerspType { NONE, SIMPLE, CAMERA_BASED }; - const bool enableLCPDist = pLCPMap && params->lensProf.useDist; - const bool enableLCPCA = pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable(); + const bool enableLCPDist = pLCPMap && params->lensProf.useDist && pLCPMap->hasDistortionCorrection(); + const bool enableLCPCA = pLCPMap && params->lensProf.useCA && pLCPMap->hasCACorrection(); const bool enableCA = highQuality && needsCA(); const bool doCACorrection = enableCA || enableLCPCA; const bool enableGradient = needsGradient(); diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index ba96147dc..0947cf709 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -985,11 +985,23 @@ rtengine::LCPMapper::LCPMapper( isFisheye = pProf->isFisheye; } -bool rtengine::LCPMapper::isCACorrectionAvailable() const +bool rtengine::LCPMapper::hasDistortionCorrection() const +{ + // assume lcp always provides distortion correction + return true; +} + +bool rtengine::LCPMapper::hasCACorrection() const { return enableCA; } +bool rtengine::LCPMapper::hasVignettingCorrection() const +{ + // assume lcp always provides vignetting correction + return true; +} + void rtengine::LCPMapper::correctDistortionAndCA(double &x, double &y, int cx, int cy, int channel) const { correctDistortion(x, y, cx, cy); diff --git a/rtengine/lcp.h b/rtengine/lcp.h index 97cdd0890..114131b4a 100644 --- a/rtengine/lcp.h +++ b/rtengine/lcp.h @@ -167,9 +167,12 @@ class LensCorrection { public: virtual ~LensCorrection() {} + virtual bool hasDistortionCorrection() const = 0; + virtual bool hasCACorrection() const = 0; + virtual bool hasVignettingCorrection() const = 0; + virtual void correctDistortionAndCA(double &x, double &y, int cx, int cy, int channel) const = 0; virtual void correctDistortion(double &x, double &y, int cx, int cy) const = 0; - virtual bool isCACorrectionAvailable() const = 0; virtual void correctCA(double &x, double &y, int cx, int cy, int channel) const = 0; virtual void processVignette(int width, int height, float** rawData) const = 0; virtual void processVignette3Channels(int width, int height, float** rawData) const = 0; @@ -196,9 +199,12 @@ public: ); + bool hasDistortionCorrection() const override; + bool hasCACorrection() const override; + bool hasVignettingCorrection() const override; + void correctDistortionAndCA(double &x, double &y, int cx, int cy, int channel) const override; void correctDistortion(double &x, double &y, int cx, int cy) const override; - bool isCACorrectionAvailable() const override; void correctCA(double& x, double& y, int cx, int cy, int channel) const override; void processVignette(int width, int height, float** rawData) const override; void processVignette3Channels(int width, int height, float** rawData) const override; diff --git a/rtengine/rtlensfun.cc b/rtengine/rtlensfun.cc index 505346ad0..f4714b6f7 100644 --- a/rtengine/rtlensfun.cc +++ b/rtengine/rtlensfun.cc @@ -102,6 +102,21 @@ LFModifier::operator bool() const } +bool LFModifier::hasDistortionCorrection() const +{ + return (flags_ & LF_MODIFY_DISTORTION); +} + +bool LFModifier::hasCACorrection() const +{ + return (flags_ & LF_MODIFY_TCA); +} + +bool LFModifier::hasVignettingCorrection() const +{ + return (flags_ & LF_MODIFY_VIGNETTING); +} + void LFModifier::correctDistortion(double &x, double &y, int cx, int cy) const { if (!data_) { @@ -125,11 +140,6 @@ void LFModifier::correctDistortion(double &x, double &y, int cx, int cy) const } } -bool LFModifier::isCACorrectionAvailable() const -{ - return (flags_ & LF_MODIFY_TCA); -} - void LFModifier::correctCA(double &x, double &y, int cx, int cy, int channel) const { assert(channel >= 0 && channel <= 2); diff --git a/rtengine/rtlensfun.h b/rtengine/rtlensfun.h index 39ca67ec2..78c9c9ff6 100644 --- a/rtengine/rtlensfun.h +++ b/rtengine/rtlensfun.h @@ -53,9 +53,12 @@ public: explicit operator bool() const; + bool hasDistortionCorrection() const override; + bool hasCACorrection() const override; + bool hasVignettingCorrection() const override; + void correctDistortionAndCA(double &x, double &y, int cx, int cy, int channel) const override; void correctDistortion(double &x, double &y, int cx, int cy) const override; - bool isCACorrectionAvailable() const override; void correctCA(double &x, double &y, int cx, int cy, int channel) const override; void processVignette(int width, int height, float** rawData) const override; void processVignette3Channels(int width, int height, float** rawData) const override; From 5159de89cbb113e51dbeda546294f7cb5b65a6ab Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Thu, 13 Jun 2024 09:42:15 +0200 Subject: [PATCH 32/39] imagedata: report if file is DNG --- rtengine/imagedata.cc | 7 +++++++ rtengine/imagedata.h | 2 ++ rtengine/rtengine.h | 2 ++ rtgui/cacheimagedata.cc | 6 ++++++ rtgui/cacheimagedata.h | 2 ++ 5 files changed, 19 insertions(+) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 6507a970d..45db99f1e 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -565,6 +565,8 @@ FramesData::FramesData(const Glib::ustring &fname, time_t ts) : meta.getDimensions(w_, h_); + isDNG = find_exif_tag("Exif.Image.DNGVersion"); + // ----------------------- // Special file type detection (HDR, PixelShift) // ------------------------ @@ -778,6 +780,11 @@ bool FramesData::getHDR() const return isHDR; } +bool FramesData::getDNG() const +{ + return isDNG; +} + std::string FramesData::getImageType() const { return isPixelShift ? "PS" : isHDR ? "HDR" : "STD"; diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index 08f55bd62..f999d59e6 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -59,6 +59,7 @@ private: time_t modTimeStamp; bool isPixelShift; bool isHDR; + bool isDNG; int w_; int h_; @@ -69,6 +70,7 @@ public: unsigned int getFrameCount() const override; bool getPixelShift() const override; bool getHDR() const override; + bool getDNG() const override; std::string getImageType() const override; IIOSampleFormat getSampleFormat() const override; bool hasExif() const override; diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index f1ee4108c..0010f42b8 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -130,6 +130,8 @@ public: virtual bool getPixelShift () const = 0; /** @return false: not an HDR file ; true: single or multi-frame HDR file (e.g. Pentax HDR raw file or 32 bit float DNG file or Log compressed) */ virtual bool getHDR() const = 0; + /** @return true if the file is a DNG file */ + virtual bool getDNG() const = 0; /** @return false: not an HDR file ; true: single or multi-frame HDR file (e.g. Pentax HDR raw file or 32 bit float DNG file or Log compressed) */ virtual std::string getImageType() const = 0; diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 0e9cc7f0f..872c60504 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -59,6 +59,7 @@ CacheImageData::CacheImageData() : iso(0), rating(0), isHDR (false), + isDNG (false), isPixelShift (false), sensortype(rtengine::ST_NONE), sampleFormat(rtengine::IIOSF_UNKNOWN), @@ -194,6 +195,10 @@ int CacheImageData::load (const Glib::ustring& fname) isHDR = keyFile.get_boolean ("ExifInfo", "IsHDR"); } + if (keyFile.has_key ("ExifInfo", "IsDNG")) { + isDNG = keyFile.get_boolean ("ExifInfo", "IsDNG"); + } + if (keyFile.has_key ("ExifInfo", "IsPixelShift")) { isPixelShift = keyFile.get_boolean ("ExifInfo", "IsPixelShift"); } @@ -316,6 +321,7 @@ int CacheImageData::save (const Glib::ustring& fname) keyFile.set_double ("ExifInfo", "FocusDist", focusDist); keyFile.set_integer ("ExifInfo", "ISO", iso); keyFile.set_boolean ("ExifInfo", "IsHDR", isHDR); + keyFile.set_boolean ("ExifInfo", "IsDNG", isDNG); keyFile.set_boolean ("ExifInfo", "IsPixelShift", isPixelShift); keyFile.set_string ("ExifInfo", "ExpComp", expcomp); } diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index 8c0fa6513..e3d5cc3da 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -60,6 +60,7 @@ public: unsigned iso; int rating; bool isHDR; + bool isDNG; bool isPixelShift; int sensortype; rtengine::IIO_Sample_Format sampleFormat; @@ -114,6 +115,7 @@ public: int getRating () const override { return rating; } // FIXME-piotr : missing rating bool getPixelShift () const override { return isPixelShift; } bool getHDR() const override { return isHDR; } + bool getDNG() const override { return isDNG; } std::string getImageType() const override { return isPixelShift ? "PS" : isHDR ? "HDR" : "STD"; } rtengine::IIOSampleFormat getSampleFormat() const override { return sampleFormat; } void getDimensions(int &w, int &h) const override From 2b97de233f330becff648c296daf009e3a6d1e07 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Thu, 13 Jun 2024 09:51:08 +0200 Subject: [PATCH 33/39] Add initial metadata lens correction handling --- rtdata/languages/default | 1 + rtengine/CMakeLists.txt | 1 + rtengine/dcrop.cc | 2 +- rtengine/improcfun.h | 3 +- rtengine/iptransform.cc | 18 +++++- rtengine/lensmetadata.cc | 42 +++++++++++++ rtengine/lensmetadata.h | 47 +++++++++++++++ rtengine/procparams.cc | 8 ++- rtengine/procparams.h | 4 +- rtengine/rawimagesource.cc | 9 ++- rtgui/lensprofile.cc | 120 +++++++++++++++++++++++++++---------- rtgui/lensprofile.h | 6 +- 12 files changed, 222 insertions(+), 39 deletions(-) create mode 100644 rtengine/lensmetadata.cc create mode 100644 rtengine/lensmetadata.h diff --git a/rtdata/languages/default b/rtdata/languages/default index 46496826a..e6eb09b06 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -2837,6 +2837,7 @@ TP_LENSGEOM_FILL;Auto-fill TP_LENSGEOM_LABEL;Lens / Geometry TP_LENSGEOM_LIN;Linear TP_LENSGEOM_LOG;Logarithmic +TP_LENSPROFILE_CORRECTION_METADATA;From file metadata TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 5d87310b9..c937198c8 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -148,6 +148,7 @@ set(RTENGINESOURCEFILES jpeg_ijg/jpeg_memsrc.cc labimage.cc lcp.cc + lensmetadata.cc lmmse_demosaic.cc loadinitial.cc metadata.cc diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 580475c37..e630d1936 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -1850,7 +1850,7 @@ bool check_need_larger_crop_for_lcp_distortion(int fw, int fh, int x, int y, int return false; } - return (params.lensProf.useDist && (params.lensProf.useLensfun() || params.lensProf.useLcp())); + return (params.lensProf.useDist && (params.lensProf.useLensfun() || params.lensProf.useLcp() || params.lensProf.useMetadata())); } } // namespace diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 9c6c794f0..c8c6e166e 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -130,6 +130,7 @@ class ImProcFunctions bool needsGradient() const; bool needsVignetting() const; bool needsLCP() const; + bool needsMetadata() const; bool needsLensfun() const; // static cmsUInt8Number* Mempro = NULL; @@ -155,7 +156,7 @@ enum class BlurType { ~ImProcFunctions(); bool needsLuminanceOnly() const { - return !(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP() || needsLensfun()) && (needsVignetting() || needsPCVignetting() || needsGradient()); + return !(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP() || needsLensfun() || needsMetadata()) && (needsVignetting() || needsPCVignetting() || needsGradient()); } void setScale(double iscale); diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 468507385..10f37e781 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -26,6 +26,7 @@ #include "rt_math.h" #include "rtengine.h" #include "rtlensfun.h" +#include "lensmetadata.h" #include "sleef.h" using namespace std; @@ -659,7 +660,13 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, std::unique_ptr pLCPMap; - if (needsLensfun()) { + if (needsMetadata()) { + auto corr = MetadataLensCorrectionFinder::findCorrection(metadata); + if (corr) { + corr->initCorrections(oW, oH, params->coarse, rawRotationDeg); + pLCPMap = std::move(corr); + } + } else if (needsLensfun()) { pLCPMap = LFDatabase::getInstance()->findModifier(params->lensProf, metadata, oW, oH, params->coarse, rawRotationDeg); } else if (needsLCP()) { // don't check focal length to allow distortion correction for lenses without chip const std::shared_ptr pLCPProf = LCPStore::getInstance()->getProfile (params->lensProf.lcpFile); @@ -675,7 +682,7 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, } } - if (! (needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP() || needsLensfun()) && (needsVignetting() || needsPCVignetting() || needsGradient())) { + if (! (needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP() || needsMetadata() || needsLensfun()) && (needsVignetting() || needsPCVignetting() || needsGradient())) { transformLuminanceOnly (original, transformed, cx, cy, oW, oH, fW, fH); } else { bool highQuality; @@ -1422,6 +1429,11 @@ bool ImProcFunctions::needsVignetting () const return params->vignetting.amount; } +bool ImProcFunctions::needsMetadata () const +{ + return params->lensProf.useMetadata(); +} + bool ImProcFunctions::needsLCP () const { return params->lensProf.useLcp(); @@ -1439,7 +1451,7 @@ bool ImProcFunctions::needsTransform (int oW, int oH, int rawRotationDeg, const std::unique_ptr pLCPMap = LFDatabase::getInstance()->findModifier(params->lensProf, metadata, oW, oH, params->coarse, rawRotationDeg); needsLf = pLCPMap.get(); } - return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP() || needsLf; + return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP() || needsMetadata() || needsLf; } diff --git a/rtengine/lensmetadata.cc b/rtengine/lensmetadata.cc new file mode 100644 index 000000000..e92fc6cc9 --- /dev/null +++ b/rtengine/lensmetadata.cc @@ -0,0 +1,42 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2024 Rawtherapee developers + * + * 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 "lensmetadata.h" + +namespace rtengine +{ + +std::unique_ptr MetadataLensCorrectionFinder::findCorrection(const FramesMetaData *meta) +{ + static const std::unordered_set makers = {}; + + std::string make = Glib::ustring(meta->getMake()).uppercase(); + + if (makers.find(make) == makers.end()) { + return nullptr; + } + + std::unique_ptr correction; + + return correction; +} + +} // namespace rtengine diff --git a/rtengine/lensmetadata.h b/rtengine/lensmetadata.h new file mode 100644 index 000000000..7991af8cd --- /dev/null +++ b/rtengine/lensmetadata.h @@ -0,0 +1,47 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2024 Rawtherapee developers + * + * 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 . + */ +#pragma once + +#include + +#include "lcp.h" +#include "metadata.h" +#include "procparams.h" +#include "rtengine.h" + +namespace rtengine +{ + +/* MetadataLensCorrection is an abstract class for various lens correction based on raw file metadata + this metadata is vendor dependent */ +class MetadataLensCorrection : public LensCorrection, + public NonCopyable +{ +public: + virtual void initCorrections(int width, int height, const procparams::CoarseTransformParams &coarse, int rawRotationDeg) = 0; +}; + +/* MetadataLensCorrectionFinder tries to find and return MetadataLensCorrection for the provided metadata */ +class MetadataLensCorrectionFinder +{ +public: + static std::unique_ptr findCorrection(const FramesMetaData *meta); +}; + +} // namespace rtengine diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index b868a7627..e1a56a533 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2064,13 +2064,19 @@ bool LensProfParams::lfManual() const return lcMode == LcMode::LENSFUNMANUAL; } +bool LensProfParams::useMetadata() const +{ + return lcMode == LcMode::METADATA; +} + const std::vector& LensProfParams::getMethodStrings() const { static const std::vector method_strings = { "none", "lfauto", "lfmanual", - "lcp" + "lcp", + "metadata" }; return method_strings; } diff --git a/rtengine/procparams.h b/rtengine/procparams.h index d71c3d172..e6945cfbd 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -966,7 +966,8 @@ struct LensProfParams { NONE, // No lens correction LENSFUNAUTOMATCH, // Lens correction using auto matched lensfun database entry LENSFUNMANUAL, // Lens correction using manually selected lensfun database entry - LCP // Lens correction using lcp file + LCP, // Lens correction using lcp file + METADATA // Lens correction using embedded metadata }; LcMode lcMode; @@ -985,6 +986,7 @@ struct LensProfParams { bool lfAutoMatch() const; bool useLcp() const; bool lfManual() const; + bool useMetadata() const; const std::vector& getMethodStrings() const; Glib::ustring getMethodString(LcMode mode) const; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 09b64ad41..8cd6ffedd 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -44,6 +44,7 @@ #include "rt_math.h" #include "rtengine.h" #include "rtlensfun.h" +#include "lensmetadata.h" #include "../rtgui/options.h" #define BENCHMARK @@ -1583,7 +1584,13 @@ void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lens if (!hasFlatField && lensProf.useVign && lensProf.lcMode != LensProfParams::LcMode::NONE) { std::unique_ptr pmap; - if (lensProf.useLensfun()) { + if (lensProf.useMetadata()) { + auto corr = MetadataLensCorrectionFinder::findCorrection(idata); + if (corr) { + corr->initCorrections(W, H, coarse, -1); + pmap = std::move(corr); + } + } else if (lensProf.useLensfun()) { pmap = LFDatabase::getInstance()->findModifier(lensProf, idata, W, H, coarse, -1); } else { const std::shared_ptr pLCPProf = LCPStore::getInstance()->getProfile(lensProf.lcpFile); diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 5f42a1cde..4410b2fe0 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -32,6 +32,7 @@ #include "../rtengine/lcp.h" #include "../rtengine/procparams.h" #include "../rtengine/rtlensfun.h" +#include "../rtengine/lensmetadata.h" using namespace rtengine; using namespace rtengine::procparams; @@ -56,6 +57,7 @@ LensProfilePanel::LensProfilePanel() : distGrid(Gtk::manage((new Gtk::Grid()))), corrUnchangedRB(Gtk::manage((new Gtk::RadioButton(M("GENERAL_UNCHANGED"))))), corrOffRB(Gtk::manage((new Gtk::RadioButton(corrGroup, M("GENERAL_NONE"))))), + corrMetadata(Gtk::manage((new Gtk::RadioButton(corrGroup, M("TP_LENSPROFILE_CORRECTION_METADATA"))))), corrLensfunAutoRB(Gtk::manage((new Gtk::RadioButton(corrGroup, M("TP_LENSPROFILE_CORRECTION_AUTOMATCH"))))), corrLensfunManualRB(Gtk::manage((new Gtk::RadioButton(corrGroup, M("TP_LENSPROFILE_CORRECTION_MANUAL"))))), corrLcpFileRB(Gtk::manage((new Gtk::RadioButton(corrGroup, M("TP_LENSPROFILE_CORRECTION_LCPFILE"))))), @@ -144,17 +146,18 @@ LensProfilePanel::LensProfilePanel() : // Populate modes grid: modesGrid->attach(*corrOffRB, 0, 0, 3, 1); - modesGrid->attach(*corrLensfunAutoRB, 0, 1, 3, 1); - modesGrid->attach(*corrLensfunManualRB, 0, 2, 3, 1); + modesGrid->attach(*corrMetadata, 0, 1, 3, 1); + modesGrid->attach(*corrLensfunAutoRB, 0, 2, 3, 1); + modesGrid->attach(*corrLensfunManualRB, 0, 3, 3, 1); - modesGrid->attach(*lensfunCamerasLbl, 0, 3, 1, 1); - modesGrid->attach(*lensfunCameras, 1, 3, 1, 1); - modesGrid->attach(*lensfunLensesLbl, 0, 4, 1, 1); - modesGrid->attach(*lensfunLenses, 1, 4, 1, 1); - modesGrid->attach(*warning, 2, 3, 1, 2); + modesGrid->attach(*lensfunCamerasLbl, 0, 4, 1, 1); + modesGrid->attach(*lensfunCameras, 1, 4, 1, 1); + modesGrid->attach(*lensfunLensesLbl, 0, 5, 1, 1); + modesGrid->attach(*lensfunLenses, 1, 5, 1, 1); + modesGrid->attach(*warning, 2, 4, 1, 2); - modesGrid->attach(*corrLcpFileRB, 0, 5, 1, 1); - modesGrid->attach(*corrLcpFileChooser, 1, 5, 1, 1); + modesGrid->attach(*corrLcpFileRB, 0, 6, 1, 1); + modesGrid->attach(*corrLcpFileChooser, 1, 6, 1, 1); // Populate distortions grid: @@ -179,6 +182,7 @@ LensProfilePanel::LensProfilePanel() : lensfunCameras->signal_changed().connect(sigc::mem_fun(*this, &LensProfilePanel::onLensfunCameraChanged)); lensfunLenses->signal_changed().connect(sigc::mem_fun(*this, &LensProfilePanel::onLensfunLensChanged)); corrOffRB->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrOffRB)); + corrMetadata->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrMetadata)); corrLensfunAutoRB->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrLensfunAutoRB)); corrLensfunManualRB->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrLensfunManualRB)); corrLcpFileRB->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged), corrLcpFileRB)); @@ -211,30 +215,52 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa break; } + case procparams::LensProfParams::LcMode::METADATA: { + if (metadata) { + auto metadataCorrection= rtengine::MetadataLensCorrectionFinder::findCorrection(metadata); + if (metadataCorrection) { + corrMetadata->set_active(true); + corrMetadata->set_sensitive(true); + } else { + corrMetadata->set_sensitive(false); + corrOffRB->set_active(true); + } + } else { + corrMetadata->set_sensitive(false); + } + break; + } + case procparams::LensProfParams::LcMode::NONE: { corrOffRB->set_active(true); setManualParamsVisibility(false); + + ckbUseDist->set_sensitive(false); + ckbUseVign->set_sensitive(false); + ckbUseCA->set_sensitive(false); break; } } - if (pp->lensProf.lcpFile.empty()) { - const Glib::ustring lastFolder = corrLcpFileChooser->get_current_folder(); - corrLcpFileChooser->set_current_folder(lastFolder); - corrLcpFileChooser->unselect_all(); - bindCurrentFolder(*corrLcpFileChooser, options.lastLensProfileDir); - updateDisabled(false); - } - else if (LCPStore::getInstance()->isValidLCPFileName(pp->lensProf.lcpFile)) { - corrLcpFileChooser->set_filename(pp->lensProf.lcpFile); - - if (corrLcpFileRB->get_active()) { - updateDisabled(true); + if (pp->lensProf.lcMode == procparams::LensProfParams::LcMode::LCP) { + if (pp->lensProf.lcpFile.empty()) { + const Glib::ustring lastFolder = corrLcpFileChooser->get_current_folder(); + corrLcpFileChooser->set_current_folder(lastFolder); + corrLcpFileChooser->unselect_all(); + bindCurrentFolder(*corrLcpFileChooser, options.lastLensProfileDir); + updateLCPDisabled(false); + } + else if (LCPStore::getInstance()->isValidLCPFileName(pp->lensProf.lcpFile)) { + corrLcpFileChooser->set_filename(pp->lensProf.lcpFile); + + if (corrLcpFileRB->get_active()) { + updateLCPDisabled(true); + } + } + else { + corrLcpFileChooser->unselect_filename(corrLcpFileChooser->get_filename()); + updateLCPDisabled(false); } - } - else { - corrLcpFileChooser->unselect_filename(corrLcpFileChooser->get_filename()); - updateDisabled(false); } const LFDatabase* const db = LFDatabase::getInstance(); @@ -308,6 +334,9 @@ void LensProfilePanel::write(rtengine::procparams::ProcParams* pp, ParamsEdited* if (corrLcpFileRB->get_active()) { pp->lensProf.lcMode = procparams::LensProfParams::LcMode::LCP; } + else if (corrMetadata->get_active()) { + pp->lensProf.lcMode = procparams::LensProfParams::LcMode::METADATA; + } else if (corrLensfunManualRB->get_active()) { pp->lensProf.lcMode = procparams::LensProfParams::LcMode::LENSFUNMANUAL; } @@ -367,12 +396,18 @@ void LensProfilePanel::setRawMeta(bool raw, const rtengine::FramesMetaData* pMet // CA is very focus layer dependent, otherwise it might even worsen things allowFocusDep = false; - ckbUseCA->set_active(false); - ckbUseCA->set_sensitive(false); enableListener(); } + corrMetadata->set_sensitive(false); + if (pMeta) { + metadataCorrection = MetadataLensCorrectionFinder::findCorrection(pMeta); + if (metadataCorrection) { + corrMetadata->set_sensitive(true); + } + } + isRaw = raw; metadata = pMeta; } @@ -381,7 +416,7 @@ void LensProfilePanel::onLCPFileChanged() { lcpFileChanged = true; const bool valid = LCPStore::getInstance()->isValidLCPFileName(corrLcpFileChooser->get_filename()); - updateDisabled(valid); + updateLCPDisabled(valid); if (listener) { if (valid) { @@ -552,10 +587,20 @@ void LensProfilePanel::onCorrModeChanged(const Gtk::RadioButton* rbChanged) lensfunAutoChanged = true; lcpFileChanged = true; - updateDisabled(true); + updateLCPDisabled(true); mode = M("TP_LENSPROFILE_CORRECTION_LCPFILE"); + } else if (rbChanged == corrMetadata) { + lcModeChanged = true; + useLensfunChanged = true; + lensfunAutoChanged = true; + lcpFileChanged = true; + + updateMetadataDisabled(); + + mode = M("TP_LENSPROFILE_CORRECTION_METADATA"); + } else if (rbChanged == corrUnchangedRB) { lcModeChanged = false; useLensfunChanged = false; @@ -680,7 +725,7 @@ void LensProfilePanel::LFDbHelper::fillLensfunLenses() } } -void LensProfilePanel::updateDisabled(bool enable) +void LensProfilePanel::updateLCPDisabled(bool enable) { if (!batchMode) { ckbUseDist->set_sensitive(enable); @@ -689,6 +734,21 @@ void LensProfilePanel::updateDisabled(bool enable) } } +void LensProfilePanel::updateMetadataDisabled() +{ + if (!batchMode) { + if (metadataCorrection) { + ckbUseDist->set_sensitive(metadataCorrection->hasDistortionCorrection()); + ckbUseVign->set_sensitive(metadataCorrection->hasVignettingCorrection()); + ckbUseCA->set_sensitive(metadataCorrection->hasCACorrection()); + } else { + ckbUseDist->set_sensitive(false); + ckbUseVign->set_sensitive(false); + ckbUseCA->set_sensitive(false); + } + } +} + bool LensProfilePanel::setLensfunCamera(const Glib::ustring& make, const Glib::ustring& model) { if (!make.empty() && !model.empty()) { diff --git a/rtgui/lensprofile.h b/rtgui/lensprofile.h index 42746f41e..cdf7bd6e4 100644 --- a/rtgui/lensprofile.h +++ b/rtgui/lensprofile.h @@ -22,6 +22,7 @@ #include "guiutils.h" #include "toolpanel.h" +#include "../rtengine/lensmetadata.h" class LensProfilePanel final : public ToolParamBlock, @@ -89,7 +90,8 @@ private: void fillLensfunLenses(); }; - void updateDisabled(bool enable); + void updateLCPDisabled(bool enable); + void updateMetadataDisabled(); bool setLensfunCamera(const Glib::ustring& make, const Glib::ustring& model); bool setLensfunLens(const Glib::ustring& lens); @@ -113,12 +115,14 @@ private: bool allowFocusDep; bool isRaw; const rtengine::FramesMetaData* metadata; + std::unique_ptr metadataCorrection; Gtk::Grid* const modesGrid; Gtk::Grid* const distGrid; Gtk::RadioButton* const corrUnchangedRB; Gtk::RadioButton::Group corrGroup; Gtk::RadioButton* const corrOffRB; + Gtk::RadioButton* const corrMetadata; Gtk::RadioButton* const corrLensfunAutoRB; Gtk::RadioButton* const corrLensfunManualRB; Gtk::RadioButton* const corrLcpFileRB; From f64ad13363c340815b67fe74119189126536f40c Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Thu, 13 Jun 2024 20:23:25 +0200 Subject: [PATCH 34/39] lensmetadata: add abstract center radius helper class Add a CenterRadiusMetadataLensCorrection helper class that will be implemented by vendor specific corrections based on center radius. --- rtengine/lensmetadata.cc | 108 +++++++++++++++++++++++++++++++++++++++ rtengine/lensmetadata.h | 42 +++++++++++++++ 2 files changed, 150 insertions(+) diff --git a/rtengine/lensmetadata.cc b/rtengine/lensmetadata.cc index e92fc6cc9..c531de65b 100644 --- a/rtengine/lensmetadata.cc +++ b/rtengine/lensmetadata.cc @@ -24,6 +24,114 @@ namespace rtengine { +CenterRadiusMetadataLensCorrection::CenterRadiusMetadataLensCorrection(const FramesMetaData *meta) : + swap_xy(false) +{ + metadata = Exiv2Metadata(meta->getFileName()); + metadata.load(); +} + +void CenterRadiusMetadataLensCorrection::initCorrections(int width, int height, const procparams::CoarseTransformParams &coarse, int rawRotationDeg) +{ + if (rawRotationDeg >= 0) { + int rot = (coarse.rotate + rawRotationDeg) % 360; + swap_xy = (rot == 90 || rot == 270); + if (swap_xy) { + std::swap(width, height); + } + } + + w2 = width * 0.5f; + h2 = height * 0.5f; + rf = 1 / std::sqrt(SQR(w2) + SQR(h2)); +} + +void CenterRadiusMetadataLensCorrection::process(double &x, double &y, int cx, int cy, int channel, bool dist, bool ca) const +{ + double xx = x + cx; + double yy = y + cy; + if (swap_xy) { + std::swap(xx, yy); + } + + double xc = xx - w2; + double yc = yy - h2; + + double rout = rf * std::sqrt(SQR(xc) + SQR(yc)); + double cf = 1; + if (dist && ca) { + cf = distortionAndCACorrectionFactor(rout, channel); + } else if (dist) { + cf = distortionCorrectionFactor(rout); + } else if (ca) { + cf = caCorrectionFactor(rout, channel); + } + + x = cf * xc + w2; + y = cf * yc + h2; + + if (swap_xy) { + std::swap(x, y); + } + x -= cx; + y -= cy; +} + +void CenterRadiusMetadataLensCorrection::correctDistortionAndCA(double &x, double &y, int cx, int cy, int channel) const +{ + if (!hasDistortionCorrection() || !hasCACorrection()) { + return; + } + + process(x, y, cx, cy, channel, true, true); +} + +void CenterRadiusMetadataLensCorrection::correctDistortion(double &x, double &y, int cx, int cy) const +{ + if (!hasDistortionCorrection()) { + return; + } + + process(x, y, cx, cy, 1, true, false); +} + +void CenterRadiusMetadataLensCorrection::correctCA(double &x, double &y, int cx, int cy, int channel) const +{ + if (!hasCACorrection()) { + return; + } + + process(x, y, cx, cy, channel, false, true); +} + +void CenterRadiusMetadataLensCorrection::processVignetteNChannels(int width, int height, float **rawData, int channels) const +{ + if (!hasVignettingCorrection()) { + return; + } + + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + double xc = x - w2; + double yc = y - h2; + double sf = vignettingCorrectionFactor(rf * std::sqrt(SQR(xc) + SQR(yc))); + for (int c = 0; c < channels; c++) { + rawData[y][x + c] *= sf; + } + } + } +} + +void CenterRadiusMetadataLensCorrection::processVignette(int width, int height, float **rawData) const +{ + return processVignetteNChannels(width, height, rawData, 1); +} + +void CenterRadiusMetadataLensCorrection::processVignette3Channels(int width, int height, float **rawData) const +{ + return processVignetteNChannels(width, height, rawData, 3); +} + std::unique_ptr MetadataLensCorrectionFinder::findCorrection(const FramesMetaData *meta) { static const std::unordered_set makers = {}; diff --git a/rtengine/lensmetadata.h b/rtengine/lensmetadata.h index 7991af8cd..ac042b7ce 100644 --- a/rtengine/lensmetadata.h +++ b/rtengine/lensmetadata.h @@ -37,6 +37,48 @@ public: virtual void initCorrections(int width, int height, const procparams::CoarseTransformParams &coarse, int rawRotationDeg) = 0; }; +/* CenterRadiusMetadataLensCorrection is an abstract class the extends MetadataLensCorrection to easily handle center radius based corrections */ +class CenterRadiusMetadataLensCorrection : public MetadataLensCorrection +{ +public: + CenterRadiusMetadataLensCorrection(const FramesMetaData *meta); + + void process(double &x, double &y, int cx, int cy, int channel, bool dist, bool ca) const; + + void correctDistortionAndCA(double &x, double &y, int cx, int cy, int channel) const override; + void correctDistortion(double &x, double &y, int cx, int cy) const override; + void correctCA(double &x, double &y, int cx, int cy, int channel) const override; + void processVignette(int width, int height, float **rawData) const override; + void processVignette3Channels(int width, int height, float **rawData) const override; + + void processVignetteNChannels(int width, int height, float **rawData, int channels) const; + void initCorrections(int width, int height, const procparams::CoarseTransformParams &coarse, int rawRotationDeg) override; + + /* Implementers should implement the below methods */ + virtual bool hasDistortionCorrection() const override = 0; + virtual bool hasCACorrection() const override = 0; + virtual bool hasVignettingCorrection() const override = 0; + + /* These methods should return the distortion correction factor (cf) for the + * provided radius rout (radius of the output image (corrected)). + * So rin = rout * cf + * */ + virtual double distortionCorrectionFactor(double rout) const = 0; + virtual double caCorrectionFactor(double rout, int channel) const = 0; + virtual double distortionAndCACorrectionFactor(double rout, int channel) const = 0; + + /* This methods should return the vignetting correction factor (cf) for the + * provided radius */ + virtual double vignettingCorrectionFactor(double r) const = 0; + +protected: + bool swap_xy; + double w2; + double h2; + double rf; + Exiv2Metadata metadata; +}; + /* MetadataLensCorrectionFinder tries to find and return MetadataLensCorrection for the provided metadata */ class MetadataLensCorrectionFinder { From 27dc084e81b3145eae103919a2395d3d25b0c036 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Thu, 13 Jun 2024 20:26:22 +0200 Subject: [PATCH 35/39] Add Sony metadata lens correction --- rtengine/lensmetadata.cc | 163 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 162 insertions(+), 1 deletion(-) diff --git a/rtengine/lensmetadata.cc b/rtengine/lensmetadata.cc index c531de65b..0e8156f39 100644 --- a/rtengine/lensmetadata.cc +++ b/rtengine/lensmetadata.cc @@ -24,6 +24,31 @@ namespace rtengine { +namespace +{ + +/* interpolateLinearSpline does a simple linear spline interpolation. Values + * outside the external knots will return the value of the nearest knot without + * any additional interpolation. */ +double interpolateLinearSpline(const std::vector &xi, const std::vector &yi, double x) +{ + if (x < xi[0]) { + return yi[0]; + } + + for (size_t i = 1; i < xi.size(); i++) { + if (x >= xi[i - 1] && x <= xi[i]) { + double dydx = (yi[i] - yi[i - 1]) / (xi[i] - xi[i - 1]); + + return yi[i - 1] + (x - xi[i - 1]) * dydx; + } + } + + return yi[yi.size() - 1]; +} + +} // namespace + CenterRadiusMetadataLensCorrection::CenterRadiusMetadataLensCorrection(const FramesMetaData *meta) : swap_xy(false) { @@ -132,9 +157,133 @@ void CenterRadiusMetadataLensCorrection::processVignette3Channels(int width, int return processVignetteNChannels(width, height, rawData, 3); } +/* Fuji, Sony, Olympus metadata handling and algorithms adapted from + * - src/iop/lens.cc + * - src/common/exif.cc + * in darktable 4.6 */ +/* + This file is part of darktable, + Copyright (C) 2019-2024 darktable developers. + + darktable 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. + + darktable 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 darktable. If not, see . +*/ + +class SonyMetadataLensCorrection : public CenterRadiusMetadataLensCorrection +{ +public: + SonyMetadataLensCorrection(const FramesMetaData *meta) : + CenterRadiusMetadataLensCorrection(meta) + { + parse(); + setup(); + } + +private: + int nc; + std::array distortion; + std::array ca_r; + std::array ca_b; + std::array vignetting; + + std::vector knots; + std::vector dist; + std::array, 3> ca; + std::vector vig; + + void parse() + { + if (Exiv2::versionNumber() < EXIV2_MAKE_VERSION(0, 27, 4)) { + throw std::runtime_error("cannot get Sony correction data, too old exiv2 version " + Exiv2::versionString()); + } + + auto &exif = metadata.exifData(); + + auto posd = exif.findKey(Exiv2::ExifKey("Exif.SubImage1.DistortionCorrParams")); + auto posc = exif.findKey(Exiv2::ExifKey("Exif.SubImage1.ChromaticAberrationCorrParams")); + auto posv = exif.findKey(Exiv2::ExifKey("Exif.SubImage1.VignettingCorrParams")); + + /* Sony metadata corrections parameters define some splines with N knots */ + if (posd == exif.end() || posc == exif.end() || posv == exif.end()) { + throw std::runtime_error("cannot get Sony correction data"); + } + + const int nc = to_long(posd); + if (nc <= 16 && 2 * nc == to_long(posc) && nc == to_long(posv)) { + this->nc = nc; + for (int i = 0; i < nc; i++) { + distortion[i] = to_long(posd, i + 1); + ca_r[i] = to_long(posc, i + 1); + ca_b[i] = to_long(posc, nc + i + 1); + vignetting[i] = to_long(posv, i + 1); + } + } else { + throw std::runtime_error("cannot get Sony correction data"); + } + } + + void setup() + { + knots.resize(nc); + dist.resize(nc); + vig.resize(nc); + for (int i = 0; i < 3; ++i) { + ca[i].resize(nc); + } + + for (int i = 0; i < this->nc; i++) { + knots[i] = (i + 0.5) / (nc - 1); + + dist[i] = distortion[i] * powf(2, -14) + 1; + + ca[0][i] = ca[1][i] = ca[2][i] = 1.f; + ca[0][i] *= ca_r[i] * powf(2, -21) + 1; + ca[2][i] *= ca_b[i] * powf(2, -21) + 1; + + vig[i] = 1 / powf(2, 0.5f - powf(2, vignetting[i] * powf(2, -13) - 1)); + } + } + + double distortionCorrectionFactor(double rout) const override + { + return interpolateLinearSpline(knots, dist, rout); + } + + double caCorrectionFactor(double rout, int channel) const override + { + return interpolateLinearSpline(knots, ca[channel], rout); + } + + double distortionAndCACorrectionFactor(double rout, int channel) const override + { + return distortionCorrectionFactor(rout) * caCorrectionFactor(rout, channel); + } + + double vignettingCorrectionFactor(double r) const override + { + return interpolateLinearSpline(knots, vig, r); + } + + bool hasDistortionCorrection() const override { return true; } + bool hasVignettingCorrection() const override { return true; } + bool hasCACorrection() const override { return true; } +}; + std::unique_ptr MetadataLensCorrectionFinder::findCorrection(const FramesMetaData *meta) { - static const std::unordered_set makers = {}; + static const std::unordered_set makers = { + "SONY", + }; std::string make = Glib::ustring(meta->getMake()).uppercase(); @@ -144,6 +293,18 @@ std::unique_ptr MetadataLensCorrectionFinder::findCorrec std::unique_ptr correction; + try { + if (make == "SONY") { + correction.reset(new SonyMetadataLensCorrection(meta)); + } + } catch (std::exception &exc) { + if (settings->verbose) { + std::cerr << "error parsing lens metadata: " << exc.what() << std::endl; + } + + correction.reset(nullptr); + } + return correction; } From b570c70f5b47233e3a3b8d99ac0502041a5692a4 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Thu, 13 Jun 2024 20:27:16 +0200 Subject: [PATCH 36/39] Add Fujifilm metadata lens correction --- rtengine/lensmetadata.cc | 207 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) diff --git a/rtengine/lensmetadata.cc b/rtengine/lensmetadata.cc index 0e8156f39..006976371 100644 --- a/rtengine/lensmetadata.cc +++ b/rtengine/lensmetadata.cc @@ -279,10 +279,215 @@ private: bool hasCACorrection() const override { return true; } }; +class FujiMetadataLensCorrection : public CenterRadiusMetadataLensCorrection +{ +public: + FujiMetadataLensCorrection(const FramesMetaData *meta) : + CenterRadiusMetadataLensCorrection(meta) + { + parse(); + setup(); + } + +private: + const static int MAXKNOTS = 16; + + int nc; + double cropf; + + std::array fuji_knots; + std::array fuji_distortion; + std::array fuji_ca_r; + std::array fuji_ca_b; + std::array fuji_vignetting; + + std::vector knots_dist; + std::vector dist; + std::array, 3> ca; + std::vector knots_vig; + std::vector vig; + + void parse() + { + if (Exiv2::versionNumber() < EXIV2_MAKE_VERSION(0, 27, 4)) { + throw std::runtime_error("cannot get Fuji correction data, too old exiv2 version " + Exiv2::versionString()); + } + + auto &exif = metadata.exifData(); + + /* FujiFilm metadata corrections parameters define some splines with N knots */ + auto posd = exif.findKey(Exiv2::ExifKey("Exif.Fujifilm.GeometricDistortionParams")); + auto posc = exif.findKey(Exiv2::ExifKey("Exif.Fujifilm.ChromaticAberrationParams")); + auto posv = exif.findKey(Exiv2::ExifKey("Exif.Fujifilm.VignettingParams")); + + // X-Trans IV/V + if (posd != exif.end() && posc != exif.end() && posv != exif.end() && + posd->count() == 19 && posc->count() == 29 && posv->count() == 19) { + const int nc = 9; + this->nc = nc; + + for (int i = 0; i < nc; i++) { + const float kd = posd->toFloat(i + 1); + const float kc = posc->toFloat(i + 1); + const float kv = posv->toFloat(i + 1); + + // Check that the knots position is the same for distortion, ca and vignetting, + if (kd != kc || kd != kv) { + throw std::runtime_error("cannot get Fuji correction data: unexpected data"); + } + + fuji_knots[i] = kd; + fuji_distortion[i] = posd->toFloat(i + 10); + fuji_ca_r[i] = posc->toFloat(i + 10); + fuji_ca_b[i] = posc->toFloat(i + 19); + fuji_vignetting[i] = posv->toFloat(i + 10); + } + + // Account for the 1.25x crop modes in some Fuji cameras + auto it = exif.findKey(Exiv2::ExifKey("Exif.Fujifilm.CropMode")); + + if (it != exif.end() && (to_long(it) == 2 || to_long(it) == 4)) { + cropf = 1.25f; + } else { + cropf = 1; + } + } + // X-Trans I/II/III + else if (posd != exif.end() && posc != exif.end() && posv != exif.end() && + posd->count() == 23 && posc->count() == 31 && posv->count() == 23) { + const int nc = 11; + this->nc = nc; + + for (int i = 0; i < nc; i++) { + const float kd = posd->toFloat(i + 1); + float kc = 0; + // ca data doesn't provide first knot (0) + if (i != 0) kc = posc->toFloat(i); + const float kv = posv->toFloat(i + 1); + // check that the knots position is the same for distortion, ca and vignetting, + if (kd != kc || kd != kv) { + throw std::runtime_error("cannot get Fuji correction data: unexpected data"); + } + + fuji_knots[i] = kd; + fuji_distortion[i] = posd->toFloat(i + 12); + + // ca data doesn't provide first knot (0) + if (i == 0) { + fuji_ca_r[i] = 0; + fuji_ca_b[i] = 0; + } else { + fuji_ca_r[i] = posc->toFloat(i + 10); + fuji_ca_b[i] = posc->toFloat(i + 20); + } + fuji_vignetting[i] = posv->toFloat(i + 12); + } + + // Account for the 1.25x crop modes in some Fuji cameras + auto it = exif.findKey(Exiv2::ExifKey("Exif.Fujifilm.CropMode")); + + if (it != exif.end() && (to_long(it) == 2 || to_long(it) == 4)) { + cropf = 1.25f; + } else { + cropf = 1; + } + } else { + throw std::runtime_error("cannot get Fuji correction data"); + } + } + + void setup() + { + std::vector knots_in; + std::vector distortion_in; + std::vector ca_r_in; + std::vector ca_b_in; + + // add a knot with no corrections at 0 value if not existing + int size = nc; + if (fuji_knots[0] > 0.f) { + knots_in.push_back(0); + distortion_in.push_back(1); + ca_r_in.push_back(0); + ca_b_in.push_back(0); + + knots_vig.push_back(0); + vig.push_back(1); + + size++; + } + + knots_in.reserve(size); + vig.reserve(size); + + for (int i = 0; i < nc; i++) { + knots_in.push_back(cropf * fuji_knots[i]); + distortion_in.push_back(fuji_distortion[i] / 100 + 1); + ca_r_in.push_back(fuji_ca_r[i]); + ca_b_in.push_back(fuji_ca_b[i]); + + // vignetting correction is applied before distortion correction. So the + // spline is related to the source image before distortion. + knots_vig.push_back(cropf * fuji_knots[i]); + + vig.push_back(100 / fuji_vignetting[i]); + } + + knots_dist.resize(MAXKNOTS); + dist.resize(MAXKNOTS); + for (int i = 0; i < 3; ++i) { + ca[i].resize(MAXKNOTS); + } + + // convert from spline related to source image (input is source image + // radius) to spline related to dest image (input is dest image radius) + for (int i = 0; i < MAXKNOTS; i++) { + const double rin = static_cast(i) / static_cast(nc - 1); + const double m = interpolateLinearSpline(knots_in, distortion_in, rin); + const double r = rin / m; + knots_dist[i] = r; + + dist[i] = m; + + const double mcar = interpolateLinearSpline(knots_in, ca_r_in, rin); + const double mcab = interpolateLinearSpline(knots_in, ca_b_in, rin); + + ca[0][i] = ca[1][i] = ca[2][i] = 1.f; + ca[0][i] *= mcar + 1; + ca[2][i] *= mcab + 1; + } + } + + double distortionCorrectionFactor(double rout) const override + { + return interpolateLinearSpline(knots_dist, dist, rout); + } + + double caCorrectionFactor(double rout, int channel) const override + { + return interpolateLinearSpline(knots_dist, ca[channel], rout); + } + + double distortionAndCACorrectionFactor(double rout, int channel) const override + { + return distortionCorrectionFactor(rout) * caCorrectionFactor(rout, channel); + } + + double vignettingCorrectionFactor(double r) const override + { + return interpolateLinearSpline(knots_vig, vig, r); + } + + bool hasDistortionCorrection() const override { return true; } + bool hasVignettingCorrection() const override { return true; } + bool hasCACorrection() const override { return true; } +}; + std::unique_ptr MetadataLensCorrectionFinder::findCorrection(const FramesMetaData *meta) { static const std::unordered_set makers = { "SONY", + "FUJIFILM", }; std::string make = Glib::ustring(meta->getMake()).uppercase(); @@ -296,6 +501,8 @@ std::unique_ptr MetadataLensCorrectionFinder::findCorrec try { if (make == "SONY") { correction.reset(new SonyMetadataLensCorrection(meta)); + } else if (make == "FUJIFILM") { + correction.reset(new FujiMetadataLensCorrection(meta)); } } catch (std::exception &exc) { if (settings->verbose) { From 3189efddceb1d28b5b619caec56527ecacc5a974 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Thu, 13 Jun 2024 20:28:19 +0200 Subject: [PATCH 37/39] Add Olympus metadata lens correction --- rtengine/lensmetadata.cc | 131 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/rtengine/lensmetadata.cc b/rtengine/lensmetadata.cc index 006976371..91adadd8a 100644 --- a/rtengine/lensmetadata.cc +++ b/rtengine/lensmetadata.cc @@ -483,11 +483,140 @@ private: bool hasCACorrection() const override { return true; } }; +class OlympusMetadataLensCorrection : public CenterRadiusMetadataLensCorrection +{ +public: + OlympusMetadataLensCorrection(const FramesMetaData *meta) : + CenterRadiusMetadataLensCorrection(meta), has_dist(false), has_ca(false) + { + parse(); + } + +private: + bool has_dist, has_ca; + + double drs; + double dk2; + double dk4; + double dk6; + + double car0; + double car2; + double car4; + double cab0; + double cab2; + double cab4; + + void parse() + { + if (Exiv2::versionNumber() < EXIV2_MAKE_VERSION(0, 27, 4)) { + throw std::runtime_error("cannot get Olympus correction data, too old exiv2 version " + Exiv2::versionString()); + } + + auto &exif = metadata.exifData(); + + std::array distortion; + std::array cacorr; + + auto it = exif.findKey(Exiv2::ExifKey("Exif.OlympusIp.0x150a")); + if (it != exif.end() && it->count() == 4) { + for (int i = 0; i < 4; ++i) { + distortion[i] = it->toFloat(i); + } + has_dist = true; + } + + it = exif.findKey(Exiv2::ExifKey("Exif.OlympusIp.0x150c")); + if (it != exif.end() && it->count() == 6) { + for (int i = 0; i < 6; ++i) { + cacorr[i] = it->toFloat(i); + } + has_ca = true; + } + + if (has_dist) { + drs = distortion[3]; + dk2 = distortion[0]; + dk4 = distortion[1]; + dk6 = distortion[2]; + } + + if (has_ca) { + car0 = cacorr[0]; + car2 = cacorr[1]; + car4 = cacorr[2]; + cab0 = cacorr[3]; + cab2 = cacorr[4]; + cab4 = cacorr[5]; + } + + if (!has_dist && !has_ca) { + throw std::runtime_error("no Olympus correction data"); + } + } + + double distortionCorrectionFactor(double rout) const override + { + // The distortion polynomial maps a radius Rout in the output + // (undistorted) image, where the corner is defined as Rout=1, to a + // radius in the input (distorted) image, where the corner is defined + // as Rin=1. + // Rin = Rout*drs * (1 + dk2 * (Rout*drs)^2 + dk4 * (Rout*drs)^4 + dk6 * (Rout*drs)^6) + // + // cf is Rin / Rout. + + const double rs2 = std::pow(rout * drs, 2); + const double cf = drs * (1 + rs2 * (dk2 + rs2 * (dk4 + rs2 * dk6))); + + return cf; + } + + double caCorrectionFactor(double rout, int channel) const override + { + // ca corrects only red and blue channel + if (channel != 0 && channel != 2) return 1; + + // CA correction is applied as: + // Rin = Rout * ((1 + car0) + car2 * Rout^2 + car4 * Rout^4) + // + // cf is Rin / Rout. + + const double r2 = powf(rout, 2); + if (channel == 0) { + return 1 + (car0 + r2 * (car2 + r2 * car4)); + } else if (channel == 2) { + return 1 + (cab0 + r2 * (cab2 + r2 * cab4)); + } + + return 1; + } + + double distortionAndCACorrectionFactor(double rout, int channel) const override + { + return distortionCorrectionFactor(rout) * caCorrectionFactor(rout, channel); + } + + double vignettingCorrectionFactor(double r) const override + { + return 1; + } + + bool hasDistortionCorrection() const override { return has_dist; } + // Olympus cameras have a shading correction option that fixes vignetting + // already in the raw file. Looks like they don't report vignetting + // correction parameters inside metadata even if shading correction is + // disabled. + bool hasVignettingCorrection() const override { return false; } + bool hasCACorrection() const override { return has_ca; } +}; + std::unique_ptr MetadataLensCorrectionFinder::findCorrection(const FramesMetaData *meta) { static const std::unordered_set makers = { "SONY", "FUJIFILM", + "OLYMPUS", + "OM DIGITAL SOLUTIONS", }; std::string make = Glib::ustring(meta->getMake()).uppercase(); @@ -503,6 +632,8 @@ std::unique_ptr MetadataLensCorrectionFinder::findCorrec correction.reset(new SonyMetadataLensCorrection(meta)); } else if (make == "FUJIFILM") { correction.reset(new FujiMetadataLensCorrection(meta)); + } else if (make == "OLYMPUS" || make == "OM DIGITAL SOLUTIONS") { + correction.reset(new OlympusMetadataLensCorrection(meta)); } } catch (std::exception &exc) { if (settings->verbose) { From c589e9d469cb41bfc24f39051735647d315d0d29 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Thu, 13 Jun 2024 20:29:07 +0200 Subject: [PATCH 38/39] Add Panasonic metadata lens correction --- rtengine/lensmetadata.cc | 92 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/rtengine/lensmetadata.cc b/rtengine/lensmetadata.cc index 91adadd8a..f6b7e7331 100644 --- a/rtengine/lensmetadata.cc +++ b/rtengine/lensmetadata.cc @@ -610,6 +610,95 @@ private: bool hasCACorrection() const override { return has_ca; } }; +/* Panasonic metadata lens correction + * Currently disabled since the algorithm is not stable and works well with only some lenses. + * + * Data extraction and distortion correction formula from: + * https://web.archive.org/web/20120701131817/https://syscall.eu/#pana + * + * TODO(sgotti) + * * CA corrections not yet reverse engineered. + * * From a post on the exiftool forum: + * https://exiftool.org/forum/index.php?topic=9366.0 + * looks like there's another additional tag that provides similar data and it's + * used by newer cameras. + */ +class PanasonicMetadataLensCorrection : public CenterRadiusMetadataLensCorrection +{ +public: + PanasonicMetadataLensCorrection(const FramesMetaData *meta) : + CenterRadiusMetadataLensCorrection(meta), has_dist(false), a(0), b(0), c(0) + { + // Currently disabled since the algorithm is not stable and works well with only some lenses. + throw std::runtime_error("panasonic correction disabled as it's not yet working properly"); + + // parse(); + } + +private: + bool has_dist; + double scale, a, b, c; + + void parse() + { + if (Exiv2::versionNumber() < EXIV2_MAKE_VERSION(0, 27, 4)) { + throw std::runtime_error("cannot get Panasonic correction data, too old exiv2 version " + Exiv2::versionString()); + } + + auto &exif = metadata.exifData(); + + auto it = exif.findKey(Exiv2::ExifKey("Exif.PanasonicRaw.0x0119")); + if (it != exif.end()) { + std::vector buf; + buf.resize(it->value().size()); + it->value().copy(buf.data(), Exiv2::littleEndian); + + const Exiv2::byte *data = buf.data(); + // n is currently unused + // uint32_t n = Exiv2::getShort(data + 24, Exiv2::littleEndian); + scale = 1.0f / (1.0f + Exiv2::getShort(data + 10, Exiv2::littleEndian) / 32768.0f); + a = Exiv2::getShort(data + 16, Exiv2::littleEndian) / 32768.0f; + b = Exiv2::getShort(data + 8, Exiv2::littleEndian) / 32768.0f; + c = Exiv2::getShort(data + 22, Exiv2::littleEndian) / 32768.0f; + + has_dist = true; + } + } + + double distortionCorrectionFactor(double rout) const override + { + const double rs2 = std::pow(rout, 2); + + const double rin = scale * rout * (1 + rs2 * (a + rs2 * (b + rs2 * c))); + const double cf = rout / rin; + + return cf; + } + + double caCorrectionFactor(double rout, int channel) const override + { + return 1; + } + + double distortionAndCACorrectionFactor(double rout, int channel) const override + { + return distortionCorrectionFactor(rout); + } + + double vignettingCorrectionFactor(double r) const override + { + return 1; + } + + bool hasDistortionCorrection() const override { return has_dist; } + // Panasonic cameras have a shading correction option that fixes vignetting + // already in the raw file. Looks like they don't report vignetting + // correction parameters inside metadata even if shading correction is + // disabled. + bool hasVignettingCorrection() const override { return false; } + bool hasCACorrection() const override { return false; } +}; + std::unique_ptr MetadataLensCorrectionFinder::findCorrection(const FramesMetaData *meta) { static const std::unordered_set makers = { @@ -617,6 +706,7 @@ std::unique_ptr MetadataLensCorrectionFinder::findCorrec "FUJIFILM", "OLYMPUS", "OM DIGITAL SOLUTIONS", + "PANASONIC", }; std::string make = Glib::ustring(meta->getMake()).uppercase(); @@ -634,6 +724,8 @@ std::unique_ptr MetadataLensCorrectionFinder::findCorrec correction.reset(new FujiMetadataLensCorrection(meta)); } else if (make == "OLYMPUS" || make == "OM DIGITAL SOLUTIONS") { correction.reset(new OlympusMetadataLensCorrection(meta)); + } else if (make == "PANASONIC") { + correction.reset(new PanasonicMetadataLensCorrection(meta)); } } catch (std::exception &exc) { if (settings->verbose) { From 7deb2754d1f31beff891063b476905d4093e8570 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Thu, 13 Jun 2024 20:29:30 +0200 Subject: [PATCH 39/39] Add DNG metadata lens correction --- rtengine/lensmetadata.cc | 306 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 304 insertions(+), 2 deletions(-) diff --git a/rtengine/lensmetadata.cc b/rtengine/lensmetadata.cc index f6b7e7331..89a1ab13b 100644 --- a/rtengine/lensmetadata.cc +++ b/rtengine/lensmetadata.cc @@ -699,6 +699,306 @@ private: bool hasCACorrection() const override { return false; } }; +// Class DNGMetadatalensCorrection handles OpcodeList3 operations: operations to +// be done after demosaicing. +// OpcodeList1 is already handled by rawimagesource.cc. OpcodeList2 is not yet +// handled by rawtherapee. +// TODO(sgotti): dng spec provides clear rules on how and when to process the +// various opcodeList1/2/3 and the order of the various operations that should +// be done. +// Currently we only handle a subset of all the available opcodes and only one +// WarpRectilinar for distortion and FixVignetteRadial for vignetting (that's +// usually the case with Leica DNGs and ADC generated DNGs). +// This should be extended to support more exotic operations lists (i.e. +// multiple WarpRectilinear) +class DNGMetadataLensCorrection : public MetadataLensCorrection +{ +public: + DNGMetadataLensCorrection(const FramesMetaData *meta) : + MetadataLensCorrection(), swap_xy(false) + { + metadata = Exiv2Metadata(meta->getFileName()); + metadata.load(); + + parse(); + } + +private: + Exiv2Metadata metadata; + + bool swap_xy; + int width, height; + + double crx_d; + double cry_d; + double crx_v; + double cry_v; + + double cx_d; + double cy_d; + double m_v; + + double cx_v; + double cy_v; + double m_d; + + int planes; + + bool has_dist, has_ca, has_vign; + std::array, 3> warp_rectilinear; + std::array vignette_radial; + + void initCorrections(int width, int height, const procparams::CoarseTransformParams &coarse, int rawRotationDeg) override + { + if (rawRotationDeg >= 0) { + int rot = (coarse.rotate + rawRotationDeg) % 360; + swap_xy = (rot == 90 || rot == 270); + if (swap_xy) { + std::swap(width, height); + } + } + + this->width = width; + this->height = height; + + setup(); + } + + void parse() + { + std::set processed_opcodes; + + has_dist = has_ca = has_vign = false; + + auto &exif = metadata.exifData(); + + auto it = exif.findKey(Exiv2::ExifKey("Exif.SubImage1.OpcodeList3")); + + if (it != exif.end()) { + std::vector buf; + buf.resize(it->value().size()); + it->value().copy(buf.data(), Exiv2::invalidByteOrder); + + const Exiv2::byte *data = buf.data(); + uint32_t num_entries = Exiv2::getULong(data, Exiv2::bigEndian); + size_t idx = 4; + + for (size_t i = 0; i < num_entries && idx < buf.size(); ++i) { + uint32_t opcodeID = Exiv2::getULong(data + idx, Exiv2::bigEndian); + idx += 4; + idx += 4; // version + uint32_t flags = Exiv2::getULong(data + idx, Exiv2::bigEndian); + idx += 4; + size_t paramSize = Exiv2::getULong(data + idx, Exiv2::bigEndian); + idx += 4; + + if (idx + paramSize > buf.size()) { + throw std::runtime_error("error parsing DNG OpcodeList3"); + } + + if (processed_opcodes.find(opcodeID) != processed_opcodes.end()) { + // we currently handle only one opcode per type and ignore next ones if provided. + if (settings->verbose) { + std::printf("DNG OpcodeList3 %s opcode %d already processed\n", flags & 1 ? "optional" : "mandatory", opcodeID); + } + + idx += paramSize; + continue; + } + + processed_opcodes.insert(opcodeID); + + // we currently handle only one dist correction + if (opcodeID == 1 && !has_dist) { // WarpRectilinear + + planes = Exiv2::getULong(data + idx, Exiv2::bigEndian); + + if ((planes != 1) && (planes != 3)) { + throw std::runtime_error("cannot parse DNG WarpRectilinear"); + } + + for (int p = 0; p < planes; p++) { + for (int i = 0; i < 6; i++) { + warp_rectilinear[p][i] = Exiv2::getDouble(data + idx + 4 + 8 * (i + p * 6), Exiv2::bigEndian); + } + } + + crx_d = Exiv2::getDouble(data + idx + 4 + 8 * (0 + planes * 6), Exiv2::bigEndian); + cry_d = Exiv2::getDouble(data + idx + 4 + 8 * (1 + planes * 6), Exiv2::bigEndian); + + has_dist = true; + if (planes == 3) { + has_ca = true; + } + + // we currently handle only one vignetting correction + } else if (opcodeID == 3 && !has_vign) { // FixVignetteRadial + size_t start = idx; + size_t end = idx + 7 * 8; + if (end > buf.size()) { + throw std::runtime_error("cannot parse DNG FixVignetteRadial"); + } + for (int j = 0; j < 5; j++) { + vignette_radial[j] = Exiv2::getDouble(data + start, Exiv2::bigEndian); + start += 8; + } + crx_v = Exiv2::getDouble(data + start, Exiv2::bigEndian); + start += 8; + cry_v = Exiv2::getDouble(data + start, Exiv2::bigEndian); + has_vign = true; + + } else { + if (settings->verbose) { + std::printf("DNG OpcodeList3 has unsupported %s opcode %d\n", flags & 1 ? "optional" : "mandatory", opcodeID); + } + } + + idx += paramSize; + } + } + + if (!has_dist && !has_vign) { + throw std::runtime_error("no known DNG correction data"); + } + } + + void setup() + { + cx_d = crx_d * width; + cy_d = cry_d * height; + cx_v = crx_v * width; + cy_v = cry_v * height; + double mx_d = std::max(cx_d, width - cx_d); + double my_d = std::max(cy_d, height - cy_d); + m_d = std::sqrt(SQR(mx_d) + SQR(my_d)); + double mx_v = std::max(cx_v, width - cx_v); + double my_v = std::max(cy_v, height - cy_v); + m_v = std::sqrt(SQR(mx_v) + SQR(my_v)); + } + + void correctPlaneDistortion(double &x, double &y, int cx, int cy, int plane) const + { + if (plane < 0 || plane > 2 || plane > planes) { + return; + } + + double xx = x + cx; + double yy = y + cy; + if (swap_xy) { + std::swap(xx, yy); + } + + const double cx1 = cx_d; + const double cy1 = cy_d; + const double m = m_d; + + const double dx = (xx - cx1) / m; + const double dy = (yy - cy1) / m; + const double dx2 = SQR(dx); + const double dy2 = SQR(dy); + const double r2 = dx2 + dy2; + const double f = warp_rectilinear[plane][0] + r2 * (warp_rectilinear[plane][1] + r2 * (warp_rectilinear[plane][2] + r2 * warp_rectilinear[plane][3])); + const double dx_r = f * dx; + const double dy_r = f * dy; + const double dxdy2 = 2 * dx * dy; + const double dx_t = warp_rectilinear[plane][4] * dxdy2 + warp_rectilinear[plane][5] * (r2 + 2 * dx2); + const double dy_t = warp_rectilinear[plane][5] * dxdy2 + warp_rectilinear[plane][4] * (r2 + 2 * dy2); + + x = cx1 + m * (dx_r + dx_t); + y = cy1 + m * (dy_r + dy_t); + + if (swap_xy) { + std::swap(x, y); + } + x -= cx; + y -= cy; + } + + void correctDistortionAndCA(double &x, double &y, int cx, int cy, int channel) const override + { + if (!hasDistortionCorrection() || !hasCACorrection()) { + return; + } + + correctPlaneDistortion(x, y, cx, cy, channel); + } + + void correctDistortion(double &x, double &y, int cx, int cy) const override + { + if (!hasDistortionCorrection()) { + return; + } + + int plane = 1; // 3 planes correction, use plane 1 (green) + if (planes == 1) { + plane = 0; // 1 single plane correction + } + + correctPlaneDistortion(x, y, cx, cy, plane); + } + + void correctCA(double &x, double &y, int cx, int cy, int channel) const override + { + if (!hasCACorrection()) { + return; + } + + // we use plane 0 (red) and plane 2 (blue) for ca correction + if (channel != 0 && channel != 2) return; + if (planes != 3) return; + + double xgreen = x, ygreen = y; + correctPlaneDistortion(xgreen, ygreen, cx, cy, 1); + + double xch = x, ych = y; + correctPlaneDistortion(xch, ych, cx, cy, channel); + + // Calculate diff from green plane + x += xch - xgreen; + y += ych - ygreen; + } + + void processVignetteNChannels(int width, int height, float **rawData, int channels) const + { + if (!hasVignettingCorrection()) { + return; + } + + const double cx = cx_v; + const double cy = cy_v; + const double m2 = 1.f / SQR(m_v); + + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + const double r2 = m2 * (SQR(x - cx) + SQR(y - cy)); + const double g = 1.f + r2 * (vignette_radial[0] + r2 * (vignette_radial[1] + r2 * (vignette_radial[2] + r2 * (vignette_radial[3] + r2 * vignette_radial[4])))); + for (int c = 0; c < channels; ++c) { + rawData[y][x*channels + c] *= g; + } + } + } + } + + void processVignette(int width, int height, float **rawData) const override + { + return processVignetteNChannels(width, height, rawData, 1); + } + + void processVignette3Channels(int width, int height, float **rawData) const override + { + return processVignetteNChannels(width, height, rawData, 3); + } + + bool isCACorrectionAvailable() const + { + return hasCACorrection(); + } + + bool hasDistortionCorrection() const override { return has_dist; } + bool hasVignettingCorrection() const override { return has_vign; } + bool hasCACorrection() const override { return has_ca; } +}; + std::unique_ptr MetadataLensCorrectionFinder::findCorrection(const FramesMetaData *meta) { static const std::unordered_set makers = { @@ -711,14 +1011,16 @@ std::unique_ptr MetadataLensCorrectionFinder::findCorrec std::string make = Glib::ustring(meta->getMake()).uppercase(); - if (makers.find(make) == makers.end()) { + if (!meta->getDNG() && makers.find(make) == makers.end()) { return nullptr; } std::unique_ptr correction; try { - if (make == "SONY") { + if (meta->getDNG()) { + correction.reset(new DNGMetadataLensCorrection(meta)); + } else if (make == "SONY") { correction.reset(new SonyMetadataLensCorrection(meta)); } else if (make == "FUJIFILM") { correction.reset(new FujiMetadataLensCorrection(meta));