Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Bill Ferguson
2016-04-06 22:16:11 -04:00
29 changed files with 1249 additions and 64 deletions

View File

@@ -41,7 +41,7 @@ local darktable = require "darktable"
local autostyle_apply_one_image,autostyle_apply_one_image_event,autostyle_apply,exiftool_attribute,capture
-- Tested it with darktable 1.6.1 and darktable git from 2014-01-25
darktable.configuration.check_version(...,{2,0,2},{2,1,0})
darktable.configuration.check_version(...,{2,0,2},{2,1,0},{3,0,0})
-- Receive the event triggered
function autostyle_apply_one_image_event(event,image)

View File

@@ -1,6 +1,6 @@
--[[
This file is part of darktable,
Copyright 2014 by Tobias Jakobs.
Copyright 2014-2016 by Tobias Jakobs.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,7 +26,15 @@ USAGE
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,1},{3,0,0})
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("calcDistance",dt.configuration.config_dir.."/lua/")
local function _(msgid)
return gettext.dgettext("calcDistance", msgid)
end
local function calcDistance()
local sel_images = dt.gui.selection()
@@ -35,6 +43,9 @@ local function calcDistance()
local lon1 = 0;
local lat2 = 0;
local lon2 = 0;
local ele1 = 0;
local ele2 = 0;
local i = 0;
local sel_images = dt.gui.selection()
@@ -49,10 +60,12 @@ local function calcDistance()
if (i == 1) then
lat1 = image.latitude;
lon1 = image.longitude;
ele1 = image.elevation;
end
lat2 = image.latitude;
lon2 = image.longitude;
ele2 = image.elevation;
end
end
@@ -71,10 +84,23 @@ local function calcDistance()
local angle = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a));
local distance = earthRadius * angle; -- Distance in km
dt.print(distance.." km")
-- Add the elevation to the calculation
local elevation = 0;
elevation = math.abs(ele1 - ele2) / 1000; --in km
distance = math.sqrt(math.pow(elevation,2) + math.pow(distance,2) );
local distanceUnit
if (distance < 1) then
distance = distance * 1000
distanceUnit = "m"
else
distanceUnit = "km"
end
dt.print(string.format("Distance: %.2f %s", distance, distanceUnit))
end
-- Register
dt.register_event("shortcut",calcDistance,"Calculate the distance from latitude and longitude in km")
dt.register_event("shortcut",calcDistance,_("Calculate the distance from latitude and longitude in km"))

View File

@@ -34,8 +34,8 @@ USAGE
local darktable = require "darktable"
-- Tested with darktable 1.6.2
darktable.configuration.check_version(...,{2,0,2})
-- Tested with darktable 2.0.1
darktable.configuration.check_version(...,{2,0,0},{3,0,0})
local queue = {}
local processed_files = {}

View File

@@ -0,0 +1,22 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-01-31 22:57+0100\n"
"PO-Revision-Date: 2016-01-31 23:02+0100\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.4\n"
#: calcDistance.lua:93
msgid "Calculate the distance from latitude and longitude in km"
msgstr "Errechne die Entfernung mit Hilfe des Längen- und Breitengrads in km"

View File

@@ -0,0 +1,30 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-01-31 22:58+0100\n"
"PO-Revision-Date: 2016-01-31 23:13+0100\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.4\n"
#: geo_uri.lua:55
msgid "gnome-maps not found"
msgstr "gnome-maps wurde nicht gefunden"
#: geo_uri.lua:81
msgid "Command failed ..."
msgstr "Aufruf fehlgeschlagen ..."
#: geo_uri.lua:88
msgid "Open Location in Gnome Maps"
msgstr "Öffnet den Ort in Gnome Maps"

View File

@@ -0,0 +1,26 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-01-31 22:58+0100\n"
"PO-Revision-Date: 2016-01-31 23:05+0100\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.4\n"
#: gps_select.lua:59
msgid "Select all images with GPS information"
msgstr "Markiert alle Bilder mit GPS-Informationen"
#: gps_select.lua:60
msgid "Select all images without GPS information"
msgstr "Markiert alle Bilder ohne GPS-Informationen"

View File

@@ -0,0 +1,42 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-01-31 22:59+0100\n"
"PO-Revision-Date: 2016-01-31 23:09+0100\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.4\n"
#: hugin.lua:73
msgid "hugin not found"
msgstr "Hugin wurde nicht gefunden"
#: hugin.lua:97
msgid "Will try to stitch now"
msgstr "Versuche Bilder zusammenzufügen"
#: hugin.lua:102
msgid "Creating pto file"
msgstr "Erzeuge pto Datei"
#: hugin.lua:105
msgid "Running Assistent"
msgstr "Starte den Assistenten"
#: hugin.lua:118
msgid "Command hugin failed ..."
msgstr "Aufruf von hugin fehlgeschlagen ..."
#: hugin.lua:124
msgid "Hugin Panorama"
msgstr "Hugin Panorama"

View File

