diff --git a/Cargo.toml b/Cargo.toml index 48c36b96..22e3a4cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ display-window = ["sdl2"] [dependencies] approx = "0.5" conv = "0.3.3" -image = { version = "0.23.6", default-features = false } +image = { version = "0.24.1", default-features = false } itertools = "0.10" nalgebra = { version = "0.30", default-features = false, features = ["std"] } num = "0.4" @@ -31,7 +31,7 @@ sdl2 = { version = "0.35", optional = true, default-features = false, features = [dev-dependencies] assert_approx_eq = "1.1.0" -image = "0.23.6" +image = "0.24.1" quickcheck = "0.9.2" wasm-bindgen-test = "0.3.14" diff --git a/src/definitions.rs b/src/definitions.rs index 7ab8471e..b97c5f40 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -1,6 +1,6 @@ //! Trait definitions and type aliases. -use image::{Bgr, Bgra, ImageBuffer, Luma, LumaA, Pixel, Rgb, Rgba}; +use image::{ImageBuffer, Luma, LumaA, Pixel, Rgb, Rgba}; use std::{i16, u16, u8}; /// An `ImageBuffer` containing Pixels of type P with storage `Vec`. @@ -64,18 +64,6 @@ impl_black_white!( Rgba([u16::MIN, u16::MIN, u16::MIN, u16::MAX]), Rgba([u16::MAX, u16::MAX, u16::MAX, u16::MAX]) ); -impl_black_white!(Bgr, Bgr([u8::MIN; 3]), Bgr([u8::MAX; 3])); -impl_black_white!(Bgr, Bgr([u16::MIN; 3]), Bgr([u16::MAX; 3])); -impl_black_white!( - Bgra, - Bgra([u8::MIN, u8::MIN, u8::MIN, u8::MAX]), - Bgra([u8::MAX, u8::MAX, u8::MAX, u8::MAX]) -); -impl_black_white!( - Bgra, - Bgra([u16::MIN, u16::MIN, u16::MIN, u16::MAX]), - Bgra([u16::MAX, u16::MAX, u16::MAX, u16::MAX]) -); /// Something with a 2d position. pub trait Position { diff --git a/src/drawing/bezier.rs b/src/drawing/bezier.rs index 9feee3ca..3fe82489 100644 --- a/src/drawing/bezier.rs +++ b/src/drawing/bezier.rs @@ -19,7 +19,6 @@ pub fn draw_cubic_bezier_curve( ) -> Image where I: GenericImage, - I::Pixel: 'static, { let mut out = ImageBuffer::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); @@ -39,7 +38,6 @@ pub fn draw_cubic_bezier_curve_mut( color: C::Pixel, ) where C: Canvas, - C::Pixel: 'static, { // Bezier Curve function from: https://pomax.github.io/bezierinfo/#control let cubic_bezier_curve = |t: f32| { diff --git a/src/drawing/canvas.rs b/src/drawing/canvas.rs index 65d6aab0..471ce2a2 100644 --- a/src/drawing/canvas.rs +++ b/src/drawing/canvas.rs @@ -110,6 +110,8 @@ impl Canvas for Blend { } fn draw_pixel(&mut self, x: u32, y: u32, color: Self::Pixel) { - self.0.get_pixel_mut(x, y).blend(&color) + let mut pix = self.0.get_pixel(x, y); + pix.blend(&color); + self.0.put_pixel(x, y, pix); } } diff --git a/src/drawing/conics.rs b/src/drawing/conics.rs index 458cf8f9..ac7f2337 100644 --- a/src/drawing/conics.rs +++ b/src/drawing/conics.rs @@ -26,7 +26,6 @@ pub fn draw_hollow_ellipse( ) -> Image where I: GenericImage, - I::Pixel: 'static, { let mut out = ImageBuffer::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); @@ -52,7 +51,6 @@ pub fn draw_hollow_ellipse_mut( color: C::Pixel, ) where C: Canvas, - C::Pixel: 'static, { // Circle drawing algorithm is faster, so use it if the given ellipse is actually a circle. if width_radius == height_radius { @@ -90,7 +88,6 @@ pub fn draw_filled_ellipse( ) -> Image where I: GenericImage, - I::Pixel: 'static, { let mut out = ImageBuffer::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); @@ -116,7 +113,6 @@ pub fn draw_filled_ellipse_mut( color: C::Pixel, ) where C: Canvas, - C::Pixel: 'static, { // Circle drawing algorithm is faster, so use it if the given ellipse is actually a circle. if width_radius == height_radius { @@ -204,7 +200,6 @@ pub fn draw_hollow_circle( ) -> Image where I: GenericImage, - I::Pixel: 'static, { let mut out = ImageBuffer::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); @@ -218,7 +213,6 @@ where pub fn draw_hollow_circle_mut(canvas: &mut C, center: (i32, i32), radius: i32, color: C::Pixel) where C: Canvas, - C::Pixel: 'static, { let mut x = 0i32; let mut y = radius; @@ -252,7 +246,6 @@ where pub fn draw_filled_circle_mut(canvas: &mut C, center: (i32, i32), radius: i32, color: C::Pixel) where C: Canvas, - C::Pixel: 'static, { let mut x = 0i32; let mut y = radius; @@ -308,7 +301,6 @@ pub fn draw_filled_circle( ) -> Image where I: GenericImage, - I::Pixel: 'static, { let mut out = ImageBuffer::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); diff --git a/src/drawing/cross.rs b/src/drawing/cross.rs index 00dcbd01..7eb3ab64 100644 --- a/src/drawing/cross.rs +++ b/src/drawing/cross.rs @@ -43,7 +43,6 @@ where pub fn draw_cross(image: &I, color: I::Pixel, x: i32, y: i32) -> Image where I: GenericImage, - I::Pixel: 'static, { let mut out = ImageBuffer::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); diff --git a/src/drawing/line.rs b/src/drawing/line.rs index cfb22b13..815fecd2 100644 --- a/src/drawing/line.rs +++ b/src/drawing/line.rs @@ -92,12 +92,12 @@ fn clamp_point(p: (f32, f32), image: &I) -> (f32, f32) { /// Iterates over the image pixels in a line segment using /// [Bresenham's line drawing algorithm](https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm). -pub struct BresenhamLinePixelIter<'a, P: Pixel + 'static> { +pub struct BresenhamLinePixelIter<'a, P: Pixel> { iter: BresenhamLineIter, image: &'a Image

, } -impl<'a, P: Pixel + 'static> BresenhamLinePixelIter<'a, P> { +impl<'a, P: Pixel> BresenhamLinePixelIter<'a, P> { /// Creates a [`BresenhamLinePixelIter`](struct.BresenhamLinePixelIter.html) which will iterate over /// the image pixels with coordinates between `start` and `end`. pub fn new( @@ -114,7 +114,7 @@ impl<'a, P: Pixel + 'static> BresenhamLinePixelIter<'a, P> { } } -impl<'a, P: Pixel + 'static> Iterator for BresenhamLinePixelIter<'a, P> { +impl<'a, P: Pixel> Iterator for BresenhamLinePixelIter<'a, P> { type Item = &'a P; fn next(&mut self) -> Option { @@ -126,12 +126,12 @@ impl<'a, P: Pixel + 'static> Iterator for BresenhamLinePixelIter<'a, P> { /// Iterates over the image pixels in a line segment using /// [Bresenham's line drawing algorithm](https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm). -pub struct BresenhamLinePixelIterMut<'a, P: Pixel + 'static> { +pub struct BresenhamLinePixelIterMut<'a, P: Pixel> { iter: BresenhamLineIter, image: &'a mut Image

, } -impl<'a, P: Pixel + 'static> BresenhamLinePixelIterMut<'a, P> { +impl<'a, P: Pixel> BresenhamLinePixelIterMut<'a, P> { /// Creates a [`BresenhamLinePixelIterMut`](struct.BresenhamLinePixelIterMut.html) which will iterate over /// the image pixels with coordinates between `start` and `end`. pub fn new( @@ -154,7 +154,7 @@ impl<'a, P: Pixel + 'static> BresenhamLinePixelIterMut<'a, P> { } } -impl<'a, P: Pixel + 'static> Iterator for BresenhamLinePixelIterMut<'a, P> { +impl<'a, P: Pixel> Iterator for BresenhamLinePixelIterMut<'a, P> { type Item = &'a mut P; fn next(&mut self) -> Option { @@ -179,7 +179,6 @@ pub fn draw_line_segment( ) -> Image where I: GenericImage, - I::Pixel: 'static, { let mut out = ImageBuffer::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); @@ -195,7 +194,6 @@ where pub fn draw_line_segment_mut(canvas: &mut C, start: (f32, f32), end: (f32, f32), color: C::Pixel) where C: Canvas, - C::Pixel: 'static, { let (width, height) = canvas.dimensions(); let in_bounds = |x, y| x >= 0 && x < width as i32 && y >= 0 && y < height as i32; @@ -230,7 +228,7 @@ pub fn draw_antialiased_line_segment( ) -> Image where I: GenericImage, - I::Pixel: 'static, + B: Fn(I::Pixel, I::Pixel, f32) -> I::Pixel, { let mut out = ImageBuffer::new(image.width(), image.height()); @@ -255,7 +253,7 @@ pub fn draw_antialiased_line_segment_mut( blend: B, ) where I: GenericImage, - I::Pixel: 'static, + B: Fn(I::Pixel, I::Pixel, f32) -> I::Pixel, { let (mut x0, mut y0) = (start.0, start.1); @@ -295,7 +293,7 @@ fn plot_wu_line( color: I::Pixel, ) where I: GenericImage, - I::Pixel: 'static, + T: Fn(i32, i32) -> (i32, i32), B: Fn(I::Pixel, I::Pixel, f32) -> I::Pixel, { @@ -314,7 +312,7 @@ fn plot_wu_line( struct Plotter<'a, I, T, B> where I: GenericImage, - I::Pixel: 'static, + T: Fn(i32, i32) -> (i32, i32), B: Fn(I::Pixel, I::Pixel, f32) -> I::Pixel, { @@ -326,7 +324,7 @@ where impl<'a, I, T, B> Plotter<'a, I, T, B> where I: GenericImage, - I::Pixel: 'static, + T: Fn(i32, i32) -> (i32, i32), B: Fn(I::Pixel, I::Pixel, f32) -> I::Pixel, { diff --git a/src/drawing/mod.rs b/src/drawing/mod.rs index 3527fca0..2b72db4f 100644 --- a/src/drawing/mod.rs +++ b/src/drawing/mod.rs @@ -40,7 +40,6 @@ pub use self::text::{draw_text, draw_text_mut, text_size}; fn draw_if_in_bounds(canvas: &mut C, x: i32, y: i32, color: C::Pixel) where C: Canvas, - C::Pixel: 'static, { if x >= 0 && x < canvas.width() as i32 && y >= 0 && y < canvas.height() as i32 { canvas.draw_pixel(x as u32, y as u32, color); diff --git a/src/drawing/polygon.rs b/src/drawing/polygon.rs index b7ca7173..29639065 100644 --- a/src/drawing/polygon.rs +++ b/src/drawing/polygon.rs @@ -16,7 +16,6 @@ use std::i32; pub fn draw_polygon(image: &I, poly: &[Point], color: I::Pixel) -> Image where I: GenericImage, - I::Pixel: 'static, { let mut out = ImageBuffer::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); @@ -32,7 +31,6 @@ where pub fn draw_polygon_mut(canvas: &mut C, poly: &[Point], color: C::Pixel) where C: Canvas, - C::Pixel: 'static, { if poly.is_empty() { return; diff --git a/src/drawing/rect.rs b/src/drawing/rect.rs index 8013124f..97aac56f 100644 --- a/src/drawing/rect.rs +++ b/src/drawing/rect.rs @@ -12,7 +12,6 @@ use std::f32; pub fn draw_hollow_rect(image: &I, rect: Rect, color: I::Pixel) -> Image where I: GenericImage, - I::Pixel: 'static, { let mut out = ImageBuffer::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); @@ -26,7 +25,6 @@ where pub fn draw_hollow_rect_mut(canvas: &mut C, rect: Rect, color: C::Pixel) where C: Canvas, - C::Pixel: 'static, { let left = rect.left() as f32; let right = rect.right() as f32; @@ -46,7 +44,6 @@ where pub fn draw_filled_rect(image: &I, rect: Rect, color: I::Pixel) -> Image where I: GenericImage, - I::Pixel: 'static, { let mut out = ImageBuffer::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); @@ -60,7 +57,6 @@ where pub fn draw_filled_rect_mut(canvas: &mut C, rect: Rect, color: C::Pixel) where C: Canvas, - C::Pixel: 'static, { let canvas_bounds = Rect::at(0, 0).of_size(canvas.width(), canvas.height()); if let Some(intersection) = canvas_bounds.intersect(rect) { diff --git a/src/drawing/text.rs b/src/drawing/text.rs index 628040c2..e55d7e7c 100644 --- a/src/drawing/text.rs +++ b/src/drawing/text.rs @@ -92,7 +92,6 @@ pub fn draw_text<'a, I>( where I: GenericImage, ::Subpixel: ValueInto + Clamp, - I::Pixel: 'static, { let mut out = ImageBuffer::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); diff --git a/src/filter/median.rs b/src/filter/median.rs index 99d634c5..3b636a50 100644 --- a/src/filter/median.rs +++ b/src/filter/median.rs @@ -108,7 +108,7 @@ use std::cmp::{max, min}; #[must_use = "the function does not modify the original image"] pub fn median_filter

(image: &Image

, x_radius: u32, y_radius: u32) -> Image

where - P: Pixel + 'static, + P: Pixel, { let (width, height) = image.dimensions(); @@ -141,7 +141,7 @@ fn initialise_histogram_for_top_left_pixel

( y_radius: u32, ) -> HistSet where - P: Pixel + 'static, + P: Pixel, { let (width, height) = image.dimensions(); let kernel_size = (2 * x_radius + 1) * (2 * y_radius + 1); @@ -166,7 +166,7 @@ where fn slide_right

(hist: &mut HistSet, image: &Image

, x: u32, y: u32, rx: i32, ry: i32) where - P: Pixel + 'static, + P: Pixel, { let (width, height) = image.dimensions(); @@ -189,7 +189,7 @@ fn slide_down_column

( rx: i32, ry: i32, ) where - P: Pixel + 'static, + P: Pixel, { let (width, height) = image.dimensions(); hist.set_to_median(out, x, 0); @@ -217,7 +217,7 @@ fn slide_up_column

( rx: i32, ry: i32, ) where - P: Pixel + 'static, + P: Pixel, { let (width, height) = image.dimensions(); hist.set_to_median(out, x, height - 1); @@ -265,7 +265,7 @@ impl HistSet { fn incr

(&mut self, image: &Image

, x: u32, y: u32) where - P: Pixel + 'static, + P: Pixel, { unsafe { let pixel = image.unsafe_get_pixel(x, y); @@ -280,7 +280,7 @@ impl HistSet { fn decr

(&mut self, image: &Image

, x: u32, y: u32) where - P: Pixel + 'static, + P: Pixel, { unsafe { let pixel = image.unsafe_get_pixel(x, y); @@ -295,7 +295,7 @@ impl HistSet { fn set_to_median

(&self, image: &mut Image

, x: u32, y: u32) where - P: Pixel + 'static, + P: Pixel, { unsafe { let target = image.get_pixel_mut(x, y); diff --git a/src/filter/mod.rs b/src/filter/mod.rs index 258d9873..eacdc29a 100644 --- a/src/filter/mod.rs +++ b/src/filter/mod.rs @@ -242,9 +242,9 @@ impl<'a, K: Num + Copy + 'a> Kernel<'a, K> { /// at type K, and the results converted to pixel Q via f. Pads by continuity. pub fn filter(&self, image: &Image

, mut f: F) -> Image where - P: Pixel + 'static, + P: Pixel,

::Subpixel: ValueInto, - Q: Pixel + 'static, + Q: Pixel, F: FnMut(&mut Q::Subpixel, K), { let (width, height) = image.dimensions(); @@ -309,7 +309,7 @@ fn gaussian_kernel_f32(sigma: f32) -> Vec { #[must_use = "the function does not modify the original image"] pub fn gaussian_blur_f32

(image: &Image

, sigma: f32) -> Image

where - P: Pixel + 'static, + P: Pixel,

::Subpixel: ValueInto + Clamp, { assert!(sigma > 0.0, "sigma must be > 0.0"); @@ -322,7 +322,7 @@ where #[must_use = "the function does not modify the original image"] pub fn separable_filter(image: &Image

, h_kernel: &[K], v_kernel: &[K]) -> Image

where - P: Pixel + 'static, + P: Pixel,

::Subpixel: ValueInto + Clamp, K: Num + Copy, { @@ -335,7 +335,7 @@ where #[must_use = "the function does not modify the original image"] pub fn separable_filter_equal(image: &Image

, kernel: &[K]) -> Image

where - P: Pixel + 'static, + P: Pixel,

::Subpixel: ValueInto + Clamp, K: Num + Copy, { @@ -348,8 +348,8 @@ where pub fn filter3x3(image: &Image

, kernel: &[K]) -> Image> where P::Subpixel: ValueInto, - S: Clamp + Primitive + 'static, - P: WithChannel + 'static, + S: Clamp + Primitive, + P: WithChannel, K: Num + Copy, { let kernel = Kernel::new(kernel, 3, 3); @@ -362,7 +362,7 @@ where #[must_use = "the function does not modify the original image"] pub fn horizontal_filter(image: &Image

, kernel: &[K]) -> Image

where - P: Pixel + 'static, + P: Pixel,

::Subpixel: ValueInto + Clamp, K: Num + Copy, { @@ -458,7 +458,7 @@ where #[must_use = "the function does not modify the original image"] pub fn vertical_filter(image: &Image

, kernel: &[K]) -> Image

where - P: Pixel + 'static, + P: Pixel,

::Subpixel: ValueInto + Clamp, K: Num + Copy, { @@ -946,7 +946,7 @@ mod tests { /// We can also use this to validate correctnes of any implementations we add here. fn gaussian_baseline_rgb(image: &I, stdev: f32) -> Image> where - I: GenericImage> + 'static, + I: GenericImage>, { blur(image, stdev) } diff --git a/src/geometric_transformations.rs b/src/geometric_transformations.rs index c17c0df7..aeb73eeb 100644 --- a/src/geometric_transformations.rs +++ b/src/geometric_transformations.rs @@ -284,7 +284,7 @@ pub fn rotate_about_center

( default: P, ) -> Image

where - P: Pixel + Send + Sync + 'static, + P: Pixel + Send + Sync,

::Subpixel: Send + Sync,

::Subpixel: ValueInto + Clamp, { @@ -309,7 +309,7 @@ pub fn rotate

( default: P, ) -> Image

where - P: Pixel + Send + Sync + 'static, + P: Pixel + Send + Sync,

::Subpixel: Send + Sync,

::Subpixel: ValueInto + Clamp, { @@ -326,7 +326,7 @@ where // TODO: attempting the equivalent transformation using Projection. pub fn translate

(image: &Image

, t: (i32, i32)) -> Image

where - P: Pixel + 'static, + P: Pixel, { let (width, height) = image.dimensions(); let (tx, ty) = t; @@ -381,7 +381,7 @@ pub fn warp

( default: P, ) -> Image

where - P: Pixel + Send + Sync + 'static, + P: Pixel + Send + Sync,

::Subpixel: Send + Sync,

::Subpixel: ValueInto + Clamp, { @@ -401,7 +401,7 @@ pub fn warp_into

( default: P, out: &mut Image

, ) where - P: Pixel + Send + Sync + 'static, + P: Pixel + Send + Sync,

::Subpixel: Send + Sync,

::Subpixel: ValueInto + Clamp + Sync, { @@ -453,7 +453,7 @@ pub fn warp_with( ) -> Image

where F: Fn(f32, f32) -> (f32, f32) + Sync + Send, - P: Pixel + Send + Sync + 'static, + P: Pixel + Send + Sync,

::Subpixel: Send + Sync,

::Subpixel: ValueInto + Clamp, { @@ -475,7 +475,7 @@ pub fn warp_into_with( out: &mut Image

, ) where F: Fn(f32, f32) -> (f32, f32) + Send + Sync, - P: Pixel + Send + Sync + 'static, + P: Pixel + Send + Sync,

::Subpixel: Send + Sync,

::Subpixel: ValueInto + Clamp, { @@ -495,7 +495,7 @@ pub fn warp_into_with( // TODO: make faster by avoiding boundary checks in inner section of src image fn warp_inner(out: &mut Image

, mapping: Fc, get_pixel: Fi) where - P: Pixel + 'static, + P: Pixel,

::Subpixel: Send + Sync,

::Subpixel: ValueInto + Clamp, Fc: Fn(f32, f32) -> (f32, f32) + Send + Sync, @@ -618,7 +618,7 @@ where fn interpolate_bicubic

(image: &Image

, x: f32, y: f32, default: P) -> P where - P: Pixel + 'static, + P: Pixel,

::Subpixel: ValueInto + Clamp, { let left = x.floor() - 1f32; @@ -680,7 +680,7 @@ where fn interpolate_bilinear

(image: &Image

, x: f32, y: f32, default: P) -> P where - P: Pixel + 'static, + P: Pixel,

::Subpixel: ValueInto + Clamp, { let left = x.floor(); @@ -709,7 +709,7 @@ where } #[inline(always)] -fn interpolate_nearest(image: &Image

, x: f32, y: f32, default: P) -> P { +fn interpolate_nearest(image: &Image

, x: f32, y: f32, default: P) -> P { let rx = x.round(); let ry = y.round(); diff --git a/src/gradients.rs b/src/gradients.rs index eabdaf23..3f2e0947 100644 --- a/src/gradients.rs +++ b/src/gradients.rs @@ -169,8 +169,8 @@ pub fn sobel_gradients(image: &GrayImage) -> Image> { /// # } pub fn sobel_gradient_map(image: &Image

, f: F) -> Image where - P: Pixel + WithChannel + WithChannel + 'static, - Q: Pixel + 'static, + P: Pixel + WithChannel + WithChannel, + Q: Pixel, ChannelMap: HasBlack, F: Fn(ChannelMap) -> Q, { @@ -193,8 +193,8 @@ fn gradients( f: F, ) -> Image where - P: Pixel + WithChannel + WithChannel + 'static, - Q: Pixel + 'static, + P: Pixel + WithChannel + WithChannel, + Q: Pixel, ChannelMap: HasBlack, F: Fn(ChannelMap) -> Q, { diff --git a/src/haar.rs b/src/haar.rs index a8b2fccd..4931e045 100644 --- a/src/haar.rs +++ b/src/haar.rs @@ -384,7 +384,7 @@ fn num_features(image_side: u32, num_blocks: u32) -> u32 { pub fn draw_haar_feature(image: &I, feature: HaarFeature) -> Image where I: GenericImage, - I::Pixel: HasBlack + HasWhite + 'static, + I::Pixel: HasBlack + HasWhite, { let mut out = ImageBuffer::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); diff --git a/src/hog.rs b/src/hog.rs index e015c67b..f31e8600 100644 --- a/src/hog.rs +++ b/src/hog.rs @@ -379,7 +379,7 @@ pub fn render_hist_grid(star_side: u32, grid: &View3d<'_, f32>, signed: bool) -> let x_window = x as u32 * star_side; let mut window = out.sub_image(x_window, y_window, star_side, star_side); let hist = grid.inner_slice(x, y); - draw_star_mut(&mut window, hist, signed); + draw_star_mut(window.inner_mut(), hist, signed); } } @@ -392,7 +392,6 @@ pub fn render_hist_grid(star_side: u32, grid: &View3d<'_, f32>, signed: bool) -> fn draw_ray_mut(image: &mut I, theta: f32, color: I::Pixel) where I: GenericImage, - I::Pixel: 'static, { use crate::drawing::draw_line_segment_mut; use std::cmp; diff --git a/src/hough.rs b/src/hough.rs index 85e9b8a3..ce1a663d 100644 --- a/src/hough.rs +++ b/src/hough.rs @@ -98,7 +98,7 @@ pub fn detect_lines(image: &GrayImage, options: LineDetectionOptions) -> Vec(image: &Image

, lines: &[PolarLine], color: P) -> Image

where - P: Pixel + 'static, + P: Pixel, { let mut out = image.clone(); draw_polar_lines_mut(&mut out, lines, color); @@ -110,7 +110,7 @@ where /// See ./examples/hough.rs for example usage. pub fn draw_polar_lines_mut

(image: &mut Image

, lines: &[PolarLine], color: P) where - P: Pixel + 'static, + P: Pixel, { for line in lines { draw_polar_line(image, *line, color); @@ -119,7 +119,7 @@ where fn draw_polar_line

(image: &mut Image

, line: PolarLine, color: P) where - P: Pixel + 'static, + P: Pixel, { if let Some((s, e)) = intersection_points(line, image.width(), image.height()) { draw_line_segment_mut(image, s, e, color); diff --git a/src/integral_image.rs b/src/integral_image.rs index 74717cb1..2b2edb98 100644 --- a/src/integral_image.rs +++ b/src/integral_image.rs @@ -49,8 +49,8 @@ use std::ops::AddAssign; /// ``` pub fn integral_image(image: &Image

) -> Image> where - P: Pixel + WithChannel + 'static, - T: From + Primitive + AddAssign + 'static, + P: Pixel + WithChannel, + T: From + Primitive + AddAssign, { integral_image_impl(image, false) } @@ -88,8 +88,8 @@ where /// ``` pub fn integral_squared_image(image: &Image

) -> Image> where - P: Pixel + WithChannel + 'static, - T: From + Primitive + AddAssign + 'static, + P: Pixel + WithChannel, + T: From + Primitive + AddAssign, { integral_image_impl(image, true) } @@ -97,8 +97,8 @@ where /// Implementation of `integral_image` and `integral_squared_image`. fn integral_image_impl(image: &Image

, square: bool) -> Image> where - P: Pixel + WithChannel + 'static, - T: From + Primitive + AddAssign + 'static, + P: Pixel + WithChannel, + T: From + Primitive + AddAssign, { // TODO: Make faster, add a new IntegralImage type // TODO: to make it harder to make off-by-one errors when computing sums of regions. @@ -163,7 +163,7 @@ pub trait ArrayData { fn sub(lhs: Self::DataType, other: Self::DataType) -> Self::DataType; } -impl ArrayData for Luma { +impl ArrayData for Luma { type DataType = [T; 1]; fn data(&self) -> Self::DataType { @@ -179,7 +179,11 @@ impl ArrayData for Luma { } } -impl ArrayData for Rgb { +impl ArrayData for Rgb +where + Rgb: Pixel, + T: Primitive, +{ type DataType = [T; 3]; fn data(&self) -> Self::DataType { @@ -195,7 +199,11 @@ impl ArrayData for Rgb { } } -impl ArrayData for Rgba { +impl ArrayData for Rgba +where + Rgba: Pixel, + T: Primitive, +{ type DataType = [T; 4]; fn data(&self) -> Self::DataType { @@ -243,7 +251,7 @@ pub fn sum_image_pixels

( bottom: u32, ) -> P::DataType where - P: Pixel + ArrayData + Copy + 'static, + P: Pixel + ArrayData + Copy, { // TODO: better type-safety. It's too easy to pass the original image in here by mistake. // TODO: it's also hard to see what the four u32s mean at the call site - use a Rect instead. diff --git a/src/map.rs b/src/map.rs index 2160b6fe..466682e5 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,6 +1,6 @@ //! Functions for mapping over pixels, colors or subpixels of images. -use image::{Bgr, Bgra, GenericImage, ImageBuffer, Luma, LumaA, Pixel, Primitive, Rgb, Rgba}; +use image::{GenericImage, ImageBuffer, Luma, LumaA, Pixel, Primitive, Rgb, Rgba}; use crate::definitions::Image; @@ -9,7 +9,7 @@ use crate::definitions::Image; /// several algorithms will produce incorrect results or panic. pub trait WithChannel: Pixel { /// The new pixel type. - type Pixel: Pixel + 'static; + type Pixel: Pixel; } /// Alias to make uses of `WithChannel` less syntactically noisy. @@ -17,48 +17,36 @@ pub type ChannelMap = >::Pixel; impl WithChannel for Rgb where - T: Primitive + 'static, - U: Primitive + 'static, + Rgb: Pixel, + Rgb: Pixel, + T: Primitive, + U: Primitive, { type Pixel = Rgb; } impl WithChannel for Rgba where - T: Primitive + 'static, - U: Primitive + 'static, + Rgba: Pixel, + Rgba: Pixel, + T: Primitive, + U: Primitive, { type Pixel = Rgba; } -impl WithChannel for Bgr -where - T: Primitive + 'static, - U: Primitive + 'static, -{ - type Pixel = Bgr; -} - -impl WithChannel for Bgra -where - T: Primitive + 'static, - U: Primitive + 'static, -{ - type Pixel = Bgra; -} - impl WithChannel for Luma where - T: Primitive + 'static, - U: Primitive + 'static, + T: Primitive, + U: Primitive, { type Pixel = Luma; } impl WithChannel for LumaA where - T: Primitive + 'static, - U: Primitive + 'static, + T: Primitive, + U: Primitive, { type Pixel = LumaA; } @@ -89,8 +77,8 @@ where pub fn map_subpixels(image: &I, f: F) -> Image> where I: GenericImage, - P: WithChannel + 'static, - S: Primitive + 'static, + P: WithChannel, + S: Primitive, F: Fn(P::Subpixel) -> S, { let (width, height) = image.dimensions(); @@ -148,14 +136,13 @@ where for y in 0..height { for x in 0..width { - for c in 0..P::CHANNEL_COUNT { - image.get_pixel_mut(x, y).channels_mut()[c as usize] = f(unsafe { - *image - .unsafe_get_pixel(x, y) - .channels() - .get_unchecked(c as usize) - }); + let mut pixel = image.get_pixel(x, y); + let channels = pixel.channels_mut(); + for c in 0..P::CHANNEL_COUNT as usize { + channels[c] = + f(unsafe { *image.unsafe_get_pixel(x, y).channels().get_unchecked(c) }); } + image.put_pixel(x, y, pixel); } } } @@ -188,7 +175,7 @@ pub fn map_colors(image: &I, f: F) -> Image where I: GenericImage, P: Pixel, - Q: Pixel + 'static, + Q: Pixel, F: Fn(P) -> Q, { let (width, height) = image.dimensions(); @@ -289,7 +276,7 @@ where J: GenericImage, P: Pixel, Q: Pixel, - R: Pixel + 'static, + R: Pixel, F: Fn(P, Q) -> R, { assert_eq!(image1.dimensions(), image2.dimensions()); @@ -340,7 +327,7 @@ pub fn map_pixels(image: &I, f: F) -> Image where I: GenericImage, P: Pixel, - Q: Pixel + 'static, + Q: Pixel, F: Fn(u32, u32, P) -> Q, { let (width, height) = image.dimensions(); @@ -430,7 +417,8 @@ where pub fn red_channel(image: &I) -> Image> where I: GenericImage>, - C: Primitive + 'static, + Rgb: Pixel, + C: Primitive, { map_colors(image, |p| Luma([p[0]])) } @@ -461,7 +449,8 @@ where pub fn as_red_channel(image: &I) -> Image> where I: GenericImage>, - C: Primitive + 'static, + Rgb: Pixel, + C: Primitive, { map_colors(image, |p| { let mut cs = [C::zero(); 3]; @@ -496,7 +485,8 @@ where pub fn green_channel(image: &I) -> Image> where I: GenericImage>, - C: Primitive + 'static, + Rgb: Pixel, + C: Primitive, { map_colors(image, |p| Luma([p[1]])) } @@ -527,7 +517,8 @@ where pub fn as_green_channel(image: &I) -> Image> where I: GenericImage>, - C: Primitive + 'static, + Rgb: Pixel, + C: Primitive, { map_colors(image, |p| { let mut cs = [C::zero(); 3]; @@ -562,7 +553,8 @@ where pub fn blue_channel(image: &I) -> Image> where I: GenericImage>, - C: Primitive + 'static, + Rgb: Pixel, + C: Primitive, { map_colors(image, |p| Luma([p[2]])) } @@ -593,7 +585,8 @@ where pub fn as_blue_channel(image: &I) -> Image> where I: GenericImage>, - C: Primitive + 'static, + Rgb: Pixel, + C: Primitive, { map_colors(image, |p| { let mut cs = [C::zero(); 3]; diff --git a/src/noise.rs b/src/noise.rs index d3740a75..21d3a4bd 100644 --- a/src/noise.rs +++ b/src/noise.rs @@ -11,7 +11,7 @@ use rand_distr::{Distribution, Normal, Uniform}; /// of an image, with the given mean and standard deviation. pub fn gaussian_noise

(image: &Image

, mean: f64, stddev: f64, seed: u64) -> Image

where - P: Pixel + 'static, + P: Pixel, P::Subpixel: ValueInto + Clamp, { let mut out = image.clone(); @@ -23,7 +23,7 @@ where /// of an image in place, with the given mean and standard deviation. pub fn gaussian_noise_mut

(image: &mut Image

, mean: f64, stddev: f64, seed: u64) where - P: Pixel + 'static, + P: Pixel, P::Subpixel: ValueInto + Clamp, { let mut rng: StdRng = SeedableRng::seed_from_u64(seed); @@ -41,7 +41,7 @@ where /// Black and white occur with equal probability. pub fn salt_and_pepper_noise

(image: &Image

, rate: f64, seed: u64) -> Image

where - P: Pixel + HasBlack + HasWhite + 'static, + P: Pixel + HasBlack + HasWhite, { let mut out = image.clone(); salt_and_pepper_noise_mut(&mut out, rate, seed); @@ -52,7 +52,7 @@ where /// Black and white occur with equal probability. pub fn salt_and_pepper_noise_mut

(image: &mut Image

, rate: f64, seed: u64) where - P: Pixel + HasBlack + HasWhite + 'static, + P: Pixel + HasBlack + HasWhite, { let mut rng: StdRng = SeedableRng::seed_from_u64(seed); let uniform = Uniform::new(0.0, 1.0); diff --git a/src/property_testing.rs b/src/property_testing.rs index 37c4e136..a1d7ddd2 100644 --- a/src/property_testing.rs +++ b/src/property_testing.rs @@ -77,7 +77,6 @@ where fn copy_sub(image: &I, x: u32, y: u32, width: u32, height: u32) -> Image where I: GenericImage, - I::Pixel: 'static, { let mut out = ImageBuffer::new(width, height); for dy in 0..height { @@ -90,7 +89,7 @@ where out } -impl fmt::Debug for TestBuffer { +impl fmt::Debug for TestBuffer { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, diff --git a/src/seam_carving.rs b/src/seam_carving.rs index ac6122f4..5ae4b41a 100644 --- a/src/seam_carving.rs +++ b/src/seam_carving.rs @@ -22,7 +22,7 @@ pub struct VerticalSeam(Vec); pub fn shrink_width

(image: &Image

, target_width: u32) -> Image

// TODO: this is pretty silly! We should just be able to express that we want a pixel which is a slice of integral values where - P: Pixel + WithChannel + WithChannel + 'static, + P: Pixel + WithChannel + WithChannel,

>::Pixel: HasBlack, { assert!( @@ -45,7 +45,7 @@ where /// gradient magnitudes is minimal. pub fn find_vertical_seam

(image: &Image

) -> VerticalSeam where - P: Pixel + WithChannel + WithChannel + 'static, + P: Pixel + WithChannel + WithChannel,

>::Pixel: HasBlack, { let (width, height) = image.dimensions(); @@ -134,7 +134,7 @@ fn set_path_energy(path_energies: &mut Image>, x: u32, y: u32) { // it would make them a lot slower. pub fn remove_vertical_seam

(image: &Image

, seam: &VerticalSeam) -> Image

where - P: Pixel + 'static, + P: Pixel, { assert!( seam.0.len() as u32 == image.height(), diff --git a/src/stats.rs b/src/stats.rs index 779103e5..1fd57ea6 100644 --- a/src/stats.rs +++ b/src/stats.rs @@ -15,7 +15,7 @@ pub struct ChannelHistogram { /// Returns a vector of per-channel histograms. pub fn histogram

(image: &Image

) -> ChannelHistogram where - P: Pixel + 'static, + P: Pixel, { let mut hist = vec![[0u32; 256]; P::CHANNEL_COUNT as usize]; @@ -37,7 +37,7 @@ pub struct CumulativeChannelHistogram { /// Returns per-channel cumulative histograms. pub fn cumulative_histogram

(image: &Image

) -> CumulativeChannelHistogram where - P: Pixel + 'static, + P: Pixel, { let mut hist = histogram(image); diff --git a/src/suppress.rs b/src/suppress.rs index 9e9bfa79..fe61dfae 100644 --- a/src/suppress.rs +++ b/src/suppress.rs @@ -10,7 +10,7 @@ use std::cmp; pub fn suppress_non_maximum(image: &I, radius: u32) -> ImageBuffer, Vec> where I: GenericImage>, - C: Primitive + Ord + 'static, + C: Primitive + Ord, { let (width, height) = image.dimensions(); let mut out: ImageBuffer, Vec> = ImageBuffer::new(width, height); @@ -89,7 +89,7 @@ fn contains_greater_value( ) -> bool where I: GenericImage>, - C: Primitive + Ord + 'static, + C: Primitive + Ord, { for cy in y_lower..y_upper { for cx in x_lower..x_upper { @@ -340,7 +340,7 @@ mod tests { fn suppress_non_maximum_reference(image: &I, radius: u32) -> ImageBuffer, Vec> where I: GenericImage>, - C: Primitive + Ord + 'static, + C: Primitive + Ord, { let (width, height) = image.dimensions(); let mut out = ImageBuffer::new(width, height); diff --git a/src/template_matching.rs b/src/template_matching.rs index f0877ff4..12883257 100644 --- a/src/template_matching.rs +++ b/src/template_matching.rs @@ -147,7 +147,7 @@ pub struct Extremes { /// If there are multiple such values then the lexicographically smallest is returned. pub fn find_extremes(image: &Image>) -> Extremes where - T: Primitive + 'static, + T: Primitive, { assert!( image.width() > 0 && image.height() > 0, diff --git a/tests/data/truth/antialiased_lines_rgb.png b/tests/data/truth/antialiased_lines_rgb.png index a5723b62..be86f363 100644 Binary files a/tests/data/truth/antialiased_lines_rgb.png and b/tests/data/truth/antialiased_lines_rgb.png differ diff --git a/tests/data/truth/cubic_bezier_curve.png b/tests/data/truth/cubic_bezier_curve.png index 9f2f93b3..d5108f7c 100644 Binary files a/tests/data/truth/cubic_bezier_curve.png and b/tests/data/truth/cubic_bezier_curve.png differ diff --git a/tests/data/truth/elephant_affine_bicubic.png b/tests/data/truth/elephant_affine_bicubic.png index e96da54e..5e235380 100644 Binary files a/tests/data/truth/elephant_affine_bicubic.png and b/tests/data/truth/elephant_affine_bicubic.png differ diff --git a/tests/data/truth/elephant_affine_bilinear.png b/tests/data/truth/elephant_affine_bilinear.png index c2ba060f..ef6f7e01 100644 Binary files a/tests/data/truth/elephant_affine_bilinear.png and b/tests/data/truth/elephant_affine_bilinear.png differ diff --git a/tests/data/truth/elephant_affine_nearest.png b/tests/data/truth/elephant_affine_nearest.png index 6c7174c1..87299b60 100644 Binary files a/tests/data/truth/elephant_affine_nearest.png and b/tests/data/truth/elephant_affine_nearest.png differ diff --git a/tests/data/truth/elephant_gradients.png b/tests/data/truth/elephant_gradients.png index b32ba69a..16695a84 100644 Binary files a/tests/data/truth/elephant_gradients.png and b/tests/data/truth/elephant_gradients.png differ diff --git a/tests/data/truth/elephant_matched.png b/tests/data/truth/elephant_matched.png index 8fd29601..ad33f030 100644 Binary files a/tests/data/truth/elephant_matched.png and b/tests/data/truth/elephant_matched.png differ diff --git a/tests/data/truth/elephant_rotate_bicubic.png b/tests/data/truth/elephant_rotate_bicubic.png index 73bc7c41..25c4ff98 100644 Binary files a/tests/data/truth/elephant_rotate_bicubic.png and b/tests/data/truth/elephant_rotate_bicubic.png differ diff --git a/tests/data/truth/elephant_rotate_bicubic_rgba.png b/tests/data/truth/elephant_rotate_bicubic_rgba.png index 1864492a..466b47ab 100644 Binary files a/tests/data/truth/elephant_rotate_bicubic_rgba.png and b/tests/data/truth/elephant_rotate_bicubic_rgba.png differ diff --git a/tests/data/truth/elephant_rotate_bilinear.png b/tests/data/truth/elephant_rotate_bilinear.png index f5730469..e7f8636c 100644 Binary files a/tests/data/truth/elephant_rotate_bilinear.png and b/tests/data/truth/elephant_rotate_bilinear.png differ diff --git a/tests/data/truth/elephant_rotate_bilinear_rgba.png b/tests/data/truth/elephant_rotate_bilinear_rgba.png index d48e6be2..7f7558f5 100644 Binary files a/tests/data/truth/elephant_rotate_bilinear_rgba.png and b/tests/data/truth/elephant_rotate_bilinear_rgba.png differ diff --git a/tests/data/truth/elephant_rotate_nearest.png b/tests/data/truth/elephant_rotate_nearest.png index c48fecd7..b4758c2a 100644 Binary files a/tests/data/truth/elephant_rotate_nearest.png and b/tests/data/truth/elephant_rotate_nearest.png differ diff --git a/tests/data/truth/elephant_rotate_nearest_rgba.png b/tests/data/truth/elephant_rotate_nearest_rgba.png index 8a7594e7..45a26345 100644 Binary files a/tests/data/truth/elephant_rotate_nearest_rgba.png and b/tests/data/truth/elephant_rotate_nearest_rgba.png differ diff --git a/tests/data/truth/filled_ellipse.png b/tests/data/truth/filled_ellipse.png index 14ea93a3..a6766072 100644 Binary files a/tests/data/truth/filled_ellipse.png and b/tests/data/truth/filled_ellipse.png differ diff --git a/tests/data/truth/hollow_ellipse.png b/tests/data/truth/hollow_ellipse.png index be9b8318..6f7f065d 100644 Binary files a/tests/data/truth/hollow_ellipse.png and b/tests/data/truth/hollow_ellipse.png differ diff --git a/tests/data/truth/hough_lines.png b/tests/data/truth/hough_lines.png index 18940d82..30bbe4f2 100644 Binary files a/tests/data/truth/hough_lines.png and b/tests/data/truth/hough_lines.png differ diff --git a/tests/data/truth/lumaphant_bilateral.png b/tests/data/truth/lumaphant_bilateral.png index f2e099d7..1c3efd32 100644 Binary files a/tests/data/truth/lumaphant_bilateral.png and b/tests/data/truth/lumaphant_bilateral.png differ diff --git a/tests/data/truth/lumaphant_eq.png b/tests/data/truth/lumaphant_eq.png index a836b1ad..f2042a2a 100644 Binary files a/tests/data/truth/lumaphant_eq.png and b/tests/data/truth/lumaphant_eq.png differ diff --git a/tests/data/truth/polygon.png b/tests/data/truth/polygon.png index ccb74999..541ac526 100644 Binary files a/tests/data/truth/polygon.png and b/tests/data/truth/polygon.png differ diff --git a/tests/data/truth/robin_sharpen3x3.png b/tests/data/truth/robin_sharpen3x3.png index 3c8d0e12..e278dfa6 100644 Binary files a/tests/data/truth/robin_sharpen3x3.png and b/tests/data/truth/robin_sharpen3x3.png differ diff --git a/tests/data/truth/robin_sharpen_gaussian.png b/tests/data/truth/robin_sharpen_gaussian.png index 0f6104a9..365599a3 100644 Binary files a/tests/data/truth/robin_sharpen_gaussian.png and b/tests/data/truth/robin_sharpen_gaussian.png differ diff --git a/tests/data/truth/spiral_polygon.png b/tests/data/truth/spiral_polygon.png index ab7a535a..fa89c5a7 100644 Binary files a/tests/data/truth/spiral_polygon.png and b/tests/data/truth/spiral_polygon.png differ diff --git a/tests/data/truth/zebra_adaptive_threshold.png b/tests/data/truth/zebra_adaptive_threshold.png index 4ed3841e..6e1daf49 100644 Binary files a/tests/data/truth/zebra_adaptive_threshold.png and b/tests/data/truth/zebra_adaptive_threshold.png differ diff --git a/tests/data/truth/zebra_canny.png b/tests/data/truth/zebra_canny.png index c21b607b..3fb8be96 100644 Binary files a/tests/data/truth/zebra_canny.png and b/tests/data/truth/zebra_canny.png differ diff --git a/tests/data/truth/zebra_gaussian_10.png b/tests/data/truth/zebra_gaussian_10.png index ab8ecf51..81c41b20 100644 Binary files a/tests/data/truth/zebra_gaussian_10.png and b/tests/data/truth/zebra_gaussian_10.png differ diff --git a/tests/data/truth/zebra_gaussian_3.png b/tests/data/truth/zebra_gaussian_3.png index d3a74f87..2d08d334 100644 Binary files a/tests/data/truth/zebra_gaussian_3.png and b/tests/data/truth/zebra_gaussian_3.png differ diff --git a/tests/data/truth/zebra_otsu.png b/tests/data/truth/zebra_otsu.png index fe0b50fe..b59e84f9 100644 Binary files a/tests/data/truth/zebra_otsu.png and b/tests/data/truth/zebra_otsu.png differ diff --git a/tests/regression.rs b/tests/regression.rs index 3683a1db..1d06f00e 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -17,7 +17,10 @@ #[macro_use] extern crate imageproc; -use image::{DynamicImage, GrayImage, ImageBuffer, Luma, Pixel, Rgb, RgbImage, Rgba, RgbaImage}; +use image::{ + DynamicImage, GrayImage, ImageBuffer, Luma, Pixel, PixelWithColorType, Rgb, RgbImage, Rgba, + RgbaImage, +}; use imageproc::{ definitions::{Clamp, HasBlack, HasWhite}, edges::canny, @@ -65,7 +68,7 @@ impl FromDynamic for RgbaImage { /// Loads an input image, applies a function to it and checks that the result matches a 'truth' image. fn compare_to_truth(input_file_name: &str, truth_file_name: &str, op: F) where - P: Pixel + 'static, + P: Pixel + PixelWithColorType, ImageBuffer>: FromDynamic, F: Fn(&ImageBuffer>) -> ImageBuffer>, { @@ -80,7 +83,7 @@ fn compare_to_truth_with_tolerance( op: F, tol: u8, ) where - P: Pixel + 'static, + P: Pixel + PixelWithColorType, ImageBuffer>: FromDynamic, F: Fn(&ImageBuffer>) -> ImageBuffer>, { @@ -94,7 +97,7 @@ fn compare_to_truth_with_tolerance( /// Checks that an image matches a 'truth' image. fn compare_to_truth_image

(actual: &ImageBuffer>, truth_file_name: &str) where - P: Pixel + 'static, + P: Pixel + PixelWithColorType, ImageBuffer>: FromDynamic, { compare_to_truth_image_with_tolerance(actual, truth_file_name, 0u8); @@ -106,7 +109,7 @@ fn compare_to_truth_image_with_tolerance

( truth_file_name: &str, tol: u8, ) where - P: Pixel + 'static, + P: Pixel + PixelWithColorType, ImageBuffer>: FromDynamic, { if should_regenerate() {