Skip to main content

edgefirst_codec/
traits.rs

1// SPDX-FileCopyrightText: Copyright 2026 Au-Zone Technologies
2// SPDX-License-Identifier: Apache-2.0
3
4//! [`ImageLoad`] extension trait for loading images into pre-allocated tensors.
5
6use crate::decoder::ImageDecoder;
7use crate::error::CodecError;
8use crate::options::ImageInfo;
9use crate::pixel::ImagePixel;
10use edgefirst_tensor::{Tensor, TensorDyn};
11use std::io::{BufReader, Read};
12use std::path::Path;
13
14/// Extension trait for loading images into pre-allocated tensors.
15///
16/// Import this trait to add `load_image`, `load_image_read`, and
17/// `load_image_file` methods to [`Tensor<T>`] and [`TensorDyn`].
18///
19/// The decoder configures the tensor's dimensions and pixel format to the
20/// decoded native format (JPEG → `Nv12`/`Grey`, PNG → `Rgb`/`Rgba`/`Grey`).
21/// Allocate the tensor at the maximum expected image size; smaller images
22/// reconfigure it within the same allocation.
23///
24/// # Example
25///
26/// ```rust,no_run
27/// use edgefirst_codec::{ImageDecoder, ImageLoad};
28/// use edgefirst_tensor::{CpuAccess, Tensor, TensorTrait, TensorMemory, PixelFormat};
29///
30/// let mut tensor = Tensor::<u8>::image(1920, 1080, PixelFormat::Nv12, Some(TensorMemory::Mem),
31///                                       CpuAccess::Write)
32///     .expect("alloc");
33/// let mut decoder = ImageDecoder::new();
34///
35/// let jpeg = std::fs::read("image.jpg").unwrap();
36/// let info = tensor.load_image(&mut decoder, &jpeg).unwrap();
37/// println!("Decoded {}×{} {:?}", info.width, info.height, info.format);
38///
39/// let info = tensor.load_image_file(&mut decoder, "image.jpg").unwrap();
40/// ```
41pub trait ImageLoad {
42    /// Decode image bytes (`&[u8]`) into this tensor, configuring its
43    /// dimensions and format to the decoded native format.
44    ///
45    /// The image format (JPEG or PNG) is detected from magic bytes.
46    ///
47    /// # Errors
48    ///
49    /// Returns [`CodecError::InsufficientCapacity`] if the decoded image is
50    /// larger than the tensor's allocation.
51    fn load_image(&mut self, decoder: &mut ImageDecoder, data: &[u8]) -> crate::Result<ImageInfo>;
52
53    /// Decode image data from a [`Read`] source into this tensor.
54    fn load_image_read<R: Read>(
55        &mut self,
56        decoder: &mut ImageDecoder,
57        reader: R,
58    ) -> crate::Result<ImageInfo>;
59
60    /// Decode an image file into this tensor.
61    fn load_image_file(
62        &mut self,
63        decoder: &mut ImageDecoder,
64        path: impl AsRef<Path>,
65    ) -> crate::Result<ImageInfo>;
66}
67
68impl<T: ImagePixel> ImageLoad for Tensor<T> {
69    fn load_image(&mut self, decoder: &mut ImageDecoder, data: &[u8]) -> crate::Result<ImageInfo> {
70        decoder.decode_into(data, self)
71    }
72
73    fn load_image_read<R: Read>(
74        &mut self,
75        decoder: &mut ImageDecoder,
76        reader: R,
77    ) -> crate::Result<ImageInfo> {
78        decoder.decode_from_reader(reader, self)
79    }
80
81    fn load_image_file(
82        &mut self,
83        decoder: &mut ImageDecoder,
84        path: impl AsRef<Path>,
85    ) -> crate::Result<ImageInfo> {
86        let file = std::fs::File::open(path.as_ref()).map_err(CodecError::Io)?;
87        self.load_image_read(decoder, BufReader::new(file))
88    }
89}
90
91impl ImageLoad for TensorDyn {
92    fn load_image(&mut self, decoder: &mut ImageDecoder, data: &[u8]) -> crate::Result<ImageInfo> {
93        decoder.decode_into_dyn(data, self)
94    }
95
96    fn load_image_read<R: Read>(
97        &mut self,
98        decoder: &mut ImageDecoder,
99        reader: R,
100    ) -> crate::Result<ImageInfo> {
101        decoder.decode_from_reader_dyn(reader, self)
102    }
103
104    fn load_image_file(
105        &mut self,
106        decoder: &mut ImageDecoder,
107        path: impl AsRef<Path>,
108    ) -> crate::Result<ImageInfo> {
109        let file = std::fs::File::open(path.as_ref()).map_err(CodecError::Io)?;
110        self.load_image_read(decoder, BufReader::new(file))
111    }
112}