Skip to main content

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;
55mod png;
56mod traits;
57
58pub use decoder::{peek_info, ImageDecoder};
59pub use error::{CodecError, UnsupportedFeature};
60pub use options::ImageInfo;
61pub use pixel::ImagePixel;
62pub use traits::ImageLoad;
63
64/// Returns `true` when the nvJPEG GPU JPEG decoder is available at runtime —
65/// Linux with CUDA + libnvjpeg loaded **and** opted in via
66/// `EDGEFIRST_ENABLE_NVJPEG` (off by default, so it never silently contends with
67/// CUDA inference). When `true` the codec prefers it over the V4L2/CPU backends
68/// for CUDA-backed destinations. Always `false` on other platforms or when the
69/// `nvjpeg` feature is disabled. Useful for benchmarks and consumers that branch
70/// on backend availability.
71pub fn nvjpeg_available() -> bool {
72    #[cfg(all(target_os = "linux", feature = "nvjpeg"))]
73    {
74        jpeg::nvjpeg_available()
75    }
76    #[cfg(not(all(target_os = "linux", feature = "nvjpeg")))]
77    {
78        false
79    }
80}
81
82/// Result type for codec operations.
83pub type Result<T> = std::result::Result<T, CodecError>;