Skip to content
Nano-AIPublic

About

A fast RAW photo editor with no subscription. C++20 engine on Metal compute; every filter cites a published reference. macOS now, Windows and Linux in progress.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

Release License Stars Issues


The Orion app icon: a fir under Orion's Belt

Orion

A fast, subscription-free RAW photo editor for macOS.
Read where it stands »

Download · Report a bug · Request a feature

Table of Contents
  1. About the project
  2. Getting started
  3. Usage
  4. Tests
  5. Roadmap
  6. Contributing
  7. License
  8. Contact
  9. Acknowledgments

About the project

Orion with a linear mask on a seascape

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.

(back to top)

Built with

  • 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

How it is built

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.

Algorithms are cited, not invented

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.

(back to top)

Getting started

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.

Prerequisites

  • 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/

Installation

  1. Clone the repository
    git clone https://github.com/Nano-AI/Orion.git
    cd Orion
  2. Configure and build
    cmake -S . -B build -G Ninja
    cmake --build build
  3. 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
  4. Package Orion.app and a disk image a stranger can run: tools/package-app.sh.

(back to top)

Usage

Opening a folder or photo from the shell

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.

Driving Orion from an agent

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's own flags

The app lives in shell/; its README has the build, every flag and the headless selftest.

(back to top)

Tests

./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 approve

CLAUDE.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.

The screenshot harness

shell/bin/Release/net10.0/Orion x.ARW --tab Light --screenshot out.png

Renders 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.

(back to top)

Roadmap

  • 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.

(back to top)

Contributing

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.

  1. Fork the project
  2. Create a branch (git checkout -b feature/your-change)
  3. Commit your changes (git commit -m 'Add your change')
  4. Push the branch (git push origin feature/your-change)
  5. 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.

Top contributors

Contributors to Orion

(back to top)

License

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.

(back to top)

Contact

Orion: alpha@bankoti.dev · bankoti.dev/Orion

Project: github.com/Nano-AI/Orion

(back to top)

Acknowledgments

(back to top)

About

A fast RAW photo editor with no subscription. C++20 engine on Metal compute; every filter cites a published reference. macOS now, Windows and Linux in progress.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages