pbrt_r3/core/imageio/
write_image.rs1use 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}