1 | use super::Img; |
2 | use alloc::vec::Vec; |
3 | use core::ops; |
4 | |
5 | #[cfg (test)] |
6 | use alloc::vec; |
7 | |
8 | macro_rules! impl_imgref_index { |
9 | ($container:ty, $index:ty) => { |
10 | impl<'a, Pixel: Copy> ops::Index<($index, $index)> for Img<$container> { |
11 | type Output = Pixel; |
12 | |
13 | /// Read a pixel at `(x,y)` location (e.g. px = `img[(x,y)]`) |
14 | /// |
15 | /// Coordinates may be outside `width`/`height` if the buffer has enough padding. |
16 | /// The x coordinate can't exceed `stride`. |
17 | #[inline(always)] |
18 | #[cfg_attr(debug_assertions, track_caller)] |
19 | fn index(&self, index: ($index, $index)) -> &Self::Output { |
20 | let stride = self.stride(); |
21 | debug_assert_eq!(stride, stride as $index as usize); |
22 | debug_assert!(index.0 < stride as $index); |
23 | &self.buf()[(index.1 * (stride as $index) + index.0) as usize] |
24 | } |
25 | } |
26 | }; |
27 | } |
28 | |
29 | macro_rules! impl_imgref_index_mut { |
30 | ($container:ty, $index:ty) => { |
31 | impl<'a, Pixel: Copy> ops::IndexMut<($index, $index)> for Img<$container> { |
32 | /// Write a pixel at `(x,y)` location (e.g. `img[(x,y)] = px`) |
33 | /// |
34 | /// Coordinates may be outside `width`/`height` if the buffer has enough padding. |
35 | /// The x coordinate can't exceed `stride`. |
36 | #[inline(always)] |
37 | #[cfg_attr(debug_assertions, track_caller)] |
38 | fn index_mut(&mut self, index: ($index, $index)) -> &mut Self::Output { |
39 | let stride = self.stride(); |
40 | debug_assert_eq!(stride, stride as $index as usize); |
41 | debug_assert!(index.0 < stride as $index); |
42 | &mut self.buf_mut()[(index.1 * (stride as $index) + index.0) as usize] |
43 | } |
44 | } |
45 | }; |
46 | } |
47 | |
48 | impl_imgref_index! {&'a [Pixel], usize} |
49 | impl_imgref_index! {&'a [Pixel], u32} |
50 | impl_imgref_index! {&'a mut [Pixel], usize} |
51 | impl_imgref_index! {&'a mut [Pixel], u32} |
52 | impl_imgref_index_mut! {&'a mut [Pixel], usize} |
53 | impl_imgref_index_mut! {&'a mut [Pixel], u32} |
54 | impl_imgref_index! {Vec<Pixel>, usize} |
55 | impl_imgref_index! {Vec<Pixel>, u32} |
56 | impl_imgref_index_mut! {Vec<Pixel>, usize} |
57 | impl_imgref_index_mut! {Vec<Pixel>, u32} |
58 | |
59 | #[test ] |
60 | fn index() { |
61 | let mut img = Img::new_stride(vec![1,2,3,4,5,6,7,8], 2, 2, 3); |
62 | assert_eq!(1, img[(0u32,0u32)]); |
63 | assert_eq!(2, img.as_ref()[(1usize,0usize)]); |
64 | assert_eq!(3, img.as_ref()[(2u32,0u32)]); |
65 | assert_eq!(4, img[(0usize,1usize)]); |
66 | assert_eq!(8, img[(1usize,2usize)]); |
67 | assert_eq!(5, img.sub_image_mut(1,1,1,1)[(0usize,0usize)]); |
68 | } |
69 | |
70 | macro_rules! impl_imgref_row_index { |
71 | ($container:ty) => { |
72 | impl<'a, Pixel: Copy> ops::Index<usize> for Img<$container> { |
73 | type Output = [Pixel]; |
74 | |
75 | #[inline(always)] |
76 | /// Take n-th row as a slice. Same as `.rows().nth(n).unwrap()` |
77 | /// |
78 | /// Slice length is guaranteed to equal image width. |
79 | /// Row must be within image height. |
80 | fn index(&self, row: usize) -> &Self::Output { |
81 | let stride = self.stride(); |
82 | let width = self.width(); |
83 | let start = row * stride; |
84 | &self.buf()[start .. start + width] |
85 | } |
86 | } |
87 | }; |
88 | } |
89 | |
90 | macro_rules! impl_imgref_row_index_mut { |
91 | ($container:ty) => { |
92 | impl<'a, Pixel: Copy> ops::IndexMut<usize> for Img<$container> { |
93 | #[inline(always)] |
94 | /// Take n-th row as a mutable slice. Same as `.rows().nth(n).unwrap()` |
95 | /// |
96 | /// Slice length is guaranteed to equal image width. |
97 | /// Row must be within image height. |
98 | fn index_mut(&mut self, row: usize) -> &mut Self::Output { |
99 | let stride = self.stride(); |
100 | let width = self.width(); |
101 | let start = row * stride; |
102 | &mut self.buf_mut()[start .. start + width] |
103 | } |
104 | } |
105 | }; |
106 | } |
107 | |
108 | impl_imgref_row_index! {&'a [Pixel]} |
109 | impl_imgref_row_index! {&'a mut [Pixel]} |
110 | impl_imgref_row_index_mut! {&'a mut [Pixel]} |
111 | impl_imgref_row_index! {Vec<Pixel>} |
112 | impl_imgref_row_index_mut! {Vec<Pixel>} |
113 | |
114 | #[test ] |
115 | fn index_by_row() { |
116 | let mut img = Img::new_stride(vec![1,2,3,4,5,6,7,8], 2, 2, 3); |
117 | assert_eq!(&[1,2], &img[0]); |
118 | assert_eq!(&[4,5], &img[1]); |
119 | assert_eq!(&[1,2], &img.as_ref()[0]); |
120 | assert_eq!(&[4,5], &img.as_ref()[1]); |
121 | assert_eq!(&[1,2], &img.as_mut()[0]); |
122 | assert_eq!(&[4,5], &img.as_mut()[1]); |
123 | } |
124 | |