pixel_sort/render/
draw_line.rs

1use crate::VrellisCanvas;
2use image::{GrayImage, Luma, LumaA};
3use imageproc::drawing::{draw_antialiased_line_segment_mut, draw_line_segment_mut, BresenhamLinePixelIter};
4use serde::{Deserialize, Serialize};
5
6#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
7pub enum VrellisAlgorithm {
8    /// Not actually render on the original image
9    NonRendered,
10    /// Render all the passed pixels to maximum values
11    ThinLine,
12    /// Render an anti-aliased line with a velocity of 64
13    AntiAliased,
14}
15
16impl Default for VrellisAlgorithm {
17    fn default() -> Self {
18        Self::AntiAliased
19    }
20}
21
22impl VrellisAlgorithm {
23    pub fn line_score(&self, img: &GrayImage, x1: u32, x2: u32, y1: u32, y2: u32, reversed: bool) -> f32 {
24        let line = BresenhamLinePixelIter::<Luma<u8>>::new(img, (x1 as f32, x2 as f32), (y1 as f32, y2 as f32));
25        let mut sum = 0.0;
26        for p in line {
27            let s = unsafe { *p.0.get_unchecked(0) };
28            sum += match reversed {
29                true => s as f32,
30                false => (255 - s) as f32,
31            }
32        }
33        return sum;
34    }
35    pub fn draw_line(&self, img: &mut GrayImage, x1: u32, x2: u32, y1: u32, y2: u32, reversed: bool) {
36        let pixel = match reversed {
37            true => Luma([0]),
38            false => Luma([255]),
39        };
40        match self {
41            VrellisAlgorithm::NonRendered => (),
42            VrellisAlgorithm::ThinLine => draw_line_segment_mut(img, (x1 as f32, x2 as f32), (y1 as f32, y2 as f32), pixel),
43            VrellisAlgorithm::AntiAliased => draw_antialiased_line_segment_mut(
44                img,
45                (x1 as i32, x2 as i32),
46                (y1 as i32, y2 as i32),
47                pixel,
48                |a, b, c| unsafe {
49                    let a = *a.0.get_unchecked(0) as f32;
50                    let b = *b.0.get_unchecked(0) as f32;
51                    let mix = a + c * (b - a);
52                    Luma([mix.round() as u8])
53                },
54            ),
55        }
56    }
57}
58
59#[allow(dead_code)]
60impl VrellisCanvas {
61    pub(in crate::render) fn draw_canvas_line(&mut self, x1: u32, x2: u32, y1: u32, y2: u32, reversed: bool) {
62        let pixel = match reversed {
63            true => LumaA([255, 255]),
64            false => LumaA([0, 255]),
65        };
66        draw_line_segment_mut(&mut self.current_image, (x1 as f32, x2 as f32), (y1 as f32, y2 as f32), pixel)
67    }
68}