Skip to content
 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

368 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Autoshop icon

Autoshop

AI-assisted automatic development of RAW photographs.

Point it at a RAW (or an exported PNG/TIFF); an AI advisor decides the develop adjustments and a deterministic Rust engine applies them — or writes an XMP sidecar so the edit opens as adjustable sliders in Lightroom.


The idea

The judgement-heavy part of developing a photo is deciding what to change (this sky is blown, those shadows are crushed, the white balance is too cool). The mechanical part is applying it. Autoshop splits exactly there:

 RAW ─► decode + features ─► [GPT vision advisor] ─► EditRecipe ─► [Claude verify] ─► Rust render engine
  .ARW    preview+EXIF+hist        looks at photo        JSON          QA / accept           │
                                                                                             ▼
                                                                    XMP sidecar  +  16-bit master

The AI never touches a pixel in the main path. The vision model only emits an EditRecipe — a small, bounded, Lightroom/ACR-style JSON of slider values — and a deterministic engine renders from the original RAW. That keeps results reproducible, non-destructive, auditable, and free of hallucinated detail. (Three opt-in, clearly-labelled exceptions touch pixels: AI denoise, generative retouch, and pixel heal — see below.)

Features

  • One-shot developauto decodes a RAW, asks GPT for an EditRecipe, has Claude acceptance-verify it, then renders a 16-bit TIFF master.
  • XMP sidecar — the same recipe serialises to an ACR/Lightroom .xmp (global sliders + local linear/radial masks), so the AI's edit opens as fully-adjustable sliders in your catalog.
  • AI Denoise (SCUNet, GPU) — ACR/LR-style denoise for high-ISO / astro frames. Off by default, triggered by a flag, a CLI command, or a UI button.
  • PNG/TIFF source mode — feed an already-processed image (e.g. denoised in Lightroom/Photoshop) and Autoshop grades it directly. Auto-detected by file type; no RAW required. Embedded ICC profiles (LR "Edit in…" exports ProPhoto 16-bit by default) are normalised into the sRGB working space — 16-bit depth preserved — instead of being read as if they were sRGB.
  • Desktop app (native GUI)autoshop-gui: a library grid that marks which photos already have a saved develop, the full develop panel (tone, presence, curves, 8-band HSL, colour grading), local masks (linear / radial / brush / AI-selected — rotatable radials, add/subtract/intersect shape composition, per-mask eye toggle & duplicate, brush-editable AI rasters with feather/expand/contract and full-resolution guided refine), crop & straighten, spot heal, reverse-fit, before/after, per-photo version snapshots and variant strips that survive a reopen (variants.json), and Ctrl+S to a Lightroom XMP. English / 中文.
  • Web UIserve opens a local gallery: pick a photo, Analyze, tweak the develop sliders (tone, presence, curves, 8-band HSL, colour grading) with live before/after, give a text direction, export.
  • Style retrieval — learns from similar past edits you've made (k-NN over EXIF + histogram) and offers them to the advisor as soft reference.
  • Look matching (reverse-fit)match takes the same frame twice (your source and a finished rendition of it: a reimagine output, an exported JPEG, any reference of that shot) and solves for the EditRecipe that reproduces it through the engine — CDF tone matching, then saturation, then colour cast. No pixels are copied, so the fit applies at full sensor resolution and writes recipe.json + XMP. Deterministic, no API key needed.
  • Generative (experimental)reimagine / retouch via OpenAI Images.
  • Pixel retouch / Heal (experimental) — an optional mode where the AI removes dust / blemishes / specks by healing from SURROUNDING REAL pixels (deterministic; not generative — it invents nothing). Hybrid targeting: AI auto-detect + paint-to-add. Writes a pixel master to ./out.
  • Batch the whole library, eval the AI against your own edits.
  • Your library stays read-only — the engine refuses to write into a source RAW's folder. Exports (developed/heal/retouch images) go to ./out; develop STATE (recipes, Lightroom XMP, version snapshots, mask rasters, the baked pixel-master link and the GUI's variant strip) lives in a per-user develop store (AUTOSHOP_DATA_DIR, else %LOCALAPPDATA%/autoshop/develops/<stem>-<path hash>/), so two same-named photos never collide and edits survive launching from any directory.
AI denoise before/after

Quick start

cargo build --release                                    # CLI → target/release/autoshop(.exe)
cargo build --release --features gui --bin autoshop-gui  # desktop app → autoshop-gui(.exe)
cargo test                                               # unit + engine tests

The GUI sits behind the gui feature so a plain cargo build / cargo test never pulls in eframe + winit + the GL stack. Both binaries link the same engine library, and each tagged release ships both prebuilt for Windows.

Then any of:

  • Desktop app: run autoshop-gui (or the released .exe) and point it at a folder — the full editor, no server and no browser involved.
  • Web UI: double-click Autoshop-UI.bat (Windows) — it serves your library and opens the browser. Or: autoshop serve "D:\path\to\photos" --port 8080.
  • CLI:
    autoshop auto "photo.ARW" --guidance "warm golden-hour, lift shadows"

