src/main/resources/userguide/credits.md now lists every shipped library with its license (read from the dependencies' POMs), the recognition models and the map and place data. CreditsView, opened from the ? in Settings, renders it through the new MarkdownPage helper (per-language loading, links opened in the browser), which the search help popup now shares, and the release's distrib step copies it to distrib/CREDITS.md in the same commit as the release note. MarkdownToBBCode learns [text](url) links, inside bold too. URLs are quoted in the generated BBCode: AtlantaFX's parser reads a tag ending in "/]" as self-closing, so a URL with a trailing slash broke the whole page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011xpLSeYKKHX6o16jzYLgZv
128 lines
7.2 KiB
Markdown
128 lines
7.2 KiB
Markdown
# 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 <dir>` 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=<dir>` | 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 <dir> [--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-<version>.md` from the Conventional Commits since the previous
|
||
release (grouped by type, then scope);
|
||
4. creates GitHub release `v<version>` 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<version>` 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.
|