Load source images in the background with a progress window

Decoding a batch of photographs took seconds on the main thread, so the
window froze with no sign of what was happening. loadImages now takes an
optional LoadProgress (per-file callback plus a cancel flag) and hands files
out from a shared cursor, so one large file cannot stall the queue behind it.

The GUI decodes off the main thread and shows a progress window with the
count, the current file and a Cancel button; it only appears if the batch is
still running after 250 ms. Headless mode keeps a "reading n/total" line on
stderr when it is attached to a terminal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
hans
2026-09-18 14:39:07 +02:00
co-authored by Claude Opus 5
parent 925a719da0
commit 7e98357070
7 changed files with 317 additions and 15 deletions
+14 -1
View File
@@ -1,7 +1,9 @@
#pragma once
#include <atomic>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <string>
#include <vector>
@@ -49,8 +51,19 @@ struct LoadFailure {
std::string message;
};
// Lets a caller follow a long batch decode and abort it. Both members are
// touched from the decoding threads, so `onFile` must be thread-safe and must
// not block: the GUI only bumps a counter from it and wakes the main thread.
struct LoadProgress {
std::function<void(std::size_t done, std::size_t total, const std::string& path)> onFile;
std::atomic<bool>* cancel = nullptr;
};
// Loads every path, collecting rather than throwing on individual failures.
// When `progress->cancel` is set the remaining paths are skipped, so the result
// is short and should be discarded rather than used.
std::vector<Image> loadImages(const std::vector<std::string>& paths,
std::vector<LoadFailure>& failures);
std::vector<LoadFailure>& failures,
const LoadProgress* progress = nullptr);
} // namespace effector