@@ -0,0 +1,46 @@
msgid ""
msgstr ""
"Project-Id-Version: Lua gettextTest\n"
"POT-Creation-Date: 2016-01-22 15:33+0100\n"
"PO-Revision-Date: 2016-01-22 23:28+0100\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.4\n"
"X-Poedit-Basepath: .\n"
"Plural-Forms: nplurals=2;t" plural=(n != 1);\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2;ngettext:1,2;dngettext:2,3\n"
"X-Poedit-SearchPath-0: .\n"
msgid "KML/KMZ Export"
msgstr "KML/KMZ Expor
msgid "Export Image %i/%i"
msgstr "Exportiere Bild %i/%i"
msgid "KML export: Open KML/KMZ file after export"
msgstr "KML export: KML/KMZ-Datei nach dem exportieren öffnen"
msgid "Opens the KML file after the export with the standard programm for KML files"
msgstr "Öffnet die KML-Datei mit dem Standardprogram für KML-Dateien"
msgid "KML export: Export directory"
msgstr "KML export: Export-Verzeichnis"
msgid "A directory that will be used to export the KML/KMZ files"
msgstr "Verzeichnis in das die KML/KMZ-Dateien exportiert werden"
msgid "KML export: Connect images with path"
msgstr "KML export: Bilder mit einer Linie verbinden"
msgid "connect all images with a path"
msgstr "Verbinde alle Bilder mit einer Linie"
msgid "KML export: Create KMZ file"
msgstr "KML export: KMZ-Datei erstellen"
msgid "Compress all imeges to one KMZ file"
msgstr "Alle Bilder in einer KMZ-Datei komprimieren"

View File

@@ -0,0 +1,30 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-01-31 22:59+0100\n"
"PO-Revision-Date: 2016-01-31 23:13+0100\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.4\n"
#: slideshowMusic.lua:80
msgid "Slideshow background music file"
msgstr "Diashow Hintergrundmusik-Datei"
#: slideshowMusic.lua:84
msgid "Play slideshow background music"
msgstr "Diashow Hintergrundmusik abspielen"
#: slideshowMusic.lua:85
msgid "Plays music with rhythmbox if a slideshow starts"
msgstr "Musik mit Rhythmbox abspielen, wenn die Diashow beginnt"

320
contrib/geoJSON_export.lua Normal file
View File

