Skip to content
byvfxPublic

About

Floki — a fast, GPU-accelerated Rust GUI for inspecting and A/B-comparing multi-layer OpenEXR files. Built for VFX/compositing TDs with native exposure, channel isolation, histograms, and pixel-perfect diffing on wgpu.

Topics

Resources

Contributing

Stars

0 stars

Watchers

1 watching

Forks

Repository files navigation

Floki

Rust egui wgpu License: MIT Ko-fi

Floki is a fast, hardware-accelerated Rust GUI application tailored for Technical Directors, Compositors, and LookDev Artists who need to deeply inspect and compare multi-layered OpenEXR files.

Powered by egui, wgpu, and the pure-Rust exr crate, it allows you to instantly view dense pixel data, isolate color channels, explore unbounded floating-point histograms, and perform pixel-perfect A/B diffing — all rendered natively on your GPU — as well as play image sequences in real time.

Floki viewer


Key Features

Hardware-Accelerated Rendering

  • Vulkan/Metal/DX12 Backend: All image exposure scaling, gamma correction, sRGB mapping, and A/B difference matte compositing are executed via custom WGSL shaders on the GPU.
  • GPU-Required Pipeline: All rendering runs on the GPU via wgpu (Vulkan/Metal/DX12); a working GPU and driver are required to launch. (An internal CPU render path exists for contact-sheet thumbnails and headless tests — it is not a runtime fallback for a missing GPU.)

Image-Sequence Playback

Open one frame of a numbered sequence (e.g. render.0101.exr) and play the whole shot — Floki is a review player, not just a still viewer.

  • Transport & timeline: Play/pause, step, reverse, and stop-in-place, with a scrubber/timeline that highlights the trimmed region and marks any missing frames (holes). Editable target fps with a live measured-fps readout.
  • Loop & pacing: Loop, Once, or Ping-Pong; choose Stutter (play every frame; fps drops under load) or Drop-frames (hold the wall-clock rate; skip frames) pacing.
  • In/out trim: Set in/out points to review just a section — the cache and playback respect the trim.
  • Smart cache: A byte-budgeted ring keeps decoded frames resident in RAM and pre-uploaded to the GPU within a live memory budget, so scrub-backs and loops are instant and playback degrades gracefully instead of crashing under memory pressure.
  • Beauty-only fast decode: While playing, only the beauty/first layer is decoded for a much faster, lighter cache on heavy multi-part AOV EXRs; the paused frame re-decodes in full so the pixel readout and AOV switch stay accurate.
  • Eager precache: Optionally cache the whole in/out range up front — a green fill bar under the scrubber shows what's resident — so the span plays and loops with the decoder idle.
  • Live render-watch: Watch the sequence folder and pick up frames as a render writes them (new frames extend the range; re-rendered frames refresh), optionally parking the playhead on the newest frame.

Sequence playback Real-time sequence playback — the scrubber highlights the trimmed in/out region, the green bar shows the cached range, and target/measured fps read out live.

Deep Inspection

  • Precision Pixel Sampling: Hover over any pixel to reveal exact floating-point values (R, G, B, A) regardless of bit-depth (F16, F32, U32).
  • Persistent Swatches: Shift + Click on the image to drop a permanent color swatch into your toolbelt for cross-referencing.
  • Metadata Explorer: Cleanly displays embedded EXR attributes (like V-Ray/Arnold custom tags), layers, and bounding box data in collapsible panels for both Image A and Image B simultaneously.
  • Dual Contact Sheets: Instantly view all AOVs (Arbitrary Output Variables) and layers as a scrollable grid of thumbnails. If a second image is loaded, view dual synchronized contact sheets side-by-side or seamlessly toggle between them.

Contact sheet Dual contact sheets — every AOV and layer as a thumbnail grid, kept in sync across Image A and Image B.

Advanced A/B Comparison

Load a Reference Image (Image B) to unlock advanced visual diffing:

  • Wipe: Split-screen slider for boundary checks — with adjustable center, rotation angle, and divider-line opacity for wipes at any orientation.
  • Side-by-Side: View Image A and Image B glued together in a continuous panorama. They share the same camera for synchronized panning and zooming.
  • Diff Matte: Renders the magnitude of A − B as a false-colour heat map to spot fractional floating-point discrepancies in your render pipelines. Choose the colormap (black-body, grayscale, turbo, viridis, magma, inferno) or build a custom multi-stop gradient in the editor; select the magnitude metric (max channel, Rec.709 luminance, or per-channel RGB); set a noise-floor threshold to ignore sub-threshold noise; and read values off the on-screen legend.
  • Composite: Blend A over B directly in-viewport with selectable blend modes (Over, Under, Add, Multiply, Screen).
  • Blink Mode: Press Spacebar to strobe between Image A and Image B at an adjustable interval.

