pbrt_r3/core/imageio/
write_image.rs

1use super::write_image_exr::*;
2use crate::core::base::*;
3use crate::core::error::*;
4use crate::core::geometry::*;
5
6use image::*;
7use std::path::Path;
8
9impl From<image::ImageError> for PbrtError {
10    fn from(value: image::ImageError) -> Self {
11        let msg = value.to_string();
12        return PbrtError::error(&msg);
13    }
14}
15
16fn to_byte(v: Float) -> u8 {
17    Float::clamp(255.0 * gamma_correct(v), 0.0, 255.0) as u8
18}
19
20pub fn write_image_bytes(
21    name: &str,
22    rgb: &[Float],
23    output_bounds: &Bounds2i,
24    _total_resolution: &Point2i,
25) -> Result<(), PbrtError> {
26    let resolution = output_bounds.diagonal();
27    let mut byte_img: Vec<u8> = vec![0; (resolution.x * resolution.y * 3) as usize];
28
29    {
30        let x0: u32 = output_bounds.min.x as u32;
31        let x1: u32 = output_bounds.max.x as u32;
32        let y0: u32 = output_bounds.min.y as u32;
33        let y1: u32 = output_bounds.max.y as u32;
34
35        let width = x1 - x0;
36
37        for y in y0..y1 {
38            let yy = y - y0;
39            for x in x0..x1 {
40                let xx = x - x0;
41                let index: usize = (yy * width + xx) as usize;
42                byte_img[3 * index + 0] = to_byte(rgb[3 * index + 0]);
43                byte_img[3 * index + 1] = to_byte(rgb[3 * index + 1]);
44                byte_img[3 * index + 2] = to_byte(rgb[3 * index + 2]);
45            }
46        }
47    }
48    let img = RgbImage::from_vec(resolution.x as u32, resolution.y as u32, byte_img).unwrap();
49    match img.save(name) {
50        Ok(()) => {
51            return Ok(());
52        }
53        Err(e) => {
54            return Err(PbrtError::from(e));
55        }
56    }
57}
58
59pub fn write_image(
60    name: &str,
61    rgb: &[Float],
62    output_bounds: &Bounds2i,
63    total_resolution: &Point2i,
64) -> Result<(), PbrtError> {
65    if let Some(ext) = Path::new(name).extension() {
66        if let Some(s) = ext.to_str() {
67            match s {
68                "exr" => {
69                    return write_image_exr(name, rgb, output_bounds, total_resolution);
70                }
71                _ => return write_image_bytes(name, rgb, output_bounds, total_resolution),
72            }
73        }
74    }
75    return Err(PbrtError::error("write_image: error"));
76}
77
78pub fn write_image_rgba(
79    _name: &str,
80    _rgba: &[Float],
81    _output_bounds: &Bounds2i,
82    _total_resolution: &Point2i,
83) {
84}
85
86pub fn write_cache_image(
87    name: &str,
88    values: &[f32],
89    resolution: &Point2i,
90) -> Result<(), PbrtError> {
91    let channels = values.len() / (resolution.x * resolution.y) as usize;
92    let float_img = if channels == 3 {
93        values.to_vec()
94    } else {
95        let mut v = vec![0.0; values.len() * 3];
96        for i in 0..values.len() {
97            v[3 * i + 0] = values[i];
98            v[3 * i + 1] = values[i];
99            v[3 * i + 2] = values[i];
100        }
101        v
102    };
103    let img = Rgb32FImage::from_vec(resolution.x as u32, resolution.y as u32, float_img).unwrap();
104    match img.save(name) {
105        Ok(()) => {
106            return Ok(());
107        }
108        Err(e) => {
109            return Err(PbrtError::from(e));
110        }
111    }
112}