# Pholio Pholio is a desktop application for managing large photo and video libraries, built for volume and speed. - **Libraries** — point Pholio at one or more folders; it indexes every photo and video into its own embedded database, one per library, and keeps it in sync as files change. - **Gallery** — a justified, date-grouped grid that stays fluid on tens of thousands of files, with a full-screen photo view and an info panel for the selected file. - **Metadata** — reads EXIF, IPTC and XMP (RAW, HEIF and video included), edits capture date, location and rating, and writes them back to the file itself. - **Places** — offline reverse geocoding from a bundled GeoNames dataset, plus optional online place search (LocationIQ). - **People** — local face and animal detection and clustering (ONNX Runtime, nothing leaves the machine); naming a person makes their photos searchable. - **Search** — free text, rating (`r:4+`), people (`p:Alice`) and folder (`path:Holidays/2024`) filters, combined freely — see the in-app guide (the `?` next to the search bar) or [`src/main/resources/userguide`](src/main/resources/userguide/search-syntax.md). - **Command line** — the same binary runs headless: `pholio scan ` reports the media files a folder holds. Built with Java 26, JavaFX (AtlantaFX, GemsFX, Ikonli), Spring Boot, H2, PicoCLI and metadata-extractor. ## Build and run Requirements: a JDK 26 that bundles JavaFX (e.g. Azul Zulu FX 26). Maven comes with the wrapper. ```bash ./mvnw verify # compile, test, build target/pholio.jar java -jar target/pholio.jar --ui # desktop interface java -jar target/pholio.jar scan ~/Pictures [-R] # headless scan; -R: do not recurse java -jar target/pholio.jar -V # version java -jar target/pholio.jar # usage, same as --help ``` Pholio runs headless by default: only `--ui` opens the window, so every launcher meant to show one (IDE run configuration, installers) passes it. Any argument Pholio does not recognise is read as a command. ## Development ### JVM options (`-D…`) | Option | Default | Effect | |---|---|---| | `--enable-native-access=javafx.graphics,ALL-UNNAMED` | — | Not a property, but recommended: silences the restricted-method warnings from JavaFX, JNA and the macOS process naming. | | `-Dpholio.home=` | OS user dirs | Puts configuration, data (libraries) and cache under one root — keeps a test run out of your real profile. | | `-Dpholio.skipTheme=true` | `false` | Starts without the AtlantaFX theme, on JavaFX's default styling (to tell a theme issue from a layout one). | | `-Dpholio.modalBackend=dialogPane` | `stage` | Shows dialogs in GemsFX's embedded `DialogPane` instead of a separate window. | | `-Djavafx.enablePreview=true` | set by the app | Required for the JavaFX `HeaderBar` preview API; `GuiBootstrap` sets it unless you pass a value. | | `-Dprism.dirtyopts=false` | set by the app | Works around a stale-paint bug in Prism; `GuiBootstrap` sets it unless you pass a value. | ### Application settings (`--pholio.…=` arguments) Spring Boot settings from `application.yaml`, overridable on the command line (they bypass PicoCLI, so they never read as a command): | Setting | Default | Effect | |---|---|---| | `--pholio.dev-tools.enabled=` | `true` | F12 opens the DevToolsFX scene-graph inspector. | | `--pholio.library.routing.enabled=` | `true` | Routes the database to the library picked in the header; `false` pins `spring.datasource.url`. | | `--pholio.pools.cpu=` | `0` | Threads for decoding work (thumbnails, hashes); `0` = cores − 1. | | `--pholio.pools.scheduler=` | `2` | Scheduler threads. | | `--pholio.window.default-width=` / `default-height=` | `1440` / `900` | First-run window size. | | `--logging.level.org.icroco.pholio=` | `DEBUG` | Log level of Pholio's own code. | ### What makes the jar big `target/pholio.jar` is ~223 MB, 89 libraries. Almost all of it is recognition: the application's own code is under 1 MB. | Size (in the jar) | Entry | Why | |---:|---|---| | 130.5 MB | `onnxruntime-1.21.1.jar` | ONNX Runtime with native libraries for 5 platforms (~590 MB unpacked, win-x64 alone 351 MB). The installers keep only their own platform's — see below. | | 34.2 MB | `models/recognition/face_recognition_sface_2021dec.onnx` | Face embedding model (SFace). | | 10.2 MB | `geodata/cities1000.txt.gz` | GeoNames seed for offline reverse geocoding, imported into H2 on first run. | | 4.4 MB | `byte-buddy` | Runtime agent behind `@FxThread`. | | 3.2 MB | `models/recognition/yolox_nano.onnx` | Animal detection model. | | 3.0 MB | `gemsfx` | UI controls. | | 2.6 MB | `h2` | Embedded database. | | ≤ 2 MB each | Spring, Jackson, JNA, AtlantaFX themes, … | The remaining ~30 MB. | Deliberately left out of the jar (`pom.xml`): Lombok and Jilt (compile-time only), the OpenJFX jars (every target runtime already has JavaFX as modules), and the JUnit/AssertJ that `devtoolsfx` wrongly declares at compile scope. The native installers go further (`distrib/packaging/common.sh`): only the target platform's ONNX Runtime natives (130 MB → ~24 MB for macOS arm64) and a jlink'ed runtime (~64 MB) — the macOS arm64 `.dmg` is ~157 MB. To re-measure: `unzip -v target/pholio.jar | sort -k3 -n -r | head -20` (third column: compressed size). ### Credits `src/main/resources/userguide/credits.md` is the single list of credits — shipped libraries with their licenses, recognition models, map and place data. The application shows it from the `?` in Settings (`CreditsView`), and each release copies it to `distrib/CREDITS.md`. Add a library or data source there when you add one to the application. ### Useful scripts - `python3 tools/icons/make-macos-icon.py` — regenerates the macOS icon, `icon.png` and `pholio.icns` from `src/main/resources/images/spo-1024x1024.png`. - `python3 tools/demo/fetch-commons-photos.py [--quality] [--places Paris Kyoto …] [--per-place N]` — downloads a demo library for screenshots from Wikimedia Commons: freely licensed JPEG originals whose own EXIF has a capture date and GPS, one folder per city, with a `CREDITS.md` (CC BY / BY-SA require the credit wherever the photos are shown). `--quality` keeps only Commons' Quality/Featured pictures — nicer, fewer, slower. `--help` for every option. ## Release ```bash ./mvnw -Prelease validate ``` Needs a clean working tree (or `-Drelease.allowDirty=true`) and a logged-in GitHub CLI (`gh auth login`). In order, it: 1. bumps the version to `YYYY.M.N` — same month as the current version: `N + 1`, otherwise build 0 of the current month; 2. runs a fresh `./mvnw verify`; 3. writes `distrib/release_note/release-note-.md` from the Conventional Commits since the previous release (grouped by type, then scope); 4. creates GitHub release `v` in [Imag-In/Pholio](https://github.com/Imag-In/Pholio) with the jar, its SHA-256 and the release note; 5. commits `pom.xml` and tags `v` locally; 6. commits the release note in `distrib/` and pushes it. The source repository itself is never pushed to GitHub: `Imag-In/Pholio` only receives release assets and the `distrib/` worktree (an orphan branch), and a local `pre-push` hook enforces it. See `AGENTS.md` for the details, and keep commit messages in the Conventional Commits format so they reach the release note.