@@ -0,0 +1,320 @@
--[[
This file is part of darktable,
Copyright 2016 by Tobias Jakobs.
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
]]
--[[
darktable geoJSON export script
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* mkdir
* convert (ImageMagick)
* xdg-open
* xdg-user-dir
WARNING
This script is only tested with Linux
USAGE
* require this script from your main Lua file
]]
local dt = require "darktable"
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("geoJSON_export",dt.configuration.config_dir.."/lua/")
local function _(msgid)
return gettext.dgettext("geoJSON_export", msgid)
end
-- Sort a table
local function spairs(_table, order) -- Code copied from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua
-- collect the keys
local keys = {}
for _key in pairs(_table) do keys[#keys + 1] = _key end
-- if order function given, sort by it by passing the table and keys a, b,
-- otherwise just sort the keys
if order then
table.sort(keys, function(a,b) return order(_table, a, b) end)
else
table.sort(keys)
end
-- return the iterator function
local i = 0
return function()
i = i + 1
if keys[i] then
return keys[i], _table[keys[i]]
end
end
end
local function show_status(storage, image, format, filename, number, total, high_quality, extra_data)
dt.print(string.format(_("Export Image %i/%i"), number, total))
end
local function checkIfBinExists(bin)
local handle = io.popen("which "..bin)
local result = handle:read()
local ret
handle:close()
if (not result) then
dt.print_error(bin.." not found")
ret = false
end
ret = true
return ret
end
local function create_geoJSON_file(storage, image_table, extra_data)
if not checkIfBinExists("mkdir") then
return
end
if not checkIfBinExists("convert") then
return
end
if not checkIfBinExists("xdg-open") then
return
end
if not checkIfBinExists("xdg-user-dir") then
return
end
dt.print_error("Will try to export geoJSON file now")
local xportDirectory = dt.preferences.read("geoJSON_export","ExportDirectory","string")
-- Creates dir if not exsists
local imageFoldername = "files/"
local mkdirCommand = "mkdir -p "..exportDirectory.."/"..imageFoldername
coroutine.yield("RUN_COMMAND", mkdirCommand)
-- Create the thumbnails
for image,exported_image in pairs(image_table) do
if ((image.longitude and image.latitude) and
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
) then
local path, filename, filetype = string.match(image, "(.-)([^\\/]-%.?([^%.\\/]*))$")
filename = string.upper(string.gsub(filename,"%.", "_"))
-- convert -size 92x92 filename.jpg -resize 92x92 +profile "*" thumbnail.jpg
-- In this example, '-size 120x120' gives a hint to the JPEG decoder that the image is going to be downscaled to
-- 120x120, allowing it to run faster by avoiding returning full-resolution images to GraphicsMagick for the
-- subsequent resizing operation. The '-resize 120x120' specifies the desired dimensions of the output image. It
-- will be scaled so its largest dimension is 120 pixels. The '+profile "*"' removes any ICM, EXIF, IPTC, or other
-- profiles that might be present in the input and aren't needed in the thumbnail.
local convertToThumbCommand = "convert -size 96x96 "..exported_image.." -resize 92x92 -mattecolor \"#FFFFFF\" -frame 2x2 +profile \"*\" "..exportDirectory.."/"..imageFoldername.."thumb_"..filename..".jpg"
-- USE coroutine.yield. It does not block the UI
coroutine.yield("RUN_COMMAND", convertToThumbCommand)
local concertCommand = "convert -size 438x438 "..exported_image.." -resize 438x438 +profile \"*\" "..exportDirectory.."/"..imageFoldername..filename..".jpg"
coroutine.yield("RUN_COMMAND", concertCommand)
end
-- delete the original image to not get into the kmz file
os.remove(image)
local pattern = "[/]?([^/]+)$"
filmName = string.match(image.film.path, pattern)
end
local exportgeoJSONFilename = filmName..".geoJSON"
local exportMapBoxHTMLFilename = filmName..".html"
-- Create the geoJSON file
local geoJSON_file = [[
{
"type": "FeatureCollection",
"features": [
]]
for image,exported_image in pairs(image_table) do
filename = string.upper(string.gsub(image.filename,"%.", "_"))
if ((image.longitude and image.latitude) and
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
) then
geoJSON_file = geoJSON_file..
[[ {
"type": "Feature",
"geometry": {
"type": "Point",
]]
geoJSON_file = geoJSON_file.." \"coordinates\": ["..string.gsub(tostring(image.longitude),",", ".")..","..string.gsub(tostring(image.latitude),",", ".").."]\n"
geoJSON_file = geoJSON_file..
[[ },
"properties": {
"title": "]]..image.title..[[",
"description": "]]..image.description..[[",
"image": "]]..imageFoldername..filename..[[.jpg",
"icon": {
"iconUrl": "]]..imageFoldername.."thumb_"..filename..[[.jpg",
"iconSize": [96, 65],
"iconAnchor": [48, 32],
"popupAnchor": [0, -32],
"className": "dot"
}
}
}
,]]
end
end
geoJSON_file = geoJSON_file:sub(0,geoJSON_file:len()-1)
geoJSON_file = geoJSON_file..
[[
]
}
]]
--HTML
if ( dt.preferences.read("geoJSON_export","CreateMapBoxHTMLFile","bool") == true ) then
local mapBoxKey = dt.preferences.read("geoJSON_export","mapBoxKey","string")
local mapBoxHTML_file = [[
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>2014-05-31 Rieselfelder</title>
<script src='https://api.tiles.mapbox.com/mapbox.js/v2.2.4/mapbox.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox.js/v2.2.4/mapbox.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
.map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map-tooltips-js' class='map'> </div>
<script>
L.mapbox.accessToken = ']]..mapBoxKey..[[';
var mapTooltipsJS = L.mapbox.map('map-tooltips-js', 'mapbox.light')
.setView([0,0], 5);
var myLayer = L.mapbox.featureLayer()
.loadURL(']]..exportgeoJSONFilename..[[')
.addTo(mapTooltipsJS);
// Set a custom icon on each marker based on feature properties.
myLayer.on('layeradd', function(e) {
var marker = e.layer,
feature = marker.feature;
marker.setIcon(L.icon(feature.properties.icon));
var content = '<h2>'+ feature.properties.title+'<\/h2>' + '<p>'+ feature.properties.description+'<\/p>' + '<img src="'+feature.properties.image+'" alt="">';
marker.bindPopup(content,{minWidth: 457});
});
// Center on click
myLayer.on('click', function(e) {
mapTooltipsJS.panTo(e.layer.getLatLng());
});
// https://www.mapbox.com/mapbox.js/example/v1.0.0/fit-map-to-markers/
// Especially with dynamic data, it's useful to automatically fit all markers
// in the map bounds instead of guessing and checking center and zoom values
// Since this layer is loaded with the asynchronous method loadURL, that uses
// AJAX in the background, we wait for all of the markers to be loaded by
// waiting for the ready event. If you don't load your markers with an async
// method and instead set them with setGeoJSON or similar, you don't need
// to do this.
myLayer.on('ready', function() {
// featureLayer.getBounds() returns the corners of the furthest-out markers,
// and map.fitBounds() makes sure that the map contains these.
mapTooltipsJS.fitBounds(myLayer.getBounds());
});
// Lines
// https://www.mapbox.com/mapbox.js/example/v1.0.0/line-marker/
myLayer.on('ready', function(e) {
var line = [];
this.eachLayer(function(marker) {
line.push(marker.getLatLng());
});
var polyline_options = {
color: '#FF0000'
};
var polyline = L.polyline(line, polyline_options).addTo(mapTooltipsJS);
});
</script>
</body>
</html>
]]
local file = io.open(exportDirectory.."/"..exportMapBoxHTMLFilename, "w")
file:write(mapBoxHTML_file)
file:close()
end
local file = io.open(exportDirectory.."/"..exportgeoJSONFilename, "w")
file:write(geoJSON_file)
file:close()
dt.print("geoJSON file created in "..exportDirectory)
-- Open the file with the standard programm
if ( dt.preferences.read("geoJSON_export","OpengeoJSONFile","bool") == true ) then
local geoJSONFileOpenCommand
geoJSONFileOpenCommand = "xdg-open "..exportDirectory.."/\""..exportgeoJSONFilename.."\""
coroutine.yield("RUN_COMMAND", geoJSONFileOpenCommand)
end
end
-- Preferences
dt.preferences.register("geoJSON_export",
"CreateMapBoxHTMLFile",
"bool",
_("geoJSON export: Create an additional HTML file"),
_("Creates a HTML file, that loads the geoJASON file. (Needs a MapBox key"),
false )
dt.preferences.register("geoJSON_export",
"mapBoxKey",
"string",
_("geoJSON export: MapBox Key"),
_("https://www.mapbox.com/studio/account/tokens"),
'' )
dt.preferences.register("geoJSON_export",
"OpengeoJSONFile",
"bool",
_("geoJSON export: Open geoJSON file after export"),
_("Opens the geoJSON file after the export with the standard program for geoJSON files"),
false )
local handle = io.popen("xdg-user-dir DESKTOP")
local result = handle:read()
handle:close()
dt.preferences.register("geoJSON_export",
"ExportDirectory",
"directory",
_("geoJSON export: Export directory"),
_("A directory that will be used to export the geoJSON files"),
result )
-- Register
dt.register_storage("geoJSON_export", "geoJSON Export", nil, create_geoJSON_file)

88
contrib/geo_uri.lua Normal file
View File

@@ -0,0 +1,88 @@
--[[
This file is part of darktable,
Copyright 2016 by Tobias Jakobs.
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
]]
--[[
darktable script to open a geo uri in gnome-maps
ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT
* gnome-maps >= 3.20
USAGE
* require this script from your main lua file
* register a shortcut
]]
local dt = require "darktable"
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("geo_uri",dt.configuration.config_dir.."/lua/")
local function _(msgid)
return gettext.dgettext("geo_uri", msgid)
end
local function checkIfBinExists(bin)
local handle = io.popen("which "..bin)
local result = handle:read()
local ret
handle:close()
if (not result) then
dt.print_error(bin.." not found")
ret = false
end
ret = true
return ret
end
local function openLocationInGnomeMaps()
if not checkIfBinExists("gnome-maps") then
dt.print_error(_("gnome-maps not found"))
return
end
local sel_images = dt.gui.selection()
local lat1 = 0;
local lon1 = 0;
local i = 0;
-- Use the first image with geo information
for _,image in ipairs(sel_images) do
if ((image.longitude and image.latitude) and
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
) then
lat1 = image.latitude;
lon1 = image.longitude;
break
end
end
local startCommand
startCommand = "gnome-maps \"geo:" .. lat1 .. "," .. lon1 .."\""
dt.print_error(startCommand)
if coroutine.yield("RUN_COMMAND", startCommand) then
dt.print(_("Command failed ..."))
end
end
end
-- Register
dt.register_event("shortcut", openLocationInGnomeMaps, _("Open Location in Gnome Maps"))

View File

@@ -24,7 +24,16 @@ USAGE
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,1})
local gettext = dt.gettext
dt.configuration.check_version(...,{2,0,1},{3,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("gps_select",dt.configuration.config_dir.."/lua/")
local function _(msgid)
return gettext.dgettext("gps_select", msgid)
end
table = require "table"
local function selectWithGPS()
@@ -47,5 +56,5 @@ local function selectWithoutGPS()
dt.gui.selection(selection)
end
dt.register_event("shortcut", selectWithGPS, "Select all images with GPS information")
dt.register_event("shortcut", selectWithoutGPS, "Select all images without GPS information")
dt.register_event("shortcut", selectWithGPS, _("Select all images with GPS information"))
dt.register_event("shortcut", selectWithoutGPS, _("Select all images without GPS information"))

View File

@@ -34,9 +34,17 @@ This plugin will add a new storage option and calls hugin after export.
]]
local dt = require "darktable"
local gettext = dt.gettext
-- should work with darktable API version 2.0.0
dt.configuration.check_version(...,{2,0,0})
-- works with darktable API version 2.0.0 and 3.0.0
dt.configuration.check_version(...,{2,0,0},{3,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("hugin",dt.configuration.config_dir.."/lua/")
local function _(msgid)
return gettext.dgettext("hugin", msgid)
end
local function checkIfBinExists(bin)
local handle = io.popen("which "..bin)
@@ -62,7 +70,7 @@ end
local function create_panorama(storage, image_table, extra_data) --finalize
if not checkIfBinExists("hugin") then
darktable.print_error("hugin not found")
dt.print_error(_("hugin not found"))
return
end
@@ -86,15 +94,15 @@ local function create_panorama(storage, image_table, extra_data) --finalize
img_list = img_list ..v.. " "
end
dt.print("Will try to stitch now")
dt.print(_("Will try to stitch now"))
local huginStartCommand
if (hugin_executor) then
huginStartCommand = "pto_gen "..img_list.." -o "..dt.configuration.tmp_dir.."/project.pto"
dt.print("Creating pto file")
dt.print(_("Creating pto file"))
coroutine.yield("RUN_COMMAND", huginStartCommand)
dt.print("Running Assistent")
dt.print(_("Running Assistent"))
huginStartCommand = "hugin_executor --assistant "..dt.configuration.tmp_dir.."/project.pto"
coroutine.yield("RUN_COMMAND", huginStartCommand)
@@ -107,13 +115,13 @@ local function create_panorama(storage, image_table, extra_data) --finalize
if coroutine.yield("RUN_COMMAND", huginStartCommand)
then
dt.print("Command hugin failed ...")
dt.print(_("Command hugin failed ..."))
end
end
-- Register
dt.register_storage("module_hugin", "Hugin Panorama", show_status, create_panorama)
dt.register_storage("module_hugin", _("Hugin Panorama"), show_status, create_panorama)
--
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua

View File

@@ -1,6 +1,6 @@
--[[
This file is part of darktable,
Copyright 2014 by Tobias Jakobs.
Copyright 2016 by Tobias Jakobs.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -29,12 +29,22 @@ WARNING
This script is only tested with Linux
USAGE
* require this script from your main lua file
* require this script from your main Lua file
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,1},{3,0,0})
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("kml_export",dt.configuration.config_dir.."/lua/")
local function _(msgid)
return gettext.dgettext("kml_export", msgid)
end
-- Sort a table
local function spairs(_table, order) -- Code copied from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua
-- collect the keys
local keys = {}
@@ -59,7 +69,7 @@ local function spairs(_table, order) -- Code copied from http://stackoverflow.co
end
local function show_status(storage, image, format, filename, number, total, high_quality, extra_data)
dt.print("Export Image "..tostring(number).."/"..tostring(total))
dt.print(string.format(_("Export Image %i/%i"), number, total))
end
local function checkIfBinExists(bin)
@@ -92,6 +102,7 @@ local function create_kml_file(storage, image_table, extra_data)
dt.print_error("Will try to export KML file now")
local imageFoldername
if ( dt.preferences.read("kml_export","CreateKMZ","bool") == true ) then
if not checkIfBinExists("zip") then
return
@@ -109,32 +120,39 @@ local function create_kml_file(storage, image_table, extra_data)
-- Create the thumbnails
for _,image in pairs(image_table) do
local path, filename, filetype = string.match(image, "(.-)([^\\/]-%.?([^%.\\/]*))$")
filename = string.upper(string.gsub(filename,"%.", "_"))
for image,exported_image in pairs(image_table) do
if ((image.longitude and image.latitude) and
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
) then
local path, filename, filetype = string.match(exported_image, "(.-)([^\\/]-%.?([^%.\\/]*))$")
filename = string.upper(string.gsub(filename,"%.", "_"))
-- convert -size 92x92 filename.jpg -resize 92x92 +profile "*" thumbnail.jpg
-- In this example, '-size 120x120' gives a hint to the JPEG decoder that the image is going to be downscaled to
-- 120x120, allowing it to run faster by avoiding returning full-resolution images to GraphicsMagick for the
-- subsequent resizing operation. The '-resize 120x120' specifies the desired dimensions of the output image. It
-- will be scaled so its largest dimension is 120 pixels. The '+profile "*"' removes any ICM, EXIF, IPTC, or other
-- profiles that might be present in the input and aren't needed in the thumbnail.
-- convert -size 92x92 filename.jpg -resize 92x92 +profile "*" thumbnail.jpg
-- In this example, '-size 120x120' gives a hint to the JPEG decoder that the image is going to be downscaled to
-- 120x120, allowing it to run faster by avoiding returning full-resolution images to GraphicsMagick for the
-- subsequent resizing operation. The '-resize 120x120' specifies the desired dimensions of the output image. It
-- will be scaled so its largest dimension is 120 pixels. The '+profile "*"' removes any ICM, EXIF, IPTC, or other
-- profiles that might be present in the input and aren't needed in the thumbnail.
local concertToThumbCommand = "convert -size 96x96 "..image.." -resize 92x92 -mattecolor \"#FFFFFF\" -frame 2x2 +profile \"*\" "..exportDirectory.."/"..imageFoldername.."thumb_"..filename..".jpg"
-- USE coroutine.yield. It does not block the UI
coroutine.yield("RUN_COMMAND", concertToThumbCommand)
local concertCommand = "convert -size 438x438 "..image.." -resize 438x438 +profile \"*\" "..exportDirectory.."/"..imageFoldername..filename..".jpg"
coroutine.yield("RUN_COMMAND", concertCommand)
local convertToThumbCommand = "convert -size 96x96 "..exported_image.." -resize 92x92 -mattecolor \"#FFFFFF\" -frame 2x2 +profile \"*\" "..exportDirectory.."/"..imageFoldername.."thumb_"..filename..".jpg"
-- USE coroutine.yield. It does not block the UI
coroutine.yield("RUN_COMMAND", convertToThumbCommand)
local concertCommand = "convert -size 438x438 "..exported_image.." -resize 438x438 +profile \"*\" "..exportDirectory.."/"..imageFoldername..filename..".jpg"
coroutine.yield("RUN_COMMAND", concertCommand)
end
-- delete the original image to not get into the kmz file
os.remove(exported_image)
local pattern = "[/]?([^/]+)$"
filmName = string.match(_.film.path, pattern)
filmName = string.match(image.film.path, pattern)
end
exportKMLFilename = filmName..".kml"
exportKMZFilename = filmName..".kmz"
-- Create the KML file
kml_file = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
local kml_file = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
kml_file = kml_file.."<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
kml_file = kml_file.."<Document>\n"
@@ -142,15 +160,20 @@ local function create_kml_file(storage, image_table, extra_data)
kml_file = kml_file.."<name>"..filmName.."</name>\n"
kml_file = kml_file.." <description>Exported from darktable</description>\n"
for image,_ in pairs(image_table) do
for image,exported_image in pairs(image_table) do
filename = string.upper(string.gsub(image.filename,"%.", "_"))
if ((image.longitude and image.latitude) and
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
) then
kml_file = kml_file.." <Placemark>\n"
kml_file = kml_file.." <name>"..image.filename.."</name>\n"
--kml_file = kml_file.." <description></description>\n"
if (image.title and image.title ~= "") then
kml_file = kml_file.." <name>"..image.title.."</name>\n"
else
kml_file = kml_file.." <name>"..image.filename.."</name>\n"
end
kml_file = kml_file.." <description>"..image.description.."</description>\n"
kml_file = kml_file.." <Style>\n"
kml_file = kml_file.." <IconStyle>\n"
@@ -193,11 +216,15 @@ local function create_kml_file(storage, image_table, extra_data)
kml_file = kml_file.." <LineString>\n"
kml_file = kml_file.." <coordinates>\n"
for image,_ in spairs(image_table, function(t,a,b) return t[b] < t[a] end) do
for image,exported_image in spairs(image_table, function(t,a,b) return t[b] < t[a] end) do
if ((image.longitude and image.latitude) and
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
) then
kml_file = kml_file.." "..string.gsub(tostring(image.longitude),",", ".")..","..string.gsub(tostring(image.latitude),",", ".")..",0\n"
local altitude = 0;
if (image.elevation) then
altitude = image.elevation;
end
kml_file = kml_file.." "..string.gsub(tostring(image.longitude),",", ".")..","..string.gsub(tostring(image.latitude),",", ".")..",altitude\n"
end
end
kml_file = kml_file.." </coordinates>\n"
@@ -209,7 +236,7 @@ local function create_kml_file(storage, image_table, extra_data)
kml_file = kml_file.."</Document>\n"
kml_file = kml_file.."</kml>"
file = io.open(exportDirectory.."/"..exportKMLFilename, "w")
local file = io.open(exportDirectory.."/"..exportKMLFilename, "w")
file:write(kml_file)
file:close()
@@ -222,7 +249,7 @@ local function create_kml_file(storage, image_table, extra_data)
local createKMZCommand = "zip --test --move --junk-paths "
createKMZCommand = createKMZCommand .."\""..exportDirectory.."/"..exportKMZFilename.."\" "
createKMZCommand = createKMZCommand .."\""..dt.configuration.tmp_dir.."/"..exportKMLFilename.."\" \""..dt.configuration.tmp_dir.."/"..imageFoldername.."\"*"
coroutine.yield("RUN_COMMAND", createKMZCommand)
coroutine.yield("RUN_COMMAND", createKMZCommand)
end
-- Open the file with the standard programm
@@ -241,15 +268,35 @@ local function create_kml_file(storage, image_table, extra_data)
end
-- Preferences
dt.preferences.register("kml_export", "OpenKmlFile", "bool", "KML export: Open KML/KMZ file after export", "Opens the KML file after the export with the standard programm for KML files", false )
dt.preferences.register("kml_export",
"OpenKmlFile",
"bool",
_("KML export: Open KML/KMZ file after export"),
_("Opens the KML file after the export with the standard program for KML files"),
false )
local handle = io.popen("xdg-user-dir DESKTOP")
local result = handle:read()
handle:close()
dt.preferences.register("kml_export", "ExportDirectory", "directory", "KML export: Export directory", "A directory that will be used to export the KML/KMZ files", result )
dt.preferences.register("kml_export",
"ExportDirectory",
"directory",
_("KML export: Export directory"),
_("A directory that will be used to export the KML/KMZ files"),
result )
dt.preferences.register("kml_export", "CreatePath", "bool", "KML export: Connect images with path", "connect all images with a path", false )
dt.preferences.register("kml_export", "CreateKMZ", "bool", "KML export: Create KMZ file", "Compress all imeges to one KMZ file", true )
dt.preferences.register("kml_export",
"CreatePath",
"bool",
_("KML export: Connect images with path"),
_("connect all images with a path"),
false )
dt.preferences.register("kml_export",
"CreateKMZ",
"bool",
_("KML export: Create KMZ file"),
_("Compress all imeges to one KMZ file"),
true )
-- Register
dt.register_storage("kml_export", "KML/KMZ Export", nil, create_kml_file)
dt.register_storage("kml_export", _("KML/KMZ Export"), nil, create_kml_file)

View File

@@ -25,7 +25,15 @@ USAGE
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,2})
local gettext = dt.gettext
dt.configuration.check_version(...,{2,0,2},{3,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("slideshowMusic",dt.configuration.config_dir.."/lua/")
local function _(msgid)
return gettext.dgettext("slideshowMusic", msgid)
end
local function checkIfBinExists(bin)
local handle = io.popen("which "..bin)
@@ -59,7 +67,7 @@ local function playSlideshowMusic(_, old_view, new_view)
--dt.print_error(playCommand)
coroutine.yield("RUN_COMMAND", playCommand)
else
if (old_view.id == "slideshow") then
if (old_view and old_view.id == "slideshow") then
stopCommand = "rhythmbox-client --pause"
--dt.print_error(stopCommand)
coroutine.yield("RUN_COMMAND", stopCommand)
@@ -69,12 +77,12 @@ local function playSlideshowMusic(_, old_view, new_view)
end
-- Preferences
dt.preferences.register("slideshowMusic", "SlideshowMusic", "file", "Slideshow background music file", "", "")
dt.preferences.register("slideshowMusic", "SlideshowMusic", "file", _("Slideshow background music file"), "", "")
dt.preferences.register("slideshowMusic",
"PlaySlideshowMusic",
"bool",
"Play slideshow background music",
"Plays music with rhythmbox if a slideshow starts",
_("Play slideshow background music"),
_("Plays music with rhythmbox if a slideshow starts"),
true)
-- Register
dt.register_event("view-changed",playSlideshowMusic)

View File

@@ -0,0 +1,20 @@
msgid ""
msgstr ""
"Project-Id-Version: Lua gettextTest\n"
"POT-Creation-Date: 2016-01-07 20:33+0100\n"
"PO-Revision-Date: 2016-01-07 21:32+0100\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.4\n"
"X-Poedit-Basepath: .\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2;ngettext:1,2;dngettext:2,3\n"
"X-Poedit-SearchPath-0: .\n"
#: gettextExample.lua:36
msgid "Hello World!"
msgstr "Hallo Welt!"

View File

@@ -0,0 +1,76 @@
--[[
This file is part of darktable,
Copyright 2016 by Tobias Jakobs.
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
]]
--[[
darktable script to show how translations works
To create the .po file run:
xgettext -l lua gettextExample.lua
xgettext is not a lua tool, it knows (almost) nothing about Lua, and not
enough to do a proper parsing. It takes a text file (In our case a Lua
file) and recognises a few (language dependant) keyword in there.
It matches those keywords with internal description on how functions are
called and creates the .po file accordingly. (For example, it knows that
the first argument of gettext() is the translated string, but that it's
the second argument for dgettext)
This is important because it means that if you use some neat Lua tricks
(like renaming functions) xgettext won't recognize those calls and won't
extract the string to the .po file.
So, this is why we create a local variagle gettext = dt.gettext, so
xgettext recognises gettext.gettext as a function but not dt.gettext.gettext
To create a .mo file run:
msgfmt -v gettextExample.po -o gettextExample.mo
USAGE
* require this script from your main lua file (Add 'require "gettextExample"' to luarc.)
* copy the script to: .config/darktable/lua/
* copy the gettextExample.mo to .config/darktable/lua/de_DE/LC_MESSAGES
You need to start darktable with the Lua debug option: darktable -d lua
$LANG must set to: de_DE
The script run on darktable startup and should output this three lines:
LUA ERROR Hello World!
LUA ERROR Bild
LUA ERROR Hallo Welt!
]]
local dt = require "darktable"
dt.configuration.check_version(...,{3,0,0})
-- Not translated Text
dt.print_error("Hello World!")
local gettext = dt.gettext
-- Translate a string using the darktable textdomain
dt.print_error(gettext.gettext("image"))
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("gettextExample",dt.configuration.config_dir.."/lua/")
-- Translate a string using the specified textdomain
dt.print_error(gettext.dgettext("gettextExample", 'Hello World!'))
-- Define a local function called _ to make the code more readable and have it call dgettext
-- with the proper domain.
local function _(msgid)
return gettext.dgettext("gettextExample", msgid)
end
dt.print_error(_('Hello World!'))

View File

@@ -27,7 +27,7 @@ USAGE
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,0})
dt.configuration.check_version(...,{2,0,0},{3,0,0})
dt.print("hello, world")

