A fast, subscription-free RAW photo editor for macOS.
Read where it stands »
Download
·
Report a bug
·
Request a feature
Table of Contents
Adobe's grip on raw editing makes serious photo work expensive for students and hobbyists. The open alternatives are capable but dated or hard to learn. Orion aims at the gap: a GPU pipeline quick enough that adjustments feel instant, a toolset capable of transforming an image rather than nudging it, and an interface that stays out of the way of the photograph.
Status: M0–M4 complete. It browses a folder, culls, develops, crops, masks, heals and exports with metadata and a color profile. The panel covers white balance, tone, a tone curve, three-way color grading, an eight-band color mixer, profiled noise reduction, lens corrections from a bundled 2,600-lens database or from a DNG's own opcodes (drones, phones), sharpening, highlight recovery, clarity, dehaze, exposure fusion, creative LUTs, film grain, a creative vignette, crop and straighten. Masks come in six kinds: linear, radial, brush, subject matte, luminance range and colour range, combined as a list and optionally feathered onto the photograph's own edges. Undo is unlimited and edits persist per photo in XMP sidecars. Export writes JPEG, PNG, TIFF and JPEG XL. Past fit, the canvas renders only what is on screen, at the screen's resolution.
Not there yet: tethering, X-Trans sensors, and a Windows or Linux release.
Both build and pass their tests in CI on Dawn (D3D12, Vulkan), and the packages
are CI artifacts, but none has been released: the canvas there still copies
through the CPU, and Linux has only been run without a GPU. See
planning/STATUS.md, which is the honest list, including
the one shipped defect: a 24 MP frame allocates more intermediate memory than an
8 GB Mac has, so it will not open there.
- C++20 engine, Metal compute on macOS and Dawn (D3D12, Vulkan) on Windows and Linux, shaders in Slang
- Avalonia 12 on .NET 10 for the interface (it replaced a SwiftUI app, decision #380)
- LibRaw decode, OpenColorIO and lcms2 color
- lensfun lens data, XMP sidecars as the source of truth
A C++20 engine drives a GPU compute graph, on Metal on the Mac and on Dawn (WebGPU: D3D12, Vulkan) on Windows and Linux; on the Mac the Avalonia app shows its output on the GPU through an IOSurface, with no CPU copy. Shaders are authored in Slang and compiled to MSL and WGSL.
Edits form a DAG, not a chain, so moving a slider recomputes only what sits downstream of it. On an M4, a 24 MP Sony ARW re-renders an exposure change in about 8 ms against a 16 ms budget, at full resolution, with no preview proxy. That is why zooming to 100% shows real pixels: the full-resolution result is already in a texture.
decode → linearize + white balance + white clip → RCD demosaic
→ highlight reconstruction → wavelet denoise (4 scales)
→ lens corrections → sharpen → camera matrix
→ guided filter → tone, color → three-way grade
→ AgX display transform + curve → crop, straighten, orientation
27 nodes, about 4 GiB of intermediates on a 24 MP frame.
Everything between the camera matrix and the display transform is scene-linear and unbounded. There is exactly one display transform, and it is at the end.
The white clip in the first node is small and load-bearing. A sensor saturates at one count for every channel, so a blown highlight arrives as (S, S, S); white balance then multiplies each channel by its own gain and what was a white light is, in ratio, the gains themselves. Nothing downstream can undo that, because every stage after it preserves ratios. Without the clip, every clipped light in a night frame renders magenta.
Every non-trivial filter cites a published reference in research/,
and anything that does not is listed honestly in
research/UNSOURCED.md.
This rule exists because plausible-looking constants once shipped a purple cast on every image, a class of bug that is invisible to inspection and obvious to arithmetic. Citing the source makes the numbers checkable; testing the invariant keeps them right.
Notable ports: RCD demosaic, the fast guided filter (He & Sun, arXiv:1505.00996) for local highlight and shadow recovery, AgX (Sobotka) as the display transform, monotone cubic Hermite (Fritsch & Carlson, 1980) for tone curves, à-trous wavelet denoising (Starck et al., 2007) with a per-frame Poisson–Gaussian noise fit (Foi et al., 2008), cross-channel highlight reconstruction (Masood, Zhu & Tappen, CGF 2009), ASC CDL v1.2 for the grading wheels, and lensfun's lens correction models.
No GPL code is copied. Implementing a published algorithm from its description is fine, since mathematics is not copyrightable, and each entry says which it is.
To use Orion, download the newest alpha from bankoti.dev/Orion/download: an Apple silicon Mac on macOS 14 or later. To build it yourself, read on.
- macOS 14 or later, Xcode with the Metal toolchain, and Homebrew
- The libraries and .NET:
brew install cmake ninja libraw little-cms2 dotnet
- Slang: extract a macOS release from
shader-slang/slang into
third_party/slang/
- Clone the repository
git clone https://github.com/Nano-AI/Orion.git cd Orion - Configure and build
cmake -S . -B build -G Ninja cmake --build build - Build the app and run it
shell/native/build.sh export DOTNET_ROOT=/opt/homebrew/opt/dotnet/libexec dotnet build -c Release shell shell/bin/Release/net10.0/Orion ~/Pictures/some-shoot
- Package
Orion.appand a disk image a stranger can run:tools/package-app.sh.
Orion <folders or photos> opens them as the library. A convenient wrapper
(this is the whole feature; see decision #193):
# ~/.zshrc - `orion` opens the cwd; `orion pic.ARW` opens that photo.
orion() {
local app="/Applications/Orion.app"
if [[ ! -d "$app" ]]; then
echo "orion: $app not installed" >&2
return 1
fi
local -a paths
local p
for p in "${@:-$PWD}"; do paths+=("${p:A}"); done
open -n -a "$app" --args "${paths[@]}"
}Paths must be absolute: open(1) launches apps with cwd /, which is what
the :A modifier is for.
-n starts a new instance each time: open -a on a running app activates it
but drops --args, so the path would never arrive.
The agent surface is an MCP server over Orion --agent: it reads a photograph,
proposes an edit as a .proposed.json beside the RAW, and the editor shows it
for you to approve or reject.
mcp/README.md is the whole of it: the tools, what each one takes, and how a
proposal is approved. .mcp.json at the repo root wires it into Claude Code.
A packaged Orion.app carries the same server as Contents/MacOS/orion-mcp, a
Node single executable that needs no checkout and no Node, so a downloaded app
registers it with
claude mcp add orion -- /Applications/Orion.app/Contents/MacOS/orion-mcp
after clearing the download's quarantine (#310).
The app lives in shell/; its README has the build, every flag and
the headless selftest.
./build/apps/tests/orion-tests # engine maths, plus real GPU renders
shell/bin/Release/net10.0/Orion x.ARW --selftest # the app's invariants, headless
./build/apps/bench/orion-bench file.ARW # latency gate and per-control checks
./tools/check-agent.py # the agent surface: a real render and a real approveCLAUDE.md lists every gate to run before claiming anything works; none opens
a window, and the ones that render read their photographs from ORION_SAMPLES. The GPU
tests matter most: pure maths tests pass happily on code that renders garbage,
because they never touch a texture. Two shipped bugs proved it.
shell/bin/Release/net10.0/Orion x.ARW --tab Light --screenshot out.pngRenders the real window through Avalonia's headless platform: no window, no
Screen Recording permission. tools/check-screens.py renders every tab this
way and fails on one that is blank, unchanged from another, or unstable.
- M0–M4: library, culling, develop, crop, masks, healing, export
- An MCP server so agents can propose edits for you to approve
- The Avalonia interface, shipping as Orion.app in place of the Swift one
- The Avalonia canvas fed from the GPU with no CPU copy
- Region-of-interest rendering: only what is on screen, at screen resolution
- Dawn as the GPU backend, for Windows and Linux builds (in CI, unreleased)
- Windows and Linux releases: zero-copy canvas, a GPU Linux runner
- X-Trans sensors
- Tethering
See planning/ROADMAP.md for the milestones and
planning/FEATURES.md for every feature and its target.
Contributions are welcome. Read CONTRIBUTING.md
and CLAUDE.md first: its hard constraints (no GPL code, every
non-trivial filter cited in research/) apply to every change, and planning/DECISIONS.md
records the choices already settled.
- Fork the project
- Create a branch (
git checkout -b feature/your-change) - Commit your changes (
git commit -m 'Add your change') - Push the branch (
git push origin feature/your-change) - Open a pull request
Forks exist to send pull requests back; LICENSE forbids distributing your own version. By contributing you grant the project the rights its additional permissions describe.
Source-available, not open source. See LICENSE.
PolyForm Internal Use 1.0.0, plus permission for personal use and pull requests. Use Orion for your own work or your company's, paid or not, and help improve it through pull requests. You may not redistribute it, in source or binary form, or sell it or your own version of it. Revisions through commit abf3a51, and commits 82ec298 and 4005930, were published under Apache-2.0 and remain available under it.
⚠ NOTICE carries third-party licenses and obligations:
| What | Terms |
|---|---|
| LibRaw | LGPL-2.1 / CDDL-1.0, linked dynamically |
data/lensfun/ |
CC BY-SA 3.0: share-alike binds the data, so a corrected calibration goes back under the same licence |
| Adobe DNG | royalty-free patent grant, conditional on the notice appearing |
web/fonts/ |
SIL OFL 1.1 |
⚠ A licence is not a freedom-to-operate assessment, and none has been done.
CLAUDE.md says this in as many words: a method can be published, dated,
correctly attributed and still be covered by a live patent. Every algorithm here
is implemented from a published description and cited in research/, and no
GPL source was read to write any of it, but nobody has searched the patent
literature.
Orion: alpha@bankoti.dev · bankoti.dev/Orion
Project: github.com/Nano-AI/Orion
- LibRaw, lensfun, OpenColorIO and Little CMS
- Troy Sobotka's AgX display transform
- The papers cited in
research/, which every filter is built from - Best-README-Template, which this README follows