Commands

autoshop decode  <src>                       # preview + EXIF + histogram
autoshop analyze <src> [--guidance "..."]    # AI → recipe.json + .xmp (no render)
autoshop apply   <src> <recipe.json> -o out  # render a recipe to an image
autoshop auto    <src> [--denoise] [--guidance "..."]   # analyze + render, end-to-end
autoshop denoise <src> [--strength 0..1] [--model ...]  # AI denoise → clean 16-bit master
autoshop batch   <dir> [--render] [--limit N]           # process a whole folder
autoshop eval    <dir> [--limit N]           # compare AI edits vs your own .xmp
autoshop style-index <dir>                   # build the "your taste" reference index
autoshop serve   <dir> [--port 8080]         # local web UI
autoshop reimagine <raw> --prompt "..."      # experimental generative restyle
autoshop match   <raw> <target> [--render] [--zoned]    # reverse-fit a look → editable recipe + XMP (no key)
autoshop retouch   <raw> --mask m.png --prompt "..."    # experimental generative object removal
autoshop heal      <src> [--mask m.png] [--no-auto]     # pixel heal: spot/blemish removal (NOT generative)
autoshop recipe-schema                       # print the EditRecipe JSON shape

<src> is a RAW (.arw/.dng/...) or a baked image (.png/.tif/.jpg) — the develop pipeline runs on either. RAWs also get an .xmp; baked sources get recipe.json only (XMP is meaningful only for RAW in Lightroom).

AI setup

Two roles, each configurable in the in-app Settings (⚙) panel (or via env):

Role What Default Other option
分析 / Analysis (verifier) data-only acceptance-check of each recipe OAuth — the claude CLI on PATH, signed in (reuses Claude Code OAuth, no API key), model opus API — any OpenAI-compatible chat endpoint (base URL + key + model)
图像 / Image (vision advisor) looks at the photo → EditRecipe APIOPENAI_API_KEY, model gpt-5.5 point the base URL at any OpenAI-compatible vision endpoint. Without a key, a histogram heuristic is used.

The claude CLI has no image input in print mode, so the image role always speaks the OpenAI-compatible HTTP protocol. The Settings panel's "OAuth" choice for the image role is a preset that points the endpoint at a local subscription bridge (e.g. CLIProxyAPI) instead of a keyed API — same wire protocol, different endpoint/credentials.

Configure keys + models from the Settings panel — written to autoshop.local.json in your per-user Autoshop folder (never in a repo), which overrides the environment. Keys never leave your machine: the server binds 127.0.0.1, refuses any request whose Host/Origin is not that exact loopback authority on its own port, requires the page's per-run session token on every state-changing request, marks all /api/* responses no-store, never returns a key (settings answer key_present: true/false), and sends X-Frame-Options: DENY so a page you visit cannot frame the UI. You can also use .env:

OPENAI_API_KEY=sk-...

A settings file in the current directory is not trusted with your key. Autoshop still reads a autoshop.local.json sitting in the folder it was launched from — that is the pre-store layout, kept so old setups keep working — but from v0.18.0 such a file may only choose models and providers. Its API-key and base-URL fields are ignored, with a warning, because settings resolve per field: a file supplying just image_base_url would have redirected the endpoint while your real key still came from .env, and the next Analyze would have posted that key to whoever wrote the file. Extracting a shared archive of photos and running Autoshop inside it was enough. Your own settings, saved from the panel into your user profile, are unaffected.

The same rule now covers two routes that were still open. Saving settings no longer launders an ambient file into your trusted one — both settings writers read-merge-write, so a save used to copy a planted image_base_url into your user profile, where nothing strips it again and one ordinary "save" undid the whole guard. And a .env may no longer choose the endpoint: dotenvy searches the working directory and every parent, and its override mode beats a variable you really set, so a .env dropped beside shared photos could redirect your key exactly as the settings file could. Keys and model names from .env still work — that is where this project's own key lives; only AUTOSHOP_OPENAI_BASE_URL and AUTOSHOP_ANALYSIS_BASE_URL are ignored from it, with a warning.

White balance renders slightly differently. The blackbody curve behind the Temp slider is a published piecewise fit whose branches did not meet: at 6600 K green jumped 1.31 % and blue 0.96 %, and red sat clamped flat from 6600 to 6688 K, so an 88 K band carried no temperature signal at all for the eyedropper to solve against. The branches are now rescaled to meet exactly. The cost is that white-balance gains change. Measured against a 5500 K shot, as the change in the gain each channel receives:

