From a570dc384279bf9b38ff0cc9d4635c2081aa3147 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 6 Mar 2021 11:21:41 +0530 Subject: add image manip apis --- src/lib.rs | 40 ++++++++++++++++++++++++++++++---------- tests/image.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 tests/image.rs diff --git a/src/lib.rs b/src/lib.rs index 7429101..f949d06 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![allow(unreachable_patterns)] #![allow(non_snake_case)] +#![allow(dead_code)] use std::io; @@ -24,6 +25,7 @@ impl OBIVersion { } #[non_exhaustive] +#[derive(Debug)] pub struct FileHeader { pub file_size: u32, pub data_offset: u32, @@ -45,6 +47,7 @@ impl FileHeader { } #[non_exhaustive] +#[derive(Debug)] pub struct ImageInfoHeader { pub width: u32, pub height: u32, @@ -82,6 +85,7 @@ impl CompressionType { } } +#[derive(Debug)] pub struct Image { pub file_header: FileHeader, pub image_info_header: ImageInfoHeader, @@ -90,11 +94,15 @@ pub struct Image { impl Image { pub fn new(width: u32, height: u32) -> Self { + Self::new_with(width, height, false) + } + + pub fn new_with(width: u32, height: u32, default_val: bool) -> Self { // round to the nearest multiple of 8 // convert to number of bytes by dividing by 8 let mut data_size = width * height + 7; data_size = data_size - (data_size % 8); - let data = vec![false; data_size as usize]; + let data = vec![default_val; data_size as usize]; Self { file_header: FileHeader::new(OBIVersion::One, data_size / 8), @@ -111,20 +119,32 @@ impl Image { self.image_info_header.height } - fn to_index(&self, x: u32, y: u32) -> usize { - (y * self.width() + x) as usize - } - - pub fn set_pixel(&mut self, x: u32, y: u32, val: bool) -> OBIResult<()> { - if x >= self.width() || y > self.height() { + #[doc(hidden)] + pub fn index(&self, x: u32, y: u32) -> OBIResult { + if x >= self.width() || y >= self.height() { Err(OBIError::Image) } else { - let index = self.to_index(x, y); - self.data[index] = val; - Ok(()) + return Ok((y * self.width() + x) as usize); } } + pub fn set(&mut self, x: u32, y: u32, val: bool) -> OBIResult<()> { + let index = self.index(x, y)?; + self.data[index] = val; + Ok(()) + } + + pub fn flip(&mut self, x: u32, y: u32) -> OBIResult<()> { + let index = self.index(x, y)?; + self.data[index] = !self.data[index]; + Ok(()) + } + + pub fn get(&self, x: u32, y: u32) -> OBIResult { + let index = self.index(x, y)?; + Ok(self.data[index]) + } + pub fn encode(&self) -> OBIResult> { encode::encode_image(self) } diff --git a/tests/image.rs b/tests/image.rs new file mode 100644 index 0000000..2006a3b --- /dev/null +++ b/tests/image.rs @@ -0,0 +1,49 @@ +use obi::Image; + +#[test] +fn image_indexing() { + let (width, height) = (30, 50); + let img = Image::new(width, height); + for x in 0..width { + for y in 0..height { + assert_eq!((y * width + x) as usize, img.index(x, y).unwrap()); + } + } +} + +#[test] +#[should_panic] +fn x_value_out_of_bounds() { + let img = Image::new(30, 50); + img.index(30, 0).unwrap(); +} + +#[test] +#[should_panic] +fn y_value_out_of_bounds() { + let img = Image::new(30, 50); + img.index(0, 50).unwrap(); +} + +#[test] +fn pixel_setter_and_getters() { + let mut img = Image::new(100, 200); + img.set(2, 3, true).unwrap(); + assert!(img.get(2, 3).unwrap()); + assert_eq!(1, img.data.iter().filter(|&&x| x).count()); +} + +#[test] +fn flip_bits() { + let (width, height) = (100, 200); + let mut img = Image::new(width, height); + img.set(2, 3, true).expect("Indexing error"); + for i in 0..width { + for j in 0..height { + img.flip(i, j).unwrap(); + } + } + let mut expected = Image::new_with(width, height, true); + expected.set(2, 3, false).expect("Indexing error"); + assert_eq!(expected.data, img.data); +} -- cgit v1.2.3