284 Commits

Author SHA1 Message Date
supertobi
97dd8a1257 Merge pull request #80 from GHswitt/master
Add new GUI entry in lighttable for renaming tags
2017-11-15 16:11:33 +01:00
supertobi
83fc339c4b Merge pull request #99 from Sitwon/master
Support for importing the in-camera ratings from Fujifilm cameras
2017-10-14 21:20:16 +02:00
Ben Mendis
693c535428 Improving with feedback from @supertobi 2017-10-14 11:24:14 -04:00
supertobi
d74f2eba92 Create printExamples.lua 2017-10-11 11:29:48 +02:00
supertobi
d0ec941009 check if exiftool exists in autostyle.lua 2017-10-11 09:32:29 +02:00
Ben Mendis
178528508b Support for importing the in-camera ratings from Fujifilm cameras 2017-10-10 21:10:00 -04:00
supertobi
20a31b39e0 Added section_label moduleExample.lua 2017-10-10 20:22:39 +02:00
supertobi
fc252d5e7e New example for the running_os command 2017-10-10 17:27:09 +02:00
supertobi
4090266989 Removed not needed code in yield.lua 2017-10-10 17:22:24 +02:00
supertobi
19b7d29483 added {5,0,0} to the check_version 2017-09-26 15:21:20 +02:00
supertobi
af4e3884bb check result from io.popen("xdg-user-dir VIDEOS") 2017-09-26 15:02:50 +02:00
supertobi
d3742bb410 added {5,0,0} to the check_version 2017-09-26 14:55:12 +02:00
supertobi
75cb1a5fdd added {5,0,0} to the check_version 2017-09-26 14:55:07 +02:00
supertobi
8436c878e8 added {5,0,0} to the check_version 2017-09-26 14:53:54 +02:00
supertobi
63d3a34f46 added {5,0,0} to the check_version 2017-09-26 10:55:23 +02:00
supertobi
6cda97c335 check result from io.popen("xdg-user-dir DESKTOP") 2017-09-26 10:39:36 +02:00
supertobi
a40d8b8bc5 added {5,0,0} to the check_version 2017-09-26 10:34:16 +02:00
supertobi
15a492cfa3 added {5,0,0} to the check_version 2017-09-26 10:27:39 +02:00
supertobi
445e882579 check result from io.popen("xdg-user-dir DESKTOP") 2017-09-26 10:24:22 +02:00
supertobi
d4b155d0c2 Merge pull request #98 from jbvoelker/select-untagged
Add french and german .mo files for select_untagged.lua
2017-09-25 15:52:10 +02:00
Jannis_V
65f4960302 Add french and german .mo files for select_untagged.lua 2017-09-25 15:45:16 +02:00
supertobi
dc9e8d406d Update README.md
Added Windows path and the new path to hello_world.lua
2017-09-25 14:19:24 +02:00
supertobi
4d76006c2d Merge pull request #97 from jbvoelker/select-untagged
Selection of untagged images
2017-09-25 13:42:26 +02:00
Jannis Völker
731a6d0410 German and french translation for the select_untagged script 2017-09-14 16:00:48 +02:00
Jannis Völker
e4542aa451 Remove require 2017-09-14 11:52:05 +02:00
Jannis Völker
ecc4a29be4 Select all untagged images in the collection. Pictures containg only automatic tags added by darktable are also considered untagged 2017-09-13 17:26:47 +02:00
supertobi
0f0b3d6df5 Merge pull request #96 from chrisaga/patch-1
use dt.gettext after defining dt to avoid fatal error
2017-09-02 23:15:38 +02:00
chrisaga
a826c1725b use dt.gettext after defining dt to avoid fatal error 2017-09-02 14:30:52 +02:00
supertobi
4e3b461fd3 Merge pull request #95 from elman22/master
Fixed quotation marks typos
2017-08-08 09:24:07 +02:00
elman
d8a9dfafb2 Fixed quotation marks typos 2017-08-07 22:49:45 +02:00
supertobi
ede621bea7 Update geoJSON_export.lua
Removed wrong comment.
2017-07-25 15:49:50 +02:00
supertobi
2f7da8356f Update geoToolbox.lua
Label changed: select non-geo images
2017-04-29 20:46:38 +02:00
supertobi
d555cb2c94 Update geoJSON_export.lua
cleanup
2017-04-29 09:03:43 +02:00
supertobi
750d70bfff Update geoJSON_export.lua
check_version 5
2017-04-29 08:06:15 +02:00
supertobi
dcc205ec4f Update kml_export.lua
check_version 5
2017-04-29 08:05:19 +02:00
supertobi
356756286e Update gimp.lua
use "lib/dtutils.file"
2017-04-27 22:19:00 +02:00
supertobi
79511d9b42 Update geoJSON_export.lua
use "lib/dtutils.file"
2017-04-27 22:12:34 +02:00
supertobi
bff2df018b Update enfuse.lua
use "lib/dtutils.file"
2017-04-27 22:07:23 +02:00
supertobi
2562a218a0 Update kml_export.lua
use "lib/dtutils.file"
2017-04-27 22:04:15 +02:00
supertobi
d46b7e4aaf Update slideshowMusic.lua
use "lib/dtutils.file"
2017-04-27 21:55:19 +02:00
supertobi
dee7ee1dde Update hugin.lua
use "lib/dtutils.file"
2017-04-27 21:51:29 +02:00
supertobi
01fc339da5 Update video_mencoder.lua
use "lib/dtutils.file" and gettext
2017-04-27 21:46:30 +02:00
supertobi
ef46cd9b45 Update geoToolbox.lua
reverse geocodeing start
2017-04-27 20:20:29 +02:00
supertobi
ac3ccb287b Merge pull request #92 from khampf/passport-guide
ISO 19794-5/ICAO 9303 clipping guide as contrib/passport_guide.lua
2017-04-23 08:11:31 +02:00
khampf
f52292e8d1 Translatable by using gettext 2017-04-22 23:47:30 +03:00
khampf
693c9858c2 variables renamed for clarity (local functions tested without success) 2017-04-22 23:24:43 +03:00
khampf
c8d5e9d9d2 Longer version of GPL text 2017-04-22 22:06:55 +03:00
khampf
50668817db added API 5 to version check 2017-04-21 21:43:02 +03:00
khampf
91758b61c3 ISO 19794-5/ICAO 9303 clipping guide as contrib/passport_guide.lua 2017-04-21 13:51:40 +03:00
supertobi
39ae92a0fa Update geoToolbox.lua
fix open with gnome-maps
2017-04-18 22:31:49 +02:00
supertobi
95c203793c Merge pull request #91 from TurboGit/master
Ensure that a dot is used for decimal numbers.
2017-04-16 18:11:54 +02:00
Pascal Obry
c7ac974ab9 Ensure that a dot is used for decimal numbers.
This unbreak the slide show for acrobat reader.
2017-04-15 15:35:09 +02:00
supertobi
51931d2b01 Merge pull request #90 from TurboGit/master
general translation reorg.
2017-04-11 08:28:47 +02:00
Pascal Obry
d271f6d46d Add french translation for pdf_slideshow plugin. 2017-04-10 16:59:46 +02:00
Pascal Obry
efcd48f1d9 Remove trailing whitespaces. 2017-04-10 16:59:35 +02:00
Pascal Obry
76daa583b3 Move all translation into the main locale directory.
This is for consistency reason as the lib/dtutils/file.lua use this
directory. Also all translation into contrib where not usable as
not checked into this directory which was expected to be just lua.

All in all using locale directory will avoid clutter the main
directory with all possible languages and fixes the current scripts.
2017-04-10 16:56:59 +02:00
supertobi
3425a85fd0 Merge pull request #89 from TurboGit/master
Better renaming of the images to keep files in temp dir.
2017-04-09 22:10:49 +02:00
Pascal Obry
9a6c1510fd Another change to get better output.
This changeset gives better output for portrait and landscape pictures.
Now in both cases the image is properly center on the screen.
2017-04-09 18:46:21 +02:00
Pascal Obry
44c391cb5a Better renaming of the images to keep files in temp dir. 2017-04-09 11:07:29 +02:00
supertobi
6085be7589 Merge pull request #88 from TurboGit/master
Initial version of PDF Slideshow.
2017-04-09 10:35:28 +02:00
Pascal Obry
7d9bf8c729 Check for pdflatex tool.
If not present, exit.
2017-04-09 10:18:02 +02:00
Pascal Obry
1d72457dc1 Put author before title as this is what is rendered. 2017-04-09 10:17:39 +02:00
Pascal Obry
0e32d2b1b4 Rename jpeg files to use for the slideshow.
Some accents and weird characters could confuse pdflatex.
2017-04-09 10:17:00 +02:00
Pascal Obry
75165e8838 Ensure UTF-8 text from title or creator field are properly rendered. 2017-04-09 10:16:38 +02:00
Pascal Obry
d9536f1294 Initial version of PDF Slideshow.
A simple PDF slideshow generator. Each image is on a single slide and
a title bar at the bottom is added with the slide show general title,
the image author and title if defined in the metadata.

