hank-bond/x3fuse-core

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

Rust

0

51 commits

updated Oct 4, 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)
-dng-highlight-mapping <MODE>store recovered highlights with linear (default) or shoulder mapping
-dng-recovery-maskwrite a source-reliability mask beside the DNG (requires recovery)
-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

See DNG highlight recovery for usage, sensor support, and reconstruction stages. Recovery is off by default.

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. Linear highlight recovery uses BaselineExposure to compensate for its shared encoding scale.

  • -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: on Merrill, estimates brightness, reconstructs spatial detail, and adds color from nearby reliable pixels. Older sensors and Quattro retain separate recovery paths. Linear mapping preserves relative brightness by default, with shoulder compression available through -dng-highlight-mapping shoulder.
  • -dng-recovery-mask: writes a separate mask of unreliable source measurements for training exclusions. See the recovery mask guide.

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.

hank-bond/x3fuse-core

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

Rust

0

51 commits

updated Oct 4, 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)
-dng-highlight-mapping <MODE>store recovered highlights with linear (default) or shoulder mapping
-dng-recovery-maskwrite a source-reliability mask beside the DNG (requires recovery)
-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

See DNG highlight recovery for usage, sensor support, and reconstruction stages. Recovery is off by default.

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. Linear highlight recovery uses BaselineExposure to compensate for its shared encoding scale.

  • -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: on Merrill, estimates brightness, reconstructs spatial detail, and adds color from nearby reliable pixels. Older sensors and Quattro retain separate recovery paths. Linear mapping preserves relative brightness by default, with shoulder compression available through -dng-highlight-mapping shoulder.
  • -dng-recovery-mask: writes a separate mask of unreliable source measurements for training exclusions. See the recovery mask guide.

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.