1use image::{GenericImageView, ImageBuffer, Pixel};
2
3use crate::matrix::Matrix;
4use crate::pos::Pos;
5use crate::{image_view_to_buffer, max_pos};
6
7pub struct Carved<'a, IMG: GenericImageView> {
11 img: &'a IMG,
12 removed: u32,
13 pos_aliases: Matrix<u32>,
15}
16
17impl<'a, IMG: GenericImageView> Carved<'a, IMG> {
18 pub(crate) fn new(img: &'a IMG) -> Self {
19 let size = max_pos(img);
20 let pos_aliases = Matrix::from_fn(size, |x, _y| x as u32);
21 Carved {
22 img,
23 removed: 0,
24 pos_aliases,
25 }
26 }
27 pub(crate) fn remove_seam(&mut self, seam: &[Pos]) {
28 self.pos_aliases.remove_seam(seam);
29 self.removed += 1;
30 }
31 #[inline(always)]
33 fn transform_pos(&self, pos: Pos) -> Pos {
34 let mut pos = pos;
35 pos.0 = self.pos_aliases[pos];
36 pos
37 }
38}
39
40impl<'a, 'b, IMG: GenericImageView>
41 Into<ImageBuffer<IMG::Pixel, Vec<<<IMG as GenericImageView>::Pixel as Pixel>::Subpixel>>>
42 for &'b Carved<'a, IMG>
43where
44 <IMG as GenericImageView>::Pixel: 'static,
45{
46 fn into(
51 self,
52 ) -> ImageBuffer<IMG::Pixel, Vec<<<IMG as GenericImageView>::Pixel as Pixel>::Subpixel>> {
53 image_view_to_buffer(self)
54 }
55}
56
57impl<'a, IMG: GenericImageView> GenericImageView for Carved<'a, IMG>
58where
59 <IMG as GenericImageView>::Pixel: 'a,
60{
61 type Pixel = IMG::Pixel;
62 type InnerImageView = IMG::InnerImageView;
63
64 #[inline(always)]
65 fn dimensions(&self) -> (u32, u32) {
66 let (w, h) = self.img.dimensions();
67 (w - self.removed, h)
68 }
69
70 #[inline(always)]
71 fn bounds(&self) -> (u32, u32, u32, u32) {
72 let (w, h) = self.dimensions();
73 (0, 0, w, h)
74 }
75
76 #[inline(always)]
77 fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
78 let Pos(u, v) = self.transform_pos(Pos(x, y));
79 self.img.get_pixel(u, v)
80 }
81
82 fn inner(&self) -> &Self::InnerImageView {
83 self.img.inner()
84 }
85}