Comparison controls follow a two-tier toolbar: the everyday controls stay on a single row, while the active mode's parameters slide into a contextual second row only when needed.

Wipe compare mode Wipe compare mode — drag the divider at any angle to check Image A against Image B.

Side-by-side compare mode Side-by-side — Image A and Image B share one camera for synchronized panning and zooming.

Diff matte Diff matte — the magnitude of A − B as a false-colour heat map, with the value legend on-screen.

Image Analysis

  • Dynamic Luminance Histogram: Real-time histogram mapped to Exposure Values (EV stops). Effortlessly spot floating-point highlights over 1.0 using the Logarithmic view.
  • Dual Histogram Mode: When comparing two images, the histogram overlays a translucent Red graph (Image B) on top of the White graph (Image A) so you can visually align black levels.
  • Channel Isolation: Quickly isolate R, G, B, A, or view RGB composite with single-key shortcuts.

Luminance histogram Dual EV histogram — Image B (translucent red) overlaid on Image A (white) to align black levels and catch highlights over 1.0.

Color Management

  • OpenColorIO (built in): OCIO is compiled into every build — there is no non-OCIO build. Point Floki at a config and pick the display/view transform to see your footage in the right space; it auto-enables when a config loads and can be toggled on/off from Color Management. The transform runs on the GPU and can optionally be baked to a 3D LUT for smoother pan/zoom on weaker GPUs.
  • 3D LUT Support: Load Adobe .cube 3D LUTs and apply them in real time on the GPU as a display transform, alongside the built-in Exposure/Gamma/sRGB controls.

OpenColorIO color management Color Management — point Floki at an OCIO config and pick the display/view transform; the transform runs on the GPU.

Customizable Viewport Background

  • Background Modes: Replace the default transparency checkerboard with a checkerboard (custom cell colours and size), a solid colour, or a multi-stop gradient at any angle — set from View ▸ Viewport Background. Save named presets that persist across sessions. The background composites consistently across the GPU and OCIO display paths.
Checkerboard Solid Gradient
Checkerboard background Solid background Gradient background

Snapshot & Review

  • Snapshot to Clipboard: Copy exactly what's on screen to the system clipboard with Cmd/Ctrl + Shift + S (or View ▸ Snapshot to Clipboard) — background, compare mode, OCIO, and annotations all included. Optionally also save a timestamped PNG to ~/.floki/snapshots/.
  • Annotation Overlay: Mark up the view with arrows, boxes, a freehand pen, and text labels (adjustable colour and stroke width) before snapshotting. Annotations anchor to image pixels so they track pan/zoom, support undo/redo and clear-all, and are flattened into the snapshot automatically.

Annotation overlay Annotation overlay — arrows, boxes, freehand pen, and text labels anchor to image pixels and flatten into the snapshot.

Batch Tooling

  • EXR Header Converter: Bulk-rename channels across an entire directory to standard RGBA — available both as an in-app Tools window and a headless convert_dir CLI, parallelized across CPU cores via rayon with live progress and cancellation.

High-Performance UI

  • Immediate-Mode UI: Built on egui for a responsive, minimal-overhead interface.
  • Light / Dark / System Themes: Switch the interface theme from the Theme menu; the System option tracks your OS light/dark setting live. Your choice persists across sessions.
  • Recent Files for A & B: File ▸ Open Recent A / Open Recent B reload a recent EXR straight into the main or reference slot.
  • Drag & Drop Loading: Drop an EXR onto the window to load it — the left half loads it as Image A, the right half as the reference Image B, with a live overlay highlighting which side will receive the drop. Drop two files at once to fill A and B together.
  • Persistent State: Remembers your UI layout, recent files list, theme, and preferences across sessions.
  • Software Tone Mapping: Apply Exposure, Gamma, and sRGB transforms instantly without altering the underlying raw data.
  • Resource Monitor: A discrete status-bar readout tracks floki's own memory footprint and system RAM, plus live GPU VRAM usage on macOS — handy when loading heavy EXRs or sequences. It samples about once a second and tucks into the bottom-right. (The VRAM figure is macOS/Metal only for now; Windows and Linux show RAM.)

