Files
lua-scripts-w-api/contrib/gpx_export.lua
2021-06-11 21:44:38 -04:00

188 lines
5.9 KiB
Lua

--[[
This file is part of darktable,
copyright (c) 2017 Jannis_V
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 <http://www.gnu.org/licenses/>.
]]
--[[
Simple darktable GPX generator script
This script generates a GPX track from all images having GPS latitude
and longitude information.
For each source folder, a separate <trk> is generated in the gpx file.
]]
local dt = require "darktable"
local df = require "lib/dtutils.file"
local dl = require "lib/dtutils"
local gettext = dt.gettext
dl.check_min_api_version("3.0.0", "gpx-export")
local CURR_API_STRING = dt.configuration.api_version_string
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("gpx_export",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("gpx_export", msgid)
end
local gpx = {}
gpx.module_installed = false
gpx.event_registered = false
local path_entry = dt.new_widget("entry")
{
text = dt.preferences.read("gpx_exporter", "gpxExportPath", "string"),
editable=true,
reset_callback = function(self)
self.text = "~/darktable.gpx"
dt.preferences.write("gpx_exporter", "gpxExportPath", "string", self.text)
end,
tooltip = _("gpx file path"),
}
local function stop_job(job)
job.valid = false
end
local function create_gpx_file()
dt.preferences.write("gpx_exporter", "gpxExportPath", "string", path_entry.text)
path = path_entry.text:gsub("^~", os.getenv("HOME")) -- Expand ~ to home
path = path:gsub("//", "/")
dt.print(_("exporting gpx file..."))
job = dt.gui.create_job(_("gpx export"), true, stop_job)
local sel_images = dt.gui.action_images
local segments = {}
for key,image in dl.spairs(sel_images, function(t, a, b) return t[b].path > t[a].path end) do
print(image.path)
if (job.valid) then
job.percent = (key - 1) / #sel_images
if ((image.longitude and image.latitude) and
(image.longitude ~= 0 and image.latitude ~= 90) -- Just in case
) then
if (segments[image.path] == nil) then
segments[image.path] = {}
end
if (image.exif_datetime_taken == "") then
dt.print(image.path.."/"..image.filename.._(" does not have date information and won't be processed"))
print(image.path.."/"..image.filename.._(" does not have date information and won't be processed")) -- Also print to terminal
else
segments[image.path][image.filename] = image
end
end
else
break
end
end
local gpx_file = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"
gpx_file = gpx_file.."<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" creator=\"Darktable GPX Exporter\"\n"
gpx_file = gpx_file.."version=\"1.1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
gpx_file = gpx_file.."xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n"
for key, folder in dl.spairs(segments) do
gpx_file = gpx_file.."\t<trk>\n"
gpx_file = gpx_file.."\t\t<name>"..key.."</name>\n";
gpx_file = gpx_file.."\t\t<trkseg>\n";
for key2, image in dl.spairs(folder, function(t, a, b) return t[b].exif_datetime_taken > t[a].exif_datetime_taken end) do
date_format = "(%d+):(%d+):(%d+) (%d+):(%d+):(%d+)"
my_year, my_month, my_day, my_hour, my_min, my_sec = image.exif_datetime_taken:match(date_format)
local my_timestamp = os.time({year=my_year, month=my_month, day=my_day, hour=my_hour, min=my_min, sec=my_sec})
gpx_file = gpx_file.."\t\t\t<trkpt lat=\""..string.gsub(tostring(image.latitude), ",", ".").."\" lon=\""..string.gsub(tostring(image.longitude), ",", ".").."\">\n"
gpx_file = gpx_file.."\t\t\t\t<time>"..os.date("!%Y-%m-%dT%H:%M:%SZ", my_timestamp).."</time>\n"
gpx_file = gpx_file.."\t\t\t\t<name>"..image.path.."/"..image.filename.."</name>\n"
gpx_file = gpx_file.."\t\t\t</trkpt>\n"
end
gpx_file = gpx_file.."\t\t</trkseg>\n";
gpx_file = gpx_file.."\t</trk>\n";
end
job.valid = false
gpx_file = gpx_file.."</gpx>\n";
local file = io.open(path, "w")
if (file == nil) then
dt.print(_("invalid path: ")..path)
else
file:write(gpx_file)
file:close()
dt.print(_("gpx file created: ")..path)
end
end
local function install_module()
if not gpx.module_installed then
dt.register_lib(
"gpx_exporter",
"gpx export",
true, -- expandable
true, -- resetable
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers
gpx.widget,
nil,-- view_enter
nil -- view_leave
)
gpx.module_installed = true
end
end
gpx.widget = dt.new_widget("box")
{
orientation = "vertical",
dt.new_widget("button")
{
label = _("export"),
tooltip = _("export gpx file"),
clicked_callback = create_gpx_file
},
dt.new_widget("box")
{
orientation = "horizontal",
dt.new_widget("label")
{
label = _("file:"),
},
path_entry
},
}
if dt.gui.current_view().id == "lighttable" then
install_module()
else
if not gpx.event_registered then
dt.register_event(
"view-changed",
function(event, old_view, new_view)
if new_view.name == "lighttable" and old_view.name == "darkroom" then
install_module()
end
end
)
gpx.event_registered = true
end
end