rawshift-image 0.1.1

Still-image decoding, RAW processing, and encoding for rawshift
Documentation
[package]
name = "rawshift-image"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
description = "Still-image decoding, RAW processing, and encoding for rawshift"
documentation = "https://docs.rs/rawshift-image"
keywords = ["raw", "image", "dng", "arw", "photo"]
categories = ["multimedia::images", "encoding", "parser-implementations"]
readme = "README.md"

[package.metadata.docs.rs]
# `heic-vendored` and the `jxl-encode-libjxl*` features are intentionally
# excluded: each builds a C/C++ library from source (or links a system one) and
# is an alternative linking mode, not an additive feature.
features = ["full"]
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
rawshift-core  = { workspace = true }
binrw          = { version = "0.15",   optional = true }
libheif-rs     = { version = "2.7",    optional = true }
libwebp-sys    = { version = "0.14",   optional = true }
img-parts      = { version = "0.4",    optional = true }
jpeg-encoder   = { version = "0.7",    optional = true }
jxl-oxide      = { version = "0.12.5", optional = true }
little_exif    = { version = "0.6",    optional = true }
rayon          = { workspace = true }
image          = { version = "0.25", default-features = false, features = ["avif-native"], optional = true }
ravif          = { version = "0.13",   optional = true }
resvg          = { version = "0.44",   optional = true }
serde          = { workspace = true, optional = true }
thiserror      = { workspace = true }
tracing        = { workspace = true }
zune-core      = { version = "0.5",    optional = true }
zune-jpeg      = { version = "0.5",    optional = true }
zune-jpegxl    = { version = "0.5",    optional = true }
zune-png       = { version = "0.5",    optional = true }
zune-ppm       = { version = "0.5",    optional = true }
gif            = { version = "0.13",   optional = true }
tiff           = { version = "0.11",   optional = true }

[build-dependencies]
# Compiled only when a `jxl-encode-libjxl*` feature is enabled (see [features]).
# All permissive (no GPL): bindgen (BSD-3) generates the libjxl C-API bindings;
# pkg-config resolves a system libjxl; jpegxl-src (BSD-3) builds libjxl from
# source via cmake for the vendored feature.
bindgen    = { version = "0.72",   optional = true }
pkg-config = { version = "0.3",    optional = true }
jpegxl-src = { version = "0.11.4", optional = true }

