|
|
|
|
@@ -35,13 +35,16 @@ TODO
|
|
|
|
|
local dt = require "darktable"
|
|
|
|
|
local du = require "lib/dtutils"
|
|
|
|
|
local df = require "lib/dtutils.file"
|
|
|
|
|
require "official/yield"
|
|
|
|
|
local dtsys = require "lib/dtutils.system"
|
|
|
|
|
|
|
|
|
|
local PS = dt.configuration.running_os == "windows" and "\\" or "/"
|
|
|
|
|
|
|
|
|
|
local gettext = dt.gettext
|
|
|
|
|
|
|
|
|
|
du.check_min_api_version("3.0.0", "enfuse")
|
|
|
|
|
|
|
|
|
|
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
|
|
|
|
gettext.bindtextdomain("enfuse",dt.configuration.config_dir.."/lua/locale/")
|
|
|
|
|
gettext.bindtextdomain("enfuse",dt.configuration.config_dir..PS .. "lua" .. PS .. "locale" .. PS)
|
|
|
|
|
|
|
|
|
|
local function _(msgid)
|
|
|
|
|
return gettext.dgettext("enfuse", msgid)
|
|
|
|
|
@@ -61,11 +64,11 @@ tiff_exporter.max_width = 0
|
|
|
|
|
|
|
|
|
|
local version = nil
|
|
|
|
|
|
|
|
|
|
local p = io.popen(enfuse_installed .. " --version | grep enfuse | grep -e \"[0123456789\\.]\"")
|
|
|
|
|
local p = io.popen(enfuse_installed .. " --version")
|
|
|
|
|
local f = p:read("all")
|
|
|
|
|
version = string.match(f, "[%d\\.]+" )
|
|
|
|
|
dt.print_log("enfuse version is " .. version)
|
|
|
|
|
p:close()
|
|
|
|
|
version = string.match(f, "enfuse (%d.%d)")
|
|
|
|
|
dt.print_log("enfuse version is " .. version)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- initialize exposure_mu value and depth setting in config to sane defaults (would be 0 otherwise)
|
|
|
|
|
@@ -111,6 +114,115 @@ local depth = dt.new_widget("combobox")
|
|
|
|
|
"8", "16", "32"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local enfuse_button = dt.new_widget("button")
|
|
|
|
|
{
|
|
|
|
|
label = enfuse_installed and "run enfuse" or "enfuse not installed",
|
|
|
|
|
clicked_callback = function ()
|
|
|
|
|
-- remember exposure_mu
|
|
|
|
|
-- TODO: find a way to save it whenever the value changes
|
|
|
|
|
local mu = exposure_mu.value
|
|
|
|
|
if version < "4.2" then
|
|
|
|
|
dt.preferences.write("enfuse", "exposure-mu", "float", mu)
|
|
|
|
|
else
|
|
|
|
|
dt.preferences.write("enfuse", "exposure-optimum", "float", mu)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- create a temp response file
|
|
|
|
|
local response_file = os.tmpname()
|
|
|
|
|
if dt.configuration.running_os == "windows" then
|
|
|
|
|
response_file = dt.configuration.tmp_dir .. response_file -- windows os.tmpname() defaults to root directory
|
|
|
|
|
end
|
|
|
|
|
local f = io.open(response_file, "w")
|
|
|
|
|
if not f then
|
|
|
|
|
dt.print(string.format(_("Error writing to `%s`"), response_file))
|
|
|
|
|
os.remove(response_file)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- add all filenames to the response file
|
|
|
|
|
local cnt = 0
|
|
|
|
|
local n_skipped = 0
|
|
|
|
|
local target_dir
|
|
|
|
|
for i_, i in ipairs(dt.gui.action_images) do
|
|
|
|
|
|
|
|
|
|
-- only use ldr files as enfuse can't open raws
|
|
|
|
|
if i.is_ldr then
|
|
|
|
|
cnt = cnt + 1
|
|
|
|
|
f:write(i.path..PS..i.filename.."\n")
|
|
|
|
|
target_dir = i.path
|
|
|
|
|
|
|
|
|
|
-- alternatively raws will be exported as tiff
|
|
|
|
|
elseif i.is_raw then
|
|
|
|
|
local tmp_exported = os.tmpname()..".tif"
|
|
|
|
|
if dt.configuration.running_os == "windows" then
|
|
|
|
|
tmp_exported = dt.configuration.tmp_dir .. tmp_exported -- windows os.tmpname() defaults to root directory
|
|
|
|
|
end
|
|
|
|
|
dt.print(string.format(_("Converting raw file '%s' to tiff..."), i.filename))
|
|
|
|
|
tiff_exporter:write_image(i, tmp_exported, false)
|
|
|
|
|
dt.print_log(string.format("Raw file '%s' converted to '%s'", i.filename, tmp_exported))
|
|
|
|
|
|
|
|
|
|
cnt = cnt + 1
|
|
|
|
|
f:write(tmp_exported.."\n")
|
|
|
|
|
target_dir = i.path
|
|
|
|
|
|
|
|
|
|
-- other images will be skipped
|
|
|
|
|
else
|
|
|
|
|
dt.print(string.format(_("Skipping %s..."), i.filename))
|
|
|
|
|
n_skipped = n_skipped + 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
f:close()
|
|
|
|
|
-- bail out if there is nothing to do
|
|
|
|
|
if cnt == 0 then
|
|
|
|
|
dt.print(_("No suitable images selected, nothing to do for enfuse"))
|
|
|
|
|
os.remove(response_file)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if n_skipped > 0 then
|
|
|
|
|
dt.print(string.format(_("%d image(s) skipped"), n_skipped))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- call enfuse on the response file
|
|
|
|
|
-- TODO: find something nicer
|
|
|
|
|
local ugly_decimal_point_hack = string.gsub(string.format("%.04f", mu), ",", ".")
|
|
|
|
|
-- TODO: make filename unique
|
|
|
|
|
local output_image = target_dir.. PS .. "enfuse.tif"
|
|
|
|
|
local exposure_option = " --exposure-optimum "
|
|
|
|
|
if version < "4.2" then
|
|
|
|
|
exposure_option = " --exposure-mu "
|
|
|
|
|
end
|
|
|
|
|
local command = enfuse_installed.." --depth "..depth.value..exposure_option..ugly_decimal_point_hack
|
|
|
|
|
.." -o \""..output_image.."\" \"@"..response_file.."\""
|
|
|
|
|
if dtsys.external_command( command) > 0 then
|
|
|
|
|
dt.print(_("Enfuse failed, see terminal output for details"))
|
|
|
|
|
os.remove(response_file)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- remove the response file
|
|
|
|
|
os.remove(response_file)
|
|
|
|
|
|
|
|
|
|
-- import resulting tiff
|
|
|
|
|
local image = dt.database.import(output_image)
|
|
|
|
|
|
|
|
|
|
-- tell the user that everything worked
|
|
|
|
|
dt.print(_("enfuse was successful, resulting image has been imported"))
|
|
|
|
|
-- normally printing to stdout is bad, but we allow enfuse to show its output, so adding one extra line is ok
|
|
|
|
|
print(string.format(_("enfuse: done, resulting image '%s' has been imported with id %d"), output_image, image.id))
|
|
|
|
|
end
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local lib_widgets = {}
|
|
|
|
|
|
|
|
|
|
if not enfuse_installed then
|
|
|
|
|
table.insert(lib_widgets, df.executable_path_widget({"ffmpeg"}))
|
|
|
|
|
end
|
|
|
|
|
table.insert(lib_widgets, exposure_mu)
|
|
|
|
|
table.insert(lib_widgets, depth)
|
|
|
|
|
table.insert(lib_widgets, enfuse_button)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- ... and tell dt about it all
|
|
|
|
|
dt.register_lib(
|
|
|
|
|
"enfuse", -- plugin name
|
|
|
|
|
@@ -122,100 +234,7 @@ dt.register_lib(
|
|
|
|
|
{
|
|
|
|
|
orientation = "vertical",
|
|
|
|
|
sensitive = enfuse_installed,
|
|
|
|
|
exposure_mu,
|
|
|
|
|
depth,
|
|
|
|
|
dt.new_widget("button")
|
|
|
|
|
{
|
|
|
|
|
label = enfuse_installed and "run enfuse" or "enfuse not installed",
|
|
|
|
|
clicked_callback = function ()
|
|
|
|
|
-- remember exposure_mu
|
|
|
|
|
-- TODO: find a way to save it whenever the value changes
|
|
|
|
|
local mu = exposure_mu.value
|
|
|
|
|
if version < "4.2" then
|
|
|
|
|
dt.preferences.write("enfuse", "exposure-mu", "float", mu)
|
|
|
|
|
else
|
|
|
|
|
dt.preferences.write("enfuse", "exposure-optimum", "float", mu)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- create a temp response file
|
|
|
|
|
local response_file = os.tmpname()
|
|
|
|
|
local f = io.open(response_file, "w")
|
|
|
|
|
if not f then
|
|
|
|
|
dt.print(string.format(_("Error writing to `%s`"), response_file))
|
|
|
|
|
os.remove(response_file)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- add all filenames to the response file
|
|
|
|
|
local cnt = 0
|
|
|
|
|
local n_skipped = 0
|
|
|
|
|
local target_dir
|
|
|
|
|
for i_, i in ipairs(dt.gui.action_images) do
|
|
|
|
|
|
|
|
|
|
-- only use ldr files as enfuse can't open raws
|
|
|
|
|
if i.is_ldr then
|
|
|
|
|
cnt = cnt + 1
|
|
|
|
|
f:write(i.path.."/"..i.filename.."\n")
|
|
|
|
|
target_dir = i.path
|
|
|
|
|
|
|
|
|
|
-- alternatively raws will be exported as tiff
|
|
|
|
|
elseif i.is_raw then
|
|
|
|
|
local tmp_exported = os.tmpname()..".tiff"
|
|
|
|
|
dt.print(string.format(_("Converting raw file '%s' to tiff..."), i.filename))
|
|
|
|
|
tiff_exporter.write_image(tiff_exporter, i, tmp_exported, false)
|
|
|
|
|
dt.print_log(string.format("Raw file '%s' converted to '%s'", i.filename, tmp_exported))
|
|
|
|
|
|
|
|
|
|
cnt = cnt + 1
|
|
|
|
|
f:write(tmp_exported.."\n")
|
|
|
|
|
target_dir = i.path
|
|
|
|
|
|
|
|
|
|
-- other images will be skipped
|
|
|
|
|
else
|
|
|
|
|
dt.print(string.format(_("Skipping %s..."), i.filename))
|
|
|
|
|
n_skipped = n_skipped + 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
f:close()
|
|
|
|
|
-- bail out if there is nothing to do
|
|
|
|
|
if cnt == 0 then
|
|
|
|
|
dt.print(_("No suitable images selected, nothing to do for enfuse"))
|
|
|
|
|
os.remove(response_file)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if n_skipped > 0 then
|
|
|
|
|
dt.print(string.format(_("%d image(s) skipped"), n_skipped))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- call enfuse on the response file
|
|
|
|
|
-- TODO: find something nicer
|
|
|
|
|
local ugly_decimal_point_hack = string.gsub(string.format("%.04f", mu), ",", ".")
|
|
|
|
|
-- TODO: make filename unique
|
|
|
|
|
local output_image = target_dir.."/enfuse.tiff"
|
|
|
|
|
local exposure_option = " --exposure-optimum "
|
|
|
|
|
if version < "4.2" then
|
|
|
|
|
exposure_option = " --exposure-mu "
|
|
|
|
|
end
|
|
|
|
|
local command = enfuse_installed.." --depth "..depth.value..exposure_option..ugly_decimal_point_hack
|
|
|
|
|
.." -o \""..output_image.."\" \"@"..response_file.."\""
|
|
|
|
|
if dt.control.execute( command) > 0 then
|
|
|
|
|
dt.print(_("Enfuse failed, see terminal output for details"))
|
|
|
|
|
os.remove(response_file)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- remove the response file
|
|
|
|
|
os.remove(response_file)
|
|
|
|
|
|
|
|
|
|
-- import resulting tiff
|
|
|
|
|
local image = dt.database.import(output_image)
|
|
|
|
|
|
|
|
|
|
-- tell the user that everything worked
|
|
|
|
|
dt.print(_("enfuse was successful, resulting image has been imported"))
|
|
|
|
|
-- normally printing to stdout is bad, but we allow enfuse to show its output, so adding one extra line is ok
|
|
|
|
|
print(string.format(_("enfuse: done, resulting image '%s' has been imported with id %d"), output_image, image.id))
|
|
|
|
|
end
|
|
|
|
|
}
|
|
|
|
|
table.unpack(lib_widgets)
|
|
|
|
|
},
|
|
|
|
|
nil,-- view_enter
|
|
|
|
|
nil -- view_leave
|
|
|
|
|
|