1use super::constants;
2use image::imageops;
3use image::GrayImage;
4use image::DynamicImage;
5
6pub struct Image {
7 width: u32,
8 height: u32,
9 pixels: Vec<bool>,
10}
11
12fn resize_image(img: &DynamicImage) -> DynamicImage {
13 img.resize(constants::MAX_X_WIDTH/2 + constants::MAX_X_WIDTH/16, std::u32::MAX, imageops::FilterType::Nearest)
14}
15
16fn get_image(path: &str) ->
17 Result<DynamicImage, String> {
18 return match image::open(path) {
19 Ok(img) => Ok(img),
20 Err(_) => Err(String::from("Could not open image")),
21 }
22}
23
24fn buffer_to_bool_vec(buffer: &GrayImage) -> Vec<bool> {
25 let mut vec: Vec<bool> = Vec::new();
26 for pixel in buffer.pixels() {
27 vec.push(pixel[0] == 0);
28 }
29 return vec;
30}
31
32pub fn image_from_dynamic(buffer: &image::DynamicImage) -> Result<Image, String> {
34
35 let mut buffer = resize_image(buffer).into_luma8();
36 imageops::dither(&mut buffer, &image::imageops::colorops::BiLevel);
37
38 let vec = buffer_to_bool_vec(&buffer);
39
40 return match Image::new(buffer.width(), buffer.height(), vec) {
41 Ok(img) => Ok(img),
42 Err(_) => Err("Could not create image from buffer".to_string()),
43 }
44}
45
46pub fn image_from_path(path: &str) -> Result<Image, String> {
51
52 let img = match get_image(path) {
53 Ok(img) => img,
54 Err(err) => return Err(err),
55 };
56
57 match image_from_dynamic(&img) {
58 Ok(e) => return Ok(e),
59 Err(err) => return Err(err),
60 }
61}
62
63impl Image {
64
65 pub fn new(width : u32, height: u32, image: Vec<bool>) -> Result<Image, String> {
69 if width > constants::MAX_X_WIDTH {
70 return Err(format!("Width {} exceeds maximum width of 1024",
71 width));
72 }
73 if image.len() != (width * height) as usize {
74 return Err(format!("Image size {} does not match width {} and height {} area {}",
75 image.len(),
76 width,
77 height,
78 width * height));
79 }
80 Ok(
81 Image {
82 width: width/8,
83 height,
84 pixels: image,
85 }
86 )
87 }
88
89 pub fn export(&self ) -> Vec<u8> {
91 let mut to_return = Vec::new();
92 to_return.push(constants::GS); to_return.push(0x76); to_return.push(0x30); to_return.push(0); to_return.push((self.width % 256) as u8); to_return.push((self.width / 256) as u8); to_return.push((self.height % 256) as u8); to_return.push((self.height / 256) as u8); let mut curr: u8 = 0;
102 let mut count = 0;
103 for i in 0..self.pixels.len() {
104 if self.pixels[i] {
105 curr |= 1 << (7 - count);
106 }
107 count += 1;
108 if count == 8 {
109 to_return.push(curr);
110 curr = 0;
111 count = 0;
112 }
113 }
114 to_return
115 }
116}