[dev-dependencies]
clap = { version = "4.5", features = ["derive"] }
criterion = { version = "0.5", features = ["html_reports"] }
eyre = "0.6.12"
serde = { workspace = true }
serde_json = "1.0"
tokio = { version = "1.50", features = ["full"] }
tracing = { workspace = true, features = ["release_max_level_debug"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

[features]
# Feature flags are organised in five tiers, high-level to low-level. See the
# "Feature Flags" section of README.md for the full hierarchy and rationale.
#
#   tier 1  bundles            full, experimental, raw-stabilizing, …
#   tier 2  format             jpeg, png, dng, …            (decode + encode)
#   tier 3  direction          jpeg-decode, dng-encode, …   (default impl alias)
#   tier 4  implementation     jpeg-decode-zune, …          (compressed only)
#   tier 5  infrastructure     tiff-parser, serde, zune-runtime, exif, …
#
# Only tier-4 features (and RAW tier-3 features) reference `dep:*`.
default = ["jpeg", "png", "webp", "jxl-decode", "gif-decode", "tiff-decode", "ppm-decode"]

# ── Tier 1: bundle features ───────────────────────────────────────────────────
full = ["jpeg", "png", "webp", "jxl", "gif", "tiff", "avif", "heic", "svg", "ppm",
        "serde", "experimental"]
experimental    = ["raw-stabilizing", "raw-incomplete"]
raw-stabilizing = ["arw", "dng"]      # RAW formats with fixtures + working decode
raw-incomplete  = ["cr2", "cr3", "crw", "nef", "raf"]  # missing fixtures/decode

# ── Tier 2: format features (decode + encode for one format) ──────────────────
jpeg = ["jpeg-decode", "jpeg-encode"]
png  = ["png-decode", "png-encode"]
webp = ["webp-decode", "webp-encode"]
jxl  = ["jxl-decode", "jxl-encode"]
avif = ["avif-decode", "avif-encode"]
gif  = ["gif-decode"]                 # decode-only
tiff = ["tiff-decode"]                # decode-only
heic = ["heic-decode"]                # decode-only
svg  = ["svg-decode"]                 # decode-only
ppm  = ["ppm-decode"]                 # decode-only
arw  = ["arw-decode"]
cr2  = ["cr2-decode"]
cr3  = ["cr3-decode"]
crw  = ["crw-decode"]
dng  = ["dng-decode", "dng-encode"]
nef  = ["nef-decode"]
raf  = ["raf-decode"]

# ── Tier 3: direction features ────────────────────────────────────────────────
# For compressed formats a direction feature is an alias for that
# format+direction's DEFAULT implementation (tier 4) — this is where the notion
# of a per-format default lives. RAW direction features reference infra/deps
# directly: RAW formats have a single in-repo implementation and no tier-4 layer.
jpeg-decode = ["jpeg-decode-zune"]
jpeg-encode = ["jpeg-encode-jpeg-enc"]
png-decode  = ["png-decode-zune"]
png-encode  = ["png-encode-zune"]
webp-decode = ["webp-decode-libwebp"]
webp-encode = ["webp-encode-libwebp"]
jxl-decode  = ["jxl-decode-jxl-oxide"]
jxl-encode  = ["jxl-encode-zune"]
gif-decode  = ["gif-decode-gif"]
tiff-decode = ["tiff-decode-tiff"]
avif-decode = ["avif-decode-image"]
avif-encode = ["avif-encode-ravif"]
heic-decode = ["heic-decode-libheif"]
svg-decode  = ["svg-decode-resvg"]
ppm-decode  = ["ppm-decode-zune"]
arw-decode  = ["tiff-parser"]
cr2-decode  = ["tiff-parser"]
cr3-decode  = ["tiff-parser"]
crw-decode  = []
dng-decode  = ["tiff-parser", "jxl-decode"]
dng-encode  = ["tiff-parser"]
nef-decode  = ["tiff-parser"]
raf-decode  = []

# ── Tier 4: implementation features (compressed formats only) ─────────────────
# Named `format-direction-impl`. The only tier that pulls a `dep:*`. Each impl
# feature also enables its tier-3 direction feature, so it can be selected
# standalone. Multiple implementations of the same format+direction may be
# enabled at once; the active backend is chosen at the API level — see
# `DecodeOptions` and `EncodeOptions`.
# `zune-jpeg`/`zune-png`/`zune-jpegxl` all build on the `zune-core` codec
# primitives, so each zune-backed impl feature also pulls `zune-runtime`.
jpeg-decode-zune     = ["jpeg-decode", "dep:zune-jpeg", "zune-runtime", "exif"]
jpeg-encode-jpeg-enc = ["jpeg-encode", "dep:jpeg-encoder", "exif", "container-embed"]
png-decode-zune      = ["png-decode", "dep:zune-png", "zune-runtime", "exif"]
png-encode-zune      = ["png-encode", "dep:zune-png", "zune-runtime", "exif", "container-embed"]
webp-decode-libwebp  = ["webp-decode", "dep:libwebp-sys", "exif"]
webp-encode-libwebp  = ["webp-encode", "dep:libwebp-sys", "exif", "container-embed"]
jxl-decode-jxl-oxide = ["jxl-decode", "dep:jxl-oxide"]
jxl-encode-zune      = ["jxl-encode", "jxl-decode", "dep:zune-jpegxl", "zune-runtime", "exif", "container-embed"]
# Alternative JXL encoder via libjxl (the reference encoder): 16-bit, true
# lossless, full toggle control. Enabling it keeps `jxl-encode-zune` compiled in
# too (tier-3 aliases the default impl); the active backend is chosen via
# `EncodeOptions`. Links system libjxl by default — see `jxl-encode-libjxl-vendored`.
jxl-encode-libjxl    = ["jxl-encode", "exif", "container-embed", "dep:bindgen", "dep:pkg-config"]
gif-decode-gif       = ["gif-decode", "dep:gif"]
tiff-decode-tiff     = ["tiff-decode", "dep:tiff", "exif"]
avif-decode-image    = ["avif-decode", "dep:image", "exif"]
avif-encode-ravif    = ["avif-encode", "dep:ravif", "exif", "container-embed"]
heic-decode-libheif  = ["heic-decode", "dep:libheif-rs", "exif"]
svg-decode-resvg     = ["svg-decode", "dep:resvg"]
ppm-decode-zune      = ["ppm-decode", "dep:zune-ppm", "zune-runtime"]

# ── Tier 5: infrastructure / linking features ─────────────────────────────────
# Internal TIFF structure parser (used by TIFF-based RAW formats) + public API.
tiff-parser   = ["dep:binrw"]
serde         = ["dep:serde", "rawshift-core/serde"]
# `zune-core` codec primitives (bit depth, colorspace, decoder/encoder option
# builders). Pulled by every zune-backed decode/encode impl feature.
zune-runtime  = ["dep:zune-core"]
# Typed EXIF read/write via `little_exif`. Pulled by format impl features that
# parse embedded EXIF on decode or write it on encode.
exif          = ["dep:little_exif"]
# Container segment muxing via `img-parts` (JPEG APP segments, PNG chunks).
# Pulled by encode impl features that embed EXIF/ICC/XMP metadata.
container-embed = ["dep:img-parts"]
# HEIC/HEIF linking mode. `heic` links the system libheif (resolved by
# pkg-config); `heic-vendored` builds libheif from source via cmake and links
# it statically (needs a C/C++ toolchain + cmake). Enable exactly one.
heic-vendored = ["heic-decode", "libheif-rs/embedded-libheif"]
# libjxl linking mode. `jxl-encode-libjxl` links the system libjxl (resolved by
# pkg-config); `jxl-encode-libjxl-vendored` builds libjxl from source via cmake
# and links it statically (needs a C/C++ toolchain + cmake). Distro libjxl is
# usually too old for the 0.11.x ABI, so the vendored mode is the reliable path.
jxl-encode-libjxl-vendored = ["jxl-encode-libjxl", "dep:jpegxl-src"]

[[bench]]
name = "decode"
harness = false

[[bench]]
name = "demosaic"
harness = false

[[bench]]
name = "pipeline"
harness = false

[[example]]
name = "develop_image"
required-features = ["experimental"]

[[example]]
name = "export_image"
required-features = ["experimental"]

[[example]]
name = "metadata_dump"
required-features = ["experimental"]

[[example]]
name = "heic_inspect"
required-features = ["heic"]

[[test]]
name = "raw_decode_fixtures"
required-features = ["experimental"]

[[test]]
name = "heic_aux"
required-features = ["heic"]

[[test]]
name = "tiff_parser_tests"
required-features = ["tiff-parser"]

[[test]]
name = "dng_check"
required-features = ["tiff-parser"]

[lints.rust]
# `any_raw` / `any_standard_decode` / `any_standard_encode` are cfg aliases
# emitted by build.rs (see `emit_cfg_alias`).
unexpected_cfgs = { level = "warn", check-cfg = [
    'cfg(any_raw)',
    'cfg(any_standard_decode)',
    'cfg(any_standard_encode)',
] }