- Python 96.9%
- Shell 1.8%
- PowerShell 1.3%
|
All checks were successful
## Summary Implements issue #147: crop and horizontal mirror tools in the Grid image viewer, released as **0.4.0**. - Dynamic toolbar when opening the viewer from Grid (thumbnail slider hidden): **Rotate 90°**, mirror (`< >`), **Crop**, aspect presets, **↻** rotate crop selection, **Accept** - Interactive crop overlay (corner/edge handles, dimmed exterior, directional cursors, free or fixed aspect) - Enter/Accept applies crop with backup under workspace `.originals/` (skipped by scans); session undo/redo restores or re-applies and refreshes thumbnails/viewer - Settings: default crop aspect; optional purge of `.originals` on workspace close/exit - Docs: USER_GUIDE, DESIGN, TECHNICAL_OUTLINE, DR-033, CHANGELOG for 0.4.0 ## Test plan - [x] `pytest tests/test_viewer_crop_mirror.py` (21 tests) - [x] `ruff check` / `ruff format --check` - [x] `./scripts/check-version-bump.sh origin/main` - [ ] Manual: open image from Grid → mirror, crop free/fixed aspect, Accept, undo/redo, Esc cancel - [ ] Manual: crop with border near image edge; aspect **None** keeps selection; purge `.originals` setting Closes #147 Co-authored-by: Grok <grok@devstation.vglan> Reviewed-on: #150 |
||
|---|---|---|
| .forgejo/ISSUE_TEMPLATE | ||
| .github/workflows | ||
| .grok/agents | ||
| docs | ||
| resources | ||
| scripts | ||
| src/bulk_image_organizer | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| DEVELOPMENT.md | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
| VERSION | ||
Bulk Image Organizer
A fast, keyboard-centric desktop application for power users who need to review, tag, deduplicate, and organize large batches of images—1,000 to 10,000 or more—in a single directory tree.
Everything stays on your machine. Tags and staging for deletion replace destructive edits until you explicitly confirm. Duplicate detection is ad-hoc—you run it when you need it. The filesystem is always the source of truth; a portable cache database beside your images keeps thumbnails and metadata fast.
Supported formats: JPEG, PNG, WEBP, TIFF, GIF, BMP (HEIC/HEIF not supported). Subsets can be enabled/disabled globally in Settings → Image Types; disabled formats are ignored by scans.
Platforms: Windows 11 and Linux (tested on Linux Mint)
Why Bulk Image Organizer?
Large photo dumps, wallpaper collections, and download folders are painful to triage in a file manager. Bulk Image Organizer is built for that workflow:
- Non-destructive by default — Tag images or stage them for deletion; nothing hits the recycle bin until you confirm.
- Responsive at scale — Background scanning and lazy thumbnails keep the UI usable while tens of thousands of files are indexed.
- Tag-driven organization — Filter, sort, bulk-assign, and eventually sort into folders by tag.
- Ad-hoc duplicate tools — Exact and perceptual duplicate scans on demand.
- Keyboard-first — Customizable shortcuts across grid, viewer, duplicates, and trash workbenches.
Features
Grid workbench
- Recursive directory scan with progressive thumbnail loading
- Adjustable thumbnail size (display scale and cache resolution in Settings)
- Multi-select, sorting (filename, date, size, resolution, tag priority), and rich tag filtering (AND/OR, untagged-only, hide staged deletions, horizontal/vertical orientation)
- Tag badges on thumbnails; prominent red overlay on images staged for deletion
- Session undo/redo for tag assignment and deletion staging (
Ctrl+Z/Ctrl+Y)
Image viewer
- Full-resolution zoom, pan, fit/fill, and 1:1 modes
- Carousel and filmstrip navigation (global preferences)
- Rotation saved to the image file after a short debounce
- From Grid: horizontal mirror and interactive crop (aspect presets, undoable; originals backed up under
.originals/) - Quality metadata overlay to compare similar shots
- Background preloading of adjacent images for smooth prev/next
Tagging
- Unlimited custom tags per workspace, with fourteen preset colors (including black and white) or a custom picker
- New Tag and Bulk Create in the right column — bulk mode accepts one name per line with per-line colors or inline
{#rrggbb}hex suffixes - Single-click toggles tags on the current selection; creation requires an open directory
- Stage images for deletion to review them later in the Trash workbench
- Sort into Folders… moves images that have exactly one non-duplicate tag into subfolders named after that tag
Duplicates workbench
Duplicate detection is ad-hoc. When you run a scan:
- Exact duplicates — Full-file cryptographic hash (
F-DUPE_#tags) - Visual duplicates — Perceptual hash with configurable similarity (
V-DUPE_#tags)
Review groups in a comparison grid or single-image viewer. Keep Best stages lower-quality copies for deletion and advances to the next group. Duplicate membership is ordinary tags—you can rename, recolor, or remove them like any other tag.
Trash workbench
- Review everything staged for deletion without grid overlays
- Confirm Delete sends displayed rows to the system recycle bin via
send2trash - Filter-scoped Clear Deleted Flag and Unset Applied Tags
Settings & help
- Dark and light themes
- Customizable global keyboard shortcuts
- Startup, tag-filter defaults, thumbnail cache, duplicate defaults, viewer modes, and advanced tunables
- Bundled user guide and About dialog inside the app
Data & privacy
- All processing is local; no network features
- Local folders:
.bulk_image_organizer.dblives beside your images and travels with the folder - Network folders: Thumbnails stay on your computer; tags and metadata can optionally sync to a lightweight database on the share when you close the workspace
Quick start
Run a packaged build
Linux — Extract a release tarball, then run the bulk_image_organizer binary inside.
Windows — Run bulk_image_organizer.exe. On first launch, Nuitka unpacks into %LOCALAPPDATA%\ValleyGeek\Bulk Image Organizer\.
Run from source
git clone <repository-url>
cd bulk-image-organizer
python -m venv .venv
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
pip install -e ".[dev]"
python -m bulk_image_organizer
On Linux, ./scripts/launch-linux.sh sets up the virtual environment, installs dependencies if needed, and configures Qt platform plugins.
Basic workflow
- Open a directory (
Ctrl+O) — The app scans in the background and fills the grid as thumbnails are ready. - Tag and filter — Create tags with New Tag, Bulk Create, or Create from Sub-directories in the right column; use Tag Filter on the sub-toolbar to narrow the grid.
- Review in the viewer — Double-click or press Enter; use arrow keys, carousel, or filmstrip to move through images.
- Find duplicates (optional) — Switch to Duplicates, run an exact or visual scan, review groups, and use Keep Best.
- Clean up — Stage rejects for deletion, review them in Trash, then confirm delete to send files to the recycle bin.
- Organize — Use Sort into Folders… for images with a single tag.
Default shortcuts and full workbench details are in the in-app Help guide (resources/help/USER_GUIDE.md).
Building releases
Linux — AppImage (BulkImageOrganizer_{version}.AppImage) or standalone folder under build/linux/:
./scripts/build-linux-appimage.sh
./scripts/build-linux.sh
Windows — single executable in an output directory (BulkImageOrganizer_{version}.exe):
scripts\manual-build-windows.ps1 -OutputPath C:\builds
CI runs lint and tests first, then parallel Linux AppImage and Windows release jobs. main publishes versioned Forgejo releases (v{version}) with both .AppImage and .exe artifacts; development branches publish dev-{branch-slug} releases with branch-named artifacts that are pruned when the branch is deleted. Versioning policy: docs/VERSIONING.md. See DEVELOPMENT.md for local validation, test layout, and contributor workflow.
Security scanning
Nuitka-compiled binaries (especially Windows .exe files) are sometimes flagged by antivirus software as false positives due to how compiled Python code is structured. Both release CI jobs scan their build artifact before publishing it, so you can verify a release independently of that risk:
- ClamAV scans the artifact after it's built; a detection fails the build, so a published release was never flagged by ClamAV's signature database at build time.
- Static analysis runs
checksec/readelf/fileon the Linux AppImage and an Authenticode signature check + PE section/entropy dump (viapefile) on the Windows executable. This is informational only and never fails the build. - VirusTotal (optional — only runs when the
VT_API_KEYsecret is configured) uploads the artifact for a multi-engine scan and links the report. Also informational only.
Each job's summary (visible on the workflow run page) includes the artifact's SHA256 hash and the scan results — compare the hash against what you downloaded, and check the summary before trusting a build if you're unsure. The scanning logic lives in scripts/security-scan-artifact.py and scripts/virustotal-scan.py.
Development
ruff check .
ruff format --check .
pytest
Architecture, design decisions, and the implementation history live in docs/DESIGN.md, docs/TECHNICAL_OUTLINE.md, and docs/DECISIONS.md.
License
MIT License. You may use, modify, and distribute this software freely. Redistributions and derivative works must include the original copyright notice and license text, attributing Bulk Image Organizer to its authors.