This script requires pdflatex.
2017-04-08 16:47:34 +02:00
Tobias Ellinghaus
44e4c3ddc5 enfuse: Fix typo in script description 2017-03-07 18:14:58 +01:00
supertobi
f67755f3b5 Update hugin.lua
changed comment
2017-03-07 13:19:04 +01:00
supertobi
68d768cbd3 Merge pull request #86 from TurboGit/master
minor tweak of the quicktag module
2017-02-28 17:00:49 +01:00
Pascal Obry
0be268c01f Remove trailing whitespaces. 2017-02-28 16:38:50 +01:00
Pascal Obry
1831db530d Make the label smaller to fit on screen.
As we are on the quicktag module it seems quite obvious that we are
handling quicktag. So let's just use "tag" instead of "quicktag", this
is a bit smaller and it saves spaces on the widget. This ensure that
the whole module is visible in most cases (panel size, font size...).
2017-02-28 16:36:32 +01:00
supertobi
8a32bf21d0 Merge pull request #72 from chrik5/quicktag
first version of a quicktag modul
2017-02-20 22:05:48 +01:00
chrik5
81c5bb4d52 [quicktag] update copyright 2017-02-20 18:00:59 +01:00
chrik5
93796bf4a8 [quicktag] fix German translation and remove print output 2017-02-20 17:57:53 +01:00
chrik5
4c34113f78 [quicktag] use string.format in messages for better translation 2017-02-20 15:42:48 +01:00
chrik5
e4b189a06e [quicktag] update TODO list 2017-02-20 12:11:52 +01:00
chrik5
0ebc885eb1 [quicktag] update German translation 2017-02-20 12:11:06 +01:00
chrik5
b4658ddf76 [quicktag] abbrevate tag button labels to a configurable length 2017-02-20 12:00:45 +01:00
chrik5
b38e2964ca [quicktag] add German translation 2017-02-17 16:22:13 +01:00
chrik5
5021e512b9 [quicktag] make script tranlateable 2017-02-17 16:21:23 +01:00
chrik5
6d927540c8 [quicktag] remove dead code 2017-02-17 13:40:39 +01:00
chrik5
6168767766 remove accidently added *.mo file 2017-02-17 13:36:49 +01:00
chrik5
5af200a29d [quicktag] don't allow to set empty tags 2017-02-17 10:32:06 +01:00
chrik5
8b333c1ab5 [quicktag] update and fix description 2017-02-17 10:25:06 +01:00
chrik5
d1f34ec136 [quicktag] fix and update some comments 2017-02-16 16:32:50 +01:00
chrik5
c887a0d2b5 [quicktag] remove tag list from preferences dialog, because the tags can be set from the modul now 2017-02-16 16:13:55 +01:00
Jérémy Rosen
1168ba4557 Merge remote-tracking branch 'origin/pr/82'
# Conflicts:
#	contrib/calcDistance.lua
#	contrib/geo_uri.lua
#	contrib/gps_select.lua
2017-01-24 23:22:04 +01:00
chrik5
e389420f07 quicktag - make API 5.0.0 compatible 2017-01-24 21:02:53 +01:00
chrik5
0590beb876 quicktag - add tags if they not exist in the taglist of darktable 2017-01-24 20:56:07 +01:00
supertobi
d30c0d0213 Merge pull request #83 from chrik5/API5.0.0
This scripts work with API version 5.0.0 & small fix for hugin
2017-01-24 13:52:03 +01:00
chrik5
eb774d37c6 hugin - fix error message hugin failed... 2017-01-24 12:43:30 +01:00
chrik5
cade6d5e0b hugin add API version 5.0.0 2017-01-24 12:36:42 +01:00
chrik5
19b71c5782 gimp add API version to 5.0.0 2017-01-24 12:23:30 +01:00
chrik5
5f802a8179 copy_attach_detach_tags add API version to 5.0.0 2017-01-24 12:22:37 +01:00
supertobi
99e1141446 dt.database -> dt.collection
select only images in the collection, not in the database
2017-01-12 13:27:29 +01:00
supertobi
3bd76b4fb5 added a progress bar
added a progress bar to elect_without_gps() and select_with_gps()
2017-01-12 13:16:59 +01:00
supertobi
3fb4ef34f4 past -> paste 2017-01-12 12:58:17 +01:00
supertobi
f7c2abdcd7 dt.gui.action_images -> dt.gui.selection() 2017-01-12 12:56:41 +01:00
supertobi
cc6006e226 removed "the" from "Past the GPS data" 2017-01-12 12:32:42 +01:00
supertobi
2816c2bcf5 changed label to lower case 2017-01-12 12:30:45 +01:00
supertobi
abc8061cd7 Update geoToolbox.lua
gettext translations
2017-01-09 14:00:14 +01:00
supertobi
a30c4d6be5 Update geoToolbox.lua
changed camel case to "_"
2017-01-09 13:53:23 +01:00
supertobi
0bd5b6ba5d Delete calcDistance.lua
replaced by geoToolbox.lua
2017-01-08 21:05:23 +01:00
supertobi
4ea3a500e8 Delete geo_uri.lua
replaced by geoToolbox.lua
2017-01-08 21:05:04 +01:00
supertobi
56925c1eed Delete gps_select.lua
replaced by geoToolbox.lua
2017-01-08 21:04:49 +01:00
supertobi
71e7269927 geo toolbox
this script replaces:
calcDistance.lua
geo_uri.lua 
gps_select.lua
2017-01-08 20:54:12 +01:00
Boucman
6babff1be1 Merge pull request #81 from chrik5/tagging
copy_attach_detach_tags: UI clean up. module reset empties clipboard and taglist.
2017-01-07 15:19:06 +01:00
chrik5
fec000086f copy_attach_detach_tags: add modul reset to USAGE section 2016-12-28 15:05:57 +01:00
chrik5
bddf4cedb4 copy_attach_detach_tags: UI clean up. Added module reset which empties clipboard and copied taglist. 2016-12-28 14:58:44 +01:00
chrik5
91c62e208b quicktag: rework of modul layout and behaviour
* long tags are stil a problem
* maybe two colums of tag buttons saves high, if someone wants to have many tags
* option to create non existing tags will be nice I guess
2016-12-28 12:32:12 +01:00
chrik5
1e0424a83f quicktag module: place entry field and buttons side-by-side, button labels are now the quicktags 2016-12-27 15:28:43 +01:00
GHswitt
c74d29e020 Add new GUI entry in lighttable for renaming tags
Rename tag: A new tag is added to all images containing old tag. After that, the old tag is removed from all images (and removed from tags). The GUI entry has two entries: Old tag, New tag and a Go button.
2016-12-14 01:08:10 +01:00
supertobi
eadfff9cd0 Merge pull request #78 from wpferguson/dt-2.2-compatibility
Darktable 2.2 compatibility
2016-11-08 19:07:41 +01:00
Bill Ferguson
93e30a8542 Verified API 4.0.0 compatibility and made the necessary changes 2016-11-07 22:53:52 -05:00
supertobi
85ccc663c8 Merge pull request #74 from wpferguson/libraries
Libraries
2016-10-25 13:30:37 +02:00
Bill Ferguson
dab02823ff Fixed log bug in dprint function 2016-10-24 19:23:04 -04:00
Bill Ferguson
4fccfbf51d Added checks for binaries used to generate the pdf man pages 2016-10-24 12:09:04 -04:00
Boucman
b04e322df8 Merge pull request #77 from wpferguson/include_yield
require official/yield in scripts using dt.control.execute()
2016-10-21 21:17:25 +02:00
Bill Ferguson
f550822943 Added require "official/yield" to scripts that use dt.control.execute() so that they work correctly if you haven't required official/yield somewhere else. 2016-10-21 13:25:40 -04:00
Bill Ferguson
564fd20f23 Moved lib/libLog.lua to lib/dtutils/log.lua. Rewrote most of it to make it more configurable and easier to use. Updated doc format to a fixed list of fields. Did away with the comment blocks and just relying on the libdoc comments. Update doc tools to use new formats. Moved dtutils/extensions.lua to dtutils/string.lua. Pulled dtutils/processor.lua back for now since there is no context for it. Removed unneeded functions and cleaned up others. 2016-10-20 01:19:54 -04:00
supertobi
45e38a9a2d Merge pull request #75 from chrik5/tagging_translation
copy attach detach add translation submitted by Holger Klemm
2016-10-18 16:18:11 +02:00
chrik5
e51f1e0a82 copy_attach_detach_tags small updates on german translation 2016-10-18 15:37:54 +02:00
chrik5
b4b82906ea copy_attach_detach_tags make script translateable and added german translation by Holger Klemm 2016-10-18 15:30:45 +02:00
Bill Ferguson
a254ac87f7 Created libraries from commonly used functions. Moved official/debug-helpers.lua into lib/dtutils/debug.lua. Created a logging library to provide various levels of logging. Documented all libraries and functions. Created tools to extract documentation in text, man page, and pdf formats. 2016-10-15 01:47:43 -04:00
chrik5
ae8727ad96 Mark module quicktag as add API 3 compatible 2016-10-09 14:44:44 +02:00
chrik5
de823f0430 quicktag module make tag entries dynamic 2016-10-06 11:02:00 +02:00
chrik5
c6ced0b1ea first version of a quicktag modul 2016-10-05 16:33:13 +02:00
supertobi
e76a883053 Merge pull request #71 from chrik5/tagging
Tagging some code clean up
2016-10-04 16:35:18 +02:00
chrik5
f967e96aa5 exit attach tags function if there are no tags to attach 2016-10-04 16:03:35 +02:00
chrik5
c8713a7f38 cleanup the code and create UI elements before 2016-10-04 13:54:49 +02:00
supertobi
73e274cf0b Merge pull request #70 from TurboGit/contrib-fr_FR
Initial fr_FR translation of the contribution lua scripts.
2016-10-04 11:10:23 +02:00
Pascal Obry
c75c3d0734 Initial fr_FR translation of the contribution lua scripts. 2016-10-03 17:24:36 +02:00
supertobi
e74b253f64 Update clear_GPS.po
better german
2016-09-08 11:31:56 +02:00
Boucman
45009aedff Merge pull request #68 from wpferguson/clear_gps_data
clear GPS data
2016-09-08 07:42:13 +02:00
Bill Ferguson
870ba65662 Missed an edit in the _() function 2016-09-07 22:56:11 -04:00
Bill Ferguson
80ace33af1 Created clear_GPS to clear GPS data from selected images. 2016-09-07 22:53:51 -04:00
supertobi
f69455bdb7 Merge pull request #65 from wpferguson/master
Added fileCopy and fileMove functions to replace os.rename which does…
2016-09-06 10:18:03 +02:00
supertobi
4ed6dc276e Merge pull request #66 from wpferguson/geo_uri
geo_uri
2016-09-06 10:16:23 +02:00
Bill Ferguson
3dd415697a Removed extra end statement 2016-09-05 13:56:22 -04:00
Bill Ferguson
f7ce368b28 Reverted contrib/geo_uri.lua to previous version so that I can add it in it's own pull request. 2016-09-05 13:49:47 -04:00
Bill Ferguson
168236780d Incorporated supertobi's correction to the translations 2016-09-04 11:42:27 -04:00
Bill Ferguson
549e9ccd0b Changed fileMove per discussion to use os.rename first, os.execute(mv... second, and a lua solution third. The lua solution includes fileCopy with attempts os.execute(cp... first, then does a pure lua copy if that doesn't succeed 2016-08-31 20:18:29 -04:00
Bill Ferguson
21f31b403b Recoded fileMove to use os.execute and the system mv command. Removed fileCopy as it was no longer needed. 2016-08-25 22:49:59 -04:00
Bill Ferguson
3b42503bd3 Removed extra end statement 2016-08-23 21:14:39 -04:00
Bill Ferguson
95e15fc40c Changed poorly translated message to that suggested by supertobi, and took care of spacing issue. 2016-08-23 21:13:11 -04:00
Bill Ferguson
74e546c2ce Added fileCopy and fileMove functions to replace os.rename which doesn't work across filesystems. Added an error message if the move isn't accomplished so that the user knows what happened. Updated translations to reflect changes. 2016-08-23 00:09:27 -04:00
supertobi
0c0f97560e Merge pull request #50 from tejovanthn/master
Enables custom number of thumbnails per row
2016-06-29 09:33:11 +02:00
tejovanthn
8392f6f5a6 enables custom number of thumbnails per row
Changes the thumbs_per_line from a text field to a slider
2016-06-29 03:19:20 +05:30
supertobi
9a5ede0e6d Merge pull request #62 from elman22/master
Fix for issues #58 and #59 - Issue with exporting RAW images
2016-04-29 21:38:35 +02:00
elman
33417454ed Reverted back to dt.control.execute() 2016-04-29 18:59:05 +02:00
supertobi
d79237958f Create yield.lua
darktable yield compatibility script
2016-04-28 23:20:37 +02:00
elman
6ef06467b6 Added comments 2016-04-28 19:44:51 +02:00
supertobi
a85d2222eb Merge pull request #61 from spaceChRiS/import-filters-fix
Import filters fix
2016-04-28 10:47:00 +02:00
Christian Mandel
2325d24d6f Comments added for import-filters fix. 2016-04-28 10:27:25 +02:00
Christian Mandel
4397e07d7f Fix accidentally deleted first image during import. Lua is very picky about sparse table handling. 2016-04-28 00:43:21 +02:00
elman
f5a624cfb2 Remove exported image if it has no GPS data 2016-04-27 19:35:44 +02:00
elman
d2762fae73 Fixed issue with exporting RAW images 2016-04-27 19:25:03 +02:00
supertobi
22d7107305 Merge pull request #60 from chrik5/tagging_helpers
adding a modul to the UI with buttons and a replace function
2016-04-21 18:11:04 +02:00
chrik5
e22df23bc9 Tagging add label before clipboard list and make small enhancements 2016-04-21 17:08:44 +02:00
chrik5
200ef9a45e Tagging added new function replace and a modul 2016-04-21 15:54:59 +02:00
Jérémy Rosen
783194e253 update to newest API change in master 2016-04-17 20:46:32 +02:00
supertobi
204868d733 Use a file list instead of * to zip the images
kml_export - packs to kmz all files from dt.configuration.tmp_dir #53 
https://github.com/darktable-org/lua-scripts/issues/53
2016-04-17 12:33:39 +02:00
supertobi
f61a710e9b Merge pull request #55 from wpferguson/master
External editing with GIMP
2016-04-17 09:59:10 +02:00
Bill Ferguson
457731700c gimp doesn't like filenames with spaces in them, so added sanitize_filename to escape them. Updated gimp.po to reflect the changed line numbers. 2016-04-16 21:44:24 -04:00
Bill Ferguson
3dcb08cca3 Replaced checkIfFileExists with supertobi's fix and capitalized GIMP in gimp.po where I missed it. 2016-04-16 21:10:58 -04:00
supertobi
e3f1ff7d70 Strip accents from the filename, because GoogleEarth can't open them 2016-04-16 23:36:58 +02:00
Bill Ferguson
623b506691 Added check to see if the export would overwrite an existing file. If it would, the filename was incremented with _XX where XX was an increment starting at 01 and ending at 99. gimp.po line numbers adjusted to reflect the changes in code. 2016-04-15 23:58:33 -04:00
Bill Ferguson
6e5dbc0b83 Incorporated supertobi's suggestions. Replaced file and path splitting code with a regular expression (thanks Tobias Jakobs) to ensure filenames were handled correctly. Used the image data in the image table pairs instead of darktable.gui.action_images to ensure there were no mismatches as well as clean up the code nicely. Updated gimp.po to reflect the line number changes due to code refactoring. 2016-04-15 00:38:00 -04:00
Bill Ferguson
9c40a22c50 Removed gimp.lua from the top level 2016-04-14 22:21:32 -04:00
Bill Ferguson
9dbd1d9bda Incorporated supertobi's comments. Changed os.execute to os.rename to handle spaces and special characters. Capitalized GIMP in all print strings. Added de_DE translation. 2016-04-14 16:34:37 -04:00
Bill Ferguson
9693b017c4 Changed back to string.format in show_status but coded it correctly this time. 2016-04-10 16:27:49 -04:00
supertobi
670915ab36 fixed typo: will will -> will 2016-04-10 00:05:34 +02:00
Bill Ferguson
8224913b01 replaced string.format in show_status with the string and concatenation since string.format was having problems with the arguments. 2016-04-09 01:37:54 -04:00
supertobi
2b577f9755 improved the entry and file_chooser_button examples 2016-04-07 23:29:08 +02:00
Bill Ferguson
4556c9a055 Incorporated comments from supertobi, marking string for translation on line 128 and expanding variable names for lines 157-165 2016-04-07 11:59:41 -04:00
Bill Ferguson
679ce8b6ab Created gimp.lua to export an image to gimp for editing, then return the result and group it with the original image 2016-04-06 22:21:13 -04:00
Bill Ferguson
59eeb60594 Merge remote-tracking branch 'upstream/master' 2016-04-06 22:16:11 -04:00
Tobias Ellinghaus
6c4f9b2c03 Add script to copy & paste metadata between images
This not only takes care of tags (we already have a script for that in
contrib) but also color labels, rating and the things from the metadata
module.
2016-03-29 20:11:19 +02:00
Tobias Ellinghaus
f6e2037a1b Fix formatting of copyright header 2016-03-29 19:52:31 +02:00
supertobi
0c9d4a5de4 added tooltip to new_widget("entry") 2016-03-23 10:32:16 +01:00
supertobi
5006c9d6ea Added missing elevation vars, improved short distance view 2016-03-22 22:34:53 +01:00
supertobi
17a8c4f3d5 naming changes _ -> exported_image 2016-03-20 22:59:18 +01:00
supertobi
98cb1c2315 Merge pull request #52 from supertobi/patch-2
concertToThumbCommand -> convertToThumbCommand
2016-03-20 22:41:20 +01:00
supertobi
6cc5aa08e3 Merge pull request #49 from supertobi/patch-1
A geoJSON expor like the KML export
2016-03-20 22:40:45 +01:00
supertobi
ebda3865dc Update geoJSON_export.lua 2016-03-20 22:36:58 +01:00
supertobi
fb171a459e Update geoJSON_export.lua 2016-03-20 22:21:40 +01:00
supertobi
027a249837 _ -> exported_image 2016-03-20 22:03:41 +01:00
supertobi
2a2bb7199e concertToThumbCommand -> convertToThumbCommand 2016-03-20 21:51:26 +01:00
supertobi
f64892d010 concertToThumbCommand -> convertToThumbCommand 2016-03-20 21:50:25 +01:00
Boucman
d023d7f3e4 Merge pull request #51 from supertobi/patch-2
marked vars as local
2016-03-18 11:11:18 +01:00
supertobi
ef96bfa98c marked vars as local 2016-03-17 22:35:47 +01:00
supertobi
b2ee46804b marked vars as local, changed gettext domain 2016-03-17 22:33:27 +01:00
supertobi
7c9c277cf8 A geoJSON expor like the KML export 2016-03-15 22:31:04 +01:00
houz
3e376ebc74 Merge pull request #48 from supertobi/patch-3
Create moduleExample.lua
2016-03-14 12:08:44 +01:00
supertobi
102ea2da7a Added comment
This is an alternative way to the "{}" syntax to set a property
2016-03-13 21:11:04 +01:00
supertobi
e1a2fbfaa6 Copy past error in the copyright line 2016-03-13 21:07:32 +01:00
houz
c1aecf2b37 Merge pull request #47 from supertobi/patch-2
Update kml_export.lua
2016-03-12 14:26:25 +01:00
supertobi
b2754e3036 Create moduleExample.lua
lua_gui_example
2016-03-12 00:09:37 +01:00
supertobi
abbb740753 Update kml_export.lua
small changes (comments and spacing)
2016-03-11 23:57:13 +01:00
Boucman
7504224c2f Merge pull request #46 from marco44/master
Bump autostyle as 3.0.0 compatible
2016-03-08 10:28:14 +01:00
marco44
57b990409a Mark autostyle as 3.0.0 compatible 2016-03-07 18:07:04 +01:00
Boucman
cff5e06d62 Merge pull request #45 from gRuGo/patch-1
Update cr2hdr.lua
2016-03-05 22:23:26 +01:00
gRuGo
a543b409cb Update cr2hdr.lua
for darktable 2.0
2016-03-05 20:21:42 +01:00
Jérémy Rosen
e57d2f4afa force check for 3.0.0 since this is the version the repo is compatible with 2016-03-05 11:20:17 +01:00
Jérémy Rosen
9da0173e05 mark save-selection as 3.0.0 compatible 2016-03-05 10:51:12 +01:00
Tobias Ellinghaus
a21b171d96 Add a script that allows running enfuse on images 2016-03-02 14:42:38 +01:00
Boucman
2569e7ed8e Merge pull request #44 from supertobi/patch-1
Move api_version.lua into examples
2016-02-16 14:43:59 +01:00
supertobi
25d2eade8c Move api_version.lua into examples
As this script is more usable for developers then for 'normal' users I moved it into examples.
2016-02-16 13:09:16 +01:00
houz
43b949966d Merge pull request #43 from supertobi/master
Translations
2016-02-03 12:26:52 +01:00
supertobi
08205b96cd Update hugin.po
zusammenzufügen
2016-02-02 14:54:09 +01:00
supertobi
e2e63bbfc8 Update gps_select.po
GPS Informationen -> GPS-Informationen
2016-02-02 14:51:19 +01:00
supertobi
24d1a7dd67 Update calcDistance.po
2x "mit"
2016-02-02 14:48:45 +01:00
supertobi
9b4e46b625 Update gps_select.po
GPS Informationen -> GPS-Informationen
2016-02-02 14:48:17 +01:00
supertobi
e47a335dec Update calcDistance.lua
translations
2016-01-31 23:27:34 +01:00
supertobi
d46f7023d5 Update geo_uri.lua
translations
2016-01-31 23:27:00 +01:00
supertobi
19bef60752 Update gps_select.lua
translate
2016-01-31 23:26:23 +01:00
supertobi
5ff73657e1 Update hugin.lua
translations
2016-01-31 23:25:49 +01:00
supertobi
fb8da04a18 Update slideshowMusic.lua
translations
2016-01-31 23:25:18 +01:00
supertobi
3ee50a290f Create slideshowMusic.po 2016-01-31 23:23:45 +01:00
supertobi
71ea05598f Create hugin.po 2016-01-31 23:22:45 +01:00
supertobi
96d5c71e0d Create gps_select.po 2016-01-31 23:21:51 +01:00
supertobi
07318eb7aa Create geo_uri.po 2016-01-31 23:20:27 +01:00
supertobi
2ef235dddd Create calcDistance.po 2016-01-31 23:19:30 +01:00
Boucman
f7cc9865cc Merge pull request #42 from supertobi/patch-3
Update kml_export.lua - use os.remove(image)
2016-01-31 22:07:56 +01:00
supertobi
c323ce6cbb Update kml_export.lua
use os.remove(image)
2016-01-31 00:57:43 +01:00
Boucman
5d2ddc490a Merge pull request #41 from supertobi/patch-1
Update gettextExample.lua
2016-01-30 10:26:37 +01:00
Boucman
40463290a6 Merge pull request #39 from supertobi/master
added gettext to kml_export.lua
2016-01-30 10:26:27 +01:00
supertobi
6b4faac2cb Update kml_export.lua
function _(msgid)
2016-01-29 23:09:32 +01:00
supertobi
077a7de605 Update gettextExample.lua
function _(msgid)
2016-01-29 23:01:05 +01:00
supertobi
180bc06c06 Update kml_export.lua 2016-01-29 22:35:57 +01:00
supertobi
72a97ecbd6 Update gettextExample.lua 2016-01-29 22:18:54 +01:00
supertobi
87a6ed3e46 Update gettextExample.lua
bindtextdomain changed: ~/
2016-01-29 14:26:31 +01:00
supertobi
95d8e777db Update gettextExample.lua 2016-01-29 14:21:46 +01:00
supertobi
d028ecfc55 Update gettextExample.lua
improved readability
2016-01-26 22:40:36 +01:00
supertobi
225da821e4 Update kml_export.po
Added 
msgid "KML/KMZ Export"
msgstr "KML/KMZ Expor
2016-01-22 23:34:29 +01:00
supertobi
7cd4023f5c Update kml_export.lua
gettext bugfix
2016-01-22 23:30:58 +01:00
supertobi
2379832cc2 Create kml_export.po 2016-01-22 15:41:07 +01:00
supertobi
cb46e090dd Update kml_export.lua
small bugfix CreatePath
2016-01-22 15:34:51 +01:00
supertobi
a656f0f304 Update kml_export.lua
add gettext
2016-01-22 15:15:33 +01:00
Boucman
564fa313f1 Merge pull request #38 from supertobi/master
Move example scripts in a new folder to seperate them from the 'usefull' scripts
2016-01-22 10:09:31 +01:00
supertobi
47cd618bf4 Delete gettextExample.mo
No binary or generated files in git
2016-01-22 09:52:05 +01:00
supertobi
ae709a1d9b Rename contrib/de_DE/LC_MESSAGES/gettextExample.po to examples/de_DE/LC_MESSAGES/gettextExample.po 2016-01-22 09:49:22 +01:00
supertobi
0812d96068 Rename contrib/gettextExample.lua to examples/gettextExample.lua 2016-01-22 09:48:23 +01:00
supertobi
86911933db Rename contrib/preferenceExamples.lua to examples/preferenceExamples.lua 2016-01-22 09:47:19 +01:00
supertobi
69d5c139f6 Rename official/hello_world.lua to examples/hello_world.lua 2016-01-22 09:46:39 +01:00
supertobi
405b9a19f9 Merge pull request #5 from darktable-org/master
changes from master
2016-01-13 13:43:53 +01:00
Boucman
c4a696cbc4 Merge pull request #36 from supertobi/master
Update from my fork
2016-01-11 13:54:26 +01:00
Boucman
bb0e4997de Merge pull request #37 from supertobi/patch-3
Update kml_export.lua
2016-01-11 13:51:24 +01:00
supertobi
bc1b908063 Update kml_export.lua
- support of image.title and image.description
- support of image.elevation
- don't add to many images to the kmz file
2016-01-10 22:28:53 +01:00
Tobias Jakobs
29c522484c gettextExample.lua with po and mo files 2016-01-07 22:01:51 +01:00
Boucman
5b6585b115 Merge pull request #32 from supertobi/patch-3
Update calcDistance.lua
2016-01-07 17:09:45 +01:00
Boucman
3715c69c02 Merge pull request #29 from supertobi/patch-2
Update hugin.lua
2016-01-07 17:07:36 +01:00
Boucman
3d3b457c92 Merge pull request #28 from supertobi/patch-1
Update gps_select.lua
2016-01-07 17:07:14 +01:00
houz
e4f5d44658 Merge pull request #31 from wpferguson/wpferguson-patch-1
Update selection_to_pdf.lua
2016-01-07 12:30:33 +01:00
Tobias Ellinghaus
fc7a25ca4d Mark most official scripts as compatible with dt2 2016-01-07 11:23:34 +01:00
supertobi
1d3a44a157 Update calcDistance.lua
Add the elevation to the calculation of the distance
2016-01-07 09:08:35 +01:00
wpferguson
319b44f153 Merge pull request #1 from wpferguson/wpferguson-patch-1
Update selection_to_pdf.lua
2016-01-06 10:54:16 -05:00
wpferguson
98a4144403 Update selection_to_pdf.lua
Added API version 3.0.0 for compatibility with Darktable 2.0.  Tested with Darktable 2.0.
2016-01-06 10:51:56 -05:00
supertobi
a819140c88 Update hugin.lua
Tested with darktable 2.0
2016-01-05 22:12:57 +01:00
supertobi
cba5c65608 Update gps_select.lua
Tested with darktable 2.0
2016-01-05 22:05:18 +01:00
supertobi
eff4a3abcb Update geo_uri.lua
removed the old warning
2016-01-05 10:28:31 +01:00
supertobi
2e0ccef3f5 Update geo_uri.lua
Changes suggested from Boucman
2016-01-05 10:22:47 +01:00
Boucman
429a157715 Merge pull request #26 from supertobi/patch-2
Update kml_export.lua
2016-01-05 09:18:35 +01:00
Boucman
76065ee93f Merge pull request #27 from supertobi/patch-3
Update preferenceExamples.lua
2016-01-05 09:18:23 +01:00
Boucman
97def2240f Merge pull request #25 from supertobi/patch-1
Update calcDistance.lua
2016-01-05 09:18:02 +01:00
supertobi
15cd18a5c4 Update preferenceExamples.lua
Tested with darktable 2.0
2016-01-04 23:02:01 +01:00
supertobi
0b3b095eac Update kml_export.lua
Tested with darktable 2.0
2016-01-04 23:00:33 +01:00
supertobi
38bda12c4b Update calcDistance.lua
Tested with darktable 2.0
2016-01-04 22:59:18 +01:00
supertobi
d2a34226a6 Update slideshowMusic.lua
Tested with darktable 2.0
2016-01-04 22:53:10 +01:00
supertobi
92dcb29010 Update slideshowMusic.lua
Test if old_view is nil
2016-01-04 22:52:31 +01:00
supertobi
d4cc869227 Merge pull request #4 from darktable-org/master
Merge with master
2016-01-04 22:49:38 +01:00
houz
291ff86686 Merge pull request #22 from spaceChRiS/import-filters-fix
Take care for code in for loop to be run even for the last image.
2016-01-04 17:23:33 +01:00
Tobias Ellinghaus
895ad62757 Fix line endings 2016-01-04 14:49:12 +01:00
houz
4acfa36b57 Merge pull request #21 from ribmo/master
Shortcuts to rate/reject all images within a group
2016-01-04 14:47:38 +01:00
spaceChRiS
fe18256c25 Remove extra line from image list. 2016-01-04 10:44:41 +01:00
spaceChRiS
39531eb4f0 Take care for code in for loop to be run even for the last image.
The problem: If the last image is a jpeg/raw pair, the code to remove the jpeg from the import list is not run since it is the last image. This is solved by adding an empty line to the images array. It will be counted as new base and therefore the jpeg removal code will be run one more time. I don't know if this is a good solution but I think it solves the problem without adding complexity.
2016-01-03 10:44:14 +01:00
ribmo
28d73b44a6 Shortcuts to rate/reject all images within a group 2016-01-02 13:01:50 +00:00
Boucman
3983a8a1ba Merge pull request #20 from mali/fix-typo
Fix some typos
2015-12-31 10:03:35 +01:00
Laurent Navet
08151e7e21 Fix some typos 2015-12-30 22:02:18 +01:00
Boucman
446927f947 Merge pull request #19 from chrik5/tagging
make check_api_version work with API 3
2015-12-29 10:56:49 +01:00
chrik5
5d72904849 make check_api_version work with API 3 2015-12-27 14:52:21 +01:00
Jérémy Rosen
ff1f076536 Revert "disable image_path_in_ui since it relies on a disabled feature"
This reverts commit 1dc1f5f9ef.
2015-12-23 15:21:38 +01:00
supertobi
c56766ef85 Fixed spaces 2015-12-16 13:51:35 +01:00
supertobi
eff8953207 Create geo_uri.lua
Maps in 3.20 will be able to handle the 'geo' URI scheme. That means that if you enter the shortcut Gnome Maps will present the current window if there is one and go to location, and start a new instance of maps if there is none.
2015-12-15 10:41:10 +01:00
supertobi
2ba1ae7a23 Merge pull request #3 from darktable-org/master
changes from master
2015-09-29 21:52:24 +02:00
71 changed files with 5834 additions and 636 deletions

View File

@@ -1,9 +1,9 @@
lua-scripts
===========
The Lua scripts in this repository are meant to be used together with darktable. Either copy them individually to `~/.config/darktable/lua` (you might have to create that folder) or just copy/symlink the whole repository there. That allows to update all your scripts with a simple call to `git pull`.
The Lua scripts in this repository are meant to be used together with darktable. Either copy them individually to `~/.config/darktable/lua` (Linux/Unix) or `%LOCALAPPDATA%\darktable\lua` (Windows) (you might have to create that folder) or just copy/symlink the whole repository there. That allows to update all your scripts with a simple call to `git pull`.
To enable one of the scripts you have to add a line like `require "official/hello_world"` to your `~/.config/darktable/luarc` file which will enable the example script in `official/hello_world.lua` (note the lack of the `.lua` suffix).
To enable one of the scripts you have to add a line like `require "examples/hello_world"` to your: `~/.config/darktable/luarc` (Linux/Unix) or `%LOCALAPPDATA%\darktable\luarc` (Windows) file which will enable the example script in `examples/hello_world.lua` (note the lack of the `.lua` suffix).
Each script includes its own documentation and usage in its header, please refer to them.

View File

@@ -28,6 +28,8 @@ USAGE
> exiftool -AutoDynamicRange XE021351.RAF
Auto Dynamic Range : 200%
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* exiftool
LICENSE
GPLv2
@@ -41,7 +43,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},{4,0,0},{5,0,0})
-- Receive the event triggered
function autostyle_apply_one_image_event(event,image)
@@ -66,7 +68,11 @@ function autostyle_apply_one_image (image)
darktable.print("style name not found in " .. darktable.preferences.read("autostyle","exif_tag","string"))
return
end
if not checkIfBinExists("exiftool") then
return
end
-- First find the style (we have its name)
local styles= darktable.styles
local style
@@ -118,8 +124,7 @@ end
function get_stdout(cmd)
-- Open the command, for reading
local fd = assert(io.popen(cmd, 'r'))
-- yield to other lua threads until data is ready to be read
coroutine.yield("FILE_READABLE",fd)
dt.control.read(fd)
-- slurp the whole file
local data = assert(fd:read('*a'))

View File

