1use crate::error::Result;
2use crate::image::Image;
3use burn::tensor::{Tensor, TensorData, backend::Backend};
4use std::path::Path;
5
6pub fn load_image<B: Backend>(path: impl AsRef<Path>, device: &B::Device) -> Result<Image<B>> {
9 let img = image::open(path)?;
10 let img = img.to_rgb8();
11 let (width, height) = img.dimensions();
12 let w = width as usize;
13 let h = height as usize;
14 let c = 3usize;
15
16 let mut flat_data = vec![0.0f32; c * h * w];
17 let pixels = img.as_flat_samples();
18 let slice = pixels.as_slice();
19
20 for y in 0..h {
21 for x in 0..w {
22 let idx = (y * w + x) * 3;
23 flat_data[y * w + x] = f32::from(slice[idx]) / 255.0; flat_data[h * w + y * w + x] = f32::from(slice[idx + 1]) / 255.0; flat_data[2 * h * w + y * w + x] = f32::from(slice[idx + 2]) / 255.0; }
28 }
29
30 let tensor_data = TensorData::new(flat_data, [c, h, w]);
31 let tensor = Tensor::<B, 3>::from_data(tensor_data, device);
32 Ok(Image::new(tensor))
33}
34
35pub fn save_image<B: Backend>(image: &Image<B>, path: impl AsRef<Path>) -> Result<()> {
38 let dims = image.tensor.dims();
39 let c = dims[0];
40 let h = dims[1];
41 let w = dims[2];
42
43 let tensor_data = image.tensor.clone().into_data();
46 let flat_vals: Vec<f32> = tensor_data.iter::<f32>().collect();
47
48 let mut img_buf = image::ImageBuffer::new(w as u32, h as u32);
49
50 for y in 0..h {
51 for x in 0..w {
52 let r_val = flat_vals[y * w + x];
53 let g_val = if c > 1 {
54 flat_vals[h * w + y * w + x]
55 } else {
56 r_val
57 };
58 let b_val = if c > 2 {
59 flat_vals[2 * h * w + y * w + x]
60 } else {
61 r_val
62 };
63
64 let r = (r_val.clamp(0.0, 1.0) * 255.0) as u8;
65 let g = (g_val.clamp(0.0, 1.0) * 255.0) as u8;
66 let b = (b_val.clamp(0.0, 1.0) * 255.0) as u8;
67
68 img_buf.put_pixel(x as u32, y as u32, image::Rgb([r, g, b]));
69 }
70 }
71
72 img_buf.save(path)?;
73 Ok(())
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use crate::test_helpers::{TestBackend, test_device};
80
81 #[test]
82 fn test_image_io() {
83 let device = test_device();
84 let flat_data = vec![0.5f32; 3 * 8 * 8];
85 let tensor =
86 Tensor::<TestBackend, 3>::from_data(TensorData::new(flat_data, [3, 8, 8]), &device);
87 let img = Image::new(tensor);
88
89 let temp_path = "temp_test_io.png";
90 save_image(&img, temp_path).unwrap();
91
92 let loaded = load_image::<TestBackend>(temp_path, &device).unwrap();
93 assert_eq!(loaded.shape(), [3, 8, 8]);
94
95 let _ = std::fs::remove_file(temp_path);
96 }
97}