Keyboard Shortcuts

Shortcut Action
F Frame Image (Reset Zoom & Pan to fit screen)
R Isolate Red Channel
G Isolate Green Channel
B Isolate Blue Channel
A Isolate Alpha Channel
C View Full RGB (Color)
1 View Image A (when B is loaded)
2 View Image B (when B is loaded)
Space Play / pause the sequence — or, with no sequence loaded, toggle Blink Mode (requires a reference Image B)
← / → Step one frame back / forward (sequence)
I / O Set the in / out trim point to the playhead (sequence)
Cmd/Ctrl + Shift + S Snapshot the current view to the clipboard
Esc Cancel the active annotation tool (or exit fullscreen)
Shift + Click Sample pixel and save to swatch palette
Scroll Wheel Zoom in/out at cursor
Click + Drag Pan Image
Drag & Drop Load EXR — drop on left half → Image A, right half → Image B

Installation & Building

Make sure you have Rust and Cargo installed on your system.

# Clone the repository
git clone https://github.com/byvfx/floki.git
cd floki

# Build and run — needs no OpenColorIO installed (see the tiers below)
cargo run --release --no-default-features

On a clean machine, use --no-default-features. The default build links an installed OpenColorIO and fails at build time if it can't find one. The flag selects the pure-Rust stub backend — no native dependencies, no C++ toolchain — which is also what CI builds and lints. Colour management is then limited to the built-in transforms; see the three tiers below to get full OCIO.

Color management (OpenColorIO)

OCIO support is always compiled — it is mandatory, not an opt-in feature. What you choose is the backend, and there are three tiers. A bare cargo run uses the system backend, which is why it fails on a machine with no OCIO installed.

Tier Command Needs Gets you
Stub cargo run --release --no-default-features nothing beyond Rust Builds and runs anywhere. Built-in transforms only — no .ocio config support. This is what CI builds, lints and tests.
System (default) cargo run --release an installed OCIO Full OCIO, fast builds, no cmake
Vendored cargo ocio-run C++ toolchain, cmake, ninja, python3 Full OCIO, self-contained — what the release binaries ship

Fast dev — link an installed OCIO (system, the default): a plain cargo run --release links an OCIO found via OPENCOLORIO_ROOT (any OS) or Homebrew (macOS). Fast, no cmake.

cargo run --release

Recommended for distribution — self-contained (vendored): statically builds OCIO 2.4.2 from the vendored submodule, so nothing needs to be installed system-wide. Works the same on Windows, Linux, and macOS. The first build is slow (minutes); then it's cached.

# One short command on any OS (cargo alias from .cargo/config.toml):
cargo ocio-run

# …or, to also init the submodule in one shot (requires `just`):
just ocio

Prerequisites: a C++ toolchain (MSVC "Desktop development with C++" on Windows; clang/gcc elsewhere), cmake ≥ 3.14, ninja, python3, and the OCIO submodule checked out (git submodule update --init --recursive — done automatically by just ocio).

