sagwaco/x3fuse-core

A command-line tool to examine and convert Sigma Foveon .X3F raw files.

Rust

5

29 commits

updated Oct 3, 2026

See the code

README

x3fuse-core

Command-line converter for Sigma Foveon X3F raw files. Decodes Merrill, classic (SD9/SD14-era), and Quattro sensors and writes DNG, TIFF, PPM, embedded JPEG thumbnails, metadata dumps, and histogram CSVs.

Built to power X3Fuse, which provides a GUI for converting X3F files to DNG, TIFF, and JPEG. The codebase is a Rust Cargo workspace with two tiny C log/version shims. OpenCV is not required.

Quick start

Prerequisites: Rust 1.88 or newer (rustup), a C compiler and standard headers, and libclang for bindgen. No external TIFF or JPEG library is required.

cargo build --release
target/release/x3f_extract -dng photo.X3F

This produces target/release/x3f_extract. Multiple input files are processed in parallel.

Rust library

Add the safe API crate to your application's Cargo.toml:

[dependencies]
x3f-core = "0.1.5"

convert_file synchronously converts one file to DNG, TIFF, or its embedded JPEG. Pass an AtomicBool for cooperative cancellation and a callback for the four ConversionStage updates. Each call owns its reader and processing options, so a desktop application can run independent conversions on blocking workers. The destination must not already exist; failed or cancelled conversions remove the output they created.

Usage

x3f_extract <switches> <file1.X3F> [file2.X3F ...]

Output format (choose one)

FlagOutput
-dngDNG LinearRaw (default)
-tiff3×16-bit TIFF
-ppm3×16-bit PPM/P6 (binary)
-ppm-ascii3×16-bit PPM/P3 (ASCII)
-jpgembedded JPEG preview
-rawRAW area, undecoded
-metametadata dump
-histogramhistogram CSV
-loghisthistogram CSV with log exposure

Modifiers

FlagEffect
-o <DIR>write output to <DIR>
-v / -qverbose / quiet (errors only)
-color <SPACE>RGB color space: none, sRGB, AdobeRGB, ProPhotoRGB (does not affect DNG)
-compresslossless compression (DNG: lossless JPEG, TIFF: Deflate/ZIP)
-denoise <0-10>NLM denoise intensity: 0 = off, 10 = full strength (default); intermediate values linearly scale the NLM sigma
-no-denoisedisable the NLM denoise pass (alias for -denoise 0)
-no-cropdo not crop to the active image area
-no-sgain / -sgaindisable / force spatial-gain (lens color) compensation
-no-fix-baddo not fix bad pixels
-wb <PRESET>select a white-balance preset
-unprocesseddump RAW with no preprocessing
-qtopdump the Quattro top layer, unprocessed
-opcodes-dir <DIR>embed pre-rendered DNG OpcodeList3 flat-fielding blobs (see opcodes/)
-dng-highlight-recoveryFoveon highlight recovery for DNG (see DNG output)
-cineon16-bit TIFF with a Cineon-style log tone curve baked in (requires -tiff)
-offset <OFF>RAW offset for SD14 and older (automatic if omitted)
-matrixmax <M>max matrix elements in metadata dump (default 100)

A few X3F_* environment variables tune specific stages, e.g. X3F_CINEON_SCALE (Cineon log-curve scale; default 100) and X3F_DNG_SHOULDER_KNEE (highlight-recovery knee; default 0.85).

Examples

# DNG (LinearRaw) — the default
x3f_extract -dng input.X3F

# 16-bit sRGB TIFF
x3f_extract -tiff -color sRGB input.X3F

# Deflate-compressed TIFF into an output directory
x3f_extract -tiff -compress -o out/ input.X3F

# DNG with a lighter denoise pass (half the default strength)
x3f_extract -dng -denoise 5 input.X3F

# Metadata dump
x3f_extract -meta input.X3F

DNG output

