1pub mod cam2;
2pub mod cam3;
3pub mod canvas_bitmap;
4pub mod canvas_gif;
5pub mod canvas_svg;
6pub mod color;
7pub mod colormap;
8pub mod morphology;
9pub mod rasterize;
10pub mod texture;
11
12use num_traits::AsPrimitive;
13
14pub fn write_png_from_float_image_grayscale<Real, Path>(
15 path: Path,
16 img_shape: (usize, usize),
17 img: &[Real],
18) -> anyhow::Result<()>
19where
20 Real: num_traits::Float + 'static + Copy + AsPrimitive<u8>,
21 usize: AsPrimitive<Real>,
22 Path: AsRef<std::path::Path>,
23{
24 let pix2color_u8: Vec<u8> = img
25 .iter()
26 .map(|&v| {
27 let a: Real = v.clamp(Real::zero(), Real::one());
28 (a * 255.as_()).as_()
29 })
30 .collect();
31 let file = std::fs::File::create(path)?;
32 let w = std::io::BufWriter::new(file);
33 let mut encoder = png::Encoder::new(
34 w,
35 img_shape.0.try_into().unwrap(),
36 img_shape.1.try_into().unwrap(),
37 ); encoder.set_color(png::ColorType::Grayscale);
39 encoder.set_depth(png::BitDepth::Eight);
40 let mut writer = encoder.write_header()?;
41 writer.write_image_data(&pix2color_u8)?; Ok(())
43}
44
45pub fn write_png_from_float_image_rgb<Real, Path>(
46 path: Path,
47 img_shape: &(usize, usize),
48 img: &[Real],
49) -> anyhow::Result<()>
50where
51 Real: num_traits::Float + 'static + Copy + AsPrimitive<u8>,
52 usize: AsPrimitive<Real>,
53 Path: AsRef<std::path::Path>,
54{
55 let zero = Real::zero();
56 let one = Real::one();
57 let v255: Real = 255usize.as_();
58 let pix2color_u8: Vec<u8> = img
59 .iter()
60 .map(|&v| {
61 let a: Real = v.clamp(zero, one);
62 (a * v255).as_()
63 })
64 .collect();
65 let file = std::fs::File::create(path)?;
66 let w = std::io::BufWriter::new(file);
67 let mut encoder = png::Encoder::new(w, img_shape.0.try_into()?, img_shape.1.try_into()?); encoder.set_color(png::ColorType::Rgb);
69 encoder.set_depth(png::BitDepth::Eight);
70 let mut writer = encoder.write_header()?;
71 writer.write_image_data(&pix2color_u8)?; Ok(())
73}
74
75pub fn load_image_as_float_array<P>(path: P) -> anyhow::Result<(Vec<f32>, (usize, usize), usize)>
76where
77 P: AsRef<std::path::Path>,
78{
79 use image::GenericImageView;
80 let img_trg = image::open(path)?;
81 let (width, height) = img_trg.dimensions();
82 let (width, height) = (width as usize, height as usize);
83 let depth: usize = img_trg.color().bytes_per_pixel().into();
84 let img_trg = img_trg.into_bytes();
85 let img_trg: Vec<f32> = img_trg.iter().map(|&v| (v as f32) / 255.0f32).collect();
86 assert_eq!(img_trg.len(), width * height * depth);
87 Ok((img_trg, (width, height), depth))
88}
89
90pub fn write_hdr_file<P>(
91 path_output: P,
92 img_shape: (usize, usize),
93 img: &[f32],
94) -> anyhow::Result<()>
95where
96 P: AsRef<std::path::Path>,
97{
98 let file1 = std::fs::File::create(path_output)?;
100 use image::codecs::hdr::HdrEncoder;
101 let enc = HdrEncoder::new(file1);
102 let img: &[image::Rgb<f32>] =
103 unsafe { std::slice::from_raw_parts(img.as_ptr() as _, img.len() / 3) };
104 let _ = enc.encode(img, img_shape.0, img_shape.1);
105 Ok(())
106}
107
108pub fn write_hdr_file_mse_rgb_error_map(
109 target_file: String,
110 img_shape: (usize, usize),
111 ground_truth: &[f32],
112 img: &[f32],
113) -> anyhow::Result<()> {
114 assert_eq!(img.len(), img_shape.0 * img_shape.1 * 3);
115 assert_eq!(ground_truth.len(), img_shape.0 * img_shape.1 * 3);
116 let err = |a: &[f32], b: &[f32]| -> image::Rgb<f32> {
117 let sq = (a[0] - b[0]).powi(2) + (a[1] - b[1]).powi(2) + (a[2] - b[2]).powi(2);
118 image::Rgb([sq; 3])
119 };
120 let img_error: Vec<image::Rgb<f32>> = img
121 .chunks(3)
122 .zip(ground_truth.chunks(3))
123 .map(|(a, b)| err(a, b))
124 .collect();
125 use image::codecs::hdr::HdrEncoder;
126 let file = std::fs::File::create(target_file)?;
127 let enc = HdrEncoder::new(file);
128 let _ = enc.encode(&img_error, img_shape.0, img_shape.1);
129 Ok(())
130}
131
132pub fn rmse_error(gt: &[f32], rhs: &[f32]) -> f32 {
133 let up: f32 = gt
134 .iter()
135 .zip(rhs.iter())
136 .map(|(&l, &r)| (l - r) * (l - r))
137 .sum();
138 let down: f32 = gt.iter().map(|&v| v * v).sum();
139 up / down
140}
141
142pub fn expand_image(
143 (img_width_in, img_height_in): (usize, usize),
144 img_data_in: &[f32],
145 num_channel: usize,
146 ratio: usize,
147) -> ((usize, usize), Vec<f32>) {
148 assert_eq!(
149 img_width_in * img_height_in * num_channel,
150 img_data_in.len()
151 );
152 let img_width_out = img_width_in * ratio;
153 let img_height_out = img_height_in * ratio;
154 let mut img_data_out = vec![0f32; img_height_out * img_width_out * num_channel];
155 for iwi in 0..img_width_in {
156 for ihi in 0..img_height_in {
157 let pix_in = &img_data_in[(ihi * img_width_in + iwi) * num_channel
158 ..(ihi * img_width_in + iwi + 1) * num_channel];
159 for k in 0..ratio {
160 for l in 0..ratio {
161 let iwo = iwi * ratio + k;
162 let iho = ihi * ratio + l;
163 let pix_out = &mut img_data_out[(iho * img_width_out + iwo) * num_channel
164 ..(iho * img_width_out + iwo + 1) * num_channel];
165 pix_out.copy_from_slice(pix_in);
166 }
167 }
168 }
169 }
170 ((img_width_out, img_height_out), img_data_out)
171}