Applies to v1.1.0+ 12 min read
Architecture 01 / System Overview

System Architecture & Front-Back Rendering Equivalence Contract

Tauri 2 runtime, asynchronous two-phase pipeline, and WebGL2 shader vs Rust CPU export WYSIWYG contract.

# Process Model & Technical Architecture Topology

NexFilm is engineered as a modern hybrid desktop application, balancing high-throughput raw image processing with a responsive darkroom user interface. The system combines an unmanaged Rust native core with a WebGL2-accelerated web view, integrated across cross-platform environments using the Tauri 2 framework.

The architecture is supported by four core pillars:

  1. Tauri 2 Host & Process Model: The main process executes within a native Rust environment, managing window lifecycles, operating system menus, sandboxed file system access, and asynchronous worker orchestration. The presentation layer runs inside the native operating system web view (WebKit on macOS, WebView2 on Windows, and WebKitGTK 4.1 on Linux). Communication between the front-end interface and native backend occurs strictly across a type-safe asynchronous IPC boundary.
  2. Rust Multithreaded Processing Core: High-throughput tasks—such as demosaicing raw files, projective geometric transformations, relative transmittance normalization, and master file encoding—are handled by compiled Rust routines. Leveraging the Rayon data-parallelism framework, computation saturates multi-core CPU architectures and SIMD vector registers without runtime garbage collection overhead.
  3. Vanilla HTML5 / CSS / WebGL2 UI: The front-end avoids monolithic single-page application frameworks, relying instead on clean vanilla JavaScript, Tailwind CSS utility classes, and hardware-accelerated WebGL2 shaders. Interactive operations—such as adjusting printer lights, manipulating tone curves, or repositioning film gate handles—render on the GPU canvas at 60 frames per second with minimal latency.
  4. SQLite Local Persistence & State Engine: Roll library indexes, four-corner quad coordinates, printer lights offsets, base density measurements, and hardware calibration profiles reside within a local SQLite database (nexfilm_user.db), guaranteeing structured, non-destructive editing sessions.
Architecture Layer Technology & Runtime Primary Responsibilities Performance & Safety Guarantees
Host Runtime Tauri 2 (Rust) Native window management, sandboxed IPC routing, file drag-and-drop Minimal memory footprint; zero bundled Chromium dependencies
Native Core Rust 2021 + Rayon LibRaw / Rawler decoding, streaming TIFF I/O, mathematical pipeline Data parallelism across CPU cores; thread safety; zero segmentation faults
Hardware Shaders WebGL2 (GLSL ES 3.00) Fragment shaders, logarithmic density inversion, tone curve evaluation GPU-accelerated 60fps real-time viewport; smooth UI updates
Local Database SQLite 3 (rusqlite) Library roll metadata, film crop polygons, grading recipes, undo history ACID transaction safety; idempotent schema migrations; local data privacy

# Two-Phase Asynchronous Pipeline: Rapid Ingestion & On-Demand Proxies

Film digitization workflows involve large volumes of high-resolution camera RAW captures or multi-hundred-megabyte drum scanner TIFF files. Attempting to demosaic and invert an entire roll immediately upon folder ingestion would exhaust system memory and freeze the user interface.

To guarantee responsive roll loading within seconds, NexFilm employs a Two-Phase Asynchronous Performance Pipeline:

Phase 1: Library Ingestion (Near-Instantaneous Indexing)
User drops roll folder -> Scan directory contents
      │
      ├─> Extract embedded camera RAW JPEG preview (milliseconds per frame)
      ├─> Stream first-strip IFD thumbnail from TIFF / FFF files
      └─> Populate SQLite roll index; render filmstrip immediately

Phase 2: Develop Workbench (On-Demand Decoding)
User selects a negative frame to enter the Develop view
      │
      ├─> Background thread pool executes full RAW demosaic (LibRaw / Rawler)
      ├─> Linearize into 16-bit linear positive proxy (bounded LRU cache)
      ├─> Upload proxy to WebGL2 texture unit
      └─> Engage real-time 60fps GPU fragment shader grading

During ingestion, the pipeline reads solely the embedded preview thumbnails stored in the raw container headers. The system indexes dozens of film frames in seconds, populating the interactive filmstrip while keeping memory utilization minimal.

Full-resolution demosaicing occurs on demand when a user selects a specific frame to grade in the Develop workspace. The backend allocates worker threads from the background Rayon pool, decodes the raw sensor samples, generates a 16-bit linear positive proxy, and stores it in a bounded LRU cache ring. This strategy confines intensive computation strictly to active user targets, eliminating memory exhaustion risks.

# What-You-See-Is-What-You-Get: The WebGL2 and CPU Equivalence Contract

