diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-30 18:26:49 +0100 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-30 18:26:49 +0100 |
| commit | 8553d49a0801d07e21ca9b4113b51181e6c7a72b (patch) | |
| tree | 7accb511f9950bc0e2a7743259d398640004ea57 /docs/superpowers | |
| download | upscale-qt-8553d49a0801d07e21ca9b4113b51181e6c7a72b.tar.gz upscale-qt-8553d49a0801d07e21ca9b4113b51181e6c7a72b.zip | |
Initial commit: upscale-qt image upscaler GUI
PyQt6 app that upscales an image with an ESRGAN model through sd-cli,
compares before and after with a slider wipe, and saves the result or
overwrites the original. This commit holds the docs, license and design spec.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'docs/superpowers')
| -rw-r--r-- | docs/superpowers/specs/2026-10-30-upscale-qt-design.md | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-10-30-upscale-qt-design.md b/docs/superpowers/specs/2026-10-30-upscale-qt-design.md new file mode 100644 index 0000000..8db80a5 --- /dev/null +++ b/docs/superpowers/specs/2026-10-30-upscale-qt-design.md @@ -0,0 +1,81 @@ +# upscale-qt design + +## Goal + +Pick an image, preview it, upscale it with an ESRGAN model through `sd-cli`, +check the result against the original, then save it as a new file or +overwrite the original. + +## Stack + +Single file `upscale-qt`, Python 3 + PyQt6, no other dependencies. External +binaries: `sd-cli` (required), `llama-mtmd-cli` (optional, for suggestions). + +## Window + +- Toolbar: Open, model dropdown, Upscale, Save As, Overwrite, Settings. +- Center: compare view (one custom widget). +- Status bar: current activity, suggestion result, last stderr line. + +Save As and Overwrite are disabled until an upscaled result exists. Upscale is +disabled while a process runs or no model is selected. + +## Compare view + +- No result yet: shows the original only. +- With result: the original is scaled to the result's size and drawn left of + a vertical divider, the result right of it. +- Drag near the divider moves it. Drag elsewhere pans. Wheel zooms around + the cursor. Double-click resets to fit-to-window. +- Before and after share one transform, so the same pixels line up. + +## Jobs + +Internally a list of jobs, each: source path, chosen model, result path +(temp file) or None, state (idle, suggesting, upscaling, done, failed). The +UI shows only the current job. Opening an image replaces the list with one +job. Batch mode later adds UI over the same list. + +## Flow + +1. Open via file dialog or `argv[1]`. Image shown at once. +2. If imajev is configured, run + `llama-mtmd-cli -m <model> --mmproj <mmproj> --image <src> -p <prompt>`, + the prompt listing the upscaler filenames and asking for exactly one back. + The answer is matched to a filename (exact filename, then stem, then + case-insensitive substring); a match preselects the dropdown and the + status bar says "imajev suggests X". No match or failure: dropdown + unchanged, status says so. The user can always change the dropdown. +3. Upscale runs + `sd-cli -M upscale --upscale-model <dir/model> -i <src> -o <tmp>.png`. + The temp file lives in a `QTemporaryDir` for the app's lifetime. +4. On exit code 0 with a readable output, the result loads into the compare + view. Otherwise a message box shows the last stderr lines. +5. Save As: file dialog, format from the chosen extension. + Overwrite: confirmation dialog naming the file and new size, then save in + the original's format to `<file>.part` and rename over the original, so a + failed write never leaves a truncated original. + +## Settings + +`QSettings`: upscalers dir, imajev model path, imajev mmproj path, last open +dir. Defaults point at the maintainer's model folders and are editable in a +small Settings dialog. Missing upscalers dir or empty model list: Upscale +disabled with a tooltip. Missing imajev files or binary: suggestion silently +skipped. + +## Errors + +- Binary not found or crash: message box with the error. +- Non-zero exit: message box with the stderr tail. +- Unreadable input image: message box, job not created. + +## Testing + +`test_upscale_qt.py` with plain asserts for the non-GUI functions, at least +the answer-to-filename matcher. GUI checked by hand, or headless with +`QT_QPA_PLATFORM=offscreen`. + +## Out of scope for now + +Batch UI, choice of output scale, backup copies of overwritten files. |
