Skip to content

Commit 021b32c

Browse files
authored
Merge pull request darktable-org#314 from dtorop/fujifilm-dynamic-range
Fujifilm dynamic range
2 parents 62753d1 + 1d1eb6a commit 021b32c

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed

contrib/fujifilm_dynamic_range.lua

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
--[[ fujifilm_dynamic_range-0.1
2+
3+
Compensate for Fujifilm raw files made using "dynamic range".
4+
5+
Copyright (C) 2021 Dan Torop <[email protected]>
6+
7+
This program is free software; you can redistribute it and/or modify
8+
it under the terms of the GNU General Public License as published by
9+
the Free Software Foundation; either version 2 of the License, or
10+
(at your option) any later version.
11+
12+
This program is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
GNU General Public License for more details.
16+
17+
You should have received a copy of the GNU General Public License along
18+
with this program; if not, write to the Free Software Foundation, Inc.,
19+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20+
]]
21+
22+
--[[About this Plugin
23+
Support for adjusting darktable exposure by Fujifilm raw exposure
24+
bias. This corrects for a DR100/DR200/DR400 "dynamic range" setting.
25+
26+
Dependencies:
27+
- exiftool (https://www.sno.phy.queensu.ca/~phil/exiftool/)
28+
29+
Based upon fujifilm_ratings by Ben Mendis
30+
31+
The relevant tag is RawExposureBias (0x9650). This appears to
32+
represent the shift in EV for the chosen DR setting (whether manual or
33+
automatic). Note that even at 100DR ("standard") there is an EV shift:
34+
35+
100 DR -> -0.72 EV
36+
200 DR -> -1.72 EV
37+
400 DR -> -2.72 EV
38+
39+
The ideal would be to use exiv2 to read this tag, as this is the same
40+
code which darktable import uses. Unfortunately, exiv2 as of v0.27.3
41+
can't read this tag. As it is encoded as a 4-byte ratio of two signed
42+
shorts -- a novel data type -- it will require some attention to fix
43+
this.
44+
45+
There is an exiv2-readable DevelopmentDynamicRange tag which maps to
46+
RawExposureBias as above. DevelopmentDynamicRange is only present
47+
when tag DynamicRangeSetting (0x1402) is Manual/Raw (0x0001). When it
48+
is Auto (0x0000), the equivalent data is tag AutoDynamicRange
49+
(0x140b). But exiv2 currently can't read that tag either.
50+
51+
Hence for now this code uses exiftool to read RawExposureBias, as a
52+
more general solution. As exiftool is approx. 10x slower than exiv2
53+
(Perl vs. C++), this may slow large imports.
54+
55+
These tags have been checked on a Fujifilm X100S and X100V. Other
56+
cameras may behave in other ways.
57+
58+
--]]
59+
60+
local dt = require "darktable"
61+
local du = require "lib/dtutils"
62+
local df = require "lib/dtutils.file"
63+
64+
du.check_min_api_version("4.0.0", "fujifilm_dynamic_range")
65+
66+
local function detect_dynamic_range(event, image)
67+
if image.exif_maker ~= "FUJIFILM" then
68+
dt.print_log("[fujifilm_dynamic_range] ignoring non-Fujifilm image")
69+
return
70+
end
71+
-- it would be nice to check image.is_raw but this appears to not yet be set
72+
if not string.match(image.filename, "%.RAF$") then
73+
dt.print_log("[fujifilm_dynamic_range] ignoring non-raw image")
74+
return
75+
end
76+
local command = df.check_if_bin_exists("exiftool")
77+
if not command then
78+
dt.print_error("[fujifilm_dynamic_range] exiftool not found")
79+
return
80+
end
81+
local RAF_filename = df.sanitize_filename(tostring(image))
82+
-- without -n flag, exiftool will round to the nearest tenth
83+
command = command .. " -RawExposureBias -n -t " .. RAF_filename
84+
dt.print_log(command)
85+
output = io.popen(command)
86+
local raf_result = output:read("*all")
87+
output:close()
88+
if #raf_result == 0 then
89+
dt.print_error("[fujifilm_dynamic_range] no output returned by exiftool")
90+
return
91+
end
92+
raf_result = string.match(raf_result, "\t(.*)")
93+
if not raf_result then
94+
dt.print_error("[fujifilm_dynamic_range] could not parse exiftool output")
95+
return
96+
end
97+
if image.exif_exposure_bias ~= image.exif_exposure_bias then
98+
-- is NAN (this is unlikely as RAFs should have ExposureBiasValue set)
99+
image.exif_exposure_bias = 0
100+
end
101+
-- this should be auto-applied if plugins/darkroom/workflow is scene-referred
102+
-- note that scene-referred workflow exposure preset also pushes exposure up by 0.5 EV
103+
image.exif_exposure_bias = image.exif_exposure_bias + tonumber(raf_result)
104+
dt.print_log("[fujifilm_dynamic_range] raw exposure bias " .. tostring(raf_result))
105+
end
106+
107+
dt.register_event("post-import-image", detect_dynamic_range)
108+
109+
dt.print_log("[fujifilm_dynamic_range] loaded")

0 commit comments

Comments
 (0)