1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
extern crate image; use ndarray::*; use image::{ImageDecoder, DecodingResult, ColorType}; use string_error::{static_err}; use std::error::Error; use std::io::{Read, Write, Cursor}; pub fn convolve2d(base_arr: &Array2<f32>, filter: &Array2<f32>) -> Array2<f32> { let ys: isize = base_arr.shape()[0] as isize; let xs: isize = base_arr.shape()[1] as isize; let mut result: Array2<f32> = Array2::<f32>::zeros((ys as usize, xs as usize)); for yt in 1..((result.shape()[0]-1) as isize) { for xt in 1..((result.shape()[1]-1) as isize) { result[[yt as usize, xt as usize]] = (&base_arr.slice(s![yt-1..yt+2, xt-1..xt+2]) * filter).scalar_sum(); } } return result; } pub fn read_image<R: Read>(mut image_file: R) -> Result<Array3<f32>, Box<dyn Error>> { let mut image_buffer = Vec::new(); image_file.read_to_end(&mut image_buffer)?; let format = image::guess_format(&image_buffer)?; let image_reader = Cursor::new(image_buffer); match format { image::ImageFormat::PNG => read_to_array(image::png::PNGDecoder::new(image_reader)), image::ImageFormat::JPEG => read_to_array(image::jpeg::JPEGDecoder::new(image_reader)), _ => Err(static_err("Unsupported file type. Only PNG and JPEG are supported.")), } } fn read_to_array<D: ImageDecoder>(mut decoder: D) -> Result<Array3<f32>, Box<dyn Error>> { let result = decoder.read_image()?; let (x, y) = decoder.dimensions()?; let colortype = decoder.colortype()?; let raw_data = match result { DecodingResult::U8(v) => v.into_iter().map(|e| e as f32).collect::<Vec<f32>>(), DecodingResult::U16(v) => v.into_iter().map(|e| e as f32).collect::<Vec<f32>>(), }; let arr = Array1::<f32>::from(raw_data); match colortype { ColorType::RGBA(_) => arr.into_shape((y as Ix, x as Ix, 4 as Ix)).map_err(|_| static_err("Wrong shape!")), ColorType::RGB(_) => arr.into_shape((y as Ix, x as Ix, 3 as Ix)).map_err(|_| static_err("Wrong shape!")), _ => Err(static_err("Unsupported colortype")), } } pub fn write_grayscale_png(image_file: Box<dyn Write>, img: &Array2<f32>) -> Result<(), Box<dyn Error>> { let decoder = image::png::PNGEncoder::new(image_file); let shape = img.shape(); let height = shape[0] as u32; let width = shape[1] as u32; let u8img = img.clone().map(|e| *e as u8); let data = u8img.as_slice().unwrap(); decoder.encode( data, width, height, ColorType::Gray(8) ).map_err(|_| static_err("Error writing image!")) }