use image;
use std::iter::zip;
#[derive(Debug)]
pub struct Line {
pub x: Vec<u32>,
pub y: Vec<u32>,
pub dist: u32,
}
impl Line {
pub fn new(x: Vec<u32>, y: Vec<u32>, dist: u32) -> Self {
assert_eq!(x.len(), y.len(), "`x` and `y` should have the same length");
Self { x, y, dist }
}
pub fn len(&self) -> usize {
self.x.len()
}
pub fn is_empty(&self) -> bool {
self.x.is_empty()
}
pub fn zip(&self) -> std::iter::Zip<std::slice::Iter<u32>, std::slice::Iter<u32>> {
zip(&self.x, &self.y)
}
pub fn copy(&self) -> Self {
Self::new(self.x.clone(), self.y.clone(), self.dist)
}
pub fn loss(&self, image: &image::ImageBuffer<image::Luma<u8>, Vec<u8>>) -> f64 {
self.zip()
.map(|(x, y)| image.get_pixel(*x, *y))
.fold(0.0, |acc, &pixel| acc + (pixel.0[0] as f64))
/ (255. * self.len() as f64)
}
pub fn draw(
&self,
image: &mut image::ImageBuffer<image::Luma<u8>, Vec<u8>>,
line_opacity: f64,
line_color: f64,
) {
self.zip().for_each(|(x, y)| {
let pixel = image.get_pixel_mut(*x, *y);
pixel.0[0] = ((1. - line_opacity) * pixel.0[0] as f64 + line_color)
.round()
.min(255.0) as u8;
});
}
}