fix(viewer): load tall images past Qt's allocation limit; always display full resolution #134

Merged
ValleyGeek merged 3 commits from 0.2.1/issue-117-tall-image-not-rendering into main 2026-06-24 01:47:07 +00:00
Member

Summary

  • Fixes #117: a 1569x42895 image (and any image needing >256 MB at 4 bytes/pixel) silently failed to load because QImage(path) uses Qt's default 256 MB QImageReader allocation limit before any downscaling runs. The viewer fell back to showing the previously loaded image, and the Duplicates Multi view showed a blank canvas, with no error surfaced (isNull() returns True without raising). Now loads via QImageReader directly with the allocation limit raised to 1024 MB.
  • While in this code: the viewer was pre-downscaling every image to a 2048px max edge before display, so zooming in past 100% upscaled that reduced copy and looked blurry even when the source file had far more detail. ViewerImageLoader/enqueue_viewer_image_load now support max_edge=None to skip that downscale; the existing fit-to-window transform already handles shrinking the full-resolution image for the default view. All four viewer load sites (initial load, neighbor prefetch, post-rotation reload) now request full resolution. The duplicate-comparison multi-pane grid (dupe_multi_grid.py) keeps its prior capped default unchanged, since it's a separate, more memory-sensitive view.
  • Version bumped 0.2.1 → 0.2.2 (compiled inputs changed); CHANGELOG and USER_GUIDE updated.

Test plan

  • New regression test tests/test_viewer_image_loader.py reproduces the exact failing dimensions (1569x42895) and confirms it now loads and downscales correctly
  • New test confirms max_edge=None returns true full resolution instead of the capped size
  • Full suite: pytest — 540 passed, 1 skipped
  • ruff check / ruff format --check clean
  • ./scripts/smoke-ui-exit.sh (offscreen) — clean Qt teardown, no shutdown errors
  • ./scripts/check-version-bump.sh passes
  • Manual verification: synthetic large test images load and report correct full-resolution dimensions through ViewerImageLoader

🤖 Generated with Claude Code

## Summary - Fixes #117: a 1569x42895 image (and any image needing >256 MB at 4 bytes/pixel) silently failed to load because `QImage(path)` uses Qt's default 256 MB `QImageReader` allocation limit before any downscaling runs. The viewer fell back to showing the previously loaded image, and the Duplicates Multi view showed a blank canvas, with no error surfaced (`isNull()` returns `True` without raising). Now loads via `QImageReader` directly with the allocation limit raised to 1024 MB. - While in this code: the viewer was pre-downscaling every image to a 2048px max edge before display, so zooming in past 100% upscaled that reduced copy and looked blurry even when the source file had far more detail. `ViewerImageLoader`/`enqueue_viewer_image_load` now support `max_edge=None` to skip that downscale; the existing fit-to-window transform already handles shrinking the full-resolution image for the default view. All four viewer load sites (initial load, neighbor prefetch, post-rotation reload) now request full resolution. The duplicate-comparison multi-pane grid (`dupe_multi_grid.py`) keeps its prior capped default unchanged, since it's a separate, more memory-sensitive view. - Version bumped 0.2.1 → 0.2.2 (compiled inputs changed); CHANGELOG and USER_GUIDE updated. ## Test plan - [x] New regression test `tests/test_viewer_image_loader.py` reproduces the exact failing dimensions (1569x42895) and confirms it now loads and downscales correctly - [x] New test confirms `max_edge=None` returns true full resolution instead of the capped size - [x] Full suite: `pytest` — 540 passed, 1 skipped - [x] `ruff check` / `ruff format --check` clean - [x] `./scripts/smoke-ui-exit.sh` (offscreen) — clean Qt teardown, no shutdown errors - [x] `./scripts/check-version-bump.sh` passes - [x] Manual verification: synthetic large test images load and report correct full-resolution dimensions through `ViewerImageLoader` 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(viewer): raise Qt image allocation limit so tall/large images load (#117)
All checks were successful
CI / lint (push) Successful in 16s
CI / test (push) Successful in 2m39s
CI / windows-exe (push) Successful in 10m48s
CI / build-windows-exe (push) Successful in 0s
CI / appimage (push) Successful in 15m6s
CI / build-appimage (push) Successful in 0s
2161f49bc5
QImage(path) implicitly uses QImageReader's default 256 MB allocation
limit before any of our downscaling runs. A 1569x42895 image needs
~256.7 MB at 4 bytes/pixel, just over that limit, so Qt silently
returns a null image — the viewer then keeps showing the previously
loaded image and the duplicate multi-view shows a blank canvas, with
no error surfaced since isNull() returns True without raising.

Load via QImageReader directly and raise the allocation limit to
1024 MB (VIEWER_IMAGE_ALLOCATION_LIMIT_MB) before reading, so the
existing post-load downscale to VIEWER_MAX_DISPLAY_EDGE still applies
normally.

Threading notes: ViewerImageLoader.run() still executes entirely on
the worker thread and only emits plain QImage/str data via
ViewerImageSignals; no widget/model access was added.

VERSION: 0.2.1-bug.117 (dev suffix for issue #117, Kind/Bug).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(viewer): always display full-resolution images (#117)
All checks were successful
CI / lint (push) Successful in 14s
CI / test (push) Successful in 2m43s
CI / windows-exe (push) Successful in 9m53s
CI / build-windows-exe (push) Successful in 0s
CI / appimage (push) Successful in 15m33s
CI / build-appimage (push) Successful in 0s
80e22ea62b
The image viewer pre-downscaled every loaded image to a 2048px max
edge before display, then relied on the view's fit-to-window scale to
shrink it further for on-screen display. Zooming in past 100% then
upscaled that already-reduced pixel data, producing visibly blurry
detail even though the original file had far more resolution.

ViewerImageLoader/enqueue_viewer_image_load now accept max_edge=None
to skip the pixel-data downscale entirely; the existing fit-to-window
transform in image_viewer.py already scales the full-resolution
QPixmap down for the default view, so this only changes what's
available when zooming in. All four viewer load sites (initial load,
neighbor prefetch, post-rotation reload) now pass max_edge=None.
core/dupe_multi_grid.py keeps the prior capped default unchanged,
since that multi-pane comparison view is a separate, more
memory-sensitive use of the same loader.

Threading notes: no change to the threading contract — the worker
still does all image decode/scale work off the main thread and emits
only a QImage via ViewerImageSignals.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docs: PR-prep — bump to 0.2.2 for issue #117 viewer fixes
All checks were successful
CI / lint (push) Successful in 15s
CI / test (push) Successful in 2m44s
CI / windows-exe (push) Successful in 11m32s
CI / build-windows-exe (push) Successful in 0s
CI / appimage (push) Successful in 19m15s
CI / build-appimage (push) Successful in 0s
d9c3139b9d
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ValleyGeek deleted branch 0.2.1/issue-117-tall-image-not-rendering 2026-06-24 01:47:07 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ai-collab/bulk-image-organizer!134
No description provided.