-
Notifications
You must be signed in to change notification settings - Fork 0
Home
A 64-bit Python CLI (and desktop app) that batch-converts Kodak DC200/DC210
.fpx (FlashPix) photographs into archival TIFFs and shareable JPEGs, carrying
every recoverable property into standard EXIF/XMP/IPTC plus a complete
raw-property JSON sidecar.
It exists because nothing modern opens .fpx, and every off-the-shelf
converter either renders black, needs a 32-bit environment, watermarks the
output, or silently discards the metadata — and on a collection from this era
the metadata is what carries the timeline.
| Page | What it holds |
|---|---|
| Usage | Step-by-step walkthrough of every command, its flags, and the artifacts a run produces |
| Troubleshooting | Common symptoms, their real cause, and what to do |
| Release history | Per-release notes and what each one is safe to be trusted for |
These live alongside the code rather than in the wiki, because they change with it:
| File | What it holds |
|---|---|
README.md |
What it is, install, quick start, current status |
ARCHITECTURE.md |
Design rationale and the correctness rules a contributor can break |
docs/FORMAT.md |
What a .fpx file actually is: container, tile table, colour spaces, viewing transform, embedded thumbnail |
docs/DATES.md |
Why your photographs may have no capture date, and how to give the tool one it will accept |
docs/TESTING.md |
The four testing tiers, the two oracles, and the known gaps in fixture coverage |
docs/PROJECT-HISTORY.md |
The milestone record and per-release verification log. History; not needed to use the tool |
CHANGELOG.md |
Keep-a-Changelog history |
CONTRIBUTING.md |
How to work on it |
tests/fixtures/README.md |
The person-free test fixture set: what it covers, the screening rule, and the holes |
Each of these was measured against all 1,265 files of the reference archive before any decoder code was written. Several of them refuted the assumption the project started with.
-
There is no capture date in this kind of corpus. The FlashPix
capture-date property is absent from every file. The only timestamp is an
import-batch stamp, and on the reference archive it disagreed with
folder-name ground truth on 7 of 9 dated albums — once by a whole year. Dates
come from folder names plus an owner review pass, not from the file. See
Dates and
docs/DATES.md. - The stored timestamps are local wall-clock time, not UTC. Treating them as UTC and converting would move a fifth of the corpus onto the wrong calendar day.
- The colour space is NIF RGB, not PhotoYCC — on 1,261 of 1,265 files. The colour-science work everyone budgets for mostly is not there. But the handful of PhotoYCC files are exactly where the worst defect in this project's history lived, so small is not the same as safe.
-
Pillow's
FpxImagePlugincannot be the pixel path. It failed on 1,224 of 1,265 files and hard-crashed the interpreter on two of them. The custom decoder is primary; the plugin is an out-of-process oracle only. - Viewing transforms are real and are applied. 22 files carry a genuine 90° counter-clockwise rotation. 70 resolve to a crop (56 axis-aligned, 14 rotated-and-cropped). The archival TIFF preserves the full frame while the shareable JPEG applies the crop — both are worth keeping. And the output tree follows source folder names, not dates, so the album organisation matches what a person named rather than what a timestamp says.
- The version lives only in
VERSION. CI refuses a tag that disagrees, and a test refuses a second source of truth. - CI owns releases: push a
vX.Y.Ztag and nothing else. Never create a release or edit a tag by hand. - This project publishes no container image and talks to no external system. It reads local files and writes local files, and needs no credentials of any kind.
- No personal image, sidecar, or source file is ever committed.
tests/fixtures/is the only exception, and only for images confirmed to contain no people. A test enforces that on every push.