@@ -1,80 +0,0 @@
--[[
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 <http://www.gnu.org/licenses/>.
]]
--[[
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")

75
contrib/clear_GPS.lua Normal file
View File

@@ -0,0 +1,75 @@
--[[
clear_GPS.lua - export and edit with GIMP
Copyright (C) 2016 Bill Ferguson <wpferguson@gmail.com>.
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/>.
]]
--[[
clear_GPS - clear GPS data from selected image(s)
This shortcut removes the GPS coordinate data from the selected images.
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* None
USAGE
* require this script from your main lua file
* select an image or images
* click the shortcut, clear GPS data
BUGS, COMMENTS, SUGGESTIONS
* Send to Bill Ferguson, wpferguson@gmail.com
CHANGES
]]
local dt = require "darktable"
local gettext = dt.gettext
-- not a number
local NaN = 0/0
dt.configuration.check_version(...,{3,0,0},{4,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("clear_GPS",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("clear_GPS", msgid)
end
local function clear_GPS(images)
for _, image in ipairs(images) do
-- set the location information to Not a Number (NaN) so it displays correctly
image.elevation = NaN
image.latitude = NaN
image.longitude = NaN
end
end
dt.gui.libs.image.register_action(
_("clear GPS data"),
function(event, images) clear_GPS(images) end,
"clear GPS data"
)
dt.register_event(
"shortcut",
function(event, shortcut) clear_GPS(dt.gui.action_images) end,
"clear GPS data"
)

View File

@@ -1,6 +1,7 @@
--[[
This file is part of darktable,
copyright 2014-2015 by Christian Kanzian.
Copyright 2014-2016 by Christian Kanzian
Copyright 2016 by Holger Klemm
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
@@ -17,8 +18,9 @@
]]
--[[
(MULTI-)COPY ATTACH DETACH TAG
A simple script that will create three shortcuts to copy, attach and detach image tags.
(MULTI-)COPY ATTACH DETACH REPLACE TAGS
This script that will create four shortcuts and add a modul in lighttable mode to copy,
paste, replace and remove tags from images.
INSTALATION
* copy this file in $CONFIGDIR/lua/ where CONFIGDIR is your darktable configuration directory
@@ -27,17 +29,33 @@ INSTALATION
USAGE
* set the shortcuts for copy, attach and detach in the preferences dialog
* <your shortcut1> copy will create a list of tags from all selected images
* <your shortcut2> attaches copied tags to selected images, whereby
* <your shortcut2> paste copied tags to selected images, whereby
darktable internal tags starting with 'darktable|' will not be touched
* <your shortcut3> detach removes all expect darktable internal tags from selected images
* <your shortcut3> removes all expect darktable internal tags from selected images
* <your shortcut4> replaces all tags expect darktable internals
* A module reset will empty the clipboard
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,0})
local debug = require "darktable.debug"
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("copy_attach_detach_tags",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("copy_attach_detach_tags", msgid)
end
local image_tags = {}
local taglist_label = dt.new_widget("label"){selectable = true, ellipsize = "middle", halign = "start"}
taglist_label.label = ""
local function mcopy_tags()
local sel_images = dt.gui.action_images
local tag_list_tmp = {}
@@ -56,7 +74,7 @@ local function mcopy_tags()
--remove duplicate and 'darktable|' tags create final image_tags
for _,k in ipairs(tag_list_tmp) do
if not string.match(tostring(k), 'darktable|') then
if not hash[k] then
image_tags[#image_tags+1] = k
@@ -65,23 +83,38 @@ local function mcopy_tags()
end
end
dt.print("Image tags copied ...")
return(image_tags)
dt.print(_('Image tags copied ...'))
--create UI tag list
local taglist = ""
for _,tag in ipairs(image_tags) do
if taglist == "" then
taglist = tostring(tag)
else
taglist = taglist.."\n"..tostring(tag)
end
end
taglist_label.label = taglist
return(image_tags)
end
-- attach copied tags to all selected images
local function attach_tags()
if next(image_tags) == nil then
dt.print("No tags to attached, please copy tags first.")
dt.print(_('No tags to attached, please copy tags first.'))
return true
end
local sel_images = dt.gui.action_images
for _,image in ipairs(sel_images) do
local present_image_tags = {}
present_image_tags = dt.tags.get_tags(image)
for _,ct in ipairs(image_tags) do
-- check if image has tags and attach
if next(present_image_tags) == nil then
@@ -96,43 +129,111 @@ local function attach_tags()
end
end
end
dt.print("Tags attached ...")
dt.print(_('Tags attached ...'))
end
local function detach_tags()
local sel_images = dt.gui.action_images
for _,image in ipairs(sel_images) do
local present_image_tags = {}
present_image_tags = dt.tags.get_tags(image)
for _,present_tag in ipairs(present_image_tags) do
if not string.match(tostring(present_tag), 'darktable|') then
dt.tags.detach(present_tag,image)
end
end
end
dt.print("Tags removed from image(s).")
dt.print(_('Tags removed from image(s).'))
end
local function replace_tags()
detach_tags()
attach_tags()
dt.print(_('Tags replaced'))
end
-- create modul Tagging addons
taglist_label.reset_callback = mcopy_tags
-- create buttons and elements
local taglabel = dt.new_widget("label") {
label = _('tag clipboard'),
selectable = false,
ellipsize = "middle",
halign = "start"}
local box1 = dt.new_widget("box"){
orientation = "horizontal",
dt.new_widget("button") {
label = _('multi copy tags'),
clicked_callback = mcopy_tags},
dt.new_widget("button") {
label = _('paste tags'),
clicked_callback = attach_tags}
}
local box2 = dt.new_widget("box"){
orientation = "horizontal",
dt.new_widget("button") {
label = _('replace tags'),
clicked_callback = replace_tags},
dt.new_widget("button") {
label = _('remove all tags'),
clicked_callback = detach_tags}
}
local sep = dt.new_widget("separator"){}
-- pack elements into widget table for a nicer layout
local widget_table = {}
widget_table[1] = box1
widget_table[#widget_table+1] = box2
widget_table[#widget_table+1] = sep
widget_table[#widget_table+1] = taglabel
widget_table[#widget_table+1] = taglist_label
-- create modul
dt.register_lib("tagging_addon","Tagging addon",true,true,{
[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER",500}
},
dt.new_widget("box") {
-- orientation = "vertical",
reset_callback = function()
taglist_label.label = ""
image_tags = {}
end,
table.unpack(widget_table),
},
nil,
nil
)
-- shortcut for copy
dt.register_event("shortcut",
mcopy_tags,
"copy tags from selected image(s)")
_('copy tags from selected image(s)'))
-- shortcut for attach
dt.register_event("shortcut",
attach_tags,
"attach tags to selected image(s)")
_('paste tags to selected image(s)'))
-- shortcut for detaching tags
dt.register_event("shortcut",
detach_tags,
"detach tags to selected image(s)")
_('remove tags from selected image(s)'))
-- shortcut for replace tags
dt.register_event("shortcut",
replace_tags,
_('replace tags from selected image(s)'))
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
-- kate: tab-indents: off; indent-width 2; replace-tabs on; remove-trailing-space on;

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},{4,0,0})
local queue = {}
local processed_files = {}
@@ -60,7 +60,7 @@ end
local function convert_image(image)
if string.sub(image.filename, -3) == "CR2" then
local filename = image.path .. "/" .. image.filename
local result = coroutine.yield("RUN_COMMAND", "cr2hdr " .. filename)
local result = dt.control.execute( "cr2hdr " .. filename)
local out_filename = string.gsub(filename, ".CR2", ".DNG")
local file = io.open(out_filename)
if file then

View File

@@ -0,0 +1,70 @@
--[[ fujifilm_ratings-0.1
Support for importing Fujifilm in-camera ratings in darktable.
Copyright (C) 2017 Ben Mendis <ben.mendis@gmail.com>
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 2 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Dependencies:
- exiftool (https://www.sno.phy.queensu.ca/~phil/exiftool/)
--]]
local dt = require "darktable"
local df = require "lib/dtutils.file"
local gettext = dt.gettext
dt.configuration.check_version(..., {4,0,0})
gettext.bindtextdomain("fujifilm_ratings", dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("fujifilm_ratings", msgid)
end
local function detect_rating(event, image)
if not df.check_if_bin_exists("exiftool") then
dt.print_error(_("exiftool not found"))
return
end
local RAF_filename = tostring(image)
local JPEG_filename = string.gsub(RAF_filename, "%.RAF$", ".JPG")
local command = "exiftool -Rating " .. JPEG_filename
dt.print_error(command)
local output = io.popen(command)
local jpeg_result = output:read("*all")
output:close()
if string.len(jpeg_result) > 0 then
jpeg_result = string.gsub(jpeg_result, "^Rating.*(%d)", "%1")
image.rating = tonumber(jpeg_result)
dt.print_error(_("Using JPEG Rating: ") .. tostring(jpeg_result))
return
end
command = "exiftool -Rating " .. RAF_filename
dt.print_error(command)
output = io.popen(command)
local raf_result = output:read("*all")
output:close()
if string.len(raf_result) > 0 then
raf_result = string.gsub(raf_result, "^Rating.*(%d)", "%1")
image.rating = tonumber(raf_result)
dt.print_error(_("Using RAF Rating: ") .. tostring(raf_result))
end
end
dt.register_event("post-import-image", detect_rating)
print(_("fujifilm_ratings loaded."))

328
contrib/geoJSON_export.lua Normal file
View File

@@ -0,0 +1,328 @@
--[[
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 df = require "lib/dtutils.file"
require "official/yield"
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,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/locale/")
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 create_geoJSON_file(storage, image_table, extra_data)
if not df.check_if_bin_exists("mkdir") then
dt.print_error(_("mkdir not found"))
return
end
if not df.check_if_bin_exists("convert") then
dt.print_error(_("convert not found"))
return
end
if not df.check_if_bin_exists("xdg-open") then
dt.print_error(_("xdg-open not found"))
return
end
if not df.check_if_bin_exists("xdg-user-dir") then
dt.print_error(_("xdg-user-dir not found"))
return
end
dt.print_error("Will try to export geoJSON file now")
local exportDirectory = dt.preferences.read("geoJSON_export","ExportDirectory","string")
-- Creates dir if not exsists
local imageFoldername = "files/"
local mkdirCommand = "mkdir -p "..exportDirectory.."/"..imageFoldername
dt.control.execute( 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(exported_image, "(.-)([^\\/]-%.?([^%.\\/]*))$")
filename = string.upper(string.gsub(filename,"%.%w*", ""))
-- 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"
dt.control.execute( convertToThumbCommand)
local concertCommand = "convert -size 438x438 "..exported_image.." -resize 438x438 +profile \"*\" "..exportDirectory.."/"..imageFoldername..filename..".jpg"
dt.control.execute( concertCommand)
end
-- delete the original image
os.remove(exported_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,"%.", "_"))
-- Extract filename, e.g DSC9784.ARW -> DSC9784
filename = string.upper(string.gsub(image.filename,"%.%w*", ""))
-- Extract extension from exported image (user can choose JPG or PNG), e.g DSC9784.JPG -> .JPG
extension = string.match(exported_image,"%.%w*$")
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 image_title, image_description
if (image.title and image.title ~= "") then
image_title = image.title
else
image_title = image.filename
end
image_description = image.description
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>]]..filmName..[[</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.."\""
dt.control.execute( 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()
if (result == nil) then
result = ""
end
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)

687
contrib/geoToolbox.lua Normal file
View File

@@ -0,0 +1,687 @@
--[[
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 "geoToolbox"
* it creates a new geoToolbox lighttable module
]]
local dt = require "darktable"
local df = require "lib/dtutils.file"
require "official/yield"
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("geoToolbox",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("geoToolbox", msgid)
end
-- <GUI>
local labelDistance = dt.new_widget("label")
labelDistance.label = _("Distance:")
local label_copy_gps_lat = dt.new_widget("check_button")
{
label = _("latitude:"),
value = true
}
local label_copy_gps_lon = dt.new_widget("check_button")
{
label = _("longitude:"),
value = true
}
local label_copy_gps_ele = dt.new_widget("check_button")
{
label = _("elevation:"),
value = true
}
-- </GUI>
local function select_with_gps()
local selection = {}
job = dt.gui.create_job(_("GPS selection"), true, stop_selection)
for key,image in ipairs(dt.collection) do
if job.valid then
job.percent = (key-1)/#dt.collection
if (image.longitude and image.latitude) then
table.insert(selection,image)
end
else
break
end
end
dt.gui.selection(selection)
job.valid = false
end
local function select_without_gps()
local selection = {}
job = dt.gui.create_job(_("GPS selection"), true, stop_selection)
for key,image in ipairs(dt.collection) do
if job.valid then
job.percent = (key-1)/#dt.collection
if (not image.longitude and not image.latitude) then
table.insert(selection,image)
end
else
break
end
end
dt.gui.selection(selection)
job.valid = false
end
local function stop_selection(job)
job.valid = false
end
-- This is used for older images in the DB
function isnan(x) return x ~= x end
-- Function from:
-- https://forums.coronalabs.com/topic/29019-convert-string-to-date/
-- This looks much scarier than it really is. The goal is to turn that string
-- into a Unix timestamp (number of seconds since Jan 1, 1970, the standard
-- used by most systems). So we use the string.match() method to fetch the
-- various date and time parts into their own variables: xyear, xmonth,etc.
function make_time_stamp(dateString)
local convertedTimestamp
--dt.print_error(dateString)
if (dateString) then
local pattern = "(%d+)%:(%d+)%:(%d+) (%d+):(%d+):(%d+)"
local xyear, xmonth, xday, xhour, xminute, xseconds = dateString:match(pattern)
--dt.print_error(xyear)
convertedTimestamp = os.time({
year = xyear,
month = xmonth,
day = xday,
hour = xhour,
min = xminute,
sec = xseconds})
else
convertedTimestamp = 0
end
return convertedTimestamp
end
local first_have_data = false
local first_latitude = ''
local first_longitude = ''
local first_elevation = ''
local first_image_date = 0
local function get_first_coordinate()
local sel_images = dt.gui.action_images
first_latitude = ''
first_longitude = ''
first_elevation = ''
first_image_date = 0
for _,image in ipairs(sel_images) do
if not image then
first_have_data = false
else
image_date = image.exif_datetime_taken
first_have_data = true
if (image.latitude) then
first_latitude = image.latitude
end
if (image.longitude) then
first_longitude = image.longitude
end
if (image.elevation) then
first_elevation = image.elevation
end
if (image.exif_datetime_taken) then
first_image_date = make_time_stamp(image.exif_datetime_taken)
--dt.print_error(image.exif_datetime_taken)
--dt.print_error(first_image_date)
end
end
return
end
end
local second_have_data = false
local second_latitude = ''
local second_longitude = ''
local second_elevation = ''
local second_image_date = 0
local function get_second_coordinate()
local sel_images = dt.gui.action_images
second_latitude = ''
second_longitude = ''
second_elevation = ''
second_image_date = 0
for _,image in ipairs(sel_images) do
if not image then
second_have_data = false
else
image_date = image.exif_datetime_taken
second_have_data = true
if (image.latitude) then
second_latitude = image.latitude
end
if (image.longitude) then
second_longitude = image.longitude
end
if (image.elevation) then
second_elevation = image.elevation
end
if (image.exif_datetime_taken) then
second_image_date = make_time_stamp(image.exif_datetime_taken)
end
end
return
end
end
local calc_in_between_slider = dt.new_widget("slider")
{
label = "Position between",
soft_min = 0, -- 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 = -100, -- The hard minimum value for the slider, the user can't manually enter a value beyond this point
hard_max = 200, -- The hard maximum value for the slider, the user can't manually enter a value beyond this point
value = 50 -- The current value of the slider
}
--ToDo: this needs more love
local function calc_in_between()
local sel_images = dt.gui.action_images
for _,image in ipairs(sel_images) do
if image then
image_date = make_time_stamp(image.exif_datetime_taken)
if (first_have_data and second_have_data) then
local start_new = 0
local end_new = second_image_date - first_image_date
local image_date_new = image_date - first_image_date
local percent_in_between
if (end_new == 0) then
percent_in_between = 1
else
percent_in_between = image_date_new/end_new
end
calc_in_between_slider.value = percent_in_between * 100
dt.print_error(percent_in_between)
local in_between_latitude = first_latitude + (second_latitude - first_latitude) * percent_in_between
local in_between_longitude = first_longitude + (second_longitude - first_longitude) * percent_in_between
if (first_elevation and second_elevation) then
local in_between_elevation = first_elevation + (second_elevation - first_elevation) * percent_in_between
dt.print_error(first_image_date)
dt.print_error(second_image_date)
dt.print_error(image_date)
dt.print_error(first_elevation)
dt.print_error(second_elevation)
dt.print_error(in_between_elevation)
end
end
end
end
end
local copy_gps_have_data = false
local copy_gps_latitude = ''
local copy_gps_longitude = ''
local copy_gps_elevation = ''
local function copy_gps()
local sel_images = dt.gui.action_images
copy_gps_latitude = ''
copy_gps_longitude = ''
copy_gps_elevation = ''
for _,image in ipairs(sel_images) do
if not image then
copy_gps_have_data = false
else
copy_gps_have_data = true
if (image.latitude and label_copy_gps_lat.value) then
copy_gps_latitude = image.latitude
end
if (image.longitude and label_copy_gps_lon.value) then
copy_gps_longitude = image.longitude
end
if (image.elevation and label_copy_gps_ele.value) then
copy_gps_elevation = image.elevation
end
end
label_copy_gps_lat.label = _("latitude: ") .. copy_gps_latitude
label_copy_gps_lon.label = _("longitude: ") ..copy_gps_longitude
label_copy_gps_ele.label = _("elevation: ") .. copy_gps_elevation
return
end
end
local function paste_gps(image)
local sel_images = dt.gui.action_images
for _,image in ipairs(sel_images) do
if (label_copy_gps_lat.value) then
image.latitude = copy_gps_latitude
end
if (label_copy_gps_lon.value) then
image.longitude = copy_gps_longitude
end
if (label_copy_gps_ele.value) then
image.elevation = copy_gps_elevation
end
end
end
local function open_location_in_gnome_maps()
if not df.check_if_bin_exists("gnome-maps") then
dt.print_error(_("gnome-maps not found"))
return
end
local sel_images = dt.gui.action_images
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 = string.gsub(image.latitude, ",", ".");
lon1 = string.gsub(image.longitude, ",", ".");
break
end
end
local startCommand
startCommand = "gnome-maps \"geo:" .. lat1 .. "," .. lon1 .."\""
dt.print_error(startCommand)
dt.control.execute(startCommand)
end
-- Trim Funktion from: http://lua-users.org/wiki/StringTrim
local function trim12(s)
local from = s:match"^%s*()"
return from > #s and "" or s:match(".*%S", from)
end
local function reverse_geocode()
if not df.check_if_bin_exists("curl") then
dt.print_error(_("curl not found"))
return
end
if not df.check_if_bin_exists("jq") then
dt.print_error(_("jq not found"))
return
end
local sel_images = dt.gui.selection() --action_images
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 = string.gsub(image.latitude, ",", ".");
lon1 = string.gsub(image.longitude, ",", ".");
break
end
end
local startCommand
local tokan = dt.preferences.read("geoToolbox","mapBoxKey","string")
local types = "country";
local types = "region";
local types = "place";
local types = "poi";
-- MapBox documentation
-- https://www.mapbox.com/api-documentation/#retrieve-places-near-a-location
-- curl -s, --silent Silent mode (don't output anything)
-- jq could be replaced with a Lua JSON parser
startCommand = string.format("curl --silent \"https://api.mapbox.com/geocoding/v5/mapbox.places/%s,%s.json?types=%s&access_token=%s\" | jq '.features | .[0] | '.text''", lon1, lat1, types, tokan)
local handle = io.popen(startCommand)
local result = trim12(handle:read("*a"))
handle:close()
-- Errorhandling would be nice
--dt.print_error("startCommand: "..startCommand)
--dt.print_error("result: '"..result.."'")
if (result ~= "null") then
dt.print(string.sub(result, 2, string.len(result)-2))
end
end
-- I used code from here:
-- http://stackoverflow.com/questions/27928/how-do-i-calculate-distance-between-two-latitude-longitude-points
local function get_distance(lat1, lon1, ele1, lat2, lon2, ele2)
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
-- Add the elevation to the calculation
local elevation = 0
elevation = math.abs(ele1 - ele2) / 1000; --in km
if (elevation > 0) then
distance = math.sqrt(math.pow(elevation,2) + math.pow(distance,2) )
end
return distance
end
local function calc_distance()
local lat1 = 0;
local lon1 = 0;
local lat2 = 0;
local lon2 = 0;
local ele1 = 0;
local ele2 = 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
if (image.elevation) then
ele1 = image.elevation
else
ele1 = 0
end
end
lat2 = image.latitude
lon2 = image.longitude
if (image.elevation) then
ele2 = image.elevation
else
ele2 = 0;
end
end
end
local distance = get_distance(lat1, lon1, ele1, lat2, lon2, ele2)
if (distance < 1) then
distance = distance * 1000
distanceUnit = _("m")
else
distanceUnit = _("km")
end
return string.format(_("Distance: %.2f %s"), distance, distanceUnit)
end
local function print_calc_distance()
dt.print(calc_distance())
end
local function toolbox_calc_distance()
labelDistance.label = calc_distance()
end
local altitude_file_chooser_button = dt.new_widget("file_chooser_button")
{
title = _("export altitude CSV"), -- The title of the window when choosing a file
value = "", -- The currently selected file
is_directory = true -- True if the file chooser button only allows directories to be selecte
}
local altitude_filename = dt.new_widget("entry")
{
text = "altitude.csv",
placeholder = "altitude.csv",
editable = true,
tooltip = _("Name of the exported file"),
reset_callback = function(self) self.text = "text" end
}
local function altitude_profile()
dt.print(_("Start export"))
local sel_images = dt.gui.action_images
local lat1 = 0;
local lon1 = 0;
local lat2 = 0;
local lon2 = 0;
local ele1 = 0;
local ele2 = 0;
local i = 0;
local csv_file = '';
csv_file = "km;m".."\n";
local distance = 0;
local distanceFromStart = 0;
local elevation = 0;
local elevationAdd = 0;
local sel_images = dt.gui.action_images
for _,image in ipairs(sel_images) do
if ((not isnan(image.longitude) and not isnan(image.latitude) and not isnan(image.elevation) and image.elevation) 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
ele1 = image.elevation
else
lat1 = lat2
lon1 = lon2
ele1 = ele2
end
lat2 = image.latitude
lon2 = image.longitude
ele2 = image.elevation
if (i == 1) then
distanceFromStart = 0
else
local distance = get_distance(lat1, lon1, ele1, lat2, lon2, ele2)
distanceFromStart = distanceFromStart + distance;
end
csv_file = csv_file .. distanceFromStart..";"..image.elevation.."\n";
end
end --for
local exportDirectory = altitude_file_chooser_button.value
local exportFilename = altitude_filename.text
if (exportFilename == '') then
exportFilename = altitude_filename.placeholder
end
file = io.open(exportDirectory.."/"..exportFilename, "w")
file:write(csv_file)
file:close()
dt.print(_("File created in ")..exportDirectory)
end
local separator = dt.new_widget("separator"){}
local separator2 = dt.new_widget("separator"){}
local separator3 = dt.new_widget("separator"){}
local separator4 = dt.new_widget("separator"){}
local separator5 = dt.new_widget("separator"){}
dt.register_lib(
"geoToolbox", -- Module name
"geo toolbox", -- name
true, -- expandable
false, -- resetable
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers
dt.new_widget("box")
{
orientation = "vertical",
dt.new_widget("button")
{
label = _("select geo images"),
tooltip = _("Select all images with GPS information"),
clicked_callback = select_with_gps
},
dt.new_widget("button")
{
label = _("select non-geo images"),
tooltip = _("Select all images without GPS information"),
clicked_callback = select_without_gps
},
separator,--------------------------------------------------------
dt.new_widget("button")
{
label = _("copy GPS data"),
tooltip = _("Copy GPS data"),
clicked_callback = copy_gps
},
label_copy_gps_lat,
label_copy_gps_lon,
label_copy_gps_ele,
dt.new_widget("button")
{
label = _("paste GPS data"),
tooltip = _("Paste GPS data"),
clicked_callback = paste_gps
},
separator2,--------------------------------------------------------
--ToDo: This need a better UI
--[[
dt.new_widget("button")
{
label = "get 1st coordinate",
tooltip = "Select first image and click this button",
clicked_callback = get_first_coordinate
},
dt.new_widget("button")
{
label = "get 2nd coordinate",
tooltip = "Select second image and click this button",
clicked_callback = get_second_coordinate
},
dt.new_widget("button")
{
label = "calc in between",
tooltip = "Select third image and click this button",
clicked_callback = calc_in_between
},
calc_in_between_slider,
separator3,--------------------------------------------------------
]]
dt.new_widget("button")
{
label = _("open in Gnome Maps"),
tooltip = _("Open location in Gnome Maps"),
clicked_callback = open_location_in_gnome_maps
},
separator4,--------------------------------------------------------
dt.new_widget("button")
{
label = _("reverse geocode"),
tooltip = _("This just shows the name of the location, but doesn't add it as tag"),
clicked_callback = reverse_geocode
},
separator5,--------------------------------------------------------
dt.new_widget("label"){label = _("altitude CSV export")},
altitude_file_chooser_button,
altitude_filename,
dt.new_widget("button")
{
label = _("export altitude CSV file"),
tooltip = _("Create an altitude profile using the GPS data in the metadata"),
clicked_callback = altitude_profile
},
labelDistance
},
nil,-- view_enter
nil -- view_leave
)
-- Preferences
dt.preferences.register("geoToolbox",
"mapBoxKey",
"string",
_("geoToolbox export: MapBox Key"),
_("https://www.mapbox.com/studio/account/tokens"),
'' )
-- Register
dt.register_event("shortcut", print_calc_distance, _("Calculate the distance from latitude and longitude in km"))
dt.register_event("mouse-over-image-changed", toolbox_calc_distance)
dt.register_event("shortcut", select_with_gps, _("Select all images with GPS information"))
dt.register_event("shortcut", select_without_gps, _("Select all images without GPS information"))
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
-- kate: hl Lua;

302
contrib/gimp.lua Normal file
View File

@@ -0,0 +1,302 @@
--[[
gimp.lua - export and edit with GIMP
Copyright (C) 2016 Bill Ferguson <wpferguson@gmail.com>.
Portions are lifted from hugin.lua and thus are
Copyright (c) 2014 Wolfgang Goetz
Copyright (c) 2015 Christian Kanzian
Copyright (c) 2015 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/>.
]]
--[[
gimp - export an image and open with GIMP for editing
This script provides another storage (export target) for darktable. Selected
images are exported in the specified format to temporary storage. GIMP is launched
and opens the files. After editing, the exported images are overwritten to save the
changes. When GIMP exits, the exported files are moved into the current collection
and imported into the database. The imported files then show up grouped with the
originally selected images.
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* GIMP - http://www.gimp.org
USAGE
* require this script from your main lua file
* select an image or images for editing with GIMP
* in the export dialog select "Edit with GIMP" and select the format and bit depth for the
exported image
* Press "export"
* Edit the image with GIMP then save the changes with File->Overwrite....
* Exit GIMP
* The edited image will be imported and grouped with the original image
CAVEATS
* Developed and tested on Ubuntu 14.04 LTS with darktable 2.0.3 and GIMP 2.9.3 (development version with
> 8 bit color)
* There is no provision for dealing with the xcf files generated by GIMP, since darktable doesn't deal with
them. You may want to save the xcf file if you intend on doing further edits to the image or need to save
the layers used. Where you save them is up to you.
BUGS, COMMENTS, SUGGESTIONS
* Send to Bill Ferguson, wpferguson@gmail.com
CHANGES
* 20160823 - os.rename doesn't work across filesystems. Added fileCopy and fileMove functions to move the file
from the temporary location to the collection location irregardless of what filesystem it is on. If an
issue is encountered, a message is printed back to the UI so the user isn't left wondering what happened.
]]
local dt = require "darktable"
local df = require "lib/dtutils.file"
require "official/yield"
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("gimp",dt.configuration.config_dir.."/lua/locale/")
local function split_filepath(str)
local result = {}
-- Thank you Tobias Jakobs for the awesome regular expression, which I tweaked a little
result["path"], result["filename"], result["basename"], result["filetype"] = string.match(str, "(.-)(([^\\/]-)%.?([^%.\\/]*))$")
return result
end
local function get_path(str)
local parts = split_filepath(str)
return parts["path"]
end
local function get_filename(str)
local parts = split_filepath(str)
return parts["filename"]
end
local function get_basename(str)
local parts = split_filepath(str)
return parts["basename"]
end
local function get_filetype(str)
local parts = split_filepath(str)
return parts["filetype"]
end
local function _(msgid)
return gettext.dgettext("gimp", msgid)
end
-- Thanks Tobias Jakobs for the idea and the correction
function checkIfFileExists(filepath)
local file = io.open(filepath,"r")
local ret
if file ~= nil then
io.close(file)
dt.print_error("true checkIfFileExists: "..filepath)
ret = true
else
dt.print_error(filepath.." not found")
ret = false
end
return ret
end
local function filename_increment(filepath)
-- break up the filepath into parts
local path = get_path(filepath)
local basename = get_basename(filepath)
local filetype = get_filetype(filepath)
-- check to see if we've incremented before
local increment = string.match(basename, "_(%d-)$")
if increment then
-- we do 2 digit increments so make sure we didn't grab part of the filename
if string.len(increment) > 2 then
-- we got the filename so set the increment to 01
increment = "01"
else
increment = string.format("%02d", tonumber(increment) + 1)
basename = string.gsub(basename, "_(%d-)$", "")
end
else
increment = "01"
end
local incremented_filepath = path .. basename .. "_" .. increment .. "." .. filetype
dt.print_error("original file was " .. filepath)
dt.print_error("incremented file is " .. incremented_filepath)
return incremented_filepath
end
local function groupIfNotMember(img, new_img)
local image_table = img:get_group_members()
local is_member = false
for _,image in ipairs(image_table) do
dt.print_error(image.filename .. " is a member")
if image.filename == new_img.filename then
is_member = true
dt.print_error("Already in group")
end
end
if not is_member then
dt.print_error("group leader is "..img.group_leader.filename)
new_img:group_with(img.group_leader)
dt.print_error("Added to group")
end
end
local function sanitize_filename(filepath)
local path = get_path(filepath)
local basename = get_basename(filepath)
local filetype = get_filetype(filepath)
local sanitized = string.gsub(basename, " ", "\\ ")
return path .. sanitized .. "." .. filetype
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 fileCopy(fromFile, toFile)
local result = nil
-- if cp exists, use it
if df.check_if_bin_exists("cp") then
result = os.execute("cp '" .. fromFile .. "' '" .. toFile .. "'")
end
-- if cp was not present, or if cp failed, then a pure lua solution
if not result then
local fileIn, err = io.open(fromFile, 'rb')
if fileIn then
local fileOut, errr = io.open(toFile, 'w')
if fileOut then
local content = fileIn:read(4096)
while content do
fileOut:write(content)
content = fileIn:read(4096)
end
result = true
fileIn:close()
fileOut:close()
else
dt.print_error("fileCopy Error: " .. errr)
end
else
dt.print_error("fileCopy Error: " .. err)
end
end
return result
end
local function fileMove(fromFile, toFile)
local success = os.rename(fromFile, toFile)
if not success then
-- an error occurred, so let's try using the operating system function
if df.check_if_bin_exists("mv") then
success = os.execute("mv '" .. fromFile .. "' '" .. toFile .. "'")
end
-- if the mv didn't exist or succeed, then...
if not success then
-- pure lua solution
success = fileCopy(fromFile, toFile)
if success then
os.remove(fromFile)
else
dt.print_error("fileMove Error: Unable to move " .. fromFile .. " to " .. toFile .. ". Leaving " .. fromFile .. " in place.")
dt.print(string.format(_("Unable to move edited file into collection. Leaving it as %s"), fromFile))
end
end
end
return success -- nil on error, some value if success
end
local function gimp_edit(storage, image_table, extra_data) --finalize
if not df.check_if_bin_exists("gimp") then
dt.print_error(_("GIMP not found"))
return
end
-- list of exported images
local img_list
-- reset and create image list
img_list = ""
for _,exp_img in pairs(image_table) do
exp_img = sanitize_filename(exp_img)
img_list = img_list ..exp_img.. " "
end
dt.print(_("Launching GIMP..."))
local gimpStartCommand
gimpStartCommand = "gimp "..img_list
dt.print_error(gimpStartCommand)
dt.control.execute( gimpStartCommand)
-- for each of the image, exported image pairs
-- move the exported image into the directory with the original
-- then import the image into the database which will group it with the original
-- and then copy over any tags other than darktable tags
for image,exported_image in pairs(image_table) do
local myimage_name = image.path .. "/" .. get_filename(exported_image)
while checkIfFileExists(myimage_name) do
myimage_name = filename_increment(myimage_name)
-- limit to 99 more exports of the original export
if string.match(get_basename(myimage_name), "_(d-)$") == "99" then
break
end
end
dt.print_error("moving " .. exported_image .. " to " .. myimage_name)
local result = fileMove(exported_image, myimage_name)
if result then
dt.print_error("importing file")
local myimage = dt.database.import(myimage_name)
groupIfNotMember(image, myimage)
for _,tag in pairs(dt.tags.get_tags(image)) do
if not (string.sub(tag.name,1,9) == "darktable") then
dt.print_error("attaching tag")
dt.tags.attach(tag,myimage)
end
end
end
end
end
-- Register
dt.register_storage("module_gimp", _("Edit with GIMP"), show_status, gimp_edit)
--

View File

@@ -1,51 +0,0 @@
--[[
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 <http://www.gnu.org/licenses/>.
]]
--[[
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")

View File

@@ -1,119 +1,112 @@
--[[
Hugin storage for darktable
copyright (c) 2014 Wolfgang Goetz
copyright (c) 2015 Christian Kanzian
copyright (c) 2015 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/>.
]]
--[[
HUGIN
Add a new storage option to send images to hugin.
Images are exported to darktable tmp dir first.
ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT
* hugin
USAGE
* require this file from your main luarc config file.
This plugin will add a new storage option and calls hugin after export.
]]
local dt = require "darktable"
-- should work with darktable API version 2.0.0
dt.configuration.check_version(...,{2,0,0})
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
local function show_status(storage, image, format, filename,
number, total, high_quality, extra_data)
dt.print("Export to Hugin "..tostring(number).."/"..tostring(total))
end
local function create_panorama(storage, image_table, extra_data) --finalize
if not checkIfBinExists("hugin") then
darktable.print_error("hugin not found")
return
end
-- Since Hugin 2015.0.0 hugin provides a command line tool to start the assistant
-- http://wiki.panotools.org/Hugin_executor
-- We need pto_gen to create pto file for hugin_executor
-- http://hugin.sourceforge.net/docs/manual/Pto_gen.html
local hugin_executor = false
if (checkIfBinExists("hugin_executor") and checkIfBinExists("pto_gen")) then
hugin_executor = true
end
-- list of exported images
local img_list
-- reset and create image list
img_list = ""
for _,v in pairs(image_table) do
img_list = img_list ..v.. " "
end
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")
coroutine.yield("RUN_COMMAND", huginStartCommand)
dt.print("Running Assistent")
huginStartCommand = "hugin_executor --assistant "..dt.configuration.tmp_dir.."/project.pto"
coroutine.yield("RUN_COMMAND", huginStartCommand)
huginStartCommand = "hugin "..dt.configuration.tmp_dir.."/project.pto"
else
huginStartCommand = "hugin "..img_list
end
dt.print_error(huginStartCommand)
if coroutine.yield("RUN_COMMAND", huginStartCommand)
then
dt.print("Command hugin failed ...")
end
end
-- Register
dt.register_storage("module_hugin", "Hugin Panorama", show_status, create_panorama)
--
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
--[[
Hugin storage for darktable
copyright (c) 2014 Wolfgang Goetz
copyright (c) 2015 Christian Kanzian
copyright (c) 2015 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/>.
]]
--[[
HUGIN
Add a new storage option to send images to hugin.
Images are exported to darktable tmp dir first.
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* hugin
USAGE
* require this file from your main luarc config file.
This plugin will add a new storage option and calls hugin after export.
]]
local dt = require "darktable"
local df = require "lib/dtutils.file"
require "official/yield"
local gettext = dt.gettext
-- works with darktable API version from 2.0.0 to 5.0.0
dt.configuration.check_version(...,{2,0,0},{3,0,0},{4,0,0},{5,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("hugin",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("hugin", msgid)
end
local function show_status(storage, image, format, filename,
number, total, high_quality, extra_data)
dt.print("Export to Hugin "..tostring(number).."/"..tostring(total))
end
local function create_panorama(storage, image_table, extra_data) --finalize
if not df.check_if_bin_exists("hugin") then
dt.print_error(_("hugin not found"))
return
end
-- Since Hugin 2015.0.0 hugin provides a command line tool to start the assistant
-- http://wiki.panotools.org/Hugin_executor
-- We need pto_gen to create pto file for hugin_executor
-- http://hugin.sourceforge.net/docs/manual/Pto_gen.html
local hugin_executor = false
if (df.check_if_bin_exists("hugin_executor") and df.check_if_bin_exists("pto_gen")) then
hugin_executor = true
end
-- list of exported images
local img_list
-- reset and create image list
img_list = ""
for _,v in pairs(image_table) do
img_list = img_list ..v.. " "
end
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.control.execute( huginStartCommand)
dt.print(_("Running Assistent"))
huginStartCommand = "hugin_executor --assistant "..dt.configuration.tmp_dir.."/project.pto"
dt.control.execute( huginStartCommand)
huginStartCommand = "hugin "..dt.configuration.tmp_dir.."/project.pto"
else
huginStartCommand = "hugin "..img_list
end
dt.print_error(huginStartCommand)
if not dt.control.execute(huginStartCommand)
then
dt.print(_("Command hugin failed ..."))
end
end
-- Register
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,7 @@
--[[
This file is part of darktable,
Copyright 2014 by Tobias Jakobs.
Copyright 2016 by Tobias Jakobs.
Copyright 2016 by Erik Augustin.
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
@@ -18,7 +19,7 @@
--[[
darktable KML export script
ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* mkdir
* zip (only if you create KMZ files)
* convert (ImageMagick)
@@ -26,22 +27,37 @@ ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT
* xdg-user-dir
WARNING
This script is only testet with Linux
This script is only tested with Linux
USAGE
* require this script from your main lua file
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,1})
* require script "official/yield" from your main Lua file in the first line
* require this script from your main Lua file
* when choosing file format, pick JPEG or PNG as Google Earth doesn't support other formats
]]
local dt = require "darktable"
local df = require "lib/dtutils.file"
require "official/yield"
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,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/locale/")
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 = {}
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
-- otherwise just sort the keys
if order then
table.sort(keys, function(a,b) return order(_table, a, b) end)
else
@@ -59,43 +75,120 @@ 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)
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
-- Strip accents from a string
-- Copied from https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/
function string.stripAccents( str )
local tableAccents = {}
tableAccents["à"] = "a"
tableAccents["á"] = "a"
tableAccents["â"] = "a"
tableAccents["ã"] = "a"
tableAccents["ä"] = "a"
tableAccents["ç"] = "c"
tableAccents["è"] = "e"
tableAccents["é"] = "e"
tableAccents["ê"] = "e"
tableAccents["ë"] = "e"
tableAccents["ì"] = "i"
tableAccents["í"] = "i"
tableAccents["î"] = "i"
tableAccents["ï"] = "i"
tableAccents["ñ"] = "n"
tableAccents["ò"] = "o"
tableAccents["ó"] = "o"
tableAccents["ô"] = "o"
tableAccents["õ"] = "o"
tableAccents["ö"] = "o"
tableAccents["ù"] = "u"
tableAccents["ú"] = "u"
tableAccents["û"] = "u"
tableAccents["ü"] = "u"
tableAccents["ý"] = "y"
tableAccents["ÿ"] = "y"
tableAccents["À"] = "A"
tableAccents["Á"] = "A"
tableAccents["Â"] = "A"
tableAccents["Ã"] = "A"
tableAccents["Ä"] = "A"
tableAccents["Ç"] = "C"
tableAccents["È"] = "E"
tableAccents["É"] = "E"
tableAccents["Ê"] = "E"
tableAccents["Ë"] = "E"
tableAccents["Ì"] = "I"
tableAccents["Í"] = "I"
tableAccents["Î"] = "I"
tableAccents["Ï"] = "I"
tableAccents["Ñ"] = "N"
tableAccents["Ò"] = "O"
tableAccents["Ó"] = "O"
tableAccents["Ô"] = "O"
tableAccents["Õ"] = "O"
tableAccents["Ö"] = "O"
tableAccents["Ù"] = "U"
tableAccents["Ú"] = "U"
tableAccents["Û"] = "U"
tableAccents["Ü"] = "U"
tableAccents["Ý"] = "Y"
local normalizedString = ""
for strChar in string.gmatch(str, "([%z\1-\127\194-\244][\128-\191]*)") do
if tableAccents[strChar] ~= nil then
normalizedString = normalizedString..tableAccents[strChar]
else
normalizedString = normalizedString..strChar
end
ret = true
return ret
end
return normalizedString
end
-- Escape XML characters
-- Keep &amp; first, otherwise it will double escape other characters
-- https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents
function string.escapeXmlCharacters( str )
str = string.gsub(str,"&", "&amp;")
str = string.gsub(str,"\"", "&quot;")
str = string.gsub(str,"'", "&apos;")
str = string.gsub(str,"<", "&lt;")
str = string.gsub(str,">", "&gt;")
return str
end
local function create_kml_file(storage, image_table, extra_data)
if not checkIfBinExists("mkdir") then
if not df.check_if_bin_exists("mkdir") then
dt.print_error(_("mkdir not found"))
return
end
if not checkIfBinExists("convert") then
if not df.check_if_bin_exists("convert") then
dt.print_error(_("convert not found"))
return
end
if not checkIfBinExists("xdg-open") then
if not df.check_if_bin_exists("xdg-open") then
dt.print_error(_("xdg-open not found"))
return
end
if not checkIfBinExists("xdg-user-dir") then
if not df.check_if_bin_exists("xdg-user-dir") then
dt.print_error(_("xdg-user-dir not found"))
return
end
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
if not df.check_if_bin_exists("zip") then
dt.print_error(_("zip not found"))
return
end
exportDirectory = dt.configuration.tmp_dir
imageFoldername = ""
else
@@ -104,62 +197,82 @@ local function create_kml_file(storage, image_table, extra_data)
-- Creates dir if not exsists
imageFoldername = "files/"
local mkdirCommand = "mkdir -p "..exportDirectory.."/"..imageFoldername
coroutine.yield("RUN_COMMAND", mkdirCommand)
dt.control.execute(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.
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,"%.%w*", ""))
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)
-- 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"
dt.control.execute(convertToThumbCommand)
else
-- Remove exported image if it has no GPS data
os.remove(exported_image)
end
local pattern = "[/]?([^/]+)$"
filmName = string.match(_.film.path, pattern)
filmName = string.match(image.film.path, pattern)
-- Strip accents from the filename, because GoogleEarth can't open them
-- https://github.com/darktable-org/lua-scripts/issues/54
filmName = string.stripAccents(filmName)
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"
--image_table = dt.gui.selection();
kml_file = kml_file.."<name>"..filmName.."</name>\n"
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
filename = string.upper(string.gsub(image.filename,"%.", "_"))
if ((image.longitude and image.latitude) and
for image,exported_image in pairs(image_table) do
-- Extract filename, e.g DSC9784.ARW -> DSC9784
filename = string.upper(string.gsub(image.filename,"%.%w*", ""))
-- Extract extension from exported image (user can choose JPG or PNG), e.g DSC9784.JPG -> .JPG
extension = string.match(exported_image,"%.%w*$")
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"
local image_title, image_description
if (image.title and image.title ~= "") then
image_title = string.escapeXmlCharacters(image.title)
else
image_title = image.filename
end
-- Characters should not be escaped in CDATA, but we are using HTML fragment, so we must escape them
image_description = string.escapeXmlCharacters(image.description)
kml_file = kml_file.." <name>"..image_title.."</name>\n"
kml_file = kml_file.." <description>"..image_description.."</description>\n"
kml_file = kml_file.." <Style>\n"
kml_file = kml_file.." <IconStyle>\n"
kml_file = kml_file.." <Icon>\n"
kml_file = kml_file.." <href>"..imageFoldername.."thumb_"..filename..".jpg</href>\n"
kml_file = kml_file.." <href>"..imageFoldername.."thumb_"..filename..".jpg</href>\n"
kml_file = kml_file.." </Icon>\n"
kml_file = kml_file.." </IconStyle>\n"
kml_file = kml_file.." <BalloonStyle>\n"
kml_file = kml_file.." <text><![CDATA[<img src=\""..imageFoldername..filename..".jpg\"><br/>]]></text>\n"
kml_file = kml_file.." <text><![CDATA[<p><b>"..image_title.."</b></p><img src=\""..imageFoldername..filename..extension.."\"><p>"..image_description.."</p>]]></text>\n"
kml_file = kml_file.." <textColor>ff000000</textColor>\n"
kml_file = kml_file.." <displayMode>default</displayMode>\n"
kml_file = kml_file.." </BalloonStyle>\n"
@@ -172,32 +285,36 @@ local function create_kml_file(storage, image_table, extra_data)
kml_file = kml_file.." <when>"..string.gsub(image.exif_datetime_taken," ", "T").."Z".."</when>\n"
kml_file = kml_file.." </TimeStamp>\n"
kml_file = kml_file.." </Point>\n"
kml_file = kml_file.." </Placemark>\n"
end
end
-- Connects all images with an path
if ( dt.preferences.read("kml_export","CreatePath","bool") == true ) then
kml_file = kml_file.." <Placemark>\n"
kml_file = kml_file.." <Placemark>\n"
kml_file = kml_file.." <name>Path</name>\n" -- ToDo: I think a better name would be nice
--kml_file = kml_file.." <description></description>\n"
kml_file = kml_file.." <Style>\n"
kml_file = kml_file.." <LineStyle>\n"
kml_file = kml_file.." <Style>\n"
kml_file = kml_file.." <LineStyle>\n"
kml_file = kml_file.." <color>ff0000ff</color>\n"
kml_file = kml_file.." <width>5</width>\n"
kml_file = kml_file.." </LineStyle>\n"
kml_file = kml_file.." </LineStyle>\n"
kml_file = kml_file.." </Style>\n"
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
if ((image.longitude and image.latitude) and
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 +326,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()
@@ -218,38 +335,73 @@ local function create_kml_file(storage, image_table, extra_data)
-- 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)
createKMZCommand = createKMZCommand .."\""..exportDirectory.."/"..exportKMZFilename.."\" " -- KMZ filename
createKMZCommand = createKMZCommand .."\""..dt.configuration.tmp_dir.."/"..exportKMLFilename.."\" " -- KML file
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 filename = string.upper(string.gsub(image.filename,"%.%w*", ""))
createKMZCommand = createKMZCommand .."\""..dt.configuration.tmp_dir.."/"..imageFoldername.."thumb_"..filename..".jpg\" " -- thumbnails
createKMZCommand = createKMZCommand .."\""..exported_image.."\" " -- images
end
end
dt.control.execute(createKMZCommand)
end
-- Open the file with the standard programm
-- Open the file with the standard programm
if ( dt.preferences.read("kml_export","OpenKmlFile","bool") == true ) then
local kmlFileOpenCommand
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
dt.control.execute(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 )
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()
if (result == nil) then
result = ""
end
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

@@ -0,0 +1,94 @@
--[[
Passport cropping guide for darktable
copyright (c) 2017 Kåre Hampf
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/>.
]]
--[[
PASSPORT CROPPING GUIDE
guides for cropping passport photos based on documents from the Finnish police
(https://www.poliisi.fi/instancedata/prime_product_julkaisu/intermin/embeds/poliisiwwwstructure/38462_Passikuvaohje_EN.pdf) describing passport photo dimensions of 47x36 mm and 500x653 px for digital biometric data stored in passports. They use ISO 19794-5 standard based on ICAO 9303 regulations which should also be compliant for all of Europe.
INSTALLATION
* copy this file in $CONFIGDIR/lua/ where CONFIGDIR is your darktable configuration directory
* add the following line in the file $CONFIGDIR/luarc
require "passport_guide"
* (optional) add the line:
"plugins/darkroom/clipping/extra_aspect_ratios/passport 36x47mm=47:36"
to $CONFIGDIR/darktablerc
USAGE
* when using the cropping tool, select "passport" as guide and if you added the line in yout rc
select "passport 36x47mm" as aspect
]]
local dt = require "darktable"
local gettext = dt.gettext
dt.configuration.check_version(...,{2,0,0},{3,0,0},{4,0,0},{5,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("passport_guide",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("passport_guide", msgid)
end
dt.guides.register_guide("passport",
-- draw
function(cairo, x, y, width, height, zoom_scale)
local _width, _height
-- get the max 36x47 rectangle
local aspect_ratio = 47 / 36
if width * aspect_ratio > height then
_width = height / aspect_ratio
_height = height
else
_width = width
_height = width * aspect_ratio
end
cairo:save()
cairo:translate(x + (width - _width) / 2, y + (height - _height) / 2)
cairo:scale(_width / 36, _height / 47)
-- the outer rectangle
cairo:rectangle( 0, 0, 36, 47)
-- vertical bars
cairo:draw_line(16.5, 8, 16.5, 36)
cairo:draw_line(19.5, 8, 19.5, 36)
-- long horisontal bars
cairo:draw_line(6, 4, 30, 4)
cairo:draw_line(6, 40, 30, 40)
-- short horisontal bars
cairo:draw_line(9, 6, 27, 6)
cairo:draw_line(9, 38, 27, 38)
cairo:restore()
end,
-- gui
function()
return dt.new_widget("label"){label = _("ISO 19794-5/ICAO 9309 passport"), halign = "start"}
end
)
-- kate: tab-indents: off; indent-width 2; replace-tabs on; remove-trailing-space on; hl Lua;
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua

247
contrib/pdf_slideshow.lua Normal file
View File

@@ -0,0 +1,247 @@
--[[
This file is part of darktable,
copyright (c) 2017 Pascal Obry
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/>.
]]
--[[
SELECTION_TO_PDF
Generates a PDF slideshow (via Latex) containing all selected images
one per slide.
ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT
* a PDF-Viewer
* pdflatex (Latex)
USAGE
* require this file from your main lua config file:
This plugin will add a new exporter that will allow you to generate a pdf slideshow.
The interface will let you add:
- a global title for the slideshow (prefix in all slide label)
- a delay for the transition between each slide
Each slide will contain a single picture with a label at the bottom with the
format (all fields can be the empty string):
<global title> / <image creator> / <image title>
]]
local dt = require "darktable"
local df = require "lib/dtutils.file"
require "official/yield"
local gettext = dt.gettext
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("pdf_slideshow",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("pdf_slideshow", msgid)
end
if not df.check_if_bin_exists("pdflatex") then
dt.print_error(_("pdflatex not found"))
return
end
dt.configuration.check_version(...,{4,0,0},{5,0,0})
dt.preferences.register
("pdf_slideshow","open with","string",
_("a pdf viewer"),
_("can be an absolute pathname or the tool may be in the PATH"),
"xdg-open")
local title_widget = dt.new_widget("entry") {
placeholder=_("slideshow title")
}
local delay_widget = dt.new_widget("slider")
{
label = _("transition delay (s)"),
soft_min = 1, -- The soft minimum value for the slider, the slider can't go beyond this point
soft_max = 20, -- The soft maximum value for the slider, the slider can't go beyond this point
hard_min = 1, -- The hard minimum value for the slider, the user can't manually enter a value beyond this point
hard_max = 60, -- The hard maximum value for the slider, the user can't manually enter a value beyond this point
value = 5, -- The current value of the slider
step = 1,
digits = 0
}
local check_button_title = dt.new_widget("check_button")
{
label = _('include image title'),
value = true,
tooltip = _('whether to include the image title (if defined) into the slide')
}
local check_button_author = dt.new_widget("check_button")
{
label = _('include image author'),
value = true,
tooltip = _('whether to include the image author (if defined) into the slide')
}
local widget = dt.new_widget("box") {
orientation=horizontal,
dt.new_widget("label"){label = _("slideshow title")},
title_widget,
dt.new_widget("label"){label = ""},
delay_widget,
check_button_author,
check_button_title
}
local ending = [[
\end{document}
]]
-- only jpeg files are supported by latex
local function support_format(storage, format)
fmt = string.lower(format.name)
if string.match(fmt,"jpeg") ~= nil and string.match(fmt,"2000") == nil then
return true
else
return false
end
end
local filename =dt.configuration.tmp_dir.."/pdfout.tex"
local function my_write(latexfile,arg)
local res,errmsg = latexfile:write(arg)
if not res then
error(errmsg)
end
end
local function img_filename(file,i)
local dir=string.gsub(file, "(.*)(%/.*%..*)", "%1")
local ext=string.gsub(file, "(.*)(%..*)", "%2")
local lfile = dir.."/slide"..i..ext
return lfile
end
local function slide(latexfile,i,image,file)
local title = ""
if title_widget.text ~= "" then
title = title_widget.text
end
if check_button_author.value == true and image.creator ~= "" then
if title ~= "" then
title = title.." / "
end
title = title..image.creator
end
if check_button_title.value == true and image.title ~= "" then
if title ~= "" then
title = title.." / "
end
title = title..image.title
end
-- make sure there is no non-printable characters in the title
title = string.gsub(title, "\n", "")
title = string.gsub(title, "\r", "")
title = string.gsub(title, "\t", "")
local lfile = img_filename(file,i)
os.rename(file, lfile)
my_write(latexfile,"\\begin{figure}\n")
my_write(latexfile,"\\begin{measuredfigure}\n")
my_write(latexfile,"\\includegraphics[height=0.92\\textheight]{"..lfile.."}\n")
my_write(latexfile,"\\end{measuredfigure}\n")
my_write(latexfile,"\\caption{{\\color{white}"..title.."}}\n")
my_write(latexfile,"\\end{figure}\n")
end
dt.register_storage("pdf_slideshow",_("pdf slideshow"),
nil,
function(storage,image_table)
local preamble = [[
\documentclass[a4paper,12pt,landscape]{beamer}
\usetheme{default}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{threeparttable}
\usepackage[space]{grffile} % needed to support filename with spaces
\pagestyle{empty}
\parindent0pt
\usepackage{geometry}
\usepackage{color}
\pagecolor{black!100}
\color{white}
\geometry{a4paper,landscape,left=2mm,right=2mm, top=2mm, bottom=2mm}
\mode<presentation>
\transduration{]]..string.gsub(delay_widget.value, ",", ".")..[[}
\setbeamertemplate{footline}{}
\setbeamertemplate{headline}{}
\setbeamertemplate{frametitle}{}
\setbeamertemplate{navigation symbols}{}
\setbeamercolor{background canvas}{fg=white,bg=black!100}
\setbeamercolor{normal text}{fg=white}
\hypersetup{pdfstartpage=1,pdfpagemode=FullScreen}
\setbeamertemplate{caption}{\insertcaption}
\begin{document}
]]
local errmsg
local latexfile
latexfile,errmsg=io.open(filename,"w")
if not latexfile then
error(errmsg)
end
my_write(latexfile,preamble)
local i = 1
for img,file in pairs(image_table) do
slide(latexfile,i,img,file)
my_write(latexfile,"\n\\bigskip\n")
i = i+1
end
my_write(latexfile,ending)
latexfile:close()
-- convert to PDF
local dir=string.gsub(filename, "(.*/)(.*)", "%1")
local locfile=string.gsub(filename, "(.*/)(.*)", "%2")
local command = "pdflatex -halt-on-error -output-directory "..dir.." "..locfile
local result = dt.control.execute(command)
if result ~= 0 then
dt.print(_("problem running pdflatex")) -- this one is probably usefull to the user
error(_("problem running ")..command)
end
-- open the PDF
local pdffile=string.gsub(filename, ".tex", ".pdf")
command = dt.preferences.read("pdf_slideshow","open with","string")
command = command.." "..pdffile
local result = dt.control.execute(command)
if result ~= 0 then
dt.print(_("problem running pdf viewer")) -- this one is probably usefull to the user
error(_("problem running ")..command)
end
-- finally do some clean-up
local i = 1
for img,file in pairs(image_table) do
local lfile = img_filename(file,i)
os.remove(lfile)
i = i+1
end
end,
support_format,
nil,
widget)
--
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua

251
contrib/quicktag.lua Normal file
View File

@@ -0,0 +1,251 @@
--[[
This file is part of darktable,
Copyright (C) 2017 by Christian Kanzian
Thanks to
Copyright (C) 2016 Bill Ferguson
Copyright (C) 2017 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/>.
]]
--[[
QUICKTAG
For faster attaching your favorite tags, the script adds shortcuts and
the module "quicktag" in lighttable mode with a changeable number of buttons.
To each button a tag can be assigned. If the tags do not exist in your database,
they are added to the database once they get the first time attached to an image.
The number of buttons/shortcuts can be changed in the lua preferences.
Changes in the number require a restart of darktable.
INSTALATION
* copy this file in $CONFIGDIR/lua/ where CONFIGDIR is your darktable configuration directory
* add the following line in the file $CONFIGDIR/luarc require "quicktag"
USAGE
* set the number of quicktags between 2 and 10 in the preferences dialog and restart darktable
* if wanted set the shortcuts in the preferences dialog
* to add or change a quicktag, first select the old tag with the combobox "old quicktag",
enter a new tag in the "new quicktag" filed and press "set quicktag"
* use a shortcut or button to attach the tag to selected images
]]
local dt = require "darktable"
local debug = require "darktable.debug"
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("quicktag",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("quicktag", msgid)
end
-- maximum length of button labels
dt.preferences.register("quickTag",
"labellength",
"integer", -- type
_("max. length of button labels"), -- label
_("may range from 15 to 60 - needs a restart"), -- tooltip
25, -- default
15, -- min
60)
local max_label_length = dt.preferences.read("quickTag", "labellength", "integer")
-- register number of quicktags
dt.preferences.register("quickTag",
"quickTagnumber",
"integer", -- type
_("number of quicktag fields"), -- label
_("may range from 2 to 20 - needs a restart"), -- tooltip
5, -- default
2, -- min
20)
local qnr = dt.preferences.read("quickTag", "quickTagnumber", "integer")
-- get quicktags from the preferences
local quicktag_table = {}
local function read_pref_tags()
for j=1,qnr do
quicktag_table[j] = dt.preferences.read("quickTag", "quicktag"..j, "string")
end
end
local quicktag_label = {}
local function abbrevate_tags(t)
for i=1,qnr do
local taglength = string.len(t[i])
if taglength > max_label_length then
local max_2 = math.floor(max_label_length/2)
quicktag_label[i] = string.sub(t[i],0,max_2).."..."..string.sub(t[i],taglength - max_2)
else
quicktag_label[i] = t[i]
end
-- print(quicktag_label[i])
end
end
-- quicktag function to attach tags
local function tagattach(tag,qtagnr)
if tag == "" then
dt.print(string.format(_("quicktag %i is empty, please set a tag"), qtagnr))
return true
end
local tagnr = dt.tags.find(tag)
--create tag if it does not exist
if tagnr == nil then
dt.tags.create(tag)
tagnr = dt.tags.find(tag)
end
local sel_images = dt.gui.action_images
if next(sel_images) == nil then
dt.print(_("no images selected"))
return true
end
local counter = 0
for _,image in ipairs(sel_images) do
dt.tags.attach(tagnr,image)
counter = counter+1
end
dt.print(string.format(_("tag \"%s\" attached to %i image(s)"), tag, counter))
end
-- create quicktag module elements
-- read tags from preferences for initialization
read_pref_tags()
abbrevate_tags(quicktag_table)
local button = {}
-- function to create buttons with tags as labels
for j=1,qnr do
button[#button+1] = dt.new_widget("button") {
label = j..": "..quicktag_table[j],
clicked_callback = function() tagattach(tostring(quicktag_table[j]),j) end}
end
local old_quicktag = dt.new_widget("combobox"){
label = _("old tag"),
tooltip = _("select the quicktag to replace")
}
local function update_quicktag_list()
-- abrevate long tags for the labels
abbrevate_tags(quicktag_table)
for j=1,qnr do
button[j].label = j..": "..quicktag_label[j]
old_quicktag[j] = j..": "..quicktag_table[j]
end
end
update_quicktag_list()
local new_quicktag = dt.new_widget("entry"){
text = "",
placeholder = _("new tag"),
is_password = true,
editable = true,
tooltip = _("enter your tag here")
}
local set_quicktag_button = dt.new_widget("button") {
label = _("set tag"),
clicked_callback = function()
local old_tag = quicktag_table[old_quicktag.selected]
if new_quicktag.text == "" then
dt.print(_("new quicktag is empty!"))
else
quicktag_table[old_quicktag.selected] = new_quicktag.text
dt.preferences.write("quickTag", "quicktag"..old_quicktag.selected, "string", new_quicktag.text)
dt.print(string.format(_("quicktag \"%s\" replaced by \"%s\""), old_tag, new_quicktag.text))
update_quicktag_list()
new_quicktag.text = ""
end
end,
}
local new_qt_widget = dt.new_widget ("box") {
orientation = "horizontal",
dt.new_widget("label") { label = _("new tag") },
new_quicktag,
set_quicktag_button
}
-- back UI elements in a table
-- thanks to wpferguson for the hint
local widget_table = {}
for i=1,qnr do
widget_table[#widget_table + 1] = button[i]
end
widget_table[#widget_table + 1] = dt.new_widget("separator"){}
widget_table[#widget_table + 1] = old_quicktag
widget_table[#widget_table + 1] = new_qt_widget
--create module
dt.register_lib(
"quicktag", -- Module name
"quicktag", -- name
true, -- expandable
false, -- resetable
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 490}},
dt.new_widget("box"){
orientation = "vertical",
table.unpack(widget_table),
},
nil,-- view_enter
nil -- view_leave
)
-- create shortcuts
for i=1,qnr do
dt.register_event("shortcut",
function(event, shortcut) tagattach(tostring(quicktag_table[i])) end,
string.format(_("quicktag %i"),i))
end
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
-- kate: tab-indents: off; indent-width 2; replace-tabs on; remove-trailing-space on;

87
contrib/rate_group.lua Normal file
View File

@@ -0,0 +1,87 @@
--[[
Rate Group:
Script to provide shortcuts for rating or rejecting all images within a group;
particularly useful for RAW+JPEG shooters employing a star rating workflow
like the below:
http://blog.chasejarvis.com/blog/2011/03/photo-editing-101/
Installation and usage:
1. Copy this file into ~/.config/darktable/lua/
2. Add `require "rate_group"` to new line in ~/.config/darktable/luarc
3. Restart darktable
4. Assign a keyboard shortcut to each action via settings > shortcuts > lua
I use the following shortcuts:
* Reject group: Ctrl+R
* Rate group 1: Ctrl+1
* Rate group 2: Ctrl+2
* Rate group 3: Ctrl+3
* Rate group 4: Ctrl+4
* Rate group 5: Ctrl+5
* Rate group 0: Ctrl+0
Author: Dom H (dom@hxy.io)
License: GPLv2
This script is based on Thibault Jouannic's `reject_group` script:
http://redmine.darktable.org/issues/8968#note-20
]]
local dt = require "darktable"
-- added version check
dt.configuration.check_version(...,{3,0,0},{4,0,0})
local function apply_rating(rating)
local images = dt.gui.action_images
for _, i in ipairs(images) do
local members = i:get_group_members()
for _, m in ipairs(members) do
m.rating = rating
end
end
if rating < 0 then
dt.print("rejecting group(s)")
else
dt.print("applying rating " ..rating.. " to group(s)")
end
end
dt.register_event("shortcut",function(event, shortcut)
apply_rating(-1)
end, "Reject group")
dt.register_event("shortcut",function(event, shortcut)
apply_rating(0)
end, "Rate group 0")
dt.register_event("shortcut",function(event, shortcut)
apply_rating(1)
end, "Rate group 1")
dt.register_event("shortcut",function(event, shortcut)
apply_rating(2)
end, "Rate group 2")
dt.register_event("shortcut",function(event, shortcut)
apply_rating(3)
end, "Rate group 3")
dt.register_event("shortcut",function(event, shortcut)
apply_rating(4)
end, "Rate group 4")
dt.register_event("shortcut",function(event, shortcut)
apply_rating(5)
end, "Rate group 5")

114
contrib/rename-tags.lua Normal file
View File

@@ -0,0 +1,114 @@
--[[
Rename tags
AUTHOR
Sebastian Witt (se.witt@gmx.net)
INSTALLATION
* copy this file in $CONFIGDIR/lua/ where CONFIGDIR
is your darktable configuration directory
* add the following line in the file $CONFIGDIR/luarc
require "rename-tags"
USAGE
* In lighttable there is a new entry: 'rename tag'
* Enter old tag (this one gets deleted!)
* Enter new tag name
LICENSE
GPLv2
]]
local darktable = require "darktable"
local debug = require "darktable.debug"
-- GUI entries
local old_tag = darktable.new_widget("entry") { tooltip = "Enter old tag" }
local new_tag = darktable.new_widget("entry") { tooltip = "Enter new tag" }
-- This function does the renaming
local function rename_tags(widget)
-- If entries are empty, return
if old_tag.text == '' then
darktable.print ("Old tag can't be empty")
return
end
if new_tag.text == '' then
darktable.print ("New tag can't be empty")
return
end
local Count = 0
-- Check if old tag exists
local ot = darktable.tags.find (old_tag.text)
if not ot then
darktable.print ("Old tag does not exist")
return
end
-- Show job
local job = darktable.gui.create_job ("Renaming tag", true)
old_tag.editable = false
new_tag.editable = false
-- Create if it does not exists
local nt = darktable.tags.create (new_tag.text)
-- Search images for old tag
dbcount = #darktable.database
for i,image in ipairs(darktable.database) do
-- Update progress bar
job.percent = i / dbcount
local tags = image:get_tags ()
for _,t in ipairs (tags) do
if t.name == old_tag.text then
-- Found it, attach new tag
image:attach_tag (nt)
Count = Count + 1
end
end
end
-- Delete old tag, this removes it from all images
darktable.tags.delete (ot)
job.valid = false
darktable.print ("Renamed tags for " .. Count .. " images")
old_tag.editable = true
new_tag.editable = true
end
-- GUI
local old_widget = darktable.new_widget ("box") {
orientation = "horizontal",
darktable.new_widget("label") { label = "Old tag" },
old_tag
}
local new_widget = darktable.new_widget ("box") {
orientation = "horizontal",
darktable.new_widget("label") { label = "New tag" },
new_tag
}
local function rename_reset(widget)
old_tag.text = ''
new_tag.text = ''
end
local rename_widget = darktable.new_widget ("box") {
orientation = "vertical",
reset_callback = rename_reset,
old_widget,
new_widget,
darktable.new_widget("button") { label = "Go", clicked_callback = rename_tags }
}
darktable.register_lib ("rename_tags", "rename tag", true, true, {[darktable.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 20},}, rename_widget, nil, nil)

View File

@@ -0,0 +1,64 @@
--[[
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/>.
]]
--[[
Enable selection of untagged images (darktable|* tags are ignored)
]]
local dt = require "darktable"
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("select_untagged",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("select_untagged", msgid)
end
local function stop_job(job)
job.valid = false
end
local function select_untagged_images()
job = dt.gui.create_job(_("select untagged images"), true, stop_job)
local selection = {}
for key,image in ipairs(dt.collection) do
if(job.valid) then
job.percent = (key-1)/#dt.collection
local tags = dt.tags.get_tags(image)
local hasTags = false
for _,tag in ipairs(tags) do
if not string.match(tag.name,"darktable|") then
hasTags = true
end
end
if hasTags == false then
table.insert(selection,image)
end
else
break
end
end
job.valid = false
dt.gui.selection(selection)
end
dt.gui.libs.select.register_selection(_("select untagged"),select_untagged_images,_("select all images containing no tags or only tags added by darktable"))

View File

@@ -23,21 +23,19 @@ 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
local dt = require "darktable"
local df = require "lib/dtutils.file"
require "official/yield"
local gettext = dt.gettext
dt.configuration.check_version(...,{2,0,2},{3,0,0},{4,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("slideshowMusic",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("slideshowMusic", msgid)
end
local function playSlideshowMusic(_, old_view, new_view)
@@ -46,7 +44,8 @@ local function playSlideshowMusic(_, old_view, new_view)
filename = dt.preferences.read("slideshowMusic","SlideshowMusic","string")
playMusic = dt.preferences.read("slideshowMusic","PlaySlideshowMusic","bool")
if not checkIfBinExists("rhythmbox-client") then
if not df.check_if_bin_exists("rhythmbox-client") then
dt.print_error(_("rhythmbox-client not found"))
return
end
@@ -55,26 +54,26 @@ local function playSlideshowMusic(_, old_view, new_view)
if (new_view.id == "slideshow") then
playCommand = 'rhythmbox-client --play-uri="'..filename..'"'
--dt.print_error(playCommand)
coroutine.yield("RUN_COMMAND", playCommand)
dt.control.execute( 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)
dt.control.execute( stopCommand)
end
end
end
end
-- Preferences
dt.preferences.register("slideshowMusic", "SlideshowMusic", "file", "Slideshow background music file", "", "")
dt.preferences.register("slideshowMusic",
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

@@ -1,120 +1,119 @@
--[[
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 <http://www.gnu.org/licenses/>.
]]
--[[
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 (result) then
--dt.print_error("true checkIfBinExists: "..bin)
ret = true
else
dt.print_error(bin.." not found")
ret = false
end
return ret
end
local function create_video_mencoder(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_mencoder","ExportDirectory","string")
exportFilename = "output.avi"
framsePerSecond = dt.preferences.read("video_mencoder","FramesPerSecond","integer")
dt.print_error("Will try to create video now")
-- Set the codec
local codec = ""
local codecPreferences = ""
codecPreferences = dt.preferences.read("video_mencoder","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_mencoder","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_mencoder", "FramesPerSecond", "float", "Video exort (MEncoder): Frames per second", "Frames per Second in the Video export", 15, 1, 99, 0.1 )
dt.preferences.register("video_mencoder", "OpenVideo", "bool", "Video exort (MEncoder): 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_mencoder", "ExportDirectory", "directory", "Video exort (MEncoder): 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_mencoder", "Codec", "enum", "Video exort (MEncoder): Codec","Video codec","H.264 encoding","H.264 encoding","XviD encoding")
-- Register
dt.register_storage("video_mencoder", "Video Export (MEncoder)", show_status, create_video)
--[[
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 <http://www.gnu.org/licenses/>.
]]
--[[
darktable video export script
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* mencoder (MEncoder is from the MPlayer Team)
* 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 df = require "lib/dtutils.file"
require "official/yield"
local gettext = dt.gettext
dt.configuration.check_version(...,{2,0,1},{3,0,0},{4,0,0},{5,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("video_mencoder",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("video_mencoder", msgid)
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 create_video_mencoder(storage, image_table, extra_data)
if not df.check_if_bin_exists("mencoder") then
dt.print_error(_("mencoder not found"))
return
end
if not df.check_if_bin_exists("xdg-open") then
dt.print_error(_("xdg-open not found"))
return
end
if not df.check_if_bin_exists("xdg-user-dir") then
dt.print_error(_("xdg-user-dir not found"))
return
end
exportDirectory = dt.preferences.read("video_mencoder","ExportDirectory","string")
exportFilename = "output.avi"
framsePerSecond = dt.preferences.read("video_mencoder","FramesPerSecond","integer")
dt.print_error("Will try to create video now")
-- Set the codec
local codec = ""
local codecPreferences = ""
codecPreferences = dt.preferences.read("video_mencoder","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)
dt.control.execute( command)
dt.print("Video created in "..exportDirectory)
if ( dt.preferences.read("video_mencoder","OpenVideo","bool") == true ) then
local playVideoCommand = "xdg-open "..exportDirectory.."/"..exportFilename
dt.control.execute( playVideoCommand)
end
end
-- Preferences
dt.preferences.register("video_mencoder", "FramesPerSecond", "float", "Video exort (MEncoder): Frames per second", "Frames per Second in the Video export", 15, 1, 99, 0.1 )
dt.preferences.register("video_mencoder", "OpenVideo", "bool", "Video exort (MEncoder): 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()
if (result == nil) then
result = ""
end
dt.preferences.register("video_mencoder", "ExportDirectory", "directory", "Video exort (MEncoder): 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_mencoder", "Codec", "enum", "Video exort (MEncoder): Codec","Video codec","H.264 encoding","H.264 encoding","XviD encoding")
-- Register
dt.register_storage("video_mencoder", "Video Export (MEncoder)", show_status, create_video)

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},{4,0,0},{5,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/locale/")
-- 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},{4,0,0},{5,0,0})
dt.print("hello, world")

138
examples/moduleExample.lua Normal file
View File

@@ -0,0 +1,138 @@
--[[
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},{4,0,0},{5,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"}
--https://www.darktable.org/lua-api/ar01s02s54.html.php
local entry = dt.new_widget("entry")
{
text = "test",
placeholder = "placeholder",
is_password = false,
editable = true,
tooltip = "Tooltip Text",
reset_callback = function(self) self.text = "text" end
}
local file_chooser_button = dt.new_widget("file_chooser_button")
{
title = "MyFile_chooser_button", -- The title of the window when choosing a file
value = "", -- The currently selected file
is_directory = false -- True if the file chooser button only allows directories to be selecte
}
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
}
if (dt.configuration.api_version_major >= 6) then
local section_label = dt.new_widget("section_label")
{
label = "MySectionLabel"
}
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,
section_label
},
nil,-- view_enter
nil -- view_leave
)
else
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
)
end
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
-- kate: hl Lua;

View File

@@ -16,13 +16,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]
--[[
darktable script to show the different prefference types that are possible with the Lua
darktable script to show the different preference types that are possible with Lua
USAGE
* require this script from your main lua file
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,1})
dt.configuration.check_version(...,{2,0,1},{3,0,0},{4,0,0},{5,0,0})
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

View File

@@ -0,0 +1,40 @@
--[[
This file is part of darktable,
copyright (c) 2017 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/>.
]]
--[[
Print Examples
prints "hello world when DT starts
USAGE
* require this file from your main lua config file:
]]
local dt = require "darktable"
dt.configuration.check_version(...,{5,0,0})
-- Will print a string to the darktable control log (the long
-- overlayed window that appears over the main panel).
dt.print("print")
-- This function will print its parameter if the Lua logdomain is
-- activated. Start darktable with the "-d lua" command line option
-- to enable the Lua logdomain.
dt.print_error("print error")
-- This function will print its parameter if the Lua logdomain is
-- activated. Start darktable with the "-d lua" command line option
-- to enable the Lua logdomain.
dt.print_log("print log")
--
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua

34
examples/running_os.lua Normal file
View File

@@ -0,0 +1,34 @@
--[[
This file is part of darktable,
copyright (c) 2017 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 "running_os"
prints the operating system
]]
local dt = require "darktable"
dt.configuration.check_version(...,{5,0,0})
dt.print("You are running: "..dt.configuration.running_os)
--
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=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={...}

218
lib/dtutils.lua Normal file
View File

@@ -0,0 +1,218 @@
local dtutils = {}
dtutils.libdoc = {
Name = [[dtutils]],
Synopsis = [[A Darktable lua utilities library]],
Usage = [[local du = require "lib/dtutils"]],
Description = [[dtutils provides a common library of functions used to build
lua scripts. There are also sublibraries that provide more functions.]],
Return_Value = [[du - library - the library of functions]],
Limitations = [[]],
Example = [[]],
See_Also = [[dtutils.debug(3), dtutils.file(3), dtutils.log(3), dtutils.string(3)]],
Reference = [[]],
License = [[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/>.]],
Copyright = [[Copyright (C) 2016 Bill Ferguson <wpferguson@gmail.com>.
Copyright (C) 2016 Tobias Jakobs]],
functions = {}
}
local dt = require "darktable"
local log = require "lib/dtutils.log"
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
dtutils.libdoc.functions["split"] = {
Name = [[split]],
Synopsis = [[split a string on a specified separator]],
Usage = [[local du = require "lib/dtutils"
local result = du.split(str, pat)
str - string - the string to split
pat - string - the pattern to split on]],
Description = [[split separates a string into a table of strings. The strings are separated at each
occurrence of the supplied pattern. The pattern may be any pattern as described in the lua docs.
Each match of the pattern is consumed and not returned.]],
Return_Value = [[result - a table of strings on success, or an empty table on error]],
Limitations = [[]],
Example = [[split("/a/long/path/name/to/a/file.txt", "/") would return a table like
{a, "long", "path", "name", "to", a, "file.txt"}]],
See_Also = [[]],
Reference = [[http://lua-users.org/wiki/SplitJoin]],
License = [[]],
Copyright = [[]],
}
function dtutils.split(str, pat)
local t = {}
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = str:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(t,cap)
end
last_end = e+1
s, e, cap = str:find(fpat, last_end)
end
if last_end <= #str then
cap = str:sub(last_end)
table.insert(t, cap)
end
return t
end
dtutils.libdoc.functions["join"] = {
Name = [[join]],
Synopsis = [[join a table of strings with a specified separator]],
Usage = [[local du = require "lib/dtutils"
local result = du.join(tabl, pat)
tabl - a table of strings
pat - a separator]],
Description = [[join assembles a table of strings into a string with the specified pattern
in between each string]],
Return_Value = [[result - string - the joined string on success, or an empty string on failure]],
Limitations = [[]],
Example = [[join({a, "long", "path", "name", "to", a, "file.txt"}, " ") would return the string
"a long path name to a file.txt"]],
See_Also = [[]],
Reference = [[http://lua-users.org/wiki/SplitJoin]],
License = [[]],
Copyright = [[]],
}
function dtutils.join(tabl, pat)
returnstr = ""
for i,str in pairs(tabl) do
returnstr = returnstr .. str .. pat
end
return string.sub(returnstr, 1, -(pat:len() + 1))
end
--[[
NAME
prequire - a protected lua require
SYNOPSIS
local du = require "lib/dtutils"
local result = du.prequire(req_name)
req_name - the filename of the lua code to load without the ".lua" filetype
DESCRIPTION
prequire is a protected require that can survive an error in the code being loaded without
bringing down the calling routine.
RETURN VALUE
result - the code or true on success, otherwise an error message
EXAMPLE
prequire("lib/dtutils.file") which would load lib/dtutils/file.lua
]]
dtutils.libdoc.functions["prequire"] = {
Name = [[prequire]],
Synopsis = [[a protected lua require]],
Usage = [[local du = require "lib/dtutils"
local status, lib = du.prequire(req_name)
req_name - the filename of the lua code to load without the ".lua" filetype]],
Description = [[prequire is a protected require that can survive an error in the code being loaded without
bringing down the calling routine.]],
Return_Value = [[status - boolean - true on success
lib - if status is true, then the code, otherwise an error message]],
Limitations = [[]],
Example = [[local status, lib = prequire("lib/dtutils.file") which would load lib/dtutils/file.lua which
would return a status of true and the reference to the library in lib.]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils.prequire(req_name)
local status, lib = pcall(require, req_name)
if status then
log.msg(log.info, "Loaded " .. req_name)
else
log.msg(log.info, "Error loading " .. req_name)
end
return status, lib
end
dtutils.libdoc.functions["spairs"] = {
Name = [[spairs]],
Synopsis = [[an iterator that provides sorted pairs from a table]],
Usage = [[local du = require "lib/dtutils"
for key, value in du.spairs(t, order) do
t - table - table of key, value pairs
order - function - an optional function to sort the pairs
if none is supplied, table.sort() is used]],
Description = [[spairs is an iterator that returns key, value pairs from a table in sorted
order. The sorting order is the result of table.sort() if no function is
supplied, otherwise sorting is done as specified in the function.]],
Return_Value = [[]],
Limitations = [[]],
Example = [[HighScore = { Robin = 8, Jon = 10, Max = 11 }
-- basic usage, just sort by the keys
for k,v in spairs(HighScore) do
print(k,v)
end
--> Jon 10
--> Max 11
--> Robin 8
-- this uses an custom sorting function ordering by score descending
for k,v in spairs(HighScore, function(t,a,b) return t[b] < t[a] end) do
print(k,v)
end
--> Max 11
--> Jon 10
--> Robin 8]],
See_Also = [[]],
Reference = [[Code copied from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua]],
License = [[]],
Copyright = [[]],
}
-- Sort a table
function dtutils.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
return dtutils

161
lib/dtutils/debug.lua Normal file
View File

@@ -0,0 +1,161 @@
--[[
This file is part of darktable,
Copyright (c) 2014 Jérémy Rosen
Copyright (c) 2016 Bill Ferguson
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/>.
]]
--[[
DEBUG HELPERS
A collection of helper functions to help debugging lua scripts.
require it as
dhelpers = require "lib/dtutils.debug"
Each function is documented in its own header
]]
local dt = require "darktable"
local io = require "io"
local table = require "table"
require "darktable.debug"
local log = require "lib/dtutils.log"
local M = {} -- The actual content of the module
M.libdoc = {
Name = [[dtutils.debug]],
Synopsis = [[debugging helpers used in developing darktable lua scripts]],
Usage = [[local dd = require "lib/dtutils.debug"]],
Description = [[dtutils.debug provides an interface to the darktable debugging routines.]],
Return_Value = [[dd - library - the darktable lua debugging helpers]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = log.libdoc.License,
Copyright = [[Copyright (c) 2014 Jérémy Rosen
Copyright (c) 2016 Bill Ferguson
]],
functions = {}
}
M.libdoc.functions["tracepoint"] = {
Name = [[tracepoint]],
Synopsis = [[print out a tracepoint and dump the arguments]],
Usage = [[local dd = require "lib/dtutils.debug"
local result = tracepoint(name, ...)
name - string - the name of the tracepoint to print out
... - arguments - variables to dump the contents of]],
Description = [[tracepoint prints its name and dumps its parameters using
dt.debug]],
Return_Value = [[result - ... - the supplied argument list]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function M.tracepoint(name,...)
log.msg(log.always, 4, "***** "..name.." ****")
params = {...}
log.msg(log.always, 0, dt.debug.dump(params,"parameters"))
return ...;
end
M.libdoc.functions["new_tracepoint"] = {
Name = [[new_tracepoint]],
Synopsis = [[create a function returning a tracepoint]],
Usage = [[local dd = require "lib/dtutils.debug"
local result = new_tracepoint(name, ...)
name - string - the name of the tracepoint to print out
... - arguments - variables to dump the contents of]],
Description = [[A function that returns a tracepoint function with the given name
This is mainly used to debug callbacks.]],
Return_Value = [[result - function - a function that returns the result of a tracepoint]],
Limitations = [[]],
Example = [[register_event(event, dd.new_tracepoint("hit callback"))
will print the following each time the callback is called
**** hit callback ****
<all the callback's parameters dumped>]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function M.new_tracepoint(name)
return function(...) return M.tracepoint(name,...) end
end
M.libdoc.functions["dprint"] = {
Name = [[dprint]],
Synopsis = [[pass a variable to dt.debug.dump and print the results to stdout]],
Usage = [[local dd = require "lib/dtutils.debug"
dd.dprint(var)
var - variable - any variable that you want to see the contents of]],
Description = [[Wrapper around debug.dump, will directly print to stdout,
same calling convention]],
Return_Value = [[]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function M.dprint(...)
log.msg(log.always, 4, dt.debug.dump(...))
end
M.libdoc.functions["terse_dump"] = {
Name = [[terse_dump]],
Synopsis = [[set dt.debug.known to shorten all image dumps to a single line]],
Usage = [[local dd = require "lib/dtutils.debug"
dd.terse_dump()]],
Description = [[terse_dump sets dt.debug.known to shorten all images to a single line.
If you don't need to debug the content of images, this will avoid them flooding your logs]],
Return_Value = [[]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function M.terse_dump()
for _,v in ipairs(dt.database) do
dt.debug.known[v] = tostring(v)
end
end
return M
-- vim: shiftwidth=2 expandtab tabstop=2 cindent
-- kate: tab-indents: off; indent-width 2; replace-tabs on; remove-trailing-space on;

394
lib/dtutils/file.lua Normal file
View File

@@ -0,0 +1,394 @@
local dtutils_file = {}
local dt = require "darktable"
local log = require "lib/dtutils.log"
dtutils_file.libdoc = {
Name = [[dtutils.file]],
Synopsis = [[common darktable lua file functions]],
Usage = [[local df = require "lib/dtutils.file"]],
Description = [[[dtutils.file provides common file manipulation functions used in
constructing Darktable lua scripts]],
Return_Value = [[df - library - the file functions]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = log.libdoc.License,
Copyright = [[Copyright (C) 2016 Bill Ferguson <wpferguson@gmail.com>.]],
Copyright = [[Copyright (C) 2016 Bill Ferguson <wpferguson@gmail.com>.
Copyright (C) 2016 Tobias Jakobs]],
functions = {}
}
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("dtutils.file",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("dtutils.file", msgid)
end
dtutils_file.libdoc.functions["check_if_bin_exists"] = {
Name = [[check_if_bin_exists]],
Synopsis = [[check if an executable is in the path]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.check_if_bin_exists(bin)
bin - string - the binary to check for]],
Description = [[check_if_bin_exists checks to see if the specified binary executable is
in the path.]],
Return_Value = [[result - boolean - true if the executable was found, false if not]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.check_if_bin_exists(bin)
local result = os.execute("which " .. bin)
if not result then
result = false
end
return result
end
dtutils_file.libdoc.functions["split_filepath"] = {
Name = [[split_filepath]],
Synopsis = [[split a filepath into parts]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.split_filepath(filepath)
filepath - string - path and filename]],
Description = [[split_filepath splits a filepath into the path, filename, basename and filetype and puts
that in a table]],
Return_Value = [[result - table - a table containing the path, filename, basename, and filetype]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.split_filepath(str)
-- strip out single quotes from quoted pathnames
str = string.gsub(str, "'", "")
local result = {}
-- Thank you Tobias Jakobs for the awesome regular expression, which I tweaked a little
result["path"], result["filename"], result["basename"], result["filetype"] = string.match(str, "(.-)(([^\\/]-)%.?([^%.\\/]*))$")
return result
end
dtutils_file.libdoc.functions["get_path"] = {
Name = [[get_path]],
Synopsis = [[get the path from a file path]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.get_path(filepath)
filepath - string - path and filename]],
Description = [[get_path strips the filename and filetype from a path and returns the path]],
Return_Value = [[result - string - the path]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.get_path(str)
local parts = dtutils_file.split_filepath(str)
return parts["path"]
end
dtutils_file.libdoc.functions["get_filename"] = {
Name = [[get_filename]],
Synopsis = [[get the filename and extension from a file path]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.get_filename(filepath)
filepath - string - path and filename]],
Description = [[get_filename strips the path from a filepath and returns the filename]],
Return_Value = [[result - string - the file name and type]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.get_filename(str)
local parts = dtutils_file.split_filepath(str)
return parts["filename"]
end
dtutils_file.libdoc.functions["get_basename"] = {
Name = [[get_basename]],
Synopsis = [[get the filename without the path or extension]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.get_basename(filepath)
filepath - string - path and filename]],
Description = [[get_basename returns the name of the file without the path or filetype
]],
Return_Value = [[result - string - the basename of the file]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.get_basename(str)
local parts = dtutils_file.split_filepath(str)
return parts["basename"]
end
dtutils_file.libdoc.functions["get_filetype"] = {
Name = [[get_filetype]],
Synopsis = [[get the filetype from a filename]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.get_filetype(filepath)
filepath - string - path and filename]],
Description = [[get_filetype returns the filetype from the supplied filepath]],
Return_Value = [[result - string - the filetype]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.get_filetype(str)
local parts = dtutils_file.split_filepath(str)
return parts["filetype"]
end
-- Thanks Tobias Jakobs for the idea
dtutils_file.libdoc.functions["check_if_file_exists"] = {
Name = [[check_if_file_exists]],
Synopsis = [[check if a file or path exist]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.check_if_file_exists(filepath)
filepath - string - a file or path to check]],
Description = [[check_if_file_exists checks to see if a file or path exists]],
Return_Value = [[result - boolean - true if the file or path exists, false if it doesn't]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.check_if_file_exists(filepath)
local result = os.execute("test -e " .. filepath)
if not result then
result = false
end
return result
end
dtutils_file.libdoc.functions["chop_filetype"] = {
Name = [[chop_filetype]],
Synopsis = [[remove a filetype from a filename]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.chop_filetype(path)
path - string - a filename with or without a path]],
Description = [[chop_filetype removes the filetype from the filename]],
Return_Value = [[result - string - the path and filename without the filetype]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.chop_filetype(path)
local length = dtutils_file.get_filetype(path):len() + 2
return string.sub(path, 1, -length)
end
dtutils_file.libdoc.functions["file_copy"] = {
Name = [[file_copy]],
Synopsis = [[copy a file to another name/location]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.file_copy(fromFile, toFile)
fromFile - string - name of file to copy from
toFile - string - name of file to copy to]],
Description = [[copy a file using a succession of methods from operating system
to a pure lua solution]],
Return_Value = [[result - boolean - nil on error, true on success]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.file_copy(fromFile, toFile)
local result = nil
-- if cp exists, use it
if dtutils_file.check_if_bin_exists("cp") then
result = os.execute("cp '" .. fromFile .. "' '" .. toFile .. "'")
end
-- if cp was not present, or if cp failed, then a pure lua solution
if not result then
local fileIn, err = io.open(fromFile, 'rb')
if fileIn then
local fileOut, errr = io.open(toFile, 'w')
if fileOut then
local content = fileIn:read(4096)
while content do
fileOut:write(content)
content = fileIn:read(4096)
end
result = true
fileIn:close()
fileOut:close()
else
log.msg(log.error, errr)
end
else
log.msg(log.error, err)
end
end
return result
end
dtutils_file.libdoc.functions["file_move"] = {
Name = [[file_move]],
Synopsis = [[move a file from one directory to another]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.file_move(fromFile, toFile)
fromFile - string - name of the original file
toFile - string - the new file location and name]],
Description = [[Move a file from one place to another. Try a succession of methods from
builtin to operating system to a pure lua solution.]],
Return_Value = [[result - boolean - nil on error, some value on success]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.file_move(fromFile, toFile)
local success = os.rename(fromFile, toFile)
if not success then
-- an error occurred, so let's try using the operating system function
if dtutils_file.check_if_bin_exists("mv") then
success = os.execute("mv '" .. fromFile .. "' '" .. toFile .. "'")
end
-- if the mv didn't exist or succeed, then...
if not success then
-- pure lua solution
success = dtutils_file.file_copy(fromFile, toFile)
if success then
os.remove(fromFile)
else
log.msg(log.error, "Unable to move " .. fromFile .. " to " .. toFile .. ". Leaving " .. fromFile .. " in place.")
end
end
end
return success -- nil on error, some value if success
end
dtutils_file.libdoc.functions["filename_increment"] = {
Name = [[filename_increment]],
Synopsis = [[add a two digit increment to a filename]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.filename_increment(filepath)
filepath - string - filename to increment]],
Description = [[filename_increment solves the problem of filename confllict by adding an
increment to the filename. If the supplied filename has no increment then
"01" is added to the basename. If the filename already has an increment, then
1 is added to it and the filename returned.]],
Return_Value = [[result - string - the incremented filename]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.filename_increment(filepath)
-- break up the filepath into parts
local path = dtutils_file.get_path(filepath)
local basename = dtutils_file.get_basename(filepath)
local filetype = dtutils_file.get_filetype(filepath)
-- check to see if we've incremented before
local increment = string.match(basename, "_(%d-)$")
if increment then
-- we do 2 digit increments so make sure we didn't grab part of the filename
if string.len(increment) > 2 then
-- we got the filename so set the increment to 01
increment = "01"
else
increment = string.format("%02d", tonumber(increment) + 1)
basename = string.gsub(basename, "_(%d-)$", "")
end
else
increment = "01"
end
local incremented_filepath = path .. basename .. "_" .. increment .. "." .. filetype
return incremented_filepath
end
dtutils_file.libdoc.functions["create_unique_filename"] = {
Name = [[create_unique_filename]],
Synopsis = [[create a unique filename from the supplied argment]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.create_unique_filename(filepath)
filepath - string - the path and filename requested]],
Description = [[create_unique_filename takes a requested filepath and checks to see if
it exists. If if doesn't then it's returned intact. If it already exists, then a two
digit increment is added to the filename and it is tested again. The increment keeps
increasing until either a unique filename is found or there have been 100 attempts.]],
Return_Value = [[result - string - the incremented filename]],
Limitations = [[create_unique_filename will only attempt 100 increments.]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.create_unique_filename(filepath)
while dtutils_file.check_if_file_exists(filepath) do
filepath = dtutils_file.filename_increment(filepath)
-- limit to 99 more exports of the original export
if string.match(dtfileutils.get_basename(filepath), "_(d-)$") == "99" then
break
end
end
return filepath
end
return dtutils_file

291
lib/dtutils/log.lua Normal file
View File

@@ -0,0 +1,291 @@
local dtutils_log = {}
dtutils_log.libdoc = {
Name = [[dtutils.log]],
Synopsis = [[darktable lua logging library]],
Usage = [[local log = require "lib/dtutils.log"]],
Description = [[log provides a multi-level logging solution for use with
the darktable lua scripts. With this library you can leave log messages
scattered through out your code and only turn them on as necessary.]],
Return_Value = [[log - library - the darktable lua logging functions]],
Limitations = [[]],
Example = [[local log = require "lib/dtutils.log"
local cur_level = log.log_level()
log.log_level(log.warn)
print out warning, error and success messages as code is running
log.log_level(debug)
print out debugging messages too because this isnt working
log.log_level(info)
I want to make sure this is working ok
log.log_level(cur_level)
reset the logging level back to normal]],
See_Also = [[]],
Reference = [[]],
License = [[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/>.]],
Copyright = [[Copyright (C) 2016 Bill Ferguson <wpferguson@gmail.com>.]],
functions = {}
}
local dt = require "darktable"
local dt_print_error = dt.print_error
-- work around until dt.print_log()
local dt_print_log = dt.print_error
local dt_print = dt.print
-- set the default log levels
dtutils_log.debug = {
label = "DEBUG:",
enabled = false,
engine = dt_print_log,
level = 1,
}
dtutils_log.info = {
label = "INFO:",
enable = false,
engine = dt_print_log,
level = 2,
}
dtutils_log.warn = {
label = "WARN:",
enabled = false,
engine = dt_print_log,
level = 3,
}
dtutils_log.error = {
label = "ERROR:",
enabled = true,
engine = dt_print_error,
level = 4,
}
dtutils_log.success = {
label = "SUCCESS:",
enabled = true,
engine = dt_print_log,
level = 5,
}
dtutils_log.screen = {
label = "",
enabled = true,
engine = dt_print,
level = 9,
}
dtutils_log.always = {
label = "",
enabled = true,
engine = dt_print_log,
level = 9,
}
dtutils_log.critical = {
label = "CRITICAL:",
enabled = true,
engine = print,
level = 9,
}
dtutils_log.libdoc.functions["caller"] = {
Name = [[caller]],
Synopsis = [[get the name and line number of the calling routine]],
Usage = [[local log = require "lib/dtutils.log"
result = log.caller(level)
level - number - the number of stack levels to go down to retrieve the caller routine information]],
Description = [[caller gets the name and line number of the calling routine and returns it]],
Return_Value = [[result - string - the name and line number of the calling function or 'callback: ' if the attempt to get the
caller returns nil]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_log.caller(level)
local name = debug.getinfo(level).name
local lineno = nil
local source = nil
if name then
lineno = debug.getinfo(level).currentline
-- returns the path to the file prefixed with @
source = debug.getinfo(level).source
-- we just need the filename, so grab it from the string
-- Thanks, Tobias Jakobs :-)
source = string.match(source, "@.-([^\\/]-%.?[^%.\\/]*)$")
return name .. ": " .. source .. ": " .. lineno .. ":"
else
return "callback:"
end
end
dtutils_log.libdoc.functions["msg"] = {
Name = [[msg]],
Synopsis = [[print a log message]],
Usage = [[local log = require "lib/log"
log.msg(level, ...)
level - table - the type of message, one of:
log.debug - debugging messages
log.info - informational messages
log.warn - warning messages
log.error - error messages
log.success - success messages
log.always - an internal message for debugging
log.screen - output 1 line of text to the screen
log.critical - print a critical message to the console
... - string(s) - the message to print, which could be a comma separated set of strings]],
Description = [[msg checks the level to see if it is enabled, then prints the level type and message if it is.
Messages are output using the engine configured in each log level.]],
Return_Value = [[]],
Limitations = [[If you use log.msg in a callback, the name of the calling routine can't be determined. A solution
is to include some means of reference such as the name of the callback as an argument, i.e.
log.msg(log.debug, "libPlugin.format_combobox:", "value is " .. self.value)
which would result in
DEBUG: callback: libPlugin.format_combobox: value is JPEG]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_log.msg(level, ...)
if level.enabled then
local args = {...}
local call_level = 3
if level == dtutils_log.always then
call_level = args[1]
table.remove(args, 1)
end
local log_msg = level.label
if level.engine ~= dt_screen and call_level ~= 0 then
log_msg = log_msg .. dtutils_log.caller(call_level) .. " "
elseif log_msg:len() > 2 then
log_msg = log_msg .. " "
end
for i = 1,#args do
log_msg = log_msg .. tostring(args[i]) .. " "
end
level.engine(log_msg)
end
end
dtutils_log.libdoc.functions["log_level"] = {
Name = [[log_level]],
Synopsis = [[get or set the log level]],
Usage = [[local log = require "lib/log"
local result = log.log_level(...)
... - arguments - if none is supplied, then the current log level is returned as one of:
log.debug, log.info, log.warn, log.error, log.success. If one of log.debug, log.info, log.warn,
log.error, or log.success is supplied as the argument then the log level is set to that value. All
log levels greater than or equal in value will be enabled. Any levels of lesser value will be disabled.]],
Description = [[log_level gets and sets the logging level. When called with no arguments the current log level
is returned as one of log.debug, log.info, log.warn, log.error, or log.success. When called with one of log.debug,
log.info, log.warn, log.error or log.success then the log level is set. When setting the log level all levels
equal or greater are enabled and any of lesser value are disabled. See the example.]],
Return_Value = [[result - the log level, one of log.debug, log.info, log.warn, log.error or log.success]],
Limitations = [[]],
Example = [[Assume that the current log level is log.error. Calling log.log_level() will return log.error.
Calling log.log_level(log.info) will leave log.debug disabled, and enable log.info, log.warn, log.error and
log.success. log.info will be returned as the log_level.]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_log.log_level(...)
local levels = {"debug", "info", "warn", "error", "success"}
local args = {...}
local log_level = nil
if #args > 0 then
log_level = args[1]
if log_level == dtutils_log.critical or
log_level == dtutils_log.screen or
log_level == dtutils_log.always then
-- these aren't valid for setting levels
return nil
else
for _,v in ipairs(levels) do
if dtutils_log[v].level >= log_level.level then
dtutils_log[v].enabled = true
else
dtutils_log[v].enabled = false
end
end
end
else
for _,v in ipairs(levels) do
if dtutils_log[v].enabled == true then
log_level = dtutils_log[v]
end
end
end
return log_level
end
dtutils_log.libdoc.functions["engine"] = {
Name = [[engine]],
Synopsis = [[get and set the output engine]],
Usage = [[local log = require "lib/dtutils.log"
result = log.engine(level, ...)
level - table - the log level to get or set the engine for, one of log.debug, log.info, log.warn, log.error
log.success, log.always, log.screen, log.critical
... - function - the output function, one of dt.print, dt.print_error, dt.print_log, print
if not function is included, the current engine is returned for the specified log level]],
Description = [[engine returns the output engine for the specified log level if a second argument is not
supplied. If a function is supplied as the second argment, then the output engine for the specified log level
is set to that.]],
Return_Value = [[result - function - the current output engine]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_log.print_engine(level, ...)
local engines = {"dt_print", "dt_print_error", "dt_print_log", "print"}
local args = {...}
local cur_engine = ""
if #args == 0 then
cur_engine = level.engine
else
for _,v in ipairs(engines) do
if args[1] == v then
level.engine = args[1]
cur_engine = level.engine
end
end
end
return cur_engine
end
return dtutils_log

173
lib/dtutils/string.lua Normal file
View File

@@ -0,0 +1,173 @@
local dtutils_string = {}
dtutils_string.libdoc = {
Name = [[dtutils.string]],
Synopsis = [[a library of string utilities for use in darktable lua scripts]],
Usage = [[local ds = require "lib/dtutils.string"]],
Description = [[This library contains string manipulation routines to aid in building
darktable lua scripts.]],
Return_Value = [[du - library - the darktable lua string library]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[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/>.]],
Copyright = [[Copyright (c) 2016 Bill Ferguson <wpferguson@gmail.com>]],
functions = {}
}
dtutils_string.libdoc.functions["strip_accents"] = {
Name = [[strip_accents]],
Synopsis = [[strip accents from characters]],
Usage = [[local ds = require "lib/dtutils.string"
local result = ds.strip_accents(str)
str - string - the string with characters that need accents removed]],
Description = [[strip_accents removes accents from accented characters returning the
unaccented character.]],
Return_Value = [[result - string - the string containing unaccented characters]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[Copied from https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/]],
License = [[]],
Copyright = [[]],
}
function dtutils_string.strip_accents( str )
local tableAccents = {}
tableAccents["à"] = "a"
tableAccents["á"] = "a"
tableAccents["â"] = "a"
tableAccents["ã"] = "a"
tableAccents["ä"] = "a"
tableAccents["ç"] = "c"
tableAccents["è"] = "e"
tableAccents["é"] = "e"
tableAccents["ê"] = "e"
tableAccents["ë"] = "e"
tableAccents["ì"] = "i"
tableAccents["í"] = "i"
tableAccents["î"] = "i"
tableAccents["ï"] = "i"
tableAccents["ñ"] = "n"
tableAccents["ò"] = "o"
tableAccents["ó"] = "o"
tableAccents["ô"] = "o"
tableAccents["õ"] = "o"
tableAccents["ö"] = "o"
tableAccents["ù"] = "u"
tableAccents["ú"] = "u"
tableAccents["û"] = "u"
tableAccents["ü"] = "u"
tableAccents["ý"] = "y"
tableAccents["ÿ"] = "y"
tableAccents["À"] = "A"
tableAccents["Á"] = "A"
tableAccents["Â"] = "A"
tableAccents["Ã"] = "A"
tableAccents["Ä"] = "A"
tableAccents["Ç"] = "C"
tableAccents["È"] = "E"
tableAccents["É"] = "E"
tableAccents["Ê"] = "E"
tableAccents["Ë"] = "E"
tableAccents["Ì"] = "I"
tableAccents["Í"] = "I"
tableAccents["Î"] = "I"
tableAccents["Ï"] = "I"
tableAccents["Ñ"] = "N"
tableAccents["Ò"] = "O"
tableAccents["Ó"] = "O"
tableAccents["Ô"] = "O"
tableAccents["Õ"] = "O"
tableAccents["Ö"] = "O"
tableAccents["Ù"] = "U"
tableAccents["Ú"] = "U"
tableAccents["Û"] = "U"
tableAccents["Ü"] = "U"
tableAccents["Ý"] = "Y"
local normalizedString = ""
for strChar in string.gmatch(str, "([%z\1-\127\194-\244][\128-\191]*)") do
if tableAccents[strChar] ~= nil then
normalizedString = normalizedString..tableAccents[strChar]
else
normalizedString = normalizedString..strChar
end
end
return normalizedString
end
dtutils_string.libdoc.functions["escape_xml_characters"] = {
Name = [[escape_xml_characters]],
Synopsis = [[escape characters for xml documents]],
Usage = [[local ds = require "lib/dtutils.string"
local result = ds.escape_xml_characters(str)
str - string - the string that needs escaped]],
Description = [[escape_xml_characters provides the escape sequences for
"&", '"', "'", "<", and ">" with the corresponding "&amp;",
"&quot;", "&apos;", "&lt;", and "&gt;".]],
Return_Value = [[result - string - the string containing escapes for the xml characters]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents]],
License = [[]],
Copyright = [[]],
}
-- Keep &amp; first, otherwise it will double escape other characters
function dtutils_string.escape_xml_characters( str )
str = string.gsub(str,"&", "&amp;")
str = string.gsub(str,"\"", "&quot;")
str = string.gsub(str,"'", "&apos;")
str = string.gsub(str,"<", "&lt;")
str = string.gsub(str,">", "&gt;")
return str
end
dtutils_string.libdoc.functions["urlencode"] = {
Name = [[urlencode]],
Synopsis = [[encode a string in a websage manner]],
Usage = [[local ds = require "lib/dtutils.string"
local result = ds.urlencode(str)
str - string - the string that needs to be made websafe]],
Description = [[urlencode converts a string into a websafe version suitable for
use in a web browser.]],
Return_Value = [[result - string - a websafe string]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/]],
License = [[]],
Copyright = [[]],
}
function dtutils_string.urlencode(str)
if (str) then
str = string.gsub (str, "\n", "\r\n")
str = string.gsub (str, "([^%w ])", function () return string.format ("%%%02X", string.byte()) end)
str = string.gsub (str, " ", "+")
end
return str
end
return dtutils_string

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,28 @@
# 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.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-09-07 22:25-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Bill Ferguson <wpferguson@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.5.4\n"
"Language: de_DE\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2ngettext:1,2;"
"dngettext:2,3\n"
"X-Poedit-Basepath: .\n"
#: clear_GPS.lua:62
msgid "clear GPS data"
msgstr "GPS-Daten löschen"

View File

@@ -0,0 +1,75 @@
# Holger Klemm, 2016.
# Christian Kanzian <christian.kanzian@gmx.at>, 2016.
msgid ""
msgstr ""
"Project-Id-Version: Lua image path\n"
"POT-Creation-Date: 2016-01-07 20:33+0100\n"
"PO-Revision-Date: 2016-10-18 15:34+0200\n"
"Last-Translator: Christian Kanzian <christian.kanzian@gmx.at>\n"
"Language-Team: German <kde-i18n-de@kde.org>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Lokalize 1.5\n"
"X-Poedit-Basepath: .\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-KeywordsList: \n"
"X-Poedit-SearchPath-0: .\n"
#: copy_attach_detach_tags.lua:10
msgid "Image tags copied ..."
msgstr "Bild Tags kopiert ..."
#: copy_attach_detach_tags.lua:10
msgid "No tags to attached, please copy tags first."
msgstr "Es wurden keine Tags eingefügt. Bitte zuerst die Tags kopieren."
#: copy_attach_detach_tags.lua:10
msgid "Tags attached ..."
msgstr "Tags anhängen ..."
#: copy_attach_detach_tags.lua:10
msgid "Tags removed from image(s)."
msgstr "Tags von Bildern wurden gelöscht."
#: copy_attach_detach_tags.lua:10
msgid "Tags replaced"
msgstr "Tag ersetzen"
#: copy_attach_detach_tags.lua:10
msgid "multi copy tags"
msgstr "Tags kopieren"
#: copy_attach_detach_tags.lua:10
msgid "paste tags"
msgstr "Tags anhängen"
#: copy_attach_detach_tags.lua:10
msgid "replace tags"
msgstr "Tags ersetzen"
#: copy_attach_detach_tags.lua:10
msgid "remove all tags"
msgstr "Tags löschen"
#: copy_attach_detach_tags.lua:10
msgid "tag clipboard"
msgstr "Zwischenablage"
#: copy_attach_detach_tags.lua:10
msgid "copy tags from selected image(s)"
msgstr "Tags von ausgewählten Bildern kopieren"
#: copy_attach_detach_tags.lua:10
msgid "paste tags to selected image(s)"
msgstr "Tags an ausgewählte Bilder anhängen"
#: copy_attach_detach_tags.lua:10
msgid "remove tags from selected image(s)"
msgstr "Tags von ausgewählten Bildern löschen"
#: copy_attach_detach_tags.lua:10
msgid "replace tags from selected image(s)"
msgstr "Tags von ausgewählten Bildern ersetzen"

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,43 @@
# 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: gimp\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-04-13 23:50-0400\n"
"PO-Revision-Date: 2016-04-14 00:11-0500\n"
"Last-Translator: Bill Ferguson <wpferguson@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.5.4\n"
"Language: de_DE\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2ngettext:1,2;"
"dngettext:2,3\n"
"X-Poedit-Basepath: .\n"
#: gimp.lua:194
#, lua-format
msgid "Export Image %i/%i"
msgstr "Exportiere Bild %i/%i"
#: gimp.lua:242
msgid "Unable to move edited file into collection. Leaving it as %s"
msgstr "Die bearbeitete Datei kann nicht in die Sammlung aufgenommen werden. Bearbeitete Datei ist %s"
#: gimp.lua:251
msgid "GIMP not found"
msgstr "GIMP nicht gefunden"
#: gimp.lua:266
msgid "Launching GIMP..."
msgstr "Starten von GIMP"
#: gimp.lua:313
msgid "Edit with GIMP"
msgstr "Bearbeiten mit GIMP"

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,84 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Christian Kanzian <christian.kanzian@gmx.at>, 2017.
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-20 17:38+0100\n"
"PO-Revision-Date: 2017-02-20 17:50+0100\n"
"Last-Translator: Christian Kanzian <christian.kanzian@gmx.at>\n"
"Language-Team: German <kde-i18n-de@kde.org>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 1.5\n"
#: quicktag.lua:64
msgid "max. length of button labels"
msgstr "Max. Länge der Schaltflächen-Beschriftung"
#: quicktag.lua:65
msgid "may range from 15 to 60 - needs a restart"
msgstr "Bereich von 15 bis 60 möglich - Neustart erforderlich"
#: quicktag.lua:78
msgid "number of quicktag fields"
msgstr "Anzahl von quicktag Feldern"
#: quicktag.lua:79
msgid "may range from 2 to 20 - needs a restart"
msgstr "Bereich von 2 bis 20 möglich - Neustart erforderlich"
#: quicktag.lua:119
#, lua-format
msgid "quicktag %i is empty, please set a tag"
msgstr "quicktag %i ist leer - bitte Tag eingeben"
#: quicktag.lua:134
msgid "no images selected"
msgstr "keine Bilder ausgewählt"
#: quicktag.lua:144
#, lua-format
msgid "tag \"%s\" attached to %i image(s)"
msgstr "Tag \"%s\" an %i Bild(er) angehängt"
#: quicktag.lua:165
msgid "old quicktag"
msgstr "Alter quicktag"
#: quicktag.lua:166
msgid "select the quicktag to replace"
msgstr "Wähle den quicktag der ersetzt werden soll"
#: quicktag.lua:182 quicktag.lua:206
msgid "new quicktag"
msgstr "Neuer quicktag"
#: quicktag.lua:185
msgid "enter your tag here"
msgstr "Bitte Tag hier eingeben"
#: quicktag.lua:189
msgid "set quicktag"
msgstr "Setze Tag"
#: quicktag.lua:193
msgid "new quicktag is empty!"
msgstr "Neuer Tag ist leer!"
#: quicktag.lua:197
#, lua-format
msgid "quicktag \"%s\" replaced by \"%s\""
msgstr "quicktag \"%s\" ersetzt durch \"%s\" "
#: quicktag.lua:246
#, lua-format
msgid "quicktag %i"
msgstr "quicktag %i"

Binary file not shown.

View File

@@ -0,0 +1,27 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2017-09-14 12:18+0200\n"
"PO-Revision-Date: 2017-09-14 12:23+0200\n"
"Last-Translator: Jannis_V\n"
"Language-Team: \n"
"Language: de_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.7.1\n"
"X-Poedit-Basepath: ../../../contrib\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SearchPath-0: select_untagged.lua\n"
#: select_untagged.lua:38
msgid "select untagged images"
msgstr "Auswahl von Bildern ohne Tags"
#: select_untagged.lua:64
msgid "select untagged"
msgstr "Ohne Tags"
#: select_untagged.lua:64
msgid "select all images containing no tags or only tags added by darktable"
msgstr "Wähle alle Bilder der aktuellen Sammlung aus, die keine Tags oder nur automatisch durch darktable erzeugte Tags enthalten"

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"

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-10-03 14:58+0200\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Pascal Obry <pascal@obry.net>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.9\n"
#: calcDistance.lua:93
msgid "Calculate the distance from latitude and longitude in km"
msgstr "Calcule la distance en km entre les positions GPS de deux images"

View File

@@ -0,0 +1,27 @@
# 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-09-07 22:25-0400\n"
"PO-Revision-Date: 2016-10-03 14:55+0200\n"
"Last-Translator: Pascal Obry <pascal@obry.net>\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.9\n"
"Language: fr_FR\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2ngettext:1,2;"
"dngettext:2,3\n"
"X-Poedit-Basepath: .\n"
"Language-Team: \n"
#: clear_GPS.lua:62
msgid "clear GPS data"
msgstr "effacer données GPS"

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-10-03 15:05+0200\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Pascal Obry <pascal@obry.net>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.9\n"
#: geo_uri.lua:55
msgid "gnome-maps not found"
msgstr "gnome-maps non disponible"
#: geo_uri.lua:81
msgid "Command failed ..."
msgstr "La commande a échouée ..."
#: geo_uri.lua:88
msgid "Open Location in Gnome Maps"
msgstr "Ouvre la position dans Gnome Maps"

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: gimp\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-04-13 23:50-0400\n"
"PO-Revision-Date: 2016-10-03 15:06+0200\n"
"Last-Translator: Pascal Obry <pascal@obry.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.9\n"
"Language: fr_FR\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2ngettext:1,2;dngettext:2,3\n"
"X-Poedit-Basepath: .\n"
"Language-Team: \n"
#: gimp.lua:194
#, lua-format
msgid "Export Image %i/%i"
msgstr "Export image %i/%i"
#: gimp.lua:242
msgid "Unable to move edited file into collection. Leaving it as %s"
msgstr "Impossible de déplacer l'image modifiée dans la collection. L'image est %s"
#: gimp.lua:251
msgid "GIMP not found"
msgstr "GIMP n'est pas trouvé"
#: gimp.lua:266
msgid "Launching GIMP..."
msgstr "Lancement de GIMP..."
#: gimp.lua:313
msgid "Edit with GIMP"
msgstr "Éditer avec GIMP"

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-10-03 15:03+0200\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Pascal Obry <pascal@obry.net>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.9\n"
#: gps_select.lua:59
msgid "Select all images with GPS information"
msgstr "Sélectionner toutes les images avec des informations GPS"
#: gps_select.lua:60
msgid "Select all images without GPS information"
msgstr "Sélectionner toutes les images sans information GPS"

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-10-03 15:08+0200\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Pascal Obry <pascal@obry.net>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.9\n"
#: hugin.lua:73
msgid "hugin not found"
msgstr "hugin non disponible"
#: hugin.lua:97
msgid "Will try to stitch now"
msgstr "essayer de coller maintenant"
#: hugin.lua:102
msgid "Creating pto file"
msgstr "création du fichier pto"
#: hugin.lua:105
msgid "Running Assistent"
msgstr "lancement assistant"
#: hugin.lua:118
msgid "Command hugin failed ..."
msgstr "hugin a retourné une erreur"
#: hugin.lua:124
msgid "Hugin Panorama"
msgstr "panorama hugin"

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-10-03 15:15+0200\n"
"Last-Translator: Pascal Obry <pascal@obry.net>\n"
"Language-Team: \n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.9\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 "export kml/kmz"
msgid "Export Image %i/%i"
msgstr "export image %i/%i"
msgid "KML export: Open KML/KMZ file after export"
msgstr "export kml: ouvrir le fichier kml/kmz après l'export"
msgid "Opens the KML file after the export with the standard programm for KML files"
msgstr "ouvrir le fichier kml après l'export avec le lecteur kml par défaut"
msgid "KML export: Export directory"
msgstr "export kml : répertoire pour l'export"
msgid "A directory that will be used to export the KML/KMZ files"
msgstr "Le répertoire utiliser pour les fichiers d'export kml/kmz"
msgid "KML export: Connect images with path"
msgstr "export kml: connecter les images avec un chemin"
msgid "connect all images with a path"
msgstr "connecter toutes les images avec un chemin"
msgid "KML export: Create KMZ file"
msgstr "export kml: créer un fichier kmz"
msgid "Compress all imeges to one KMZ file"
msgstr "compresser les images en un fichier kmz"

View File

@@ -0,0 +1,70 @@
# 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: 2017-04-10 09:30+0200\n"
"PO-Revision-Date: 2017-04-10 09:48+0200\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Pascal Obry <pascal@obry.net>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.11\n"
#: pdf_slideshow.lua:55
msgid "pdflatex not found"
msgstr "pdflatex non trouvé"
#: pdf_slideshow.lua:63
msgid "a pdf viewer"
msgstr "lecteur pdf"
#: pdf_slideshow.lua:64
msgid "can be an absolute pathname or the tool may be in the PATH"
msgstr "peut être un chemin absolu où l'outil peut être dans le chemin par défaut"
#: pdf_slideshow.lua:68 pdf_slideshow.lua:95
msgid "slideshow title"
msgstr "titre du diaporama"
#: pdf_slideshow.lua:72
msgid "transition delay (s)"
msgstr "temporisation (s) entre diapositives"
#: pdf_slideshow.lua:83
msgid "include image title"
msgstr "inclus le titre de l'image"
#: pdf_slideshow.lua:85
msgid "whether to include the image title (if defined) into the slide"
msgstr "indique si le titre de l'image (si défini) doit être inclus dans la diapositive"
#: pdf_slideshow.lua:89
msgid "include image author"
msgstr "inclus l'auteur de l'image"
#: pdf_slideshow.lua:91
msgid "whether to include the image author (if defined) into the slide"
msgstr "indique si l'auteur de l'image (si défini) doit être inclus dans la diapositive"
#: pdf_slideshow.lua:167
msgid "pdf slideshow"
msgstr "diaporama pdf"
#: pdf_slideshow.lua:220
msgid "problem running pdflatex"
msgstr "impossible d'exécuter pdflatex"
#: pdf_slideshow.lua:221 pdf_slideshow.lua:231
msgid "problem running "
msgstr "impossible d'exécuter "
#: pdf_slideshow.lua:230
msgid "problem running pdf viewer"
msgstr "impossible d'exécuter le lecteur pdf"

Binary file not shown.

View File

@@ -0,0 +1,27 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2017-09-14 15:42+0200\n"
"PO-Revision-Date: 2017-09-14 15:52+0200\n"
"Last-Translator: Jannis_V\n"
"Language-Team: \n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.7.1\n"
"X-Poedit-Basepath: ../../../contrib\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Poedit-SearchPath-0: select_untagged.lua\n"
#: select_untagged.lua:38
msgid "select untagged images"
msgstr "sélection des images sans mots-clés"
#: select_untagged.lua:64
msgid "select untagged"
msgstr "sans mots-clés"
#: select_untagged.lua:64
msgid "select all images containing no tags or only tags added by darktable"
msgstr "sélection des images sans mots-clés ou seulement avec les mots-clés ajoutés par darktable"

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-10-03 15:10+0200\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Pascal Obry <pascal@obry.net>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.9\n"
#: slideshowMusic.lua:80
msgid "Slideshow background music file"
msgstr "musique pour le diaporama"
#: slideshowMusic.lua:84
msgid "Play slideshow background music"
msgstr "jouer la musique du diaporama"
#: slideshowMusic.lua:85
msgid "Plays music with rhythmbox if a slideshow starts"
msgstr "jouer la musique avec rhythmbox lorsque le diaporama démarre"

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},{4,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},{4,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

@@ -1,93 +0,0 @@
--[[
This file is part of darktable,
copyright (c) 2014 Jérémy Rosen
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/>.
]]
--[[
DEBUG HELPERS
A collection of helper functions to help debugging lua scripts.
require it as
dhelpers = require "official/debug-helpers"
Each function is documented in its own header
]]
local dt = require "darktable"
local io = require "io"
local table = require "table"
require "darktable.debug"
local M = {} -- The actual content of the module
--[[
A function which prints its name and its parameters
* name : the name of the tracepoint
* ... : anything, will be dumped using dt.debug
]]
function M.tracepoint(name,...)
print("***** "..name.." ****")
params = {...}
print(dt.debug.dump(params,"parameters"))
return ...;
end
--[[
A function that returns a tracepoint function with the given name
This is mainly used to debug callbacks,
register_event(event, dhelpers.new_tracepoint("hit callback"))
will will print the following each time the callback is called
**** hit callback ****
<all the callback's parameters dumped>
]]
function M.new_tracepoint(name)
return function(...) return M.tracepoint(name,...) end
end
--[[
Wrapper around debug.dump, will directly print to stdout,
same calling covention
]]
function M.dprint(...)
print(dt.debug.dump(...))
end
--[[
sets dt.debug.known to shorten all images to a single line
if you don't need to debug the content of images, this will avoid them flooding your logs
]]
function M.terse_dump()
for _,v in ipairs(dt.database) do
dt.debug.known[v] = tostring(v)
end
end
return M
-- vim: shiftwidth=2 expandtab tabstop=2 cindent
-- kate: tab-indents: off; indent-width 2; replace-tabs on; remove-trailing-space on;

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},{4,0,0})
dt.preferences.register("delete_long_tags", "length", "integer",
"maximum length of tags to keep",

168
official/enfuse.lua Normal file
View File

@@ -0,0 +1,168 @@
--[[
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 tonemapped image 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"
local df = require "lib/dtutils.file"
require "official/yield"
local gettext = dt.gettext
dt.configuration.check_version(...,{3,0,0},{4,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("enfuse",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("enfuse", msgid)
end
-- add a new lib
-- is enfuse installed?
local enfuse_installed = df.check_if_bin_exists("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 dt.control.execute( command) > 0 then
dt.print("enfuse failed, see terminal output for details")
os.remove(response_file)
return
end
-- remove the response file
os.remove(response_file)
-- import resulting tiff
local image = dt.database.import(output_image)
-- tell the user that everything worked
dt.print("enfuse was successful, resulting image 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,14 @@ 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})
require "official/yield"
dt.configuration.check_version(...,{2,1,0},{3,0,0},{4,0,0})
dt.preferences.register("generate_image_txt",
"enabled",
@@ -97,7 +99,7 @@ dt.register_event("mouse-over-image-changed", function(event, img)
local command = command_setting:gsub("%$%(FILE_NAME%)", '"'..img_filename..'"')..' > "'..txt_filename..'"'
-- finally, run it
coroutine.yield("RUN_COMMAND", command)
dt.control.execute( command)
end
)

View File

@@ -28,9 +28,8 @@ 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},{4,0,0})
local main_label = dt.new_widget("label"){selectable = true, ellipsize = "middle", halign = "start"}
@@ -59,6 +58,6 @@ dt.register_lib("image_path_no_ui","Selected Images path",true,false,{
);
dt.register_event("mouse-over-image-changed",reset_widget);
]]
--
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua

View File

@@ -1,6 +1,6 @@
--[[
This file is part of darktable,
copyright (c) 2015 Tobias Ellinghaus
copyright (c) 2015-2016 Tobias Ellinghaus & Christian Mandel
darktable is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -50,6 +50,11 @@ dt.register_import_filter("prefer raw over jpeg", function(event, images)
local current_base = ""
local jpg_indices = {}
local other_format_found = false
-- add dummy image to force processing for the last image
local last_index
table.insert(images, "")
for i, img in ipairs(images) do
local extension = img:match("[^.]*$"):upper()
local base = img:match("^.*[.]")
@@ -73,7 +78,14 @@ dt.register_import_filter("prefer raw over jpeg", function(event, images)
other_format_found = true
end
last_index = i
end
-- remove dummy image from list (just to make sure, it works even with keeping
-- the dummy but that may break in the future), table.remove(images) does not
-- work reliable because it can fail for sparse tables
images[last_index] = nil
end)
-- vim: shiftwidth=2 expandtab tabstop=2 cindent

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},{4,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 = {}

View File

@@ -1,6 +1,7 @@
--[[
This file is part of darktable,
copyright (c) 2015 Jérémy Rosen & Pascal Obry
edited 2016 Tejovanth N
darktable is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,10 +29,14 @@ USAGE
This plugin will add a new exporter that will allow you to generate the pdf file
Plugin allows you to choose how many thumbnails you need per row
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,0})
require "official/yield"
dt.configuration.check_version(...,{2,0,0},{3,0,0},{4,0,0})
dt.preferences.register
("selection_to_pdf","Open with","string",
@@ -40,20 +45,29 @@ dt.preferences.register
"xdg-open")
local title_widget = dt.new_widget("entry") {
placeholder="Title"
placeholder="Title"
}
local no_of_thumbs_widget = dt.new_widget("slider")
{
label = "Thumbs per Line",
soft_min = 1, -- The soft minimum value for the slider, the slider can't go beyond this point
soft_max = 10, -- The soft maximum value for the slider, the slider can't go beyond this point
hard_min = 1, -- The hard minimum value for the slider, the user can't manually enter a value beyond this point
hard_max = 10, -- The hard maximum value for the slider, the user can't manually enter a value beyond this point
value = 4 -- The current value of the slider
}
local widget = dt.new_widget("box") {
orientation=horizontal,
dt.new_widget("label"){label = "Title:"},
title_widget
orientation=horizontal,
dt.new_widget("label"){label = "Title:"},
title_widget,
dt.new_widget("label"){label = "Thumbnails per row:"},
no_of_thumbs_widget
}
local ending = [[
\end{document}
]]
local thumbs_per_line=4;
local width = 1/thumbs_per_line-0.01
local filename =dt.configuration.tmp_dir.."/pdfout.tex"
@@ -93,23 +107,27 @@ dt.register_storage("export_pdf","Export thumbnails to pdf",
local my_title = title_widget.text
if my_title == "" then
my_title = "Title"
end
local preamble = [[
\documentclass[a4paper,10pt]{article}
\usepackage{graphicx}
\pagestyle{empty}
\parindent0pt
\usepackage{geometry}
\geometry{a4paper,left=5mm,right=5mm, top=5mm, bottom=5mm}
\begin{document}
{\Large\bfseries ]]..my_title..[[} \\
\bigskip\bigskip
]]
end
local thumbs_per_line = no_of_thumbs_widget.value
thumbs_per_line = tonumber(thumbs_per_line)
width = (1/thumbs_per_line) - 0.01
local errmsg
local latexfile
latexfile,errmsg=io.open(filename,"w")
if not latexfile then
local preamble = [[
\documentclass[a4paper,10pt]{article}
\usepackage{graphicx}
\pagestyle{empty}
\parindent0pt
\usepackage{geometry}
\geometry{a4paper,left=5mm,right=5mm, top=5mm, bottom=5mm}
\begin{document}
{\Large\bfseries ]]..my_title..[[} \\
\bigskip\bigskip
]]
local errmsg
local latexfile
latexfile,errmsg=io.open(filename,"w")
if not latexfile then
error(errmsg)
end
my_write(latexfile,preamble)
@@ -128,7 +146,7 @@ dt.register_storage("export_pdf","Export thumbnails to pdf",
local dir=string.gsub(filename, "(.*/)(.*)", "%1")
local locfile=string.gsub(filename, "(.*/)(.*)", "%2")
local command = "pdflatex -halt-on-error -output-directory "..dir.." "..locfile
local result = coroutine.yield("RUN_COMMAND",command)
local result = dt.control.execute(command)
if result ~= 0 then
dt.print("Problem running pdflatex") -- this one is probably usefull to the user
error("Problem running "..command)
@@ -138,7 +156,7 @@ dt.register_storage("export_pdf","Export thumbnails to pdf",
local pdffile=string.gsub(filename, ".tex", ".pdf")
command = dt.preferences.read("selection_to_pdf","Open with","string")
command = command.." "..pdffile
local result = coroutine.yield("RUN_COMMAND",command)
local result = dt.control.execute(command)
if result ~= 0 then
dt.print("Problem running pdf viewer") -- this one is probably usefull to the user
error("Problem running "..command)

42
official/yield.lua Normal file
View File

@@ -0,0 +1,42 @@
--[[
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 yield compatibility script
USAGE
* require this script from your main Lua file in the first line
]]
local dt = require "darktable"
local yield_orig = coroutine.yield
if (dt.configuration.api_version_major < 4) then
dt.control = {}
dt.control.execute = function(command)
yield_orig("RUN_COMMAND", command)
end
dt.control.read = function(command)
yield_orig("FILE_READABLE", command)
end
dt.control.sleep = function(command)
yield_orig("WAIT_MS", command)
end
end
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
-- kate: hl Lua;

View File

@@ -0,0 +1,76 @@
--[[
get_lib_manpages.lua - retrieve the included library documentation and output it as man pages
Copyright (c) 2016, Bill Ferguson
]]
local dt = require "darktable"
local du = require "lib/dtutils"
local df = require "lib/dtutils.file"
local log = require "lib/dtutils.log"
local libname = nil
dt.configuration.check_version(...,{3,0,0})
local keys = {"Name", "Synopsis", "Usage", "Description", "Return_Value", "Limitations",
"Example", "See_Also", "Reference", "License", "Copyright"}
local function output_man(d)
local name = d["Name"]
if not libname then
libname = name
end
local fname = "/tmp/" .. name .. ".3"
local mf = io.open(fname, "w")
if mf then
mf:write(".TH " .. string.upper(name) .. " 3 \"\" \"\" \"Darktable " .. libname .. " functions\"\n")
for _,section in ipairs(keys) do
if d[section]:len() > 0 then
mf:write(".SH " .. string.upper(string.gsub(section, "_", " ")) .. "\n")
mf:write(d[section] .. "\n")
end
end
mf:close()
if df.check_if_bin_exists("groff") then
if df.check_if_bin_exists("ps2pdf") then
os.execute("groff -man " .. fname .. " | ps2pdf - " .. fname .. ".pdf")
else
log.msg(log.error, "Missing ps2pdf. Can't generate pdf man pages.")
end
else
log.msg(log.error, "Missing groff. Can't generate pdf man pages.")
end
else
log.msg(log.error, "Can't open file " .. fname .. "for writing")
end
end
-- find the libraries
local output = io.popen("cd "..dt.configuration.config_dir.."/lua/lib ;find . -name \\*.lua -print | sort")
-- loop through the libraries
for line in output:lines() do
line = string.gsub(line, "/", ".")
local lib_name = line:sub(3,-5)
if lib_name:len() > 2 then
lib_name = "lib/" .. lib_name
local lib = require(lib_name)
-- print the documentation for the library
if lib.libdoc then
local doc = lib.libdoc
if doc then
output_man(doc)
for _,fdoc in pairs(doc.functions) do
-- print the documentation for each of the functions
output_man(fdoc)
end
end
end
end
libname = nil
end

49
tools/get_libdoc.lua Normal file
View File

@@ -0,0 +1,49 @@
--[[
get_libdoc.lua - retrieve the included library documentation and output it
Copyright (c) 2016, Bill Ferguson
]]
local dt = require "darktable"
dt.configuration.check_version(...,{3,0,0})
local keys = {"Name", "Synopsis", "Usage", "Description", "Return_Value", "Limitations",
"Example", "See_Also", "Reference", "License", "Copyright"}
local function output_doc(d)
for _,section in ipairs(keys) do
if d[section]:len() > 0 then
print(string.upper(string.gsub(section, "_", " ")))
print("\t" .. d[section] .. "\n")
end
end
print("\f")
end
-- find the libraries
local output = io.popen("cd "..dt.configuration.config_dir.."/lua/lib ;find . -name \\*.lua -print | sort")
-- loop through the libraries
for line in output:lines() do
line = string.gsub(line, "/", ".")
local lib_name = line:sub(3,-5)
if lib_name:len() > 2 then
lib_name = "lib/" .. lib_name
local lib = require(lib_name)
-- print the documentation for the library
if lib.libdoc then
local doc = lib.libdoc
output_doc(doc)
for _,fdoc in pairs(doc.functions) do
-- print the documentation for each of the functions
output_doc(fdoc)
end
end
end
end