edgefirst_codec/lib.rs
1// SPDX-FileCopyrightText: Copyright 2026 Au-Zone Technologies
2// SPDX-License-Identifier: Apache-2.0
3
4//! Image codec for decoding JPEG/PNG into pre-allocated EdgeFirst tensors.
5//!
6//! This crate provides the [`ImageDecoder`] struct and [`ImageLoad`] extension
7//! trait for decoding image files directly into existing tensor buffers —
8//! including DMA-BUF tensors with GPU-aligned pitch padding. The core design
9//! goal is **allocate once, decode many**: users create a tensor at the maximum
10//! expected image size during program initialisation, then call
11//! [`ImageLoad::load_image`] in the hot loop with zero per-frame allocations.
12//!
13//! # Quick Start
14//!
15//! ```rust,no_run
16//! use edgefirst_codec::{ImageDecoder, ImageLoad};
17//! use edgefirst_tensor::{CpuAccess, Tensor, TensorTrait, TensorMemory, PixelFormat};
18//!
19//! // Allocate once (at init), sized for the largest expected image. The
20//! // decoder CPU-writes the pixels: declare `CpuAccess::Write`.
21//! let mut tensor = Tensor::<u8>::image(1920, 1080, PixelFormat::Nv12, Some(TensorMemory::Mem),
22//! CpuAccess::Write)
23//! .expect("allocation");
24//! let mut decoder = ImageDecoder::new();
25//!
26//! // Decode many (in hot loop). The decoder sets the tensor's dimensions and
27//! // native format (JPEG → Nv12/Grey); call `convert()` for RGB.
28//! let jpeg_bytes = std::fs::read("frame.jpg").unwrap();
29//! let info = tensor.load_image(&mut decoder, &jpeg_bytes).expect("decode");
30//! assert!(info.width <= 1920);
31//! assert!(info.height <= 1080);
32//! ```
33//!
34//! # Performance
35//!
36//! For best performance, allocate tensors via
37//! [`ImageProcessor::create_image()`](https://docs.rs/edgefirst-image/latest/edgefirst_image/struct.ImageProcessor.html#method.create_image)
38//! which selects the optimal memory backend (DMA → PBO → Mem) with
39//! GPU-aligned pitch. Free-standing tensors work but cannot use PBO
40//! and may not have aligned pitch.
41//!
42//! # Strided Buffers
43//!
44//! The decoder respects `effective_row_stride()` on the destination tensor.
45//! When a DMA tensor has GPU-aligned pitch padding, decoded pixel rows are
46//! written at the correct stride offsets — no intermediate contiguous buffer
47//! is exposed to the caller.
48
49mod decoder;
50mod error;
51mod exif;
52mod jpeg;
53mod options;
54mod pixel;
55#[cfg(feature = "png")]
56mod png;
57#[cfg(test)]
58mod test_support;
59mod traits;
60
61pub use decoder::{peek_info, ChromaUpsample, DctMethod, ImageDecoder};
62pub use error::{CodecError, UnsupportedFeature};
63pub use options::ImageInfo;
64pub use pixel::ImagePixel;
65pub use traits::ImageLoad;
66
67/// Returns `true` when the nvJPEG GPU JPEG decoder is available at runtime —
68/// Linux with CUDA + libnvjpeg loaded **and** opted in via
69/// `EDGEFIRST_ENABLE_NVJPEG` (off by default, so it never silently contends with
70/// CUDA inference). When `true` the codec prefers it over the V4L2/CPU backends
71/// for CUDA-backed destinations. Always `false` on other platforms or when the
72/// `nvjpeg` feature is disabled. Useful for benchmarks and consumers that branch
73/// on backend availability.
74pub fn nvjpeg_available() -> bool {
75 #[cfg(all(target_os = "linux", feature = "nvjpeg"))]
76 {
77 jpeg::nvjpeg_available()
78 }
79 #[cfg(not(all(target_os = "linux", feature = "nvjpeg")))]
80 {
81 false
82 }
83}
84
85/// Returns `true` when a V4L2 memory-to-memory JPEG decoder (e.g. the i.MX
86/// mxc-jpeg block) is present and not opted out via `EDGEFIRST_DISABLE_V4L2`.
87/// Opens and drops the device once; the decode path re-probes lazily and
88/// keeps its own context. Always `false` on other platforms or when the
89/// `v4l2` feature is disabled. Useful for benchmarks and consumers that must
90/// fail fast instead of silently falling back to the CPU decoder.
91pub fn v4l2_available() -> bool {
92 #[cfg(all(target_os = "linux", feature = "v4l2"))]
93 {
94 jpeg::v4l2_available()
95 }
96 #[cfg(not(all(target_os = "linux", feature = "v4l2")))]
97 {
98 false
99 }
100}
101
102/// Result type for codec operations.
103pub type Result<T> = std::result::Result<T, CodecError>;