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"