skymanbp's AutoShade

AI-assisted automatic development of RAW photographs.

Windows · macOS · Linux (CLI) · Open source under MIT

Desert canyon at dusk: straight conversion, generated target, the recovered recipe rendered on the RAW, and the same recipe on the AI-denoised RAW, with a 1:1 detail row
Ask for the picture, keep the RAW. One 61 MP frame at dusk: the straight conversion, the picture an image model generated from it, the recipe AutoShade recovered from that picture rendered on the full RAW (sky ΔE 3.8 against the target, whole-frame mean |diff| 0.0248), and the same recipe after AutoShade's own RAW denoiser cleaned the sensor mosaic (sky ΔE 3.5, grain in the 1:1 window 3.1 → 0.6 codes). The generated picture is a target, never the delivery. Every number.

What it is

AI proposes. The engine develops.

Describe the picture you want and get it back as an editable develop of your own RAW. Every AI proposal renders through one deterministic Rust engine.

A generated look, recovered as a recipe

reimagine asks an image model for the picture you describe, from your own frame; match fits an editable recipe to its look and renders it on the full RAW. Two pairs →

Editable AI proposals

analyze and auto propose a recipe from preview, EXIF and histogram, check it against the image's own statistics and render it. The recipe is the only channel between the AI and the pixels.

One develop engine

Exposure, white balance, curves, HSL, colour grading, texture, clarity, dehaze, sharpening, noise reduction, grain, vignettes, perspective, crop and local adjustments: one library behind the desktop app, the command line and the local web UI.

Local masks

Linear, radial, brush, bitmap, luminance-range and colour-range masks, combined by Add, Subtract and Intersect, plus subject, sky and point-prompted object selection from pinned models on your own machine. No API key.

Sidecars both ways

Lightroom and Camera Raw sidecars are the merge base: owned edits are written back, unmodeled fields survive byte for byte, and a Lightroom round trip reopens exactly.

Versions and variants

Develops, generated targets, reverse-fitted looks, denoised negatives and stacked frames stay distinct cards with numbered snapshots. The source library is read-only; the original is never rewritten.

Stacking and merging

Several frames of one scene become one over a single alignment: an HDR merge, an exposure fusion, a focus stack, a noise stack. The merge lands as its own card; the frames keep their pixels.

Every slider renders

Sharpening, noise reduction, de-fringing, Transform and Upright, camera profiles, HDR edit mode and spot removal are read from the sidecar and rendered, never carried through untouched or silently dropped.

A denoiser trained here

Weights trained on this project's own data clean the sensor mosaic before demosaic, told the noise measured on the frame itself. Only luminance grain returns, 71% by default, and faint stars survive. See the star field →

Download

Download v1.9.0.

Seven files built from the tag, checksums.txt with their SHA-256, and the trained RAW denoiser weights, which the AI denoise sidecar fetches once against a pinned digest.

FileUseBytes
autoshade.exeCLI22,929,408
autoshade-gui.exedesktop app29,768,192
AutoShade-Setup-1.9.0.exeinstaller15,278,432
autoshade-1.9.0-windows-x64.zipportable archive20,636,181
AutoShade-1.9.0-macos-universal.zipmacOS app bundle41,487,882
AutoShade-1.9.0-linux-x64.zipLinux command line only9,948,140
AutoShade-1.9.0-macos-cli.zipmacOS command line only17,993,468
autoshade-raw-denoise-v2.pthRAW denoiser weights, fetched on demand from the v1.6.0 release130,590,559

Open the v1.9.0 release

Quickstart

Desktop

  1. Start autoshade-gui.
  2. Open photo…, Ctrl+O, or drag in a supported photo.
  3. Adjust a Develop slider; compare with the neutral conversion.
  4. Ctrl+Shift+E exports a copy; the original stays untouched.

CLI

autoshade decode "photo.ARW" -o "preview.jpg"
autoshade apply "photo.ARW" "recipe.json" -o "developed.tif"

With the image/vision role configured:

autoshade auto "photo.ARW" --guidance "natural color; protect highlights" -o "developed.tif"

