diff --git a/src/lib.rs b/src/lib.rs index 0aff6eb..f0508f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(try_blocks)] #![warn(clippy::pedantic)] mod strandifier; diff --git a/src/strandifier.rs b/src/strandifier.rs index 59e90ea..ffb47cb 100644 --- a/src/strandifier.rs +++ b/src/strandifier.rs @@ -8,8 +8,8 @@ use crate::Layout; #[derive(Clone, Copy, Debug, PartialEq, Eq, Error)] #[allow(clippy::module_name_repetitions)] pub enum StrandifierError { - #[error("Wrong image dimensions")] - WrongDimensions, + #[error("Image too large")] + ImageTooLarge, #[error("Invalid strand number")] InvalidStrand, } @@ -23,6 +23,9 @@ pub struct Strandifier<'a> { pixels_remaining: u32, next_x: u32, next_y: u32, + + offset_x: u32, + offset_y: u32, } impl<'a> Strandifier<'a> { @@ -41,8 +44,8 @@ impl<'a> Strandifier<'a> { image: &'a RgbImage, strand_num: u32, ) -> Result { - if layout.width_px() != image.width() || layout.height_px() != image.height() { - return Err(StrandifierError::WrongDimensions); + if layout.width_px() < image.width() || layout.height_px() < image.height() { + return Err(StrandifierError::ImageTooLarge); } if strand_num > layout.num_strands() { @@ -55,6 +58,9 @@ impl<'a> Strandifier<'a> { let first_x = panel_x * layout.gang_len; let first_y = panel_y * layout.num_gangs; + let offset_x = (layout.width_px() - image.width()) / 2; + let offset_y = (layout.height_px() - image.height()) / 2; + Ok(Self { layout, image, @@ -62,6 +68,9 @@ impl<'a> Strandifier<'a> { pixels_remaining: layout.strand_len(), next_x: first_x, next_y: first_y, + + offset_x, + offset_y, }) } } @@ -98,7 +107,14 @@ impl<'a> Iterator for Strandifier<'a> { } self.pixels_remaining -= 1; - Some(*self.image.get_pixel(x, y)) + let opt_px: Option<_> = try { + let x = x.checked_sub(self.offset_x)?; + let y = y.checked_sub(self.offset_y)?; + + *self.image.get_pixel_checked(x, y)? + }; + + Some(opt_px.unwrap_or(Rgb([0, 0, 0]))) } fn size_hint(&self) -> (usize, Option) { @@ -259,12 +275,12 @@ mod tests { ); let layout2 = Layout { - num_gangs: 6, + num_gangs: 3, ..layout }; assert_eq!( Strandifier::make_strand(layout2, &image, 0).unwrap_err(), - StrandifierError::WrongDimensions + StrandifierError::ImageTooLarge ); } }