Temp target red blue
2000 K (candle — the slider's floor) 0 % −4.43 %
2500 K 0 % −0.67 %
3000–5000 K 0 % −0.32 % … −0.03 %
6500 K and below 0 % +0.03 %
above 6600 K (any cool target) +3.19 % +2.35 %

Red is untouched at and below 6500 K because that branch was already clamped there. The two ends move most: cool targets by the seam repair, and the very warm end because the blue branch crosses zero at 1900 K, so a small absolute change is a large relative one right at the slider's floor. Re-exports of older work at those settings will differ by that much, and this change has not had visual acceptance.

AI Denoise setup

The denoiser is a small Python sidecar (python/denoise.py) running SCUNet on the GPU. It needs Python with:

pip install torch --index-url https://download.pytorch.org/whl/cu128   # CUDA build
pip install opencv-python numpy einops requests

On first use it downloads the model weights (~69 MB/model) into python/weights/ (gitignored). The sidecar script and its weight cache are resolved against the program's own directory tree, never the folder you run from — a downloaded photo pack cannot substitute its own script or weights. Trigger it via autoshop auto --denoise, autoshop denoise <src>, or the AI Denoise checkbox in the web UI. Models: color_real_psnr (default, blind, best for real high-ISO/astro), color_real_gan, color_15/25/50.

Configuration (env vars)

The AI-provider rows below are also settable in the Settings (⚙) panel; the per-user autoshop.local.json (in the Autoshop data folder) overrides the environment. The two sidecar knobs (AUTOSHOP_PYTHON, AUTOSHOP_DENOISE_MODEL) are environment-only — the panel does not carry them.

Variable Default Purpose
OPENAI_API_KEY image (vision) advisor + generative key
AUTOSHOP_OPENAI_MODEL gpt-5.5 image/vision model id
AUTOSHOP_OPENAI_BASE_URL https://api.openai.com/v1 image API base (any OpenAI-compatible)
AUTOSHOP_OPENAI_IMAGE_MODEL gpt-image-1.5 generative (retouch/reimagine) model
AUTOSHOP_ANALYSIS_PROVIDER oauth verifier provider: oauth (claude CLI) or api
AUTOSHOP_ANALYSIS_MODEL opus verifier model (claude alias for oauth; chat id for api)
AUTOSHOP_ANALYSIS_API_KEY verifier key when provider = api
AUTOSHOP_ANALYSIS_BASE_URL https://api.openai.com/v1 verifier API base when provider = api
AUTOSHOP_PYTHON python interpreter for the denoise sidecar
AUTOSHOP_DENOISE_MODEL color_real_psnr default SCUNet weights

Honest scope

  • Render ops are tasteful approximations of Lightroom, not bit-exact. The XMP→Lightroom path renders them faithfully in the meantime.
  • AI denoise runs on the demosaiced RGB (not the raw Bayer mosaic like Adobe Denoise), and ~3 min for a 60 MP frame on an RTX 4060 Ti. Excellent, not identical to Adobe.
  • Kelvin white balance is absolute only on a RAW, where the as-shot temperature is read from the camera metadata and stamped into the develop. A baked PNG/TIFF has no as-shot reading, so the same slider anchors at 5500 K and acts as a relative shift from there — it moves pixels, it just cannot claim to be the scene's true colour temperature.
  • Generative reimagine is a low-res, lossy re-render — an experiment, not a master. retouch (generative fill) regenerates only the masked region and composites it back onto the source's own develop with a feathered seam, so the rest of the frame keeps the original pixels. That base is the engine's own neutral develop — capped at 2048 px on the long edge by default — never the camera's embedded JPEG, so the composite stays on the same tone chain as the canvas. A baked PNG/TIFF is likewise thumbnailed to 2048 px. Pass --full-res (CLI) or tick Full-res (UI) to composite at full resolution instead (~60 MP for a RAW; slow — only the small removed patch is upscaled). Both pick an aspect-correct size (no square-squash) and default to quality=high (override --quality).
  • Pixel heal (autoshop heal / the UI's 去瑕疵 panel) is the non-generative retoucher: it removes only SMALL defects (dust / blemishes / specks) by sampling surrounding REAL pixels — it never invents content. Best on fairly uniform backgrounds (sky, skin, wall, water); busy backgrounds heal approximately. AI auto-detection needs the vision key; the paint-a-mask path works offline. Runs on a ≤2048 px base by default — the engine's own neutral develop for a RAW, the source thumbnailed for a baked image; --full-res heals at full resolution instead (slow), on either source type.

Tech

Rust (rustc/cargo 1.94) · rawler (Sony ARW decode) · image · rayon · clap · serde · ureq · eframe/egui (desktop GUI) · tiny_http (web UI) · Python + PyTorch + SCUNet (denoise) · Claude CLI (verifier) · OpenAI Responses + Images (advisor + generative).

See docs/ARCHITECTURE.md for the full design.

About

AI-assisted automatic development of RAW photographs (EditRecipe + deterministic Rust render, XMP sidecar, AI denoise)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages