OmaStudio: The Complete Medium Format RAW Editor for Omarchy
OmaStudio is a non-destructive RAW editor built for Omarchy Linux. It develops RAW files with its own engine, written in Rust, and runs natively on Wayland and Hyprland. Fujifilm X and GFX, and Hasselblad medium format cameras get first-class support.
| Area | What OmaStudio provides |
|---|---|
| RAW development | The engine's own demosaicing for X-Trans and Bayer sensors on linear light, with camera colour matrices and black levels taken from the file. Demosaicing runs on the GPU through Vulkan (NVIDIA, AMD, Intel, Qualcomm Adreno) with an identical CPU fallback. LibRaw only unpacks the sensor data. |
| Medium format | Fujifilm GFX and Hasselblad RAW files with a 16-bit pipeline from sensor to export. |
| Fujifilm | Photos open with the recipe they were shot with: film simulation, tone, colour, grain, Color Chrome, white balance shift and dynamic range. X RAW Studio profiles (.FP1/.FP2/.FP3) and recipes shared as text can be imported and exported. The Fujifilm panel keeps a recipe library, reads and writes a connected camera's custom settings C1-C7, converts RAFs in camera and merges GFX Pixel Shift sequences. |
| Colour management | Little CMS 2 with built-in sRGB, Display P3, Adobe RGB, ProPhoto RGB and Rec. 2020 profiles, plus custom ICC profiles with a choice of rendering intent. ICC profiles are embedded in every export. |
| Editing | Exposure, tone, presence, HSL, tone curve, three-way colour wheels, 3D LUTs, RGB mixer, skin tone uniformity, film grain, local masks, crop and lens corrections. |
| Library | Local catalog with star ratings, pick/reject flags and colour labels; adjustments are stored in sidecar files and the original RAW is never modified. |
| Cameras over USB | A PTP/USB layer in pure Rust for tethering and Fujifilm in-camera RAW conversion. |
| Export | JPEG, PNG, TIFF (8/16-bit), WebP, JPEG XL and AVIF, with watermarking. |
OmaStudio is a native Qt 6 application, omastudio-app (Rust with cxx-qt, QML interface compiled into the binary). It runs as a Wayland client with Qt's fractional scaling, so the interface is drawn at the monitor's real pixel density under Hyprland. All image processing happens in a separate Rust engine process, omastudio-engine, which the window drives through a JSON-lines daemon over stdin/stdout. The same engine also offers a command line interface for scripts and Omarchy agents. A small Quickshell widget (Panel.qml) puts an OmaStudio button in the Omarchy bar.
The running window listens on a control socket ($XDG_RUNTIME_DIR/omastudio/ipc.sock, current user only). omastudio ipc <method> [args] calls it, for example omastudio ipc openPhoto ~/Pictures/DSCF0001.RAF or omastudio ipc getStatus; launching omastudio photo.RAF while a window is open hands the photo to that window.
graph TD
subgraph UI ["omastudio-app (Qt 6 / QML, Wayland)"]
Viewport["Viewport, crop and overlays"]
Panels["Adjustment panels, colour wheels, scopes"]
Library["Filmstrip and catalog"]
end
subgraph Engine ["omastudio-engine (Rust)"]
Decode["LibRaw unpack"]
Develop["Own demosaic, white balance, camera matrix (linear light)"]
Pipeline["Tone, colour and detail modules (rayon)"]
ICC["Little CMS 2 colour management"]
Fuji["Fujifilm recipes, X RAW Studio profiles"]
PTP["PTP/USB (nusb)"]
Export["Encoders with embedded ICC"]
end
UI <-->|JSON lines| Pipeline
Decode --> Develop --> Pipeline --> ICC --> Export
Fuji --> Pipeline
PTP --> Fuji
flowchart LR
A["RAW sensor data"] --> B["Black level and white balance (linear)"]
B --> C["Demosaic (X-Trans / Bayer)"]
C --> D["Camera matrix to working space"]
D --> E["Exposure (linear)"]
E --> F["Tone, colour, film simulation"]
F --> G["Detail, grain, lens"]
G --> H["ICC conversion and export"]
OmaStudio opens every RAW format LibRaw 0.22 supports. The engine develops Bayer and X-Trans sensors with its own pipeline. Foveon, linear DNG, Fujifilm SuperCCD and four-colour sensors fall back to LibRaw automatically.
| Manufacturer | Additional support |
|---|---|
| Fujifilm X and GFX | In-camera recipe, film simulations, Color Chrome, X RAW Studio profiles, camera lens corrections, GFX Pixel Shift, PTP/USB |
| Hasselblad | 3FR/FFF files, HNCS-style rendering (in development) |
| Other manufacturers | Full development pipeline through the generic path |
- Omarchy (Arch Linux) with Wayland and Hyprland
libraw0.22 or newer,lcms2,qt6-base,qt6-declarativeandqt6-wayland6.12 or newerquickshellonly for the button in the Omarchy barzenityfor file dialogs- To build: Rust 1.99.1 or newer (pinned in
rust-toolchain.toml),clang,pkgconf,qt6-tools(lreleasecompiles the translations)
Optional:
perl-image-exiftoolkeeps EXIF metadata in exported files.ffmpegis used for AVIF export if the built-in encoder fails.onnxruntimeruns the local AI masks; a build with your hardware's execution provider (OpenVINO, QNN, Vitis AI, CUDA, MIGraphX) uses the NPU or GPU.rcloneandlibsecret(with a keyring such asgnome-keyring) connect Google Drive, OneDrive, Dropbox, Box, pCloud and Yandex Disk;github-cliconnects GitHub.
makepkg -siThe package installs the application, the engine, the ICC profiles and a udev rule (70-omastudio-cameras.rules) that gives the logged-in user USB access to Fujifilm cameras in PTP mode.
cargo build --release --locked --workspace
install -Dm755 target/release/omastudio-engine ~/.local/bin/omastudio-engine
install -Dm755 target/release/omastudio-app ~/.local/bin/omastudio-app
install -Dm755 omastudio ~/.local/bin/omastudio
install -d ~/.local/share/omastudio/icc
install -m644 assets/icc/*.icc ~/.local/share/omastudio/icc/
omastudio| Path | Contents |
|---|---|
~/.local/share/omastudio/catalog.json |
Catalog: ratings, flags, colour labels |
~/.local/share/omastudio/fuji-recipes/ |
Saved Fujifilm recipes (.FP1) |
~/.local/share/omastudio/icc/ |
Custom ICC profiles |
~/.local/share/omastudio/models/ |
Local AI models (subject.onnx, sky.onnx) |
~/.local/share/omastudio/masks/ |
Masks made by the AI models |
~/.config/omastudio/ |
Settings |
~/.config/omastudio/language |
Interface language picked in the application (absent: system language) |
~/.config/omastudio/cloud/ |
Connected cloud accounts; rclone.conf is encrypted with a key kept in the keyring |
~/.cache/omastudio/cloud/ |
Photos downloaded from cloud accounts |
~/.cache/omastudio/ |
Thumbnails and previews |
<photo>.omastudio |
Adjustments for a photo (sidecar) |
omastudio-engine inspect <raw> # metadata, histogram, scene analysis
omastudio-engine export <raw> --recipe '<json>' --options '<json>'
omastudio-engine fuji-recipe <raf|jpg|fp1|txt> # read a Fujifilm recipe
omastudio-engine fuji-recipe list # saved recipes
omastudio-engine fuji-recipe save <file> --label "Name"
omastudio-engine fuji-recipe export <file> out.FP1 --device X-T30
omastudio-engine fuji-pixel-shift DSCF*.RAF --out merged.dng # GFX Pixel Shift to DNG
omastudio-engine fuji-camera info | presets # camera on USB, custom settings C1-C7
omastudio-engine fuji-camera write-preset C3 recipe.FP1
omastudio-engine fuji-camera convert DSCF0001.RAF --recipe recipe.FP1
omastudio-engine xmp export <raw> # Lightroom / Capture One / darktable sidecar
omastudio-engine xmp import <raw> [--save]
omastudio-engine gpu # GPU in use (OMASTUDIO_GPU=off for CPU only)
omastudio-engine npu # ONNX Runtime, NPU/GPU providers and local models
omastudio-engine ai-mask <raw> --kind subject|sky # mask from a local model
omastudio-engine icc list
omastudio-engine helpAll commands print JSON, so Omarchy agents and scripts can use them directly.
Connect in the filmstrip bar adds Google Drive, OneDrive, Dropbox, Box, pCloud, Yandex Disk or GitHub. You sign in on the service's own page in the browser; OmaStudio never sees the password. Each connected account gets a tab next to Folders and Catalog: browse its folders, click a photo to download it (once, into ~/.cache/omastudio/cloud) and open it. In Export, Upload to also copies the exported files into the account.
- Storage services go through
rclone. OmaStudio keeps its own rclone config, encrypted with a random key stored in the keyring (Secret Service,secret-tool), so access tokens are never on disk in plain text. Your own~/.config/rclone/rclone.confis not touched. - GitHub goes through the GitHub CLI (
gh auth login, device code in the browser);ghkeeps the token in the keyring. An existingghsign-in is reused, and disconnecting in OmaStudio does not logghout. Files are limited to 100 MB, GitHub's own limit. - On connecting, a folder named
OmaStudiois created in the account (on GitHub: a private repositoryOmaStudio). Uploads go there. - rclone's shared Google client is being retired; for Google Drive, a client ID of your own from the Google Cloud Console can be entered under Own Google client ID.
- Disconnecting removes the account's keys and its downloaded copies from this computer; the files in the account stay.
omastudio-engine cloud status # services, missing tools, connected accounts
omastudio-engine cloud connect dropbox # sign in in the browser
omastudio-engine cloud list dropbox-1 Photos/2024
omastudio-engine cloud fetch dropbox-1 Photos/2024/DSCF0001.RAF
omastudio-engine cloud upload dropbox-1 photo_omastudio.jpg
omastudio-engine cloud disconnect dropbox-1omastudio mcp is a Model Context Protocol server (stdio), so any MCP client on Omarchy can inspect, render, cull and export photos, read and apply Fujifilm recipes, use a camera on USB, and control the open window (open a photo, apply a recipe, adjust, zoom, take a screenshot). Rendered previews and window screenshots are returned as images.
claude mcp add omastudio -- omastudio mcp # Claude Code
omastudio skill # installs the agent skill into ~/.claude/skillsOther clients (opencode, Codex, Gemini CLI, ...) take the same command, omastudio mcp, in their MCP server settings. The skill (skill/omastudio/SKILL.md, installed to /usr/share/omastudio/skill) describes the tools, the command line and the recipe format for agents that read skills.
The AI edit assistant in the editor turns a request in plain words into adjustments, using Claude, OpenAI, OpenRouter, Gemini, or a local Ollama or LM Studio model. Keys go to the desktop keyring:
omastudio ai key anthropic # paste the key, then Enter (stored with secret-tool)
omastudio ai use ollama llava # or: anthropic, openai <model>, openrouter <model>, gemini <model>, lmstudio
omastudio ai edit DSCF0001.RAF --prompt "warmer, recover the sky""+ AI SUBJECT" and "+ AI SKY" in the layers panel add a local adjustment layer masked by a segmentation model that runs on this machine; the photo never leaves it. OmaStudio uses ONNX Runtime (onnxruntime) when it is installed and picks the fastest execution provider it offers: NPU (OpenVINO on Intel Core Ultra, QNN on Snapdragon X, Vitis AI on AMD Ryzen AI), then GPU (CUDA, MIGraphX, OpenVINO, WebGPU), then CPU. No model is bundled or downloaded. Put an ONNX segmentation model (for example a salient-object model such as U²-Net, IS-Net or BiRefNet, exported to ONNX) in ~/.local/share/omastudio/models as subject.onnx or sky.onnx. The model takes [1, 3, H, W] RGB and returns a mask; a subject.json next to it can set mean, std and size if the model does not use ImageNet normalisation at 1024 px.
omastudio npu # runtime, accelerators, installed models
OMASTUDIO_NPU=openvino-npu omastudio ai-mask DSCF0001.RAF --kind subjectThe interface is available in 30 languages: Arabic, Chinese (Simplified and Traditional), Czech, Danish, Dutch, English, Finnish, French, German, Greek, Hebrew, Hindi, Hungarian, Indonesian, Italian, Japanese, Korean, Norwegian Bokmål, Persian, Polish, Portuguese (Brazil), Romanian, Russian, Spanish, Swedish, Thai, Turkish, Ukrainian and Vietnamese. Arabic, Hebrew and Persian are laid out right to left.
OmaStudio follows the system language (LANGUAGE, LC_ALL, LC_MESSAGES, LANG) and falls back to English. Another language can be picked from the language menu in the top bar; the change applies at once.
Translations live in app/i18n/qml_<code>.ts:
tools/i18n/update.shrefreshes them from the QML (tools/i18n/update.sh xxstarts a new language).tools/i18n/check.pyfails when a string is missing, left in English, written in the wrong script or has mismatched placeholders. CI runs it on every change.tools/i18n/preview.py OUT_DIR [code ...]writes a screenshot of the interface per language (needs PySide6) to spot text that does not fit.
Engine messages (errors from RAW decoding, export and AI providers) are still in English.
| Key | Action |
|---|---|
Ctrl + O |
Open a photo |
Ctrl + S |
Save adjustments |
Alt + 1..4 |
Switch between grade versions A–D |
1–5, 0 |
Set or clear the star rating |
P, X, U |
Pick, reject, clear flag |
C |
Crop and composition guides |
Y |
Before/after split view |
Ctrl + Shift + C / V |
Copy / paste adjustments |
Ctrl + R |
Reset adjustments |
| Double click | Toggle fit and 1:1 view |
- RAW files are opened read-only and never modified.
- Catalog, settings and sidecars are written atomically with mode
0600; symbolic links are rejected. - Every file the engine reads has a size limit, and every external program it runs has a time limit and its own process group.
- API keys are never passed on the command line.
- The interface renders all dynamic text as plain text and never evaluates code.
Details are in SECURITY.md and CONTRIBUTING.md.
Planned next:
- The full editing pipeline on the GPU (demosaicing already runs there)
- Local AI features accelerated by NPUs
OmaStudio is independent open source software. You can support its development at Buy Me a Coffee.
MIT License © 2026 Ozan Özdil
