Skip to content

Commit a582f02

Browse files
authored
Merge pull request darktable-org#231 from Mark-64/RL_out_sharp
Add RL output sharpening script
2 parents 3f5cf06 + ebd33c4 commit a582f02

File tree

2 files changed

+213
-0
lines changed

2 files changed

+213
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ pdf_slideshow|No|LM|Export images to a PDF slideshow
5757
quicktag|Yes|LMW|Create shortcuts for quickly applying tags
5858
rate_group|Yes|LMW|Apply or remove a star rating from grouped images
5959
rename-tags|Yes|LMW|Change a tag name
60+
RL_out_sharp|No|LW|Output sharpening using GMic (Richardson-Lucy algorithm)
6061
select_untagged|Yes|LMW|Enable selection of untagged images
6162
slideshowMusic|No|L|Play music during a slideshow
6263
transfer_hierarchy|Yes|LMW|Image move/copy preserving directory hierarchy

contrib/RL_out_sharp.lua

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
--[[
2+
3+
DESCRIPTION
4+
RL_out_sharp.lua - Richardson-Lucy output sharpening using GMic
5+
6+
This script provides a new target storage "RL output sharpen".
7+
Images exported will be sharpened using GMic (RL deblur algorithm)
8+
9+
USAGE
10+
* require this script from main lua file
11+
* in lua preferences, select the GMic cli executable
12+
* from "export selected", choose "RL output sharpen"
13+
* configure output folder
14+
* configure RL parameters with sliders
15+
* configure temp files format and quality, jpg 8bpp (good quality)
16+
and tif 16bpp (best quality) are supported
17+
* configure other export options (size, etc.)
18+
* export, images will be first exported in the temp format, then sharpened
19+
* sharpened images will be stored in jpg format in the output folder
20+
21+
EXAMPLE
22+
set sigma = 0.7, iterations = 10, jpeg output quality = 95,
23+
to correct blur due to image resize for web usage
24+
25+
CAVEATS
26+
MAC compatibility not tested
27+
Although Darktable can handle file names containing spaces, GMic cli cannot,
28+
so if you want to use this script please make sure that your images do not
29+
have spaces in the file name and path
30+
31+
BUGS, COMMENTS, SUGGESTIONS
32+
send to Marco Carrarini, [email protected]
33+
34+
CHANGES
35+
* 20200308 - initial version
36+
37+
]]
38+
39+
local dt = require "darktable"
40+
local du = require "lib/dtutils"
41+
local df = require "lib/dtutils.file"
42+
local dtsys = require "lib/dtutils.system"
43+
44+
-- module name
45+
local MODULE_NAME = "RL_out_sharp"
46+
47+
-- check API version
48+
du.check_min_api_version("5.0.0", MODULE_NAME)
49+
50+
-- OS compatibility
51+
local PS = dt.configuration.running_os == "windows" and "\\" or "/"
52+
53+
-- translation
54+
local gettext = dt.gettext
55+
gettext.bindtextdomain(MODULE_NAME, dt.configuration.config_dir..PS.."lua"..PS.."locale"..PS)
56+
local function _(msgid)
57+
return gettext.dgettext(MODULE_NAME, msgid)
58+
end
59+
60+
-- initialize module preferences
61+
if not dt.preferences.read(MODULE_NAME, "initialized", "bool") then
62+
dt.preferences.write(MODULE_NAME, "sigma", "string", "0.7")
63+
dt.preferences.write(MODULE_NAME, "iterations", "string", "10")
64+
dt.preferences.write(MODULE_NAME, "jpg_quality", "string", "95")
65+
dt.preferences.write(MODULE_NAME, "initialized", "bool", true)
66+
end
67+
68+
69+
-- setup export ---------------------------------------------------------------
70+
local function setup_export(storage, img_format, image_table, high_quality, extra_data)
71+
-- set 16bpp if format is tif
72+
if img_format.extension == "tif" then
73+
img_format.bpp = 16
74+
end
75+
end
76+
77+
78+
-- temp export formats: jpg and tif are supported -----------------------------
79+
local function supported(storage, img_format)
80+
return (img_format.extension == "jpg") or (img_format.extension == "tif")
81+
end
82+
83+
84+
-- export and sharpen images --------------------------------------------------
85+
local function export2RL(storage, image_table, extra_data)
86+
87+
local temp_name, new_name, run_cmd, result
88+
local input_file, output_file, options
89+
90+
-- read parameters
91+
local gmic = dt.preferences.read(MODULE_NAME, "gmic_exe", "string")
92+
if gmic == "" then
93+
dt.print(_("GMic executable not configured"))
94+
return
95+
end
96+
gmic = df.sanitize_filename(gmic)
97+
local output_folder = output_folder_selector.value
98+
local sigma_str = string.gsub(string.format("%.2f", sigma_slider.value), ",", ".")
99+
local iterations_str = string.format("%.0f", iterations_slider.value)
100+
local jpg_quality_str = string.format("%.0f", jpg_quality_slider.value)
101+
102+
-- save preferences
103+
dt.preferences.write(MODULE_NAME, "sigma", "string", sigma_str)
104+
dt.preferences.write(MODULE_NAME, "iterations", "string", iterations_str)
105+
dt.preferences.write(MODULE_NAME, "jpg_quality", "string", jpg_quality_str)
106+
107+
local gmic_operation = " -deblur_richardsonlucy "..sigma_str..","..iterations_str..",1"
108+
109+
local i = 0
110+
for image, temp_name in pairs(image_table) do
111+
112+
i = i + 1
113+
dt.print(_("sharpening image ")..i.." ...")
114+
-- create unique filename
115+
new_name = output_folder..PS..df.get_basename(temp_name)..".jpg"
116+
new_name = df.create_unique_filename(new_name)
117+
118+
-- build the GMic command string
119+
input_file = df.sanitize_filename(temp_name)
120+
output_file = df.sanitize_filename(new_name)
121+
options = " cut 0,255 round "
122+
if df.get_filetype(temp_name) == "tif" then options = " -/ 256"..options end
123+
124+
run_cmd = gmic.." "..input_file..gmic_operation..options.."o "..output_file..","..jpg_quality_str
125+
126+
result = dtsys.external_command(run_cmd)
127+
if result ~= 0 then
128+
dt.print(_("sharpening error"))
129+
return
130+
end
131+
132+
-- delete temp image
133+
os.remove(temp_name)
134+
135+
end
136+
137+
dt.print(_("finished exporting"))
138+
end
139+
140+
-- new widgets ----------------------------------------------------------------
141+
142+
output_folder_selector = dt.new_widget("file_chooser_button"){
143+
title = _("select output folder"),
144+
tooltip = _("select output folder"),
145+
value = dt.preferences.read(MODULE_NAME, "output_folder", "string"),
146+
is_directory = true,
147+
changed_callback = function(self)
148+
dt.preferences.write(MODULE_NAME, "output_folder", "string", self.value)
149+
end
150+
}
151+
152+
sigma_slider = dt.new_widget("slider"){
153+
label = _("sigma"),
154+
tooltip = _("controls the width of the blur that's applied"),
155+
soft_min = 0.3,
156+
soft_max = 2.0,
157+
hard_min = 0.0,
158+
hard_max = 3.0,
159+
step = 0.1,
160+
digits = 2,
161+
value = 1.0
162+
}
163+
164+
iterations_slider = dt.new_widget("slider"){
165+
label = _("iterations"),
166+
tooltip = _("increase for better sharpening, but slower"),
167+
soft_min = 0,
168+
soft_max = 100,
169+
hard_min = 0,
170+
hard_max = 100,
171+
step = 5,
172+
digits = 0,
173+
value = 10.0
174+
}
175+
176+
jpg_quality_slider = dt.new_widget("slider"){
177+
label = _("output jpg quality"),
178+
tooltip = _("quality of the output jpg file"),
179+
soft_min = 70,
180+
soft_max = 100,
181+
hard_min = 70,
182+
hard_max = 100,
183+
step = 2,
184+
digits = 0,
185+
value = 95.0
186+
}
187+
188+
local storage_widget = dt.new_widget("box"){
189+
orientation = "vertical",
190+
output_folder_selector,
191+
sigma_slider,
192+
iterations_slider,
193+
jpg_quality_slider
194+
}
195+
196+
-- register new storage -------------------------------------------------------
197+
dt.register_storage("exp2RL", _("RL output sharpen"), nil, export2RL, supported, save_preferences, storage_widget)
198+
199+
-- register the new preferences -----------------------------------------------
200+
dt.preferences.register(MODULE_NAME, "gmic_exe", "file",
201+
_("executable for GMic CLI"),
202+
_("select executable for GMic command line version") , "")
203+
204+
-- set sliders to the last used value at startup ------------------------------
205+
sigma_slider.value = dt.preferences.read(MODULE_NAME, "sigma", "float")
206+
iterations_slider.value = dt.preferences.read(MODULE_NAME, "iterations", "float")
207+
jpg_quality_slider.value = dt.preferences.read(MODULE_NAME, "jpg_quality", "float")
208+
209+
-- end of script --------------------------------------------------------------
210+
211+
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
212+
-- kate: hl Lua;

0 commit comments

Comments
 (0)