del_canvas/
lib.rs

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    ); // Width is 2 pixels and height is 1.
38    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)?; // Save
42    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()?); // Width is 2 pixels and height is 1.
68    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)?; // Save
72    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    // write output
99    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}