Merge pull request #681 from darktable-org/bug_fix_and_internal_metadata
Bug fix and internal metadata
This commit is contained in:
@@ -138,8 +138,9 @@ script_data.show = nil -- only required for libs since the destroy_method only h
|
||||
|
||||
|
||||
|
||||
local PS = dt.configuration.runnin_os == "windows" and "\\" or "/"
|
||||
local ERROR = -1
|
||||
local PS <const> = dt.configuration.runnin_os == "windows" and "\\" or "/"
|
||||
local ERROR <const> = -1
|
||||
local HAS_INTERNAL_METADATA = dt.metadata.exists("Exif.Image.DataTime")
|
||||
|
||||
-- function to convert from exif time to system time
|
||||
local function exiftime2systime(exiftime)
|
||||
@@ -241,21 +242,30 @@ end
|
||||
|
||||
local function _get_windows_image_file_creation_time(image)
|
||||
local datetime = nil
|
||||
local p = io.popen("dir " .. image.path .. PS .. image.filename)
|
||||
if p then
|
||||
for line in p:lines() do
|
||||
if string.match(line, ds.sanitize_lua(image.filename)) then
|
||||
local mo, day, yr, hr, min, apm = string.match(line, "(%d+)/(%d+)/(%d+) (%d-):(%d+) (%S+)")
|
||||
if apm == "PM" then
|
||||
hr = hr + 12
|
||||
end
|
||||
datetime = vars2exiftime(yr, mo, day, hr, min, 0)
|
||||
end
|
||||
end
|
||||
p:close()
|
||||
local datestring = nil
|
||||
|
||||
if HAS_INTERNAL_METADATA then
|
||||
datestring = image.DateString
|
||||
else
|
||||
dt.print(string.format(_("unable to get information for %s"), image.filename))
|
||||
datetime = ERROR
|
||||
local p = io.popen("dir " .. image.path .. PS .. image.filename)
|
||||
if p then
|
||||
for line in p:lines() do
|
||||
if string.match(line, ds.sanitize_lua(image.filename)) then
|
||||
datestring = line
|
||||
end
|
||||
end
|
||||
p:close()
|
||||
else
|
||||
dt.print(string.format(_("unable to get information for %s"), image.filename))
|
||||
datetime = ERROR
|
||||
end
|
||||
end
|
||||
if datestring then
|
||||
local mo, day, yr, hr, min, apm = string.match(datestring, "(%d+)/(%d+)/(%d+) (%d-):(%d+) (%S+)")
|
||||
if apm == "PM" then
|
||||
hr = hr + 12
|
||||
end
|
||||
datetime = vars2exiftime(yr, mo, day, hr, min, 0)
|
||||
end
|
||||
return datetime
|
||||
end
|
||||
|
||||
@@ -211,9 +211,14 @@ local function straighten_image(image)
|
||||
for line in pipe:lines() do
|
||||
local pr, val = string.match(line, "(.).+: (.+)")
|
||||
if pr == "R" then
|
||||
local sign = 1.0
|
||||
dt.print_log("roll angle is " .. val)
|
||||
log.msg(log.debug, "roll angle is " .. val)
|
||||
roll = determine_correction(tonumber(val))
|
||||
-- check for Nidon and change the sign
|
||||
if string.match(string.upper(image.exif_maker), "NIKON") then
|
||||
sign = -1.0
|
||||
end
|
||||
roll = determine_correction(tonumber(val) * sign)
|
||||
dt.print_log("corrected roll angle is " .. roll)
|
||||
log.msg(log.debug, "corrected roll angle is " .. roll)
|
||||
elseif pr == "P" then
|
||||
|
||||
@@ -127,6 +127,9 @@ local CS <const> = dt.configuration.running_os == "windows" and "&" or ";"
|
||||
local EXIFTOOL <const> = df.check_if_bin_exists("exiftool")
|
||||
local EXIV2 <const> = df.check_if_bin_exists("exiv2")
|
||||
local DNGLAB <const> = df.check_if_bin_exists("dnglab")
|
||||
local EXIV2TAG <const> = "Exif.Canon.RawBurstModeRoll"
|
||||
|
||||
local HAS_INTERNAL_METADATA <const> = dt.metadata.exists(EXIV2TAG)
|
||||
|
||||
local DNGLAB_ARGS <const> = " convert --image-index all --embed-raw false "
|
||||
local EXIV2_ARGS <const> = " -K Exif.Canon.RawBurstModeRoll -pt "
|
||||
@@ -150,6 +153,7 @@ local extract_burst_roll_images = {}
|
||||
|
||||
extract_burst_roll_images.preferred_tag_reader = nil
|
||||
extract_burst_roll_images.on_import = true
|
||||
extract_burst_roll_images.select_button = true
|
||||
extract_burst_roll_images.imported_images = {}
|
||||
extract_burst_roll_images.log_level = DEFAULT_LOG_LEVEL
|
||||
|
||||
@@ -172,9 +176,18 @@ dt.preferences.register(MODULE, -- script: This is a string used to avoid
|
||||
"bool", -- type
|
||||
_("extract burst roll images on import"), -- label
|
||||
_("extract burst roll images on import"), -- tooltip
|
||||
false) -- default
|
||||
|
||||
-- display selection button
|
||||
dt.preferences.register(MODULE, -- script: This is a string used to avoid name collision in preferences (i.e namespace). Set it to something unique, usually the name of the script handling the preference.
|
||||
"select_button", -- name
|
||||
"bool", -- type
|
||||
_("display select burst roll images button"), -- label
|
||||
_("add a button to the select module to select burst roll images"), -- tooltip
|
||||
true) -- default
|
||||
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- A L I A S E S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@@ -256,27 +269,40 @@ end
|
||||
local function is_burst_roll_image(image)
|
||||
local old_log_level = set_log_level()
|
||||
local result = false
|
||||
local cmd = EXIFTOOL .. EXIFTOOL_ARGS
|
||||
|
||||
if ebri.preferred_tag_reader == "exiv2" then
|
||||
cmd = EXIV2 .. EXIV2_ARGS
|
||||
end
|
||||
|
||||
local p = io.popen(cmd .. ds.sanitize(image.path) .. PS .. ds.sanitize(image.filename))
|
||||
if p then
|
||||
for line in p:lines() do
|
||||
if ebri.preferred_tag_reader == "exiv2" then
|
||||
line = get_last_value(line)
|
||||
end
|
||||
line = tonumber(line)
|
||||
if type(line) == "number" then
|
||||
if tonumber(line) > 0 then
|
||||
log.msg(log.info, image.filename .. " is a burst roll container image")
|
||||
if HAS_INTERNAL_METADATA then
|
||||
if image.RawBurstModeRoll then
|
||||
local val = get_last_value(image.RawBurstModeRoll)
|
||||
val = tonumber(val)
|
||||
if type(val) == "number" then
|
||||
if val > 0 then
|
||||
result = true
|
||||
end
|
||||
end
|
||||
end
|
||||
p:close()
|
||||
else
|
||||
local cmd = EXIFTOOL .. EXIFTOOL_ARGS
|
||||
|
||||
if ebri.preferred_tag_reader == "exiv2" then
|
||||
cmd = EXIV2 .. EXIV2_ARGS
|
||||
end
|
||||
|
||||
local p = io.popen(cmd .. ds.sanitize(image.path) .. PS .. ds.sanitize(image.filename))
|
||||
if p then
|
||||
for line in p:lines() do
|
||||
if ebri.preferred_tag_reader == "exiv2" then
|
||||
line = get_last_value(line)
|
||||
end
|
||||
line = tonumber(line)
|
||||
if type(line) == "number" then
|
||||
if line > 0 then
|
||||
log.msg(log.info, image.filename .. " is a burst roll container image")
|
||||
result = true
|
||||
end
|
||||
end
|
||||
end
|
||||
p:close()
|
||||
end
|
||||
end
|
||||
|
||||
restore_log_level(old_log_level)
|
||||
@@ -321,6 +347,14 @@ local function extract_burst(image)
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function extract_burst_images(images)
|
||||
for _, image in ipairs(images) do
|
||||
if is_burst_roll_image(image) then
|
||||
extract_burst(image)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function process_image(image)
|
||||
local old_log_level = set_log_level()
|
||||
if is_burst_roll_image(image) then
|
||||
@@ -384,36 +418,86 @@ local function process_import(images)
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function select_burst_roll_images(event, images)
|
||||
local old_log_level = set_log_level()
|
||||
local selected = {}
|
||||
|
||||
for _, image in ipairs(images) do
|
||||
if is_burst_roll_image(image) then
|
||||
table.insert(selected, image)
|
||||
end
|
||||
end
|
||||
|
||||
restore_log_level(old_log_level)
|
||||
return selected
|
||||
end
|
||||
|
||||
local function set_select_sensitive()
|
||||
if #dt.collection > 0 then
|
||||
dt.gui.libs.select.set_sensitive(MODULE, true)
|
||||
else
|
||||
dt.gui.libs.select.set_sensitive(MODULE, false)
|
||||
end
|
||||
end
|
||||
|
||||
local function set_action_sensitive()
|
||||
local sensitive = false
|
||||
if #dt.gui.action_images > 0 then
|
||||
if is_burst_roll_image(dt.gui.action_images[1]) then
|
||||
sensitive = true
|
||||
end
|
||||
end
|
||||
dt.gui.libs.image.set_sensitive(MODULE, sensitive)
|
||||
end
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- M A I N P R O G R A M
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if not DNGLAB then
|
||||
log.msg(log.error, MODULE .. _("dnglab executable not found"))
|
||||
log.msg(log.screen, script_data.metadata.name .. _(": dnglab executable not found, exiting..."))
|
||||
return
|
||||
if not DNGLAB then
|
||||
log.msg(log.error, MODULE .. _("dnglab executable not found"))
|
||||
log.msg(log.screen, script_data.metadata.name .. _(": dnglab executable not found, exiting..."))
|
||||
return
|
||||
end
|
||||
|
||||
if HAS_INTERNAL_METADATA then
|
||||
log.msg(log.info, "Exif.Canon.RawBurstModeRoll detected, using internal metadata")
|
||||
else
|
||||
if not EXIFTOOL and not EXIV2 then
|
||||
log.msg(log.error, MODULE .. _("no exif tag reader available"))
|
||||
log.msg(log.screen, script_data.metadata.name .. _(" no exif tag reader available, exiting..."))
|
||||
return
|
||||
end
|
||||
|
||||
ebri.preferred_tag_reader = pref_read("tag_reader", "enum")
|
||||
|
||||
if not string.match(EXIFTOOL, ebri.preferred_tag_reader) and not string.match(EXIV2, ebri.preferred_tag_reader) then
|
||||
log.msg(log.error, MODULE .. " selected tag " .. ebri.preferred_tag_reader .." not available")
|
||||
log.msg(log.screen, script_data.metadata.name .. string.format(_(" selected tag reader %s not available"), ebri.preferred_tag_reader))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if not EXIFTOOL and not EXIV2 then
|
||||
log.msg(log.error, MODULE .. _("no exif tag reader available"))
|
||||
log.msg(log.screen, script_data.metadata.name .. _(" no exif tag reader available, exiting..."))
|
||||
return
|
||||
end
|
||||
|
||||
ebri.preferred_tag_reader = pref_read("tag_reader", "enum")
|
||||
|
||||
if not string.match(EXIFTOOL, ebri.preferred_tag_reader) and not string.match(EXIV2, ebri.preferred_tag_reader) then
|
||||
log.msg(log.error, MODULE .. " selected tag " .. ebri.preferred_tag_reader .." not available")
|
||||
log.msg(log.screen, script_data.metadata.name .. string.format(_(" selected tag reader %s not available"), ebri.preferred_tag_reader))
|
||||
return
|
||||
end
|
||||
|
||||
ebri.on_import = dt.preferences.read(MODULE, "on_import", "bool")
|
||||
ebri.on_import = pref_read("on_import", "bool")
|
||||
ebri.select_button = pref_read("select_button", "bool")
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- U S E R I N T E R F A C E
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if ebri.select_button then
|
||||
dt.gui.libs.select.register_selection(MODULE, _("select burst roll images"), select_burst_roll_images,
|
||||
_("select burst roll image containers"))
|
||||
end
|
||||
|
||||
dt.gui.libs.image.register_action(
|
||||
MODULE,
|
||||
_("extract burst roll images"),
|
||||
function(event, images)
|
||||
extract_burst_images(images)
|
||||
end,
|
||||
_("extract and group burst roll images with container")
|
||||
)
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- D A R K T A B L E I N T E G R A T I O N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@@ -421,6 +505,10 @@ ebri.on_import = dt.preferences.read(MODULE, "on_import", "bool")
|
||||
local function destroy()
|
||||
dt.destroy_event(MODULE, "post-import-film")
|
||||
dt.destroy_event(MODULE, "post-import-image")
|
||||
if ebri.select_button then
|
||||
dt.gui.libs.select.destroy_selection(MODULE)
|
||||
end
|
||||
dt.gui.libs.image.action.destroy_action(MODULE)
|
||||
end
|
||||
|
||||
script_data.destroy = destroy
|
||||
@@ -444,6 +532,27 @@ dt.register_event(MODULE, "post-import-image",
|
||||
end
|
||||
)
|
||||
|
||||
dt.register_event(MODULE, "selection-changed",
|
||||
function(event)
|
||||
set_action_sensitive()
|
||||
end
|
||||
)
|
||||
|
||||
if dt.preferences.read("darktable", "plugins/lighttable/act_on", "bool") then
|
||||
dt.print_log("adding mouse-over-image-changed event")
|
||||
dt.register_event(MODULE, "mouse-over-image-changed",
|
||||
function(event, image)
|
||||
set_action_sensitive()
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
dt.register_event(MODULE, "collection-changed",
|
||||
function(event)
|
||||
set_select_sensitive()
|
||||
end
|
||||
)
|
||||
|
||||
if not dt.query_event(MODULE, "shortcut") then
|
||||
dt.register_event(MODULE, "shortcut",
|
||||
function(event, shortcut)
|
||||
|
||||
Reference in New Issue
Block a user