Showcase · Part A

Reimagine → reverse-fit

A generated target can invent content; a fitted render cannot. The canyon at the top of the page is the second pair; a third is on the showcase page.

Stone viaduct: straight conversion, generated target, and the recovered recipe rendered on the RAW, with a 1:1 detail row
Stone viaduct. Straight conversion, generated target, recovered recipe on the RAW. Look error 0.161 → 0.023 at Reverse-fit strength 100 %.

Showcase · Part B

AI analysis and style transfer

One RAW, three direction texts, and an index of the photographer's own 169 Lightroom edits and 94 finished looks. Recipes render at full resolution; no pixels are copied.

Lakeside island town: straight conversion and three AI develops driven by three different direction texts
One photograph, four looks. The straight conversion and three AI develops of the same RAW, changing only the direction text.

Showcase · Part C

A RAW denoiser trained and judged here

The one network this project ships its own weights for. Four training runs on this project's own data: two shipped, two were refused by pass marks written before they started. Every number here is measured against Lightroom's Denoise 50 on the same frame.

One 1:1 window of a 61 MP star field, four ways: Lightroom's develop with Denoise off and at 50, AutoShade's neutral develop with no denoise and with its own denoiser at the 71 % default
One star field, four ways. The author's own ISO 2500 frame, one 796 × 462 px window at 1:1, shown one stop brighter. Top: Lightroom with Denoise off and at 50. Bottom: AutoShade with no denoise and at the 71 % default. 98.70 % of 17,817 faint stars kept against Lightroom's 98.80 %.

Noise measured where it stands

The network expects noise of one strength everywhere, so the noise is measured per tile on the frame itself, divided out before the network and multiplied back after. On this frame the per-tile residual's maximum fell 0.508 → 0.070.

Only luminance grain returns

The clean and the original mosaic go through the same demosaic; in linear light, 1 − strength of the luminance difference returns along the grey axis. Colour noise cannot come back by construction. Hot pixels are mapped first.

Faint stars kept

The first training run had never seen a star and kept 10 % of the light of a star four times the noise level. The second, trained with stars added, keeps 54 %. Two of the ten star-field readings still trail Lightroom and are recorded in the release notes.

Supported formats

Nine cameras, 24 RAW extensions.

AutoShade's own neutral renders of one CC0 sample per format, not embedded previews.

Canon CR2 develop
.cr2Canon EOS 40D
Canon CR3 develop
.cr3Canon EOS R6
Nikon NEF develop
.nefNikon D700
Sony ARW develop
.arwSony α7 III
Olympus ORF develop
.orfOlympus E-M5
Panasonic RW2 develop
.rw2Panasonic DMC-GX85
Pentax PEF develop
.pefPentax K-5
Ricoh DNG develop
.dngRicoh GR II
Fujifilm RAF X-Trans develop
.rafFujifilm X-S10 · X-Trans, approximate

Camera RAW · 24 extensions

arw, dng, raw, raf, nef, cr2, cr3, orf, rw2, pef, srw, 3fr, fff, iiq, mef, mos, erf, kdc, dcr, dcs, crw, nrw, mrw, ari

rawler decodes; its database covers 725 camera models.

Baked rasters · 8 extensions

jpg, jpeg, png, tif, tiff, bmp, webp, gif

ICC profiles are converted when present.

Nine format samples from raw.pixls.us under CC0 1.0 Public Domain.

How it works

One binary. Three front ends.

One Rust library; the advisor and external services return bounded recipes, never pixels. Drag to pan, scroll to zoom.