View File

@@ -0,0 +1,85 @@
--[[
This file is part of darktable,
copyright (c) 2016 Tobias Jakobs
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/>.
]]
--[[
USAGE
* require this script from your main lua file
To do this add this line to the file .config/darktable/luarc:
require "moduleExample"
* it creates a new example lighttable module
More informations about building user interface elements:
https://www.darktable.org/usermanual/ch09.html.php#lua_gui_example
And about new_widget here:
https://www.darktable.org/lua-api/index.html.php#darktable_new_widget
]]
local dt = require "darktable"
dt.configuration.check_version(...,{3,0,0})
-- add a new lib
local check_button = dt.new_widget("check_button"){label = "MyCheck_button", value = true}
local combobox = dt.new_widget("combobox"){label = "MyCombobox", value = 2, "8", "16", "32"}
local entry = dt.new_widget("entry"){text = "test", placeholder = "placeholder", tooltip = "tooltip"}
local file_chooser_button = dt.new_widget("file_chooser_button"){title = "MyFile_chooser_button"}
local label = dt.new_widget("label")
label.label = "MyLabel" -- This is an alternative way to the "{}" syntax to set a property
local separator = dt.new_widget("separator"){}
local slider = dt.new_widget("slider")
{
label = "MySlider",
soft_min = 10, -- The soft minimum value for the slider, the slider can't go beyond this point
soft_max = 100, -- The soft maximum value for the slider, the slider can't go beyond this point
hard_min = 0, -- The hard minimum value for the slider, the user can't manually enter a value beyond this point
hard_max = 1000, -- The hard maximum value for the slider, the user can't manually enter a value beyond this point
value = 52 -- The current value of the slider
}
dt.register_lib(
"exampleModule", -- Module name
"exampleModule", -- name
true, -- expandable
false, -- resetable
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers
dt.new_widget("box") -- widget
{
orientation = "vertical",
dt.new_widget("button")
{
label = "MyButton",
clicked_callback = function (_)
dt.print("Button clicked")
end
},
check_button,
combobox,
entry,
file_chooser_button,
label,
separator,
slider
},
nil,-- view_enter
nil -- view_leave
)
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
-- kate: hl Lua;

