diff --git a/AGENTS.md b/AGENTS.md index 804368a..a3624ea 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,12 +14,15 @@ Vannini). Runs on Linux over Wayland or X11. This repo is a **local fork** of [macrodev8/ScanSlicer](https://github.com/macrodev8/ScanSlicer) (upstream owner inactive). License: GNU GPL v3 (must be preserved). Attribution: keep upstream -credit and the "inspired by PhotoSlicer" note. +credit and the "inspired by PhotoSlicer" note; `pyproject.toml` lists both the +fork maintainer and the upstream author, and `README.md` states the fork +relationship and the changes made. ## Goals of this fork 1. Fix the mirrored-export orientation bug and add an explicit left/right - orientation workflow (implemented, see below). This is the primary patch. + orientation workflow. Implemented, tested in the GUI, and committed — see + "The orientation fix" below. This was the primary patch. 2. Keep the app usable on the maintainer's own photo scans; afterwards only minimal maintenance is expected. 3. Push to the maintainer's Forgejo instance at `code.dgerdesmann.de` (no @@ -114,6 +117,12 @@ uv run scanslicer /path/to/scans # or: python -m scanslicer - Dependencies (from `pyproject.toml`): PySide6, opencv-python-headless, numpy. - Python >= 3.10; dev env is Python 3.12 in `.venv`. +Dependency / supply-chain decisions (deliberate — keep them): +- `opencv-python-headless` is intentional: the app uses no OpenCV GUI/highgui. +- Pillow was removed (it was unused). Don't re-add without a concrete need. +- The AppImage build exports hashes from `uv.lock` and installs with + `pip install --require-hashes`. + ### AppImage build: Docker context gotcha The maintainer's Docker points at Docker Desktop (`desktop-linux` context). Its diff --git a/README.md b/README.md index ba1281d..53a0e22 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,27 @@ -# ScanSlicer +# ScanSlicer (fork) -ScanSlicer is a desktop Qt application for extracting multiple photos from a flatbed scan image. It detects photo regions, lets you correct boxes manually, then saves perspective-corrected crops. +ScanSlicer is a desktop Qt application (Python/PySide6) that detects multiple +photos in a flatbed scan image, lets you correct each box manually, and exports +perspective-corrected crops. It runs on Linux desktops over Wayland or X11. -Inspired by [PhotoSlicer](https://github.com/francescovannini/photoslicer) by Francesco Vannini. +This is a **fork of [macrodev8/ScanSlicer](https://github.com/macrodev8/ScanSlicer)**, +whose original maintainer is inactive. It is kept in a working state for the +maintainer's own photo scans. -This repository keeps GNU GPL v3 licensing for compatibility with that upstream work. +Upstream credit: the original is inspired by +[PhotoSlicer](https://github.com/francescovannini/photoslicer) by Francesco +Vannini. This repository keeps the GNU GPL v3 license for compatibility with +that upstream work. + +## Changes from upstream + +- Fixed mirrored slice exports: added an explicit left/right orientation + workflow with a **Swap L/R** button and color-coded left/right corners and + edges. +- Orientation corrections now persist through "squarize" and "reset rotation" + (previously they were silently overwritten). +- Hardened dependencies: switched to `opencv-python-headless`, removed the + unused Pillow dependency, and made the AppImage build verify package hashes. ## What It Does @@ -13,136 +30,99 @@ This repository keeps GNU GPL v3 licensing for compatibility with that upstream - Provides manual correction tools (corner drag, edge drag, rotate, move, add/remove box). - Saves only locked boxes, each as a perspective-corrected output image. - Includes auto-tuning with feedback learning from your prior saved results. -- Works on Linux desktops over Wayland or X11. ## Requirements -- Python `>=3.10` -- Linux desktop session (for example KDE Plasma) over Wayland or X11 -- System libraries required by Qt/OpenCV (see `Dockerfile` for a known-good package set) +- Python >= 3.10 +- A Linux desktop session over Wayland or X11 +- System libraries required by Qt/OpenCV (see `Dockerfile` for a known-good set) -Project dependencies (from `pyproject.toml`): - -- `PySide6` -- `opencv-python-headless` -- `numpy` +Project dependencies (from `pyproject.toml`): `PySide6`, `opencv-python-headless`, `numpy`. ## Quick Start -### Run with `uv` +### Run from source (uv) ```bash uv sync --frozen -uv run scanslicer -``` - -Open a specific input directory at launch: - -```bash uv run scanslicer /path/to/scans ``` -Choose backend explicitly: +Open with no startup directory, or select the display backend explicitly: ```bash +uv run scanslicer uv run scanslicer --backend wayland uv run scanslicer --backend x11 ``` -### Run with Python directly +You can also run the installed package directly with `python -m scanslicer`. + +### Run the AppImage (preferred) + +Build the AppImage and run it: ```bash -python -m scanslicer +bash packaging/appimage/build-appimage-docker.sh +./appimage/dist/ScanSlicer--x86_64.AppImage ``` +See [docs/appimage.md](docs/appimage.md) for full details, including the local +build path and a Docker Desktop caveat. + ### CLI ```text scanslicer [path] [--backend {auto,wayland,x11}] ``` -- `path`: optional startup directory containing scan images. -- `--backend`: display backend selection. `auto` is default. - ## Typical Workflow 1. Open an input directory. -2. Verify output directory (defaults to the opened input directory). -3. Click `Detect` (or use auto detection triggered on image load). -4. Adjust boxes as needed. -5. Lock boxes you want to export (or use lock-all). -6. Choose save format (`jpg` or `png`) and quality/compression. +2. Verify the output directory (defaults to the opened input directory). +3. Run detection (`Detect`), or rely on automatic detection on image load. +4. Adjust boxes as needed (drag corners/edges, rotate, move, add/remove). +5. Lock the boxes to export (or use lock-all). +6. Choose the save format (`jpg` or `png`) and quality/compression. 7. Click `Save images`. Only locked boxes are exported. -## Runtime Behavior +## Configuration -- Detection and auto-tune run in background worker tasks (`QThreadPool`) so UI stays responsive. -- Status events are written to a session log file and reflected in the status bar. -- Detection results are cached (normal and filter preview) to avoid unnecessary re-processing when toggling filter preview. +ScanSlicer stores its defaults, presets, auto-tune feedback, and a session +status log under `~/.config/scanslicer/` (or `$XDG_CONFIG_HOME/scanslicer/`). +All paths can be overridden via `SCANSLICER_*_PATH` environment variables. See +[docs/runtime-config.md](docs/runtime-config.md). -## Data and Config Files +## Docker -Persistence paths depend on how ScanSlicer is run. - -Non-container runs (`uv run scanslicer`, `python -m scanslicer`): - -- Defaults: `~/.config/scanslicer/defaults.json` -- Named presets: `~/.config/scanslicer/presets.json` -- Auto-tune feedback: `~/.config/scanslicer/autotune-feedback.json` -- Session status log: `~/.config/scanslicer/status.log` - -If `XDG_CONFIG_HOME` is set, these are stored under `$XDG_CONFIG_HOME/scanslicer/` instead. - -Container runs: - -- When running in container and `/work` exists, these are stored under `/work/.scanslicer/`. -- In the provided `docker-compose.yml`, the current repository is mounted as `/work`, so these files appear in `.scanslicer/` inside the project directory on the host. - -Environment variable overrides: - -- `SCANSLICER_DEFAULTS_PATH` -- `SCANSLICER_PRESETS_PATH` -- `SCANSLICER_FEEDBACK_PATH` -- `SCANSLICER_STATUS_LOG_PATH` - -## Docker Compose - -The repo includes a GUI-oriented compose setup for Linux desktop use: +A GUI-oriented compose setup is provided for Linux desktop use: ```bash docker compose up --build ``` -See `.env.example` and `docker-compose.yml` for required host UID/GID and Wayland/XDG settings. - -## AppImage Build - -AppImage build scripts and recipe are in `packaging/appimage/`. - -- Local: `bash packaging/appimage/build-appimage.sh` -- Dockerized build: `bash packaging/appimage/build-appimage-docker.sh` - -Detailed instructions: `docs/appimage.md`. +See `.env.example` and `docker-compose.yml` for host UID/GID and Wayland/XDG +settings. ## Documentation -- `docs/README.md` - documentation index -- `docs/user-guide.md` - end-user operation guide -- `docs/architecture.md` - code architecture and execution flow -- `docs/parameters.md` - full detection parameter reference -- `docs/autotune.md` - auto-tune and feedback internals -- `docs/runtime-config.md` - backend/environment and persistence paths -- `docs/appimage.md` - AppImage packaging details -- `docs/development.md` - contributor-focused architecture/workflow notes +See [docs/README.md](docs/README.md) for an index and recommended reading order +(end-user guide, parameters, auto-tune, architecture, runtime config, +AppImage, development). -## Repository Layout +## Repository ```text -scanslicer/ - Application source (UI, controllers, canvas, detection) -packaging/appimage/ - AppImage recipe and build scripts -Dockerfile - Runtime image -docker-compose.yml - GUI container runtime wiring -pyproject.toml - Python package metadata and dependencies +scanslicer/ application source (package) +packaging/appimage/ AppImage recipe and build scripts +docs/ end-user and developer documentation +Dockerfile / docker-compose.yml container runtime +pyproject.toml / uv.lock package metadata and pinned dependencies ``` + +## License + +GNU GPL v3 — see [LICENSE](LICENSE). See +[THIRD_PARTY_NOTICES](THIRD_PARTY_NOTICES) for bundled third-party components. diff --git a/pyproject.toml b/pyproject.toml index 0d76e60..db445a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,8 @@ readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.10" license = { text = "GPLv3" } authors = [ - { name = "macrodev", email = "macron.dev@proton.me" } + { name = "dan", email = "dan@noreply.code.dgerdesmann.de" }, + { name = "macrodev", email = "macron.dev@proton.me" }, ] classifiers = [ "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",