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::{Tensor, TensorTrait, TensorMemory, PixelFormat};
18//!
19//! // Allocate once (at init), sized for the largest expected image.
20//! let mut tensor = Tensor::<u8>::image(1920, 1080, PixelFormat::Nv12, Some(TensorMemory::Mem))
21//! .expect("allocation");
22//! let mut decoder = ImageDecoder::new();
23//!
24//! // Decode many (in hot loop). The decoder sets the tensor's dimensions and
25//! // native format (JPEG → Nv12/Grey); call `convert()` for RGB.
26//! let jpeg_bytes = std::fs::read("frame.jpg").unwrap();
27//! let info = tensor.load_image(&mut decoder, &jpeg_bytes).expect("decode");
28//! assert!(info.width <= 1920);
29//! assert!(info.height <= 1080);
30//! ```
31//!
32//! # Performance
33//!
34//! For best performance, allocate tensors via
35//! [`ImageProcessor::create_image()`](https://docs.rs/edgefirst-image/latest/edgefirst_image/struct.ImageProcessor.html#method.create_image)
36//! which selects the optimal memory backend (DMA → PBO → Mem) with
37//! GPU-aligned pitch. Free-standing tensors work but cannot use PBO
38//! and may not have aligned pitch.
39//!
40//! # Strided Buffers
41//!
42//! The decoder respects `effective_row_stride()` on the destination tensor.
43//! When a DMA tensor has GPU-aligned pitch padding, decoded pixel rows are
44//! written at the correct stride offsets — no intermediate contiguous buffer
45//! is exposed to the caller.
46
47mod decoder;
48mod error;
49mod exif;
50mod jpeg;
51mod options;
52mod pixel;
53mod png;
54mod traits;
55
56pub use decoder::{peek_info, ImageDecoder};
57pub use error::{CodecError, UnsupportedFeature};
58pub use options::ImageInfo;
59pub use pixel::ImagePixel;
60pub use traits::ImageLoad;
61
62/// Returns `true` when the nvJPEG GPU JPEG decoder is available at runtime —
63/// Linux with CUDA + libnvjpeg loaded **and** opted in via
64/// `EDGEFIRST_ENABLE_NVJPEG` (off by default, so it never silently contends with
65/// CUDA inference). When `true` the codec prefers it over the V4L2/CPU backends
66/// for CUDA-backed destinations. Always `false` on other platforms or when the
67/// `nvjpeg` feature is disabled. Useful for benchmarks and consumers that branch
68/// on backend availability.
69pub fn nvjpeg_available() -> bool {
70 #[cfg(all(target_os = "linux", feature = "nvjpeg"))]
71 {
72 jpeg::nvjpeg_available()
73 }
74 #[cfg(not(all(target_os = "linux", feature = "nvjpeg")))]
75 {
76 false
77 }
78}
79
80/// Result type for codec operations.
81pub type Result<T> = std::result::Result<T, CodecError>;