Foveon sensors have no demosaicing step, so DNGs are written as Linear DNGs (PhotometricInterpretation = LinearRaw). To render consistently across RAW engines (Adobe Camera Raw / Lightroom, LibRaw / RawTherapee, Capture One, and Apple's RAW engine) the writer bakes per-channel saturation into the raster and tags a uniform BlackLevel = 0 / WhiteLevel = 65535, and never relies on optional hints like BaselineExposure.

  • -compress: lossless compression. TIFF uses Deflate/ZIP; DNG uses lossless JPEG (Compression = 7), the only 16-bit integer raw compression the spec allows and the one every engine decodes. Compressed output is bit-identical to uncompressed.
  • -dng-highlight-recovery: reconstructs clipped channels from a scene-derived chroma LUT and folds recovered highlights back under WhiteLevel via a soft shoulder baked into the raster (published as LinearResponseLimit).

See the conversion pipeline chapter for the full DNG writer design.

Project layout

x3f-cli  ──▶  x3f-core  ──▶  x3f-sys  ──FFI──▶  C (log/version shims)
PathRole
crates/x3f-clix3f_extract binary
crates/x3f-coresafe Rust API for reading and converting X3F images
crates/x3f-syslow-level layer, bindgen FFI, pure-Rust NLM denoise
crates/x3f-ffi-cC ABI for iOS / Android / WASM consumers
opcodes/pre-rendered DNG OpcodeList3 flat-fielding blobs (Merrill)
docs/mdbook — pipeline, format reference, FFI, contributor guide

Browse the book locally with mdbook serve docs --open (install via cargo install mdbook).

License

Licensed under the Apache License, Version 2.0 — see LICENSE.

This project is based on the work from the Kalpanika x3f project. It is not endorsed by nor affiliated with that project. Attribution for the original BSD-licensed work it derives from is retained in NOTICE.

sagwaco/x3fuse-core

A command-line tool to examine and convert Sigma Foveon .X3F raw files.

Rust

5

29 commits

updated Oct 3, 2026

See the code

README

x3fuse-core

Command-line converter for Sigma Foveon X3F raw files. Decodes Merrill, classic (SD9/SD14-era), and Quattro sensors and writes DNG, TIFF, PPM, embedded JPEG thumbnails, metadata dumps, and histogram CSVs.

Built to power X3Fuse, which provides a GUI for converting X3F files to DNG, TIFF, and JPEG. The codebase is a Rust Cargo workspace with two tiny C log/version shims. OpenCV is not required.

Quick start

Prerequisites: Rust 1.88 or newer (rustup), a C compiler and standard headers, and libclang for bindgen. No external TIFF or JPEG library is required.

cargo build --release
target/release/x3f_extract -dng photo.X3F

This produces target/release/x3f_extract. Multiple input files are processed in parallel.

Rust library

Add the safe API crate to your application's Cargo.toml:

[dependencies]
x3f-core = "0.1.5"

convert_file synchronously converts one file to DNG, TIFF, or its embedded JPEG. Pass an AtomicBool for cooperative cancellation and a callback for the four ConversionStage updates. Each call owns its reader and processing options, so a desktop application can run independent conversions on blocking workers. The destination must not already exist; failed or cancelled conversions remove the output they created.

Usage

x3f_extract <switches> <file1.X3F> [file2.X3F ...]

Output format (choose one)

FlagOutput
-dngDNG LinearRaw (default)
-tiff3×16-bit TIFF
-ppm3×16-bit PPM/P6 (binary)
-ppm-ascii3×16-bit PPM/P3 (ASCII)
-jpgembedded JPEG preview
-rawRAW area, undecoded
-metametadata dump
-histogramhistogram CSV
-loghisthistogram CSV with log exposure

Modifiers

FlagEffect
-o <DIR>write output to <DIR>
-v / -qverbose / quiet (errors only)
-color <SPACE>RGB color space: none, sRGB, AdobeRGB, ProPhotoRGB (does not affect DNG)
-compresslossless compression (DNG: lossless JPEG, TIFF: Deflate/ZIP)
-denoise <0-10>NLM denoise intensity: 0 = off, 10 = full strength (default); intermediate values linearly scale the NLM sigma
-no-denoisedisable the NLM denoise pass (alias for -denoise 0)
-no-cropdo not crop to the active image area
-no-sgain / -sgaindisable / force spatial-gain (lens color) compensation
-no-fix-baddo not fix bad pixels
-wb <PRESET>select a white-balance preset
-unprocesseddump RAW with no preprocessing
-qtopdump the Quattro top layer, unprocessed
-opcodes-dir <DIR>embed pre-rendered DNG OpcodeList3 flat-fielding blobs (see opcodes/)
-dng-highlight-recoveryFoveon highlight recovery for DNG (see DNG output)
-cineon16-bit TIFF with a Cineon-style log tone curve baked in (requires -tiff)
-offset <OFF>RAW offset for SD14 and older (automatic if omitted)
-matrixmax <M>max matrix elements in metadata dump (default 100)

A few X3F_* environment variables tune specific stages, e.g. X3F_CINEON_SCALE (Cineon log-curve scale; default 100) and X3F_DNG_SHOULDER_KNEE (highlight-recovery knee; default 0.85).

Examples

# DNG (LinearRaw) — the default
x3f_extract -dng input.X3F

# 16-bit sRGB TIFF
x3f_extract -tiff -color sRGB input.X3F

# Deflate-compressed TIFF into an output directory
x3f_extract -tiff -compress -o out/ input.X3F

# DNG with a lighter denoise pass (half the default strength)
x3f_extract -dng -denoise 5 input.X3F

# Metadata dump
x3f_extract -meta input.X3F

DNG output

Foveon sensors have no demosaicing step, so DNGs are written as Linear DNGs (PhotometricInterpretation = LinearRaw). To render consistently across RAW engines (Adobe Camera Raw / Lightroom, LibRaw / RawTherapee, Capture One, and Apple's RAW engine) the writer bakes per-channel saturation into the raster and tags a uniform BlackLevel = 0 / WhiteLevel = 65535, and never relies on optional hints like BaselineExposure.

  • -compress: lossless compression. TIFF uses Deflate/ZIP; DNG uses lossless JPEG (Compression = 7), the only 16-bit integer raw compression the spec allows and the one every engine decodes. Compressed output is bit-identical to uncompressed.
  • -dng-highlight-recovery: reconstructs clipped channels from a scene-derived chroma LUT and folds recovered highlights back under WhiteLevel via a soft shoulder baked into the raster (published as LinearResponseLimit).

See the conversion pipeline chapter for the full DNG writer design.

Project layout

x3f-cli  ──▶  x3f-core  ──▶  x3f-sys  ──FFI──▶  C (log/version shims)
PathRole
crates/x3f-clix3f_extract binary
crates/x3f-coresafe Rust API for reading and converting X3F images
crates/x3f-syslow-level layer, bindgen FFI, pure-Rust NLM denoise
crates/x3f-ffi-cC ABI for iOS / Android / WASM consumers
opcodes/pre-rendered DNG OpcodeList3 flat-fielding blobs (Merrill)
docs/mdbook — pipeline, format reference, FFI, contributor guide

Browse the book locally with mdbook serve docs --open (install via cargo install mdbook).

License

Licensed under the Apache License, Version 2.0 — see LICENSE.

This project is based on the work from the Kalpanika x3f project. It is not endorsed by nor affiliated with that project. Attribution for the original BSD-licensed work it derives from is retained in NOTICE.