AutoShade architecture: three front ends over one Rust library holding RAW decode, the AI advisor, the recipe, the render engine, the reference library, reverse-fit, the local producers and the local-field analyzer; six local Python sidecars below it; two opt-in external AI services above itAutoShade — the architecture, drawn from its own source21 components (2 external, 3 frontend, 13 backend, 3 database) · 20 connections · 3 boundaries, all read from docs/architecture/autoshade.architecture.jsonResponses APIOpenAI-compatible visionclaude CLIsubprocess · OAuth · data onlyno API keyDesktop GUIautoshade-gui · eframe 0.29CLIautoshade · clap 4.6Local web UIserve · tiny_http · loopbackper-run tokenRAW decodedecode.rs · rawler 0.7.224 formats · 725 bodiesAI advisorpropose · verify · judgeEditReciperecipe.rs · bounded JSONrationale + confidenceRender enginerender.rs · measured LR paritybyte-identicalReference libraryfinished photos · SigLIP 23 closestDevelop storestore.rs · versions + variantsXMP sidecarxmp.rs · hand-rolled crs: mergebyte-preservingReverse-fitCDF inverse rendering · D gateFull / AtmosphereLocal producerszones · bands · quadtree tilesfree-form masks: designedLocal-field analyzer12x8x8 bilateral grid · CGceiling, read-onlyEmbedding sidecarembed.py · SigLIP 2 base/16768-d, pinnedCorrespondence sidecarcorrespond.py · DIFT on SD 2.148x48 fieldSegmentation sidecarBiRefNet · OneFormer · SAM 2.1guided refineDescription sidecardescribe.py · Qwen3-VL-2Bone grade sentenceDenoise sidecardenoise.py · SCUNet × 5opt-in, baked sourcesRAW denoise sidecardenoise_raw.py · DRUNetopt-in, on the mosaicExternal AI services — opt-in, only on user requestOne process, one binary — the AI returns a recipe, not pixelsLocal sidecars — subprocess, weights pinned to the byte, never in the repopreview·EXIF·histogramHTTPS · strict json_schemabounded slider setverify (data, never pixels)accepted recipe.xmp + rendered imagesaved per photo path3 closest finished photos768-d image embeddingglobal fit · modeceiling · cap · band proposalsrecovered recipe + maskswhere content movedsky/land · subject · objecta few look phrases per photodenoised pixelsdenoised mosaicEvery box is a directory or a module in this repository; every arrow is a call that exists. Generated by scripts/architecture_diagram.py — no position in this picture was chosen by hand.

Three pillars

Three things this does.

Each diagram is generated from the source; each number below was measured.

AI full-image generation → editable recipe

Diagram: a generated target is measured against the input by the structural-divergence statistic D, which selects either a full solve or a bounded atmosphere mode; a Tukey-biweight tone regression and gated local stages produce a recipe, and only the recipe reaches the full-resolution renderPillar 1 — AI generates the look, the engine recovers the recipethe generated pixels are a TARGET, never the delivery01Neutral renderthe RAW, no edits02Generated targetfidelity-hardened prompt; it mayinvent content03Structural divergence Dgradient correlation + pyramid energy04Which fit is honestfull fit, or atmosphere only05Global fit64-bin Tukey-IRLS + evidence06Semantic zones OR rangesfour regions, or bands — never both07Evidence quadtree tilesfrozen evidence, depth 2, four tiles08Residual free maskwhat the layers left unexplained09Honesty budgetstrength decides what may moveEditRecipe + XMPno pixel is deliveredeach layer must earn its place against the evidence

reimagine adds a faithfulness scaffold to every prompt. Below D = 0.35 the fit is a full solve; at or above, a bounded Atmosphere mode. Local corrections come in order, semantic regions or luminance bands, then an evidence quadtree, then at most two free-form masks, each behind the same 3% evidence, D < 0.65 and 0.012 rim gates. Generated pixels never carry over.

AI analysis develop

Diagram: a RAW plus XMP library becomes exemplars carrying a 14-dimension feature, SigLIP 2 image vectors and Qwen3-VL sentences; a query retrieves four neighbours by the hybrid distance; their habits reach the proposer behind an untrusted-data fence and a capped pull moves the result toward the photographer's meansPillar 2 — AI analysis developyour own library decides what “your style” means; the model only proposes01This RAWEXIF, histogram, preview02Similarity, four terms14-dim hand feature; image, text andsentence vectors03K = 4 neighboursfrom YOUR RAW + .xmp library04Reference blocksliders, curve, colour families, look, maskhabits05Advisor proposes a recipebounded by a schema06Verifiernumbers only, never pixels; tworevisions07Style blendtoward the neighbours’ means,cappedEditReciperenderable, exports to XMPthe block is a reference, never a copyreviseEvery model input istext and numbers.The photographs stayon your disk unlessyou send one on purpose.

