Here is a much improved version that
- If “shading compensation” was enabled, crops the RAW image to remove the dark band.
- If “shading compensation” was disabled, sets up an instance of “lens corrections” using “Lensfun” to provide a much better correction.
For me this seems to work quite well. See the comment for more information.
-- Automatically handle Olympus' "shading compensation" when an image is loaded into the darkroom.
--
-- If "Shading compensation" was active, crop a 32 pixel wide column from the right border of
-- the RAW image, since it has no effect there and this results in a dark band.
--
-- If "shading compensation" has been disabled (recommended), create a new instance of
-- "lens correction" and set it to "Lensfun" correcting "only vignetting", unless such an instance
-- already exists. To prevent its recreation, disable the instance instead of deleting it.
--
-- For the RAW crop to work
-- plugins/darkroom/rawprepare/allow_editing_crop must be set to true
-- in darktablerc
local dt = require "darktable"
local df = require "lib/dtutils.file"
local SEP = dt.configuration.runnin_os == "windows" and "\\" or "/"
local function shading_compensation_on(image)
local exiv2 = df.check_if_bin_exists("exiv2")
if not exiv2 then
dt.print(dt.gettext.gettext("Unable to find exiv2 command."))
return nil
end
local p = io.popen(exiv2
.." -K Exif.OlympusCs.ShadingCompensation "
..image.path..SEP..image.filename)
if not p then return false end
local line = p:read("*l")
p:close()
return line and line:find("On", 1, true) ~= nil
end
local function maybe_setup_lensfun_vignetting_correction()
-- Search for an instance of "lens correction" that is set to "Lensfun" and "vignetting".
-- We only search the first 5 instances - is there a better way?
for i=1,5 do
if dt.gui.action("iop/lens/correction method", "selection", "popup", "", i) == -2
and dt.gui.action("iop/lens/corrections", "selection", "popup", "", i) == -8 then
-- Assume that vignetting correction is set up already (active or inactive).
return
end
end
-- Not found: Create a new instance and set it up.
dt.gui.action("iop/lens", "instance", "new", 1,000, 0)
dt.gui.action("iop/lens/correction method", "selection", "item:Lensfun database", 1,000, 0)
dt.gui.action("iop/lens/corrections", "selection", "item:only vignetting", 1,000, 0)
dt.gui.action("iop/lens/scale", "value", "reset", 1,000, 0)
end
-- See https://discuss.pixls.us/t/working-with-modules-from-lua-scripts-in-darktable/32934/224
-- and https://discuss.pixls.us/t/need-your-help-with-a-lua-script/49259/2
local function handle_oly_shading_compensation(event, clean, image)
if not clean then return end
if image.exif_maker ~= "OLYMPUS CORPORATION" or image.exif_model ~= "E-M5MarkIII" then
return
end
local sc_on = shading_compensation_on(image)
if sc_on == nil then
return
elseif sc_on then
dt.gui.action("iop/rawprepare/crop right", "value", "set", 32)
else
maybe_setup_lensfun_vignetting_correction()
end
end
dt.register_event("em5_iii_crop", "darkroom-image-loaded", handle_oly_shading_compensation)
So far the E-M5 Mark III is hardcoded (it can be changed). The next step will be to check which other Olympus/OMS cameras (all?) are affected.
If anybody else tries this out, please let me know whether it works for you.