View File

@@ -33,7 +33,7 @@ Note that you need to restart DT for your changes to enabled scripts to take eff
]]
local dt = require "darktable"
local io = require "io"
dt.configuration.check_version(...,{2,0,0})
dt.configuration.check_version(...,{3,0,0})
local output = io.popen("cd "..dt.configuration.config_dir.."/lua ;find . -name \\*.lua -print")
local my_name={...}

View File

@@ -31,7 +31,7 @@ local dt = require "darktable"
local https = require "ssl.https"
local cjson = require "cjson"
dt.configuration.check_version(...,{2,0,0})
dt.configuration.check_version(...,{2,0,0},{3,0,0})
-- compare two version strings of the form "major.minor.patch"
-- returns -1, 0, 1 if the first version is smaller, equal, greater than the second version,

View File

@@ -0,0 +1,128 @@
--[[
This file is part of darktable,
copyright (c) 2016 Tobias Ellinghaus
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/>.
]]
--[[
ADD SUPPORT FOR COPYING METADATA+RATING+COLOR LABELS+TAGS BETWEEN IMAGES
This script adds keyboard shortcuts and buttons to copy/paste metadata between images.
USAGE
* require this script from your main lua file
* it adds buttons to the selected images module
* it adds two keyboard shortcuts
]]
local dt = require "darktable"
dt.configuration.check_version(...,{3,0,0})
-- set this to "false" if you don't want to overwrite metadata fields
-- (title, description, creator, publisher and rights) that are already set
local overwrite = true
local have_data = false
local rating = 1
local red = false
local green = false
local yellow = false
local blue = false
local purple = false
local title = ""
local description = ""
local creator = ""
local publisher = ""
local rights = ""
local tags = {}
local function copy(image)
if not image then
have_data = false
else
have_data = true
rating = image.rating
red = image.red
green = image.green
yellow = image.yellow
blue = image.blue
purple = image.purple
title = image.title
description = image.description
creator = image.creator
publisher = image.publisher
rights = image.rights
tags = {}
for _, tag in ipairs(image:get_tags()) do
if not (string.sub(tag.name, 1, string.len("darktable|")) == "darktable|") then
table.insert(tags, tag)
end
end
end
end
local function paste(images)
if have_data then
for _, image in ipairs(images) do
image.rating = rating
image.red = red
image.green = green
image.yellow = yellow
image.blue = blue
image.purple = purple
if image.title == "" or overwrite then
image.title = title
end
if image.description == "" or overwrite then
image.description = description
end
if image.creator == "" or overwrite then
image.creator = creator
end
if image.publisher == "" or overwrite then
image.publisher = publisher
end
if image.rights == "" or overwrite then
image.rights = rights
end
for _, tag in ipairs(tags) do
image:attach_tag(tag)
end
end
end
end
dt.gui.libs.image.register_action(
"copy metadata",
function(event, images) copy(images[1]) end,
"copy metadata of the first selected image"
)
dt.gui.libs.image.register_action(
"paste metadata",
function(event, images) paste(images) end,
"paste metadata to the selected images"
)
dt.register_event(
"shortcut",
function(event, shortcut) copy(dt.gui.action_images[1]) end,
"copy metadata"
)
dt.register_event(
"shortcut",
function(event, shortcut) paste(dt.gui.action_images) end,
"paste metadata"
)

