Bulk RAW → JPG converter for photogrammetry shoots. A small Tkinter GUI that
drives darktable-cli over a folder tree, applies a darktable style, and
mirrors the folder structure into a JPG output root.
Built for the Opéra Paris — Maquettes & Décors pipeline
(MAQ###/N###/RAW/*.NEF → .../JPG/*.jpg), but the source/destination/style/
extension are all configurable, so it works for any darktable style preset.
- Pick darktable-cli, source RAW root, and destination JPG root from the GUI.
- Apply any darktable style preset (
--style-overwrite). - Configurable RAW extension (NEF, CR2, ARW, RAF, …) and JPEG quality.
- Mirror mode — rebuilds the source tree under the destination, swapping the
RAWfolder forJPG(src/MAQ/N001/RAW/*.NEF → dst/MAQ/N001/JPG/*.jpg). - Resume tracking — finished files are recorded in
dt_progress.txt; re-running skips work already done. - Test 1 file button to validate the style/paths on a single image first.
- Scan source to count RAW files per top-level folder before committing.
- Live progress bar, colour-coded log, and a Stop button (halts after the current file).
- Windows
- darktable installed (uses
darktable-cli.exe, default pathC:\Program Files\darktable\bin\darktable-cli.exe). - The style preset you want must already exist in darktable.
- Python 3.9+ (Tkinter ships with the standard Windows installer).
python dt_batch_GUI.pyor with uv:
uv run dt_batch_GUI.pyrun.bat is a convenience launcher.
- Confirm the darktable-cli path.
- Set Source (RAW root) and Destination (JPG root).
- Set the style, RAW extension, and JPEG quality.
- Click Test 1 file — you want
exit code: 0and✓ JPG created. - Click Run. Stop any time; resume by running again.
These are the things that quietly break batch conversion on Windows. The script already handles all of them — documented here so future-you doesn't re-debug:
database is locked—darktable-clishares one SQLite library and will fail to commit exports if the darktable GUI is open or a stale lock exists. Fixed by running each file with--core --library :memory:(isolated in-memory catalog). The default config dir is kept so styles indata.dbstill load.- Output path must use forward slashes — darktable's disk-export module
(glib) eats single backslashes, producing a garbage filename and
[imageio_storage_disk] could not export to file. The script converts the output path to/. (The old workaround was doubling backslashes\\.) - Pass an explicit output filename, not a directory — a trailing-slash
directory makes darktable build a malformed
...\/$(FILE_NAME).jpgpattern that silently writes nothing while still returning exit code 0. - Don't trust the exit code alone — darktable can return
0and write nothing. Success is keyed off a JPG actually appearing in the temp dir.
If a "Windows cannot find …\Temp\tmp…" Explorer popup appears, it's harmless: it just means you have a File Explorer window open on the temp folder that the script created and then deleted. Close that window.
| File | Purpose |
|---|---|
dt_batch_GUI.py |
The GUI application. |
dt_progress.txt |
Resume log of completed files (safe to delete / use Clear progress.txt). |
run.bat |
Launcher. |
assets/ |
Screenshot(s) used in this README. |
