1use super::Img;
2use alloc::vec::Vec;
3use core::ops;
4
5#[cfg(test)]
6use alloc::vec;
7
8macro_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
29macro_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
48impl_imgref_index! {&'a [Pixel], usize}
49impl_imgref_index! {&'a [Pixel], u32}
50impl_imgref_index! {&'a mut [Pixel], usize}
51impl_imgref_index! {&'a mut [Pixel], u32}
52impl_imgref_index_mut! {&'a mut [Pixel], usize}
53impl_imgref_index_mut! {&'a mut [Pixel], u32}
54impl_imgref_index! {Vec<Pixel>, usize}
55impl_imgref_index! {Vec<Pixel>, u32}
56impl_imgref_index_mut! {Vec<Pixel>, usize}
57impl_imgref_index_mut! {Vec<Pixel>, u32}
58
59#[test]
60fn 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
70macro_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
90macro_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
108impl_imgref_row_index! {&'a [Pixel]}
109impl_imgref_row_index! {&'a mut [Pixel]}
110impl_imgref_row_index_mut! {&'a mut [Pixel]}
111impl_imgref_row_index! {Vec<Pixel>}
112impl_imgref_row_index_mut! {Vec<Pixel>}
113
114#[test]
115fn 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