clone

a photo toolkit for your phone that never uploads: fuji film looks for raw files, social crops, error level analysis

main
gudpics / README.md
README.md 4.6K rendered
1# gud.pics23A mobile-first, installable photo toolkit. Source: https://github.com/FelineStateMachine/gudpics Every tool runs locally in the browser; Cloudflare serves static files and photos never leave the device.45Tools:67- `/fuji`: develops a Fujifilm RAF in the browser with LibRaw (WebAssembly) and applies any of 16 film simulation looks via 3D LUTs, then saves a JPEG. The in-camera JPEG can be viewed and saved too. See NOTICE.md for where the LUTs come from and how close they are.8- `/social`: crop to an aspect ratio (1:1, photo 5:4 4:3 3:2, social 4:5 9:16 1.91:1, each rotatable) or pad out, drag to position, frame in white or black, vignette and grain, then save or share a JPEG at the platform size.9- `/ela`: error level analysis. Re-saves the picture as JPEG at a chosen quality, amplifies the difference, estimates the source JPEG quality from its quantization table, and saves the map as PNG.10- `/perspective`: straightens converging verticals and horizontals using darktable's C algorithms (LSD line detection, RANSAC, perspective fit, homography) compiled to WebAssembly.1112## Run1314The checked-in `assets/core.mjs` and `assets/core.wasm` are ready to use.1516```sh17python3 scripts/package.py18python3 scripts/serve.py 876519```2021Open http://localhost:8765. The dev server maps extensionless routes such as `/perspective` to `perspective.html`, matching Cloudflare's asset handling. Service workers require localhost or HTTPS.2223## Rebuild2425Requires Python 3, Emscripten (`emcc`, built here with 6.0.9), Node.js for tests, and Pillow only to regenerate icons. No network is needed for extraction.2627```sh28sh scripts/build.sh29node scripts/test-core.mjs30python3 scripts/package.py31```3233If Emscripten's installed cache is read-only, set `EM_CACHE` to a writable directory when running the build.3435`scripts/extract.py` documents each source adaptation. Original source at the pinned revision is in `native/upstream`; retain original notices. See NOTICE.md and LICENSES before redistributing.3637## Cloudflare deployment3839```sh40npx wrangler@4 deploy --dry-run41npx wrangler@4 deploy42```4344The config serves only `dist/`; it has no backend, secrets, storage bindings, analytics, photo upload endpoint, or runtime npm dependencies. Packaging writes scripts, styles and wasm to `dist/static/` under content-hashed names and rewrites references, so hashed files are cached forever while pages are fetched network-first. Re-run packaging after changes. Existing open tabs finish using their cached version; close all app tabs and reopen to activate an update.4546## Layout4748- `index.html` + `home.mjs`: landing grid of tools, install and about.49- `fuji.html` + `fuji.mjs` + `rawworker.mjs` + `raf.mjs`: the Fuji tool. `rawworker.mjs` runs LibRaw (`assets/raw.wasm`, built by `native/raw/build.sh`) and the LUTs off the main thread. `raf.mjs` parses the RAF container and the Fuji makernote. `scripts/neutral-lut.py` regenerates the neutral LUTs with darktable-cli.50- `social.html` + `social.mjs`: the Social tool, canvas only.51- `ela.html` + `ela.mjs` + `elaworker.mjs`: the ELA tool; re-encoding and differencing run in a worker on an OffscreenCanvas.52- `perspective.html` + `app.mjs`: the perspective tool UI. `worker.mjs` runs the WebAssembly core off the main thread.53- `style.css`: shared styles. Dark, system font, safe-area aware; the tool page never scrolls.5455## Perspective tool5657Photo import; original orientation via browser decoding; LSD structure detection; RANSAC outlier rejection; vertical, horizontal, or both-axis fit (including shear for both); color-coded accepted/rejected line overlays and counts; rotation and correction strength; crop modes; grid; before/after (tap the compare button or press and hold the photo); JPG/PNG export; install manifest and offline cache.585960## Prototype limits6162- JPEG/PNG only, 60 MB file limit. Imported images are flattened onto white and reduced to at most 4 MP / 2560 px. Analysis uses a 960 px preview.63- Browser 8-bit color handling; exports omit EXIF and source ICC metadata. No RAW or lens distortion profiles.64- Generic lens model, approximate crop, bilinear resampling. Not a full darktable pipeline or a reproduction of Lightroom's proprietary Auto mode.65- No manual line drawing/selection yet. Overlay colors: green vertical accepted, blue horizontal accepted, red vertical rejected, yellow horizontal rejected, gray other edges.66- Real-device iOS/Android memory, installation, photo picker, and sharing behavior still need hands-on validation. A desktop browser with a phone-sized viewport cannot establish those guarantees.67- LSD's inherited error routine can terminate its WASM instance on allocation failure; the UI catches worker errors, but reload may be required after memory exhaustion.