# PhotoRevive (CLI prototype) PhotoRevive is a working command-line prototype for the "Pro" tier of the Media Rescue Lab product cluster. It is a CLI-native, scriptable tool for professionals with large offline media libraries spanning many directories (a photographer's entire archive across years of folders, for example): point it at multiple directories at once and it walks all of them, classifies every candidate image file as OK, CORRUPT, or UNKNOWN, and prints one consolidated report across the whole batch. It also implements a real, narrow, best-effort repair for one specific, common corruption pattern: a JPEG file that is missing its trailing End-Of-Image (EOI) marker because it was truncated (an interrupted download or copy that got cut off), but whose actual image data is otherwise intact. This differs from the sibling MediaRescue tool, which is a browser-based app where a person drags in photos from ONE folder at a time and sees which ones fail to decode, interactively, and does not attempt any repair — it is detection-only. PhotoRevive covers the same detection technique (attempt to decode; on failure, check whether the file's header even looks like the format its extension claims) but does it as a batch CLI job across many directories at once, and adds a real repair attempt on top of detection. Be clear about scope: the repair capability here covers exactly one well-understood truncation pattern (missing JPEG EOI marker). It is not general JPEG or video repair, it does not recover deleted files, it does not reconstruct fragmented or partially-overwritten video, and it has no camera/memory-card profile support. Those all require raw disk access and much more sophisticated recovery techniques than a file-level image decoder can provide, and are tracked as roadmap items, not shipped capabilities of this prototype. See ../plan.md for the full product plan, including the v1/v2 feature scope and how this narrow slice fits into it. ## Build from source Requires Go 1.24+, no external dependencies (stdlib image/jpeg, image/png, image/gif only). go build -o photorevive . Cross-compile for another platform: GOOS=windows GOARCH=amd64 go build -o photorevive.exe . GOOS=darwin GOARCH=arm64 go build -o photorevive . ## Usage photorevive scan [ ...] [--json] photorevive repair [ ...] --out-dir [--apply] photorevive help ### scan Recursively walks each given directory independently, but reports all findings together in one consolidated summary across every directory passed on the command line. For every file with an extension of .jpg, .jpeg, .png, .gif, or .bmp, PhotoRevive tries to decode it with Go's standard image.Decode: - Decode succeeds -> OK. Dimensions are recorded. - Decode fails -> PhotoRevive checks the file's first few bytes against the magic number expected for the format implied by its extension (JPEG: FF D8 FF, PNG: 89 50 4E 47, GIF: 47 49 46 38, BMP: 42 4D). - Header matches -> CORRUPT (it really does look like that format, but something inside it is broken or truncated). - Header does not match -> UNKNOWN (it is probably not a real image file at all, or is some other/unsupported format wearing the wrong extension). The report is read-only — scan never writes or modifies anything. It prints per-directory OK/CORRUPT/UNKNOWN counts plus grand totals across all directories, and lists the path of every CORRUPT and UNKNOWN file (OK files are only counted, not listed individually, so the report stays readable against a library of thousands of files). Pass --json to get the same information as machine-readable JSON, including the full per-file classification list (paths, status, detected dimensions, file size, and a human-readable detail string), suitable for piping into other tooling. Note on BMP: Go's standard library does not ship a BMP decoder (only image/jpeg, image/png, and image/gif register with image.Decode). PhotoRevive still recognizes the .bmp extension and checks its magic bytes, but because there is never a working decoder to try, a .bmp file will report CORRUPT via the header-matches-but-decode-failed path even when it is a perfectly valid bitmap. This is a known limitation of a stdlib-only build, not a bug in the detection logic, and BMP support should be considered magic-byte sniffing only until a BMP decoder is added. ### repair Runs the same scan/classification logic as "scan" across all the given directories, then looks at every file classified CORRUPT. For files that are JPEGs (magic bytes FF D8 FF) and do NOT already end with the FF D9 End-Of-Image marker, PhotoRevive attempts the repair: it reads the original file into memory, appends FF D9 to a copy (the original file on disk is never touched), and tries to decode the in-memory copy. - If the copy now decodes -> REPAIRED (or WOULD-REPAIR in dry run). The image data up to the truncation point was intact; only the terminator was missing. - If the copy still fails to decode -> REPAIR-FAILED (or WOULD-FAIL in dry run). This means the corruption goes deeper than a missing end marker — real data was lost partway through the file — and appending two bytes cannot fix that. No output file is written for a failed repair; nothing broken or partial is left behind in --out-dir. - CORRUPT files that are not JPEGs (PNG/GIF/BMP), or JPEGs that already end with FF D9 but still fail to decode (a different kind of corruption than this tool targets), are reported as SKIP (not a JPEG-EOI-repairable case) and never touched. - OK and UNKNOWN files are never repair candidates at all; only CORRUPT files are considered. Without --apply, repair is a dry run: it performs the exact same in-memory repair-and-verify logic (append FF D9, try to decode) so the WOULD-REPAIR / WOULD-FAIL preview is an accurate prediction of what --apply would actually do, not a guess — but --out-dir is never created or written to. With --apply, every file that verified as repairable is written into --out-dir, preserving its path relative to its source directory (nested under a folder named after that source directory, to avoid collisions when the same relative path exists under two different libraries being repaired in the same run). A final summary line reports the count of REPAIRED / REPAIR-FAILED / SKIP files across the whole batch. ## Prebuilt binaries See ../downloads/ for prebuilt binaries (Windows/macOS/Linux) and CHECKSUMS.txt for their SHA-256 hashes. These are unsigned indie builds — Windows SmartScreen and macOS Gatekeeper will warn on first run, which is expected until a code-signing certificate is in place.