1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use super::Img;
use alloc::vec::Vec;
use core::ops;

#[cfg(test)]
use alloc::vec;

macro_rules! impl_imgref_index {
    ($container:ty, $index:ty) => {
        impl<'a, Pixel: Copy> ops::Index<($index, $index)> for Img<$container> {
            type Output = Pixel;
            #[inline(always)]
            /// Read a pixel at `(x,y)` location (e.g. px = `img[(x,y)]`)
            ///
            /// Coordinates may be outside `width`/`height` if the buffer has enough padding.
            /// The x coordinate can't exceed `stride`.
            fn index(&self, index: ($index, $index)) -> &Self::Output {
                let stride = self.stride();
                debug_assert_eq!(stride, stride as $index as usize);
                debug_assert!(index.0 < stride as $index);
                &self.buf()[(index.1 * (stride as $index) + index.0) as usize]
            }
        }
    };
}

macro_rules! impl_imgref_index_mut {
    ($container:ty, $index:ty) => {
        impl<'a, Pixel: Copy> ops::IndexMut<($index, $index)> for Img<$container> {
            #[inline(always)]
            /// Write a pixel at `(x,y)` location (e.g. `img[(x,y)] = px`)
            ///
            /// Coordinates may be outside `width`/`height` if the buffer has enough padding.
            /// The x coordinate can't exceed `stride`.
            fn index_mut(&mut self, index: ($index, $index)) -> &mut Self::Output {
                let stride = self.stride();
                debug_assert_eq!(stride, stride as $index as usize);
                debug_assert!(index.0 < stride as $index);
                &mut self.buf_mut()[(index.1 * (stride as $index) + index.0) as usize]
            }
        }
    };
}

impl_imgref_index! {&'a [Pixel], usize}
impl_imgref_index! {&'a [Pixel], u32}
impl_imgref_index! {&'a mut [Pixel], usize}
impl_imgref_index! {&'a mut [Pixel], u32}
impl_imgref_index_mut! {&'a mut [Pixel], usize}
impl_imgref_index_mut! {&'a mut [Pixel], u32}
impl_imgref_index! {Vec<Pixel>, usize}
impl_imgref_index! {Vec<Pixel>, u32}
impl_imgref_index_mut! {Vec<Pixel>, usize}
impl_imgref_index_mut! {Vec<Pixel>, u32}

#[test]
fn index() {
    let mut img = Img::new_stride(vec![1,2,3,4,5,6,7,8], 2, 2, 3);
    assert_eq!(1, img[(0u32,0u32)]);
    assert_eq!(2, img.as_ref()[(1usize,0usize)]);
    assert_eq!(3, img.as_ref()[(2u32,0u32)]);
    assert_eq!(4, img[(0usize,1usize)]);
    assert_eq!(8, img[(1usize,2usize)]);
    assert_eq!(5, img.sub_image_mut(1,1,1,1)[(0usize,0usize)]);
}


macro_rules! impl_imgref_row_index {
    ($container:ty) => {
        impl<'a, Pixel: Copy> ops::Index<usize> for Img<$container> {
            type Output = [Pixel];
            #[inline(always)]
            /// Take n-th row as a slice. Same as .rows().nth(n).unwrap()
            ///
            /// Slice length is guaranteed to equal image width.
            /// Row must be within image height.
            fn index(&self, row: usize) -> &Self::Output {
                let stride = self.stride();
                let width = self.width();
                let start = row * stride;
                &self.buf()[start .. start + width]
            }
        }
    };
}

macro_rules! impl_imgref_row_index_mut {
    ($container:ty) => {
        impl<'a, Pixel: Copy> ops::IndexMut<usize> for Img<$container> {
            #[inline(always)]
            /// Take n-th row as a mutable slice. Same as .rows().nth(n).unwrap()
            ///
            /// Slice length is guaranteed to equal image width.
            /// Row must be within image height.
            fn index_mut(&mut self, row: usize) -> &mut Self::Output {
                let stride = self.stride();
                let width = self.width();
                let start = row * stride;
                &mut self.buf_mut()[start .. start + width]
            }
        }
    };
}

impl_imgref_row_index! {&'a [Pixel]}
impl_imgref_row_index! {&'a mut [Pixel]}
impl_imgref_row_index_mut! {&'a mut [Pixel]}
impl_imgref_row_index! {Vec<Pixel>}
impl_imgref_row_index_mut! {Vec<Pixel>}

#[test]
fn index_by_row() {
    let mut img = Img::new_stride(vec![1,2,3,4,5,6,7,8], 2, 2, 3);
    assert_eq!(&[1,2], &img[0]);
    assert_eq!(&[4,5], &img[1]);
    assert_eq!(&[1,2], &img.as_ref()[0]);
    assert_eq!(&[4,5], &img.as_ref()[1]);
    assert_eq!(&[1,2], &img.as_mut()[0]);
    assert_eq!(&[4,5], &img.as_mut()[1]);
}