diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index e0cf17531..52869e981 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 automake | 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 automake | tee -a depslog date -u echo "----====Pourage====----" cat depslog | grep Pouring @@ -35,9 +35,9 @@ 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 + -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 @@ -49,7 +49,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" \ @@ -64,7 +64,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 \ 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") 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 3f55de8aa..2841f9603 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 @@ -1784,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 @@ -2038,7 +2047,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 @@ -2830,6 +2839,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 @@ -2931,7 +2941,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 @@ -3091,7 +3101,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 @@ -3568,7 +3579,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/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/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 86b0e3135..d3a137959 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -153,6 +153,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/camconst.json b/rtengine/camconst.json index b80d776b8..8abe2a7b9 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 @@ -2101,6 +2106,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 diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index d7d058eb8..5626482fe 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; @@ -7226,7 +7227,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; @@ -8051,6 +8052,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, @@ -8089,6 +8096,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, @@ -8099,6 +8108,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, @@ -8123,8 +8134,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, @@ -8137,12 +8154,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, @@ -8165,6 +8216,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, @@ -8173,12 +8226,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, @@ -8191,6 +8248,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, @@ -8201,12 +8260,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, @@ -8243,14 +8308,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 */ @@ -8265,14 +8340,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 */ @@ -8291,6 +8376,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, @@ -8303,9 +8390,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 } }, @@ -8349,7 +8442,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 } }, @@ -8365,6 +8458,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, @@ -8379,6 +8474,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, @@ -8391,6 +8488,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, @@ -8399,22 +8498,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, @@ -8425,11 +8625,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 } }, @@ -8455,6 +8655,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, @@ -8469,16 +8671,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, @@ -8489,6 +8737,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, @@ -8529,6 +8779,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, @@ -8571,6 +8823,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, @@ -8579,6 +8833,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, @@ -8587,6 +8843,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, @@ -8625,6 +8883,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, @@ -8633,6 +8909,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, @@ -8713,6 +8993,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, @@ -8735,12 +9019,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, @@ -8762,13 +9054,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 } }, @@ -8778,6 +9072,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, @@ -8790,6 +9086,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, @@ -8810,10 +9108,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, @@ -8830,8 +9134,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, @@ -8870,6 +9184,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, @@ -8900,6 +9216,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, @@ -8934,12 +9252,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, @@ -9000,28 +9332,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, @@ -9034,20 +9412,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, @@ -9074,6 +9492,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 */ @@ -9088,6 +9508,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, @@ -9098,6 +9532,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, @@ -9138,28 +9574,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, @@ -9180,6 +9644,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, 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/imagedata.cc b/rtengine/imagedata.cc index 8b03f15d7..89f1f0105 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -732,6 +732,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) // ------------------------ @@ -961,6 +963,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 1d7f715d3..5b9eb5d9a 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -60,6 +60,7 @@ private: time_t modTimeStamp; bool isPixelShift; bool isHDR; + bool isDNG; std::uint32_t fixBadPixelsConstant; bool hasFixBadPixelsConstant_{false}; std::vector gain_maps_; @@ -73,6 +74,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/imageio.cc b/rtengine/imageio.cc index 04bdbfb93..36c16f0d2 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -485,7 +485,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; @@ -496,7 +500,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 ) { @@ -558,7 +562,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"); 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/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/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/iptransform.cc b/rtengine/iptransform.cc index 3d384ee62..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; @@ -420,7 +421,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") ? @@ -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->hasDistortionCorrection()) { + pLCPMap->correctDistortion(Dx, Dy, w2, h2); + } + // distortion correction double s = 1; @@ -660,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); @@ -676,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; @@ -686,24 +692,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); - } } } @@ -1094,8 +1084,10 @@ 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 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(); const bool enablePCVignetting = needsPCVignetting(); const bool enableVignetting = needsVignetting(); @@ -1240,25 +1232,33 @@ 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; + const double Dxr = x_d * cost - y_d * sint; + const double Dyr = x_d * sint + y_d * cost; - // distortion correction - double s = 1.0; + for (int c = 0; c < (doCACorrection ? 3 : 1); ++c) { + double Dx = Dxr; + double Dy = Dyr; - if (enableDistortion) { - const double r = sqrt(Dxc * Dxc + Dyc * Dyc) / maxRadius; - s = 1.0 - distAmount + distAmount * r; - } + 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); + } - for (int c = 0; c < (enableCA ? 3 : 1); ++c) { - double Dx = Dxc * (s + chDist[c]); - double Dy = Dyc * (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 +1305,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 +1325,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 +1333,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 +1343,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 +1357,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)) { @@ -1500,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(); @@ -1517,9 +1451,8 @@ 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/lcp.cc b/rtengine/lcp.cc index 7507bbb11..0947cf709 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -985,11 +985,29 @@ 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); + 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..114131b4a 100644 --- a/rtengine/lcp.h +++ b/rtengine/lcp.h @@ -166,8 +166,13 @@ private: 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; @@ -194,8 +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/lensmetadata.cc b/rtengine/lensmetadata.cc new file mode 100644 index 000000000..89a1ab13b --- /dev/null +++ b/rtengine/lensmetadata.cc @@ -0,0 +1,1043 @@ +/* + * 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 +{ + +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) +{ + 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); +} + +/* 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; } +}; + +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; } +}; + +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; } +}; + +/* 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; } +}; + +// 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 = { + "SONY", + "FUJIFILM", + "OLYMPUS", + "OM DIGITAL SOLUTIONS", + "PANASONIC", + }; + + std::string make = Glib::ustring(meta->getMake()).uppercase(); + + if (!meta->getDNG() && makers.find(make) == makers.end()) { + return nullptr; + } + + std::unique_ptr correction; + + try { + 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)); + } 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) { + std::cerr << "error parsing lens metadata: " << exc.what() << std::endl; + } + + correction.reset(nullptr); + } + + return correction; +} + +} // namespace rtengine diff --git a/rtengine/lensmetadata.h b/rtengine/lensmetadata.h new file mode 100644 index 000000000..ac042b7ce --- /dev/null +++ b/rtengine/lensmetadata.h @@ -0,0 +1,89 @@ +/* + * 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; +}; + +/* 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 +{ +public: + static std::unique_ptr findCorrection(const FramesMetaData *meta); +}; + +} // namespace rtengine 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); diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 9d759a723..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; } @@ -3044,6 +3050,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : strcolab(0.), strcolh(0.), angcol(0.), + feathercol(25.), blurcolde(5), blurcol(0.2), contcol(0.), @@ -3286,6 +3293,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : gamex(1.), strexp(0.), angexp(0.), + featherexp(25.), excurve{ static_cast(DCT_NURBS), 0.0, @@ -3436,6 +3444,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : blurSHde(5), strSH(0.), angSH(0.), + featherSH(25.), inverssh(false), chromaskSH(0.0), gammaskSH(1.0), @@ -3531,6 +3540,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 +3985,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 +4270,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : baselog(2.), strlog(0.0), anglog(0.0), + featherlog(25.0), CCmaskcurveL{ static_cast(FCT_MinMaxCPoints), 0.0, @@ -4386,6 +4398,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 +4682,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : surroundcie("Average"), strgradcie(0.), anggradcie(0.), + feathercie(25.), enacieMask(false), enacieMaskall(false), CCmaskciecurve{ @@ -4912,6 +4926,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 +4989,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 +5053,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 +5099,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 +5316,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 +5431,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 +5470,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 +5605,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 +6878,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 +6942,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 +7003,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 +7049,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 +7272,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 +7385,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 +7425,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 +7563,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); @@ -9120,12 +9150,29 @@ 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); assignFromKeyfile(keyFile, "Locallab", "Strcolh_" + index_str, spot.strcolh, spotEdited.strcolh); assignFromKeyfile(keyFile, "Locallab", "Angcol_" + index_str, spot.angcol, spotEdited.angcol); + 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); @@ -9202,6 +9249,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); + 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); @@ -9256,7 +9311,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); @@ -9266,6 +9328,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); + 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); @@ -9309,7 +9380,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); @@ -9325,6 +9403,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); + 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); @@ -9574,6 +9661,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); + 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); @@ -9688,7 +9784,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); @@ -9703,6 +9807,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); + 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); @@ -9740,6 +9852,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); + 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); @@ -9902,7 +10023,15 @@ 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); - + 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); assignFromKeyfile(keyFile, "Locallab", "CCmaskcieCurve_" + index_str, spot.CCmaskciecurve, spotEdited.CCmaskciecurve); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index d1cad0a5d..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; @@ -1122,6 +1124,7 @@ struct LocallabParams { double strcolab; double strcolh; double angcol; + double feathercol; int blurcolde; double blurcol; double contcol; @@ -1184,6 +1187,7 @@ struct LocallabParams { double gamex; double strexp; double angexp; + double featherexp; std::vector excurve; bool norm; bool inversex; @@ -1239,6 +1243,7 @@ struct LocallabParams { int blurSHde; double strSH; double angSH; + double featherSH; bool inverssh; double chromaskSH; double gammaskSH; @@ -1284,6 +1289,7 @@ struct LocallabParams { double strvibab; double strvibh; double angvib; + double feathervib; std::vector Lmaskvibcurve; double recothresv; double lowthresv; @@ -1500,6 +1506,7 @@ struct LocallabParams { double sigmalc2; double strwav; double angwav; + double featherwav; double strengthw; double sigmaed; double radiusw; @@ -1606,6 +1613,7 @@ struct LocallabParams { double baselog; double strlog; double anglog; + double featherlog; std::vector CCmaskcurveL; std::vector LLmaskcurveL; std::vector HHmaskcurveL; @@ -1644,6 +1652,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 +1789,7 @@ struct LocallabParams { Glib::ustring surroundcie; double strgradcie; double anggradcie; + double feathercie; bool enacieMask; bool enacieMaskall; std::vector CCmaskciecurve; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index b61503576..6d9d6fd6c 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 @@ -420,6 +421,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; +} + } @@ -744,7 +755,7 @@ void RawImageSource::getWBMults(const ColorTemp &ctemp, const RAWParams &raw, st 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); @@ -1573,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); @@ -1763,7 +1780,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(); @@ -3855,7 +3872,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; @@ -7500,7 +7517,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; @@ -7726,7 +7743,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; @@ -7944,7 +7961,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; @@ -8284,7 +8301,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; } @@ -8393,7 +8410,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]; diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 8979feb1e..569bcca25 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -132,6 +132,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/rtengine/rtlensfun.cc b/rtengine/rtlensfun.cc index 8bdda29ec..f4714b6f7 100644 --- a/rtengine/rtlensfun.cc +++ b/rtengine/rtlensfun.cc @@ -26,6 +26,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 { @@ -47,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_) { @@ -70,12 +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); @@ -86,7 +150,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); @@ -101,6 +165,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 { @@ -341,7 +430,7 @@ bool LFDatabase::init(const Glib::ustring &dbdir) if (settings->verbose) { std::cout << (ok ? "OK" : "FAIL") << std::endl; } - + return ok; } @@ -461,20 +550,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; + } } const auto find_lens_from_name = [](const lfDatabase *database, const lfCamera *cam, const Glib::ustring &lens_name) { auto found = database->FindLenses(cam, nullptr, lens_name.c_str()); @@ -576,12 +670,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..78c9c9ff6 100644 --- a/rtengine/rtlensfun.h +++ b/rtengine/rtlensfun.h @@ -53,8 +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; @@ -121,7 +125,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/cacheimagedata.cc b/rtgui/cacheimagedata.cc index f766efda7..fa71d5d44 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 91abdbf83..bb37acf2f 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -61,6 +61,7 @@ public: unsigned iso; int rating; bool isHDR; + bool isDNG; bool isPixelShift; int sensortype; rtengine::IIO_Sample_Format sampleFormat; @@ -115,6 +116,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; } std::uint32_t getFixBadPixelsConstant() const override; 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/lensprofile.cc b/rtgui/lensprofile.cc index 0e17b3f40..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(); @@ -251,7 +277,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()) { @@ -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) { @@ -522,7 +557,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()); } @@ -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()) { @@ -808,7 +868,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(); 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; 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/options.cc b/rtgui/options.cc index 7dceb9d13..bdc595f5c 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" @@ -674,8 +674,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 @@ -817,7 +817,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"); } @@ -1269,6 +1269,29 @@ void Options::readFromFile(Glib::ustring fname) } } + // check and add extensions that are missing from config + std::map checkedExtensions; + + if (parseExtensions.size() == parseExtensionsEnabled.size()) { + for (auto i = 0; i < parseExtensions.size(); ++i) { + checkedExtensions[parseExtensions[i]] = parseExtensionsEnabled[i]; + } + } + + parseExtensions.clear(); + parseExtensionsEnabled.clear(); + + for (auto const &i : knownExtensions) { + if (checkedExtensions.count(i) == 0) { + checkedExtensions[i] = 1; + } + } + + for (auto const &x : checkedExtensions) { + parseExtensions.emplace_back(x.first); + parseExtensionsEnabled.emplace_back(x.second); + } + if (keyFile.has_key("File Browser", "ThumbnailArrangement")) { fbArrangement = keyFile.get_integer("File Browser", "ThumbnailArrangement"); } @@ -2404,8 +2427,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..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) @@ -331,7 +338,7 @@ public: bool overwriteOutputFile; int complexity; int spotmet; - + bool inspectorWindow; // open inspector in separate window bool zoomOnScroll; // translate scroll events to zoom @@ -472,8 +479,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/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; 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 diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 37ef5ea98..d102a2672 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); @@ -1119,7 +1119,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); @@ -1560,9 +1560,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); @@ -1574,8 +1574,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) ); @@ -1590,6 +1592,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); @@ -1599,8 +1602,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); @@ -1678,11 +1682,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)); @@ -2021,8 +2028,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; @@ -2680,25 +2687,69 @@ void Preferences::workflowUpdate() } } -void Preferences::addExtPressed() +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().empty()) { + 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; + } + } - for (size_t i = 0; i < c.size(); i++) + addExt->set_sensitive(true); +} + +void Preferences::addExtPressed() +{ + Gtk::TreeNodeChildren c = extensionModel->children(); + + for (size_t i = 0; i < c.size(); i++) { if (c[i][extensionColumns.ext] == extension->get_text()) { return; } + } - Gtk::TreeRow row = * (extensionModel->append()); + Gtk::TreeRow row = * (extensionModel->prepend()); row[extensionColumns.enabled] = true; row[extensionColumns.ext] = extension->get_text(); + + extension->set_text(""); + addExt->set_sensitive(false); } void Preferences::delExtPressed() { - extensionModel->erase(extensions->get_selection()->get_selected()); } diff --git a/rtgui/preferences.h b/rtgui/preferences.h index 6ec528e73..9b5707be3 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -325,6 +325,8 @@ public: void observer10Toggled (); void selectStartupDir (); + void extensionsChanged (); + void extensionChanged (); void addExtPressed (); void delExtPressed (); void moveExtUpPressed (); 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; + } } } 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"