A critical vulnerability in digital darkroom software is perceptual divergence between interactive screen previews and exported high-resolution files. This discrepancy arises when front-end viewports utilize simplified shader approximations while backend export routines employ distinct CPU math, causing subtle shifts across highlight rolloffs, tonal curves, and color gamuts.

NexFilm enforces an architectural WYSIWYG Mathematical Equivalence Contract:

  1. Shared Source Formulation: When rendering master deliverables, the Rust backend invokes the foundational routine render_shader_equivalent_core in commands.rs. The front-end WebGL2 fragment shader transcribes this exact formula into GLSL code line by line.
  2. Unified Axioms & Numeric Precision:
    • Transmittance to Density Mapping: Both pathways apply the identical numerical threshold ϵ=1.0×10−6\epsilon = 1.0 \times 10^{-6} in evaluating D=−log⁡10(max⁡(T,ϵ))D = -\log_{10}(\max(T, \epsilon)).
    • Neutral Base Anchor: Whenever a valid film base measurement exists, both runtimes fix channel density offsets strictly to zero (channel_offsets = 0), ensuring that the clear base produces neutral display white.
    • Bounded Span Response: The dynamic compensation branch in the GLSL shader mirrors the 1.15×1.15\times deadzone and 1.35×1.35\times / 3.0×3.0\times bounding thresholds of the CPU implementation.
    • Tone Curve Spline Interpolation: Both the viewport shader and the export core sample tone curves via 256-entry or 4096-entry cubic spline lookup tables, guaranteeing identical highlight transitions without tonal banding.
  3. Automated Cross-Platform Verification: Using scripts/verify-density-contract.cjs and shader syntax regression suites, every release validates that shader parameters, uniform bindings, and backend memory structures remain synchronized.
Important

Any feature addition to the rendering pipeline must be implemented concurrently across both the WebGL2 fragment shader and the Rust CPU core. Introducing unaligned mathematical heuristics in either layer is strictly prohibited.

# System Architecture Diagram & End-to-End Signal Topology

The diagram below presents the comprehensive system architecture and module topology of the NexFilm Engine:

Native Front-End (WebView2 / WebKit) Darkroom UI · WebGL2 Viewport View Controllers (main.js) Library / Develop / Rolls / Calib Grading Controls (tone-curve.js) Printer lights sliders / cubic splines Film Crop Geometry (geometry.js) Gate detection / projective quad warping WebGL2 Fragment Shader (Canvas) 60fps real-time grading · GLSL ES 3.00 IPC Client (invoke / listen) Tauri 2 Host & Orchestration System Services · Async IPC Layer IPC Dispatcher (commands.rs) resolve_input_domain / analyze_base Application State (app_state.rs) PipelineState / Roll / TuningParams Async Worker Pool (Rayon) Background decoding · 16-bit proxy LRU Persistence Engine (persistence.rs) nexfilm_user.db · schema migrations File System & Security Boundary Rust Core & Mastering Engine High-Performance Native Compute Dual RAW Decoders (raw_backend.rs) LibRaw 0.22+ & Rawler Rust engine Streaming Readers (io_processor.rs) Scanline strip reader for large TIFF/FFF Color Science Library (color_science.rs) Linear ProPhoto / ACEScg / ICC profiles CPU Export Core (render_shader...) Full-resolution scanline export DNG Writer (dng_writer.rs)

# Local Persistence & Non-Destructive Editing Guarantees

In photographic digitization, user adjustments—including crop polygons, printer lights, and tone curves—represent critical creative decisions. NexFilm adheres to a strict non-destructive editing policy: the software never alters the binary contents of original RAW captures, TIFF scans, or master files on disk.

All session metadata and grading parameters are recorded as lightweight declarative state records in a local SQLite database (nexfilm_user.db). The persistence architecture (src/persistence.rs) is built upon three structural safeguards:

  1. Versioned Schema Migrations: The database tracks explicit integer revisions for MATH_VERSION and RAW_DECODE_VERSION. When optical models evolve (such as the removal of legacy legacy_linear_srgb approximations in v1.1.0), the database executes idempotent migrations via migrate_retired_density_recipe. Older session records are updated transparently while preserving audit histories.
  2. ACID Transactions & Atomic Consistency: Batch grading, parameter replication, and export tagging execute within single database transactions. If an unexpected power outage or system interruption occurs during processing, the database rolls back cleanly, preventing corrupted or half-written session files.
  3. Operating System AppData Segregation: In debug configurations, the database sits beside the repository to facilitate diagnostic testing. In release binaries, the database is stored in standard application directories (~/Library/Application Support/NexFilm Engine/ on macOS and %APPDATA%/NexFilm Engine/ on Windows). This ensures system cleanup utilities do not delete user calibration data.