View File

@@ -29,7 +29,7 @@ all tags longer than the given length will be automatically deleted at every res
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,0})
dt.configuration.check_version(...,{2,0,0},{3,0,0})
dt.preferences.register("delete_long_tags", "length", "integer",
"maximum length of tags to keep",

174
official/enfuse.lua Normal file
View File

@@ -0,0 +1,174 @@
--[[
This file is part of darktable,
copyright (c) 2016 Tobias Ellinghaus
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/>.
]]
--[[
RUN ENFUSE ON THE SELECTED IMAGES
This script uses enfuse to merge the selected images into one HDR and imports the result.
It only works on ldr images (like, JPEG).
USAGE
* require this script from your main lua file
* it creates a new lighttable module
TODO
* remember the exposure_mu value in config when the slider is moved
* make the output filename unique so you can use it more than once per filmroll
* find a less stupid way to make sure the float value of exposure_mu gets turned into a string
with a decimal point instead of a comma in some languages
* export images that are not ldr and remove them afterwards
]]
local dt = require "darktable"
dt.configuration.check_version(...,{3,0,0})
-- thanks Tobias Jakobs for this function (taken from contrib/hugin.lua)
local function checkIfBinExists(bin)
local handle = io.popen("which "..bin)
local result = handle:read()
local ret
handle:close()
if (result) then
dt.print_error("true checkIfBinExists: "..bin)
ret = true
else
dt.print_error(bin.." not found")
ret = false
end
return ret
end
-- add a new lib
-- is enfuse installed?
local enfuse_installed = checkIfBinExists("enfuse")
-- initialize exposure_mu value and depth setting in config to sane defaults (would be 0 otherwise)
if dt.preferences.read("enfuse", "depth", "integer") == 0 then
dt.preferences.write("enfuse", "depth", "integer", 2)
dt.preferences.write("enfuse", "exposure_mu", "float", 0.5)
end
-- set up some widgets, initialized from config
local exposure_mu = dt.new_widget("slider")
{
label = "exposure mu",
tooltip = "center also known as MEAN of Gaussian weighting function (0 <= MEAN <= 1); default: 0.5",
hard_min = 0,
hard_max = 1,
value = dt.preferences.read("enfuse", "exposure_mu", "float")
}
local depth = dt.new_widget("combobox")
{
label = "depth",
tooltip = "the number of bits per channel of the output image",
value = dt.preferences.read("enfuse", "depth", "integer"),
changed_callback = function(w) dt.preferences.write("enfuse", "depth", "integer", w.selected) end,
"8", "16", "32"
}
-- ... and tell dt about it all
dt.register_lib(
"enfuse", -- plugin name
"enfuse", -- name
true, -- expandable
false, -- resetable
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers
dt.new_widget("box") -- widget
{
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
dt.preferences.write("enfuse", "exposure_mu", "float", mu)
-- create a temp response file
local response_file = os.tmpname()
local f = io.open(response_file, "w")
if not f then
dt.print("error writing to `"..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 in ipairs(dt.gui.action_images) do
-- only use ldr files as enfuse can't open raws. alternatively we could export raws that we encounter
if i.is_ldr then
cnt = cnt + 1
f:write(i.path.."/"..i.filename.."\n")
target_dir = i.path
else
dt.print("skipping "..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 == 1 then
dt.print(n_skipped.." image skipped")
elseif n_skipped > 1 then
dt.print(n_skipped.." images 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 command = "enfuse --depth "..depth.value.." --exposure-mu "..ugly_decimal_point_hack
.." -o \""..output_image.."\" \"@"..response_file.."\""
if coroutine.yield("RUN_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 was imported")
-- normally printing to stdout is bad, but we allow enfuse to show its output, so adding one extra line is ok
print("enfuse: done, resulting image '"..output_image.."' was imported with id "..image.id)
end
}
},
nil,-- view_enter
nil -- view_leave
)
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
-- kate: hl Lua;

View File

@@ -31,12 +31,12 @@ USAGE
-- TODO:
-- * enable showing of the txt file (plugins/lighttable/draw_custom_metadata) if this script is enabled
-- * maybe allow a lua command returning text instead of a command line call ? both ?
-- * maybe allow a lua command returning text instead of a command line call? both?
-- * make filenames with double quotes (") work
local dt = require "darktable"
require "darktable.debug"
dt.configuration.check_version(...,{2,1,0})
dt.configuration.check_version(...,{2,1,0},{3,0,0})
dt.preferences.register("generate_image_txt",
"enabled",

View File

@@ -29,7 +29,7 @@ This plugin will add a widget at the bottom of the left column in lighttable mod
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,0})
dt.configuration.check_version(...,{2,0,0},{3,0,0})
local main_label = dt.new_widget("label"){selectable = true, ellipsize = "middle", halign = "start"}

View File

@@ -34,7 +34,7 @@ increase it if you need more temporary selection buffers
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,0})
dt.configuration.check_version(...,{2,0,0},{3,0,0})
local buffer_count = 5
@@ -45,7 +45,7 @@ for i=1,buffer_count do
end,"save to buffer "..i)
dt.register_event("shortcut",function()
dt.gui.selection(saved_selection)
end,"restor from buffer "..i)
end,"restore from buffer "..i)
end
local bounce_buffer = {}