Once running, enable it in Color Management… (check Enable OCIO). With the config-path field empty it uses the built-in ACES config, or $OCIO if that environment variable is set (e.g. OCIO=ocio://studio-config-latest). See floki-ocio/README.md for backend/build details.

Windows quick build (scripts/run-windows.ps1)

Because OCIO (and its shaderc dependency) build native code, a Windows dev box needs cmake + ninja + python + the MSVC toolchain on PATH, plus a prebuilt OpenColorIO to link against for the default system-ocio backend. Those tools usually exist but aren't on PATH (cmake/ninja ship inside Visual Studio 2022; python via Anaconda). The helper script assembles that environment (imports vcvars64, prepends the bundled tools, points system-ocio at a vcpkg OCIO) and then runs cargo:

scripts\run-windows.ps1 test          # fmt --check, clippy -D warnings, cargo test
scripts\run-windows.ps1               # cargo run --release  (default task)
scripts\run-windows.ps1 run -- "D:\shots\comp.exr"

Paths default to a common layout and are overridable via FLOKI_VCPKG, FLOKI_ANACONDA, and FLOKI_VSPATH. It's a local dev convenience only — CI does not use it.

Debugging & Logging

The app initializes env_logger, so runtime logging is controlled by the RUST_LOG environment variable. Launch the app from a terminal so log output (written to stderr) is visible.

# PowerShell — watch the EXR Header Converter work through a batch
$env:RUST_LOG = "floki=debug"
cargo run --release
# bash / zsh
RUST_LOG=floki=debug cargo run --release

Useful levels (prefix the target with floki= to filter out noisy wgpu/eframe logs):

RUST_LOG value What you see
floki=info Conversion start line, final summary (N of X files converted), and any errors
floki=debug The above plus a line per converted file and any layer left unchanged by the rename guard
info Everything at info level, including wgpu/eframe startup
floki=info,wgpu=warn App info logs while silencing graphics-backend chatter

Note: During batch conversion, files are processed in parallel across CPU cores, so per-file log lines appear interleaved/out of order. The count in the final summary is authoritative.

Architecture

A birds-eye view of the workspace. The app ships as a single binary backed by a library crate (so benches and integration tests can reach the internals), plus a standalone floki-ocio crate that wraps OpenColorIO.

App shell

  • main.rs — entry point and eframe / wgpu initialization.
  • app.rs — the top-level eframe::App: window and menus, async EXR + LUT loading, snapshot capture, persistence, and the panel layout that hosts the viewer.
  • resource_monitor.rs — throttled RAM / GPU-VRAM sampler feeding the status-bar readout.

Image data

  • exr_loader.rs — threaded OpenEXR decode and logical-layer grouping via the exr crate (the load hot path the benches exercise).

Viewer & rendering

  • viewer.rs — the heavy lifter: canvas pan/zoom, the six compare modes, pixel sampling, histograms, contact sheets, and the GPU render path (plus a CPU path used for contact-sheet thumbnails and headless tests, not as a missing-GPU fallback).
  • gpu/ — the wgpu backend: mod.rs (pipelines, uniforms, bind groups), shader.wgsl (the display / compare / diff / background fragment shader), and ocio_pass.rs (the two-pass OCIO display transform and blit).
  • render_math.rs — shared tone-mapping math (exposure / gamma / sRGB), unit-tested in one place.

Visualization & overlays

  • gradient.rs — reusable multi-stop gradients and the diff colormaps (shared by the heat map and the gradient background).
  • background.rs — the customizable viewport background (checker / solid / gradient), sampled identically across every render path.
  • annotation.rs — the transient arrow / box / pen / text overlay model.
  • snapshot.rs — framebuffer-screenshot capture plus the clipboard / PNG helpers.

Color management

  • color/cube.rs — Adobe .cube 3D-LUT parsing.
  • floki-ocio/ — a standalone crate wrapping OpenColorIO over FFI, with a GLSL→WGSL shader transpiler; always linked (the system-ocio / vendored features select the native backend).

Sequence playback

  • sequence.rs — numbered-sequence detection: parsing, numeric sort, and hole detection.
  • playback.rs — the transport state machine (playhead, loop modes, in/out trim, pacing) and the pure frame-advance logic.
  • scheduler.rs — the pure decode want-list / next-frame scheduler (priority order, prefetch window).
  • cache.rs — the byte-budgeted T1 ring of decoded frames with directional-ring + LRU eviction.
  • budget.rs — the RAM budget math sizing the T1 ring from a live memory sample.
  • pixels.rs — pure pixel access over decoded EXR channels + thumbnail decimation.
  • prefetch.rs — read-ahead file warmer; overlaps the next frame's file read with the current decode via the OS page cache.
  • proxy_cache.rs — persistent on-disk proxy cache (~/.floki/proxy-cache), so a scrub proxy's first-touch decode is paid once ever.
  • tex_upload.rs — off-thread comp-texture upload; the paint thread submits a frame and collects a finished GPU texture instead of interleaving and uploading inline.
  • layer.rs — the pure comp layer-stack model backing A/B compare (the spine for N-way / locked-step).

Tooling & CLI

  • tools.rs — the multi-threaded EXR Header Converter (batch channel renaming via rayon) with progress reporting and RUST_LOG logging.
  • bin/ — headless helpers: convert_dir (batch rename), inspect_exr, and check_types.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Floki — a fast, GPU-accelerated Rust GUI for inspecting and A/B-comparing multi-layer OpenEXR files. Built for VFX/compositing TDs with native exposure, channel isolation, histograms, and pixel-perfect diffing on wgpu.

Topics

Resources

Contributing

Stars

0 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Contributors

Languages