diff --git a/contrib/api_version.lua b/contrib/api_version.lua new file mode 100644 index 0000000..971f14c --- /dev/null +++ b/contrib/api_version.lua @@ -0,0 +1,27 @@ +--[[ + This file is part of darktable, + Copyright 2014 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 . +]] +--[[ +darktable script to show the Lua API version in the preferences + +USAGE +* require this script from your main lua file +]] +local dt = require "darktable" + +local result = dt.configuration.api_version_string +dt.print_error("API Version: "..result) diff --git a/contrib/calcDistance.lua b/contrib/calcDistance.lua new file mode 100644 index 0000000..c21dd69 --- /dev/null +++ b/contrib/calcDistance.lua @@ -0,0 +1,80 @@ +--[[ + This file is part of darktable, + Copyright 2014 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 . +]] +--[[ +darktable calc distance script + +This script calcs the distance between two images using the GPS data in the metadata + +USAGE +* require this script from your main lua file +* register a shortcut +]] + +local dt = require "darktable" +dt.configuration.check_version(...,{2,0,1}) + +local function calcDistance() + local sel_images = dt.gui.selection() + + local lat1 = 0; + local lon1 = 0; + local lat2 = 0; + local lon2 = 0; + local i = 0; + + local sel_images = dt.gui.selection() + + 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 + + i = i + 1; + + if (i == 1) then + lat1 = image.latitude; + lon1 = image.longitude; + end + + lat2 = image.latitude; + lon2 = image.longitude; + + end + end + +-- I used code from here: +-- http://stackoverflow.com/questions/27928/how-do-i-calculate-distance-between-two-latitude-longitude-points + + local earthRadius = 6371; -- Radius of the earth in km + local dLat = math.rad(lat2-lat1); -- deg2rad below + local dLon = math.rad(lon2-lon1); + local a = + math.sin(dLat/2) * math.sin(dLat/2) + + math.cos(math.rad(lat1)) * math.cos(math.rad(lat2)) * + math.sin(dLon/2) * math.sin(dLon/2) + ; + local angle = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)); + local distance = earthRadius * angle; -- Distance in km + + dt.print(distance.." km") + + +end + +-- Register +dt.register_event("shortcut",calcDistance,"Calculate the distance from latitude and longitude in km") diff --git a/contrib/gps_select.lua b/contrib/gps_select.lua new file mode 100644 index 0000000..14fbf75 --- /dev/null +++ b/contrib/gps_select.lua @@ -0,0 +1,51 @@ +--[[ + This file is part of darktable, + Copyright 2014 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 . +]] +--[[ +darktable select images with or without GPS informations + +USAGE +* require this script from your main lua file +* register a shortcuts +]] + +local dt = require "darktable" +dt.configuration.check_version(...,{2,0,1}) +table = require "table" + +local function selectWithGPS() + local selection = {} + for _,image in ipairs(dt.database) do + if (image.longitude and image.latitude) then + table.insert(selection,image) + end + end + dt.gui.selection(selection) +end + +local function selectWithoutGPS() + local selection = {} + for _,image in ipairs(dt.database) do + if (not image.longitude and not image.latitude) then + table.insert(selection,image) + end + end + 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") diff --git a/contrib/kml_export.lua b/contrib/kml_export.lua new file mode 100644 index 0000000..c4758fc --- /dev/null +++ b/contrib/kml_export.lua @@ -0,0 +1,256 @@ +--[[ + This file is part of darktable, + Copyright 2014 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 . +]] +--[[ +darktable KML export script + +ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT +* mkdir +* zip (only if you create KMZ files) +* convert (ImageMagick) +* xdg-open +* xdg-user-dir + +WARNING +This script is only testet with Linux + +USAGE +* require this script from your main lua file +]] + +local dt = require "darktable" +dt.configuration.check_version(...,{2,0,1}) + +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("Export Image "..tostring(number).."/"..tostring(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_kml_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 KML file now") + + if ( dt.preferences.read("kml_export","CreateKMZ","bool") == true ) then + if not checkIfBinExists("zip") then + return + end + exportDirectory = dt.configuration.tmp_dir + imageFoldername = "" + else + exportDirectory = dt.preferences.read("kml_export","ExportDirectory","string") + + -- Creates dir if not exsists + imageFoldername = "files/" + local mkdirCommand = "mkdir -p "..exportDirectory.."/"..imageFoldername + coroutine.yield("run_command", mkdirCommand) + end + + + -- Create the thumbnails + for _,image in pairs(image_table) do + 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 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 pattern = "[/]?([^/]+)$" + filmName = string.match(_.film.path, pattern) + end + + exportKMLFilename = filmName..".kml" + exportKMZFilename = filmName..".kmz" + + -- Create the KML file + kml_file = "\n" + kml_file = kml_file.."\n" + kml_file = kml_file.."\n" + + --image_table = dt.gui.selection(); + kml_file = kml_file..""..filmName.."\n" + kml_file = kml_file.." Exported from darktable\n" + + for 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.." \n" + kml_file = kml_file.." "..image.filename.."\n" + --kml_file = kml_file.." \n" + + kml_file = kml_file.." \n" + + kml_file = kml_file.." \n" + kml_file = kml_file.." 1\n" + kml_file = kml_file.." "..string.gsub(tostring(image.longitude),",", ".")..","..string.gsub(tostring(image.latitude),",", ".")..",0\n" + kml_file = kml_file.." \n" + kml_file = kml_file.." "..string.gsub(image.exif_datetime_taken," ", "T").."Z".."\n" + kml_file = kml_file.." \n" + kml_file = kml_file.." \n" + + kml_file = kml_file.." \n" + end + end + +-- Connects all images with an path + if ( dt.preferences.read("kml_export","CreatePath","bool") == true ) then + kml_file = kml_file.." \n" + kml_file = kml_file.." Path\n" -- ToDo: I think a better name would be nice + --kml_file = kml_file.." \n" + + kml_file = kml_file.." \n" + + kml_file = kml_file.." \n" + kml_file = kml_file.." \n" + + for 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" + end + end + kml_file = kml_file.." \n" + kml_file = kml_file.." \n" + + kml_file = kml_file.." \n" + end + + kml_file = kml_file.."\n" + kml_file = kml_file.."" + + file = io.open(exportDirectory.."/"..exportKMLFilename, "w") + file:write(kml_file) + file:close() + + dt.print("KML file created in "..exportDirectory) + +-- Compress the files to create a KMZ file + if ( dt.preferences.read("kml_export","CreateKMZ","bool") == true ) then + exportDirectory = dt.preferences.read("kml_export","ExportDirectory","string") + -- USE coroutine.yield. It does not block the UI + 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) + end + +-- Open the file with the standard programm + if ( dt.preferences.read("kml_export","OpenKmlFile","bool") == true ) then + local kmlFileOpenCommand + + if ( dt.preferences.read("kml_export","CreateKMZ","bool") == true ) then + kmlFileOpenCommand = "xdg-open "..exportDirectory.."/\""..exportKMZFilename.."\"" + else + kmlFileOpenCommand = "xdg-open "..exportDirectory.."/\""..exportKMLFilename.."\"" + end + coroutine.yield("run_command", kmlFileOpenCommand) + end + + +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 ) + +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", "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) + diff --git a/contrib/preferenceExamples.lua b/contrib/preferenceExamples.lua new file mode 100644 index 0000000..18a6553 --- /dev/null +++ b/contrib/preferenceExamples.lua @@ -0,0 +1,81 @@ +--[[ + This file is part of darktable, + Copyright 2014 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 . +]] +--[[ +darktable script to show the different prefference types that are possible with the Lua + +USAGE +* require this script from your main lua file +]] +local dt = require "darktable" +dt.configuration.check_version(...,{2,0,1}) + +dt.preferences.register("preferenceExamples", -- 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. + "preferenceExamplesString", -- name + "string", -- type + "Example String", -- label + "Example String Tooltip", -- tooltip + "String") -- default + +dt.preferences.register("preferenceExamples", -- 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. + "preferenceExamplesString", -- name + "bool", -- type + "Example Boolean", -- label + "Example Boolean Tooltip", -- tooltip + true) -- default + +dt.preferences.register("preferenceExamples", -- 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. + "preferenceExamplesString", -- name + "integer", -- type + "Example Integer", -- label + "Example Integer Tooltip", -- tooltip + 2, -- default + 1, -- min + 99) -- max + +dt.preferences.register("preferenceExamples", -- 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. + "preferenceExamplesString", -- name + "float", -- type + "Example Float", -- label + "Example Float Tooltip", -- tooltip + 1.3, -- default + 1, -- min + 99, -- max + 0.5) -- step + +dt.preferences.register("preferenceExamples", -- 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. + "preferenceExamplesString", -- name + "file", -- type + "Example File", -- label + "Example File Tooltip", -- tooltip + "") -- default + +dt.preferences.register("preferenceExamples", -- 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. + "preferenceExamplesString", -- name + "directory", -- type + "Example Directory", -- label + "Example Directory Tooltip", -- tooltip + "") -- default + +dt.preferences.register("preferenceExamples", -- 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. + "preferenceExamplesString", -- name + "enum", -- type + "Example Enum", -- label + "Example Enum Tooltip", -- tooltip + "Enum 1", -- default + "Enum 1", "Enum 2") -- values + diff --git a/contrib/slideshowMusic.lua b/contrib/slideshowMusic.lua new file mode 100644 index 0000000..a66c28a --- /dev/null +++ b/contrib/slideshowMusic.lua @@ -0,0 +1,78 @@ +--[[ + This file is part of darktable, + Copyright 2014 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 . +]] +--[[ +darktable Script to play music during a Slideshow + +You need rhythmbox-client installed to use this script + +USAGE +* require this script from your main lua file +]] + +local dt = require "darktable" +dt.configuration.check_version(...,{2,0,2}) + +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 playSlideshowMusic(_, old_view, new_view) + local filename, playMusic + + filename = dt.preferences.read("slideshowMusic","SlideshowMusic","string") + playMusic = dt.preferences.read("slideshowMusic","PlaySlideshowMusic","bool") + + if not checkIfBinExists("rhythmbox-client") then + return + end + + if (playMusic) then + local playCommand, stopCommand + + if (new_view.id == "slideshow") then + playCommand = 'rhythmbox-client --play-uri="'..filename..'"' + + --dt.print_error(playCommand) + coroutine.yield("RUN_COMMAND", playCommand) + else + stopCommand = "rhythmbox-client --pause" + --dt.print_error(stopCommand) + coroutine.yield("RUN_COMMAND", stopCommand) + end + end +end + +-- Preferences +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", + true) +-- Register +dt.register_event("view-changed",playSlideshowMusic) diff --git a/contrib/video.lua b/contrib/video.lua new file mode 100644 index 0000000..c94ab5e --- /dev/null +++ b/contrib/video.lua @@ -0,0 +1,118 @@ +--[[ + This file is part of darktable, + Copyright 2014 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 . +]] +--[[ +darktable video export script + +ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT +* mencoder (MEncoder is from the MPlayer Team) +* xdg-open +* xdg-user-dir + +WARNING +This script is only testet with Linux + +USAGE +* require this script from your main lua file +]] + +local dt = require "darktable" +dt.configuration.check_version(...,{2,0,1}) + +local function show_status(storage, image, format, filename, number, total, high_quality, extra_data) + dt.print("Export Image "..tostring(number).."/"..tostring(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_video(storage, image_table, extra_data) + if not checkIfBinExists("mencoder") then + return + end + if not checkIfBinExists("xdg-open") then + return + end + if not checkIfBinExists("xdg-user-dir") then + return + end + + exportDirectory = dt.preferences.read("video","ExportDirectory","string") + exportFilename = "output.avi" + framsePerSecond = dt.preferences.read("video","FramesPerSecond","integer") + + dt.print_error("Will try to create video now") + -- Set the codec + local codec = "" + local codecPreferences = "" + + codecPreferences = dt.preferences.read("video","Codec","string") + if (codecPreferences == "H.264 encoding") then + codec = 'x264' + end + if (codecPreferences == "XviD encoding") then + codec = 'xvid' + end + if not codecPreferences then + codec = 'x264' + end + + -- Create the command + local command = "mencoder -idx -nosound -noskip -ovc "..codec.." -lavcopts vcodec=mjpeg -o "..exportDirectory.."/"..exportFilename.." -mf fps="..framsePerSecond .." mf://" + + for _,v in pairs(image_table) do + command = command..v.."," + end + + dt.print_error("this is the command: "..command) + -- USE coroutine.yield. It does not block the UI + coroutine.yield("run_command", command) + + dt.print("Video created in "..exportDirectory) + + if ( dt.preferences.read("video","OpenVideo","bool") == true ) then + -- USE coroutine.yield. It does not block the UI + local playVideoCommand = "xdg-open "..exportDirectory.."/"..exportFilename + coroutine.yield("run_command", playVideoCommand) + end +end + +-- Preferences +dt.preferences.register("video", "FramesPerSecond", "float", "Video exort: Frames per second", "Frames per Second in the Video export", 15, 1, 99, 0.1 ) +dt.preferences.register("video", "OpenVideo", "bool", "Video exort: Open video after export", "Opens the Video after the export with the standard video player", false ) + +local handle = io.popen("xdg-user-dir VIDEOS") +local result = handle:read() +handle:close() +dt.preferences.register("video", "ExportDirectory", "directory", "Video exort: Video export directory","A directory that will be used to export a Video",result) + +-- Get the MEncoder codec list with: mencoder -ovc help +dt.preferences.register("video", "Codec", "enum", "Video exort: Codec","Video codec","H.264 encoding","H.264 encoding","XviD encoding") + +-- Register +dt.register_storage("video", "Video Export", show_status, create_video) +