Lambda Symbolics

Orfeus: a RAW processor for Olympus PEN-F and OM-1

A fast Common Lisp RAW processor for Olympus PEN-F and OM-1 files. The same processing core drives a command-line tool and an FLTK GUI, so a batch export and an interactive grade always render identically.

Grading as a node graph, not a slider panel you hope you remember.

Orfeus · Properties
Cameras
Olympus PEN-F and OM-1 ORF, embedded in DNG
Frontends
CLI and FLTK GUI over one processing core
Batch format
Readable, editable S-expression projects
Grading
DaVinci-style node graph, scene-linear blends
GPU path
Optional Vulkan compute, CPU fallback on failure
License
COLL-Attribution
Repository
luciusmagn/orfeus

One core, two frontends

The command line and the GUI call the same Common Lisp processing core, so a photo renders identically whether it came from an interactive grade or an unattended batch run. A native Rust bridge handles RAW decode and pixel work; Orfeus orchestrates it and owns every decision about what happens to a photo.

Olympus stores the original ORF embedded inside the DNG its own tools produce. Orfeus can inspect or pull that original back out before it does anything else with a photograph.

Command line
$ orfeus info photograph.dng
$ orfeus extract photograph.dng photograph.orf
$ orfeus preview photograph.orf preview.jpg
$ orfeus render photograph.orf export.tiff
$ orfeus init project.sexp exports/ first.orf second.orf
$ orfeus batch project.sexp

Grading as a node graph

A photo's grade is an explicit, piped node graph, not a single flat settings panel. Node kinds carry one adjustment category each, including repeated kinds, so two +2 EV exposure nodes make +4. Nodes are reorderable and individually bypassable, and maskless blend nodes mix two scene-linear branches by opacity.

A dedicated :color-subtract node inverts a film negative by subtracting the picked base color from each pixel in scene-linear space, with palette and eyedropper pickers in the GUI. Crop nodes carry a resolution-independent oriented rectangle, so one graph fits both a fast preview and a full-resolution export, and a negative-autocrop mode detects the frame and film-base color on its own.

Photographs without a graph keep the flat, five-stage pipeline unchanged; both paths render through the same batch runner. The GUI grabs auto-named stills into a thumbnail gallery, and right-clicking one applies its whole node graph to the current selection, optionally without its lens profile or white balance.

One photo's node graph
;; excerpt: the :graph value inside one :photos entry
(:graph
 (:nodes ((:id 1 :kind :exposure
        :inputs (0) :params (:exposure 2.0))
       (:id 2 :kind :exposure
        :inputs (1) :params (:exposure 2.0))
       (:id 3 :kind :color-subtract
        :inputs (2)
        :params (:red 0.92 :green 0.85 :blue 0.71)))
  :output 3))

Optics and film

Lens correction matches Lensfun profiles from a photo's own EXIF automatically. Adapted manual lenses can be mapped to an exact Lensfun profile with a focal reducer ratio and crop factor, so a speed-boosted vintage lens still gets correct geometry and vignetting instead of no correction at all.

The bundled film-emulation LUT library ships Agfa APX, Precisa, and Ultra Color looks alongside Kodachrome 25, 64, 64 Generic, and 200, with provenance and checksums recorded in the repository's THIRD-PARTY.md.

lenses.sexp · adapted manual lens
(("Ultron 0.7x"
  :lensfun-model "Voigtlander Ultron 40mm f/2 SLII Aspherical"
  :focal-reducer 0.71
  :crop-factor 2.0))

Batch projects are read with *read-eval* disabled, so opening someone else's project file cannot run arbitrary code. An optional Vulkan compute backend fuses display tone and the sRGB transfer curve; it stays opt-in behind ORFEUS_GPU=1 because one-shot Vulkan initialization is expensive, and any initialization, dispatch, or readback failure falls back to the CPU result automatically.

Build from source

Orfeus targets Linux and has no packaged binary yet. The Nix flake provides SBCL, Rust, the LibRaw and Lensfun native dependencies, ExifTool, JPEG and TIFF support, and FLTK. Keep a sibling lightfast checkout available when building the GUI.

There is no nix build package output yet, only a development shell. Enter it, then build the native bridge, the GUI, and the Lisp system in order.

Build · Nix development shell
Enter the environment
$ nix develop

Build the native bridge and GUI
$ cargo build --release --manifest-path native/Cargo.toml
$ make gui-native

Build the CLI
$ sbcl --no-userinit --non-interactive \
    --eval '(require :asdf)' \
    --eval '(asdf:load-asd (truename "orfeus.asd"))' \
    --eval '(asdf:make "orfeus/cli")'

Run it
$ ./orfeus info photograph.dng
$ ./orfeus-gui