Each of your Lightroom RAW+XMP pairs becomes an exemplar: a 14-dimension feature, sliders and tone curve, plus a 768-D SigLIP 2 vector and a Qwen3-VL-2B sentence from pinned local models. The 4 nearest past shots, ranked by d14 + W_EMB(1−cos) + W_TXT·z(1−cos−hub) + W_DESC·z(1−cos) with W_EMB=4, W_TXT=0.5 and W_DESC=0.5, pull the proposal toward your habits, capped at 0.18 at Style 0.3, without copying any of them.

Matching Lightroom

Diagram: a Lightroom sidecar is read by a scoped XML layer, its slider domains are measured rather than assumed, mask coordinates cross measured frame laws, and each result is published with its residualPillar 3 — the mathematics of matching Lightroommeasured against Adobe’s own output, not guessed from documentationLightroom .xmpcrs: fields, masks, curvesEditRecipeone typed model, both directionsEngine renderdeterministic f32 pipeline01Mask-frame lawradial through Lightroom’s own inverse; linearhandles transported02Lens geometryprofile ungeom; image centre derived, nottuned03Tone and falloffmonotone tone LUT; C¹ smoothstep falloff,fitted04Brush kernelk(ρ;h) = (1 − ρ^m)^n, fitted to held-out strokesread: own scope, nested Look, as-shot rulewrite: conservative merge, named lossesrenderevery law is a measured claim with a residual

Hand-rolled XML reads and writes Camera Raw's own scope; unknown namespaces survive merges. Measured: 45 of 45 Lightroom Texture anchors within ±0.02, a 290×11 radial feather table, radials closed 41/41 to ≤1 px, linear falloff on t^1.124 at rms 0.0064.

Tech stack & algorithms

The implementation details.

Nine areas; links open equations, provenance, measurements and sources.

Develop pipeline and tone model

Deterministic f32 rendering: linear-light vignette and dehaze, a monotone Fritsch–Carlson tone LUT, then curves, HSL, clarity and local edits. The camera's base look is read from the embedded preview.

Masks

Radial, linear, brush, bitmap, luminance-range and colour-range, combined by Add, Subtract and Intersect. Radial feather uses a measured 290×11 alpha LUT; brush dab flow kappa=0.1284.

AI masks

Subject: commit-pinned BiRefNet. Sky: OneFormer over the 150-class ADE20K table. Objects: positive points for SAM 2.1. Locally derived alpha is disclosed as non-Adobe.

Lens correction and Lightroom mask-frame laws

Sony lens metadata feeds a 2048-node mask solve; Newton inversion reads rectilinear .lcp profiles. Radials close 41/41 vectors to ≤1 px; Upright's 3×3 was measured to be Adobe's own [0,1] frame-centred projective form.

XMP and Lightroom interoperability

Typed traversal reads Camera Raw's own scope; a conservative merge preserves unmodeled fields. Measured domains: LocalExposure2012=EV/4, local Hue /180, global Sharpness 1:1. The whole develop rides inside the sidecar and survives a Lightroom rewrite byte for byte.

AI advisor and reverse fit

Bounded proposals use store:false and a do-no-harm gate. A colour cast ships only through four vetoes, among them foreign hues ≥45° over ≥5% of the frame.

Stacking and merging

Inverse-compositional Lucas–Kanade on a Gaussian pyramid, solved in log luminance so a change of exposure is invisible to the gradient. Measured: a bracket returns −2.49 / −4.98 EV against a −2.5 / −5.0 truth.

Application and infrastructure

Rust 2024: one library for the CLI, egui desktop and loopback web UI. The v1.9.0 battery: 1643 library, 25 CLI, 243 GUI and 2+2 contract tests.

Documentation

Follow the implementation.