Skip to main content

bayer/
raster.rs

1//! Raster implementation.
2
3use std::slice;
4
5use ::RasterMut;
6
7/// Depth of a raster.
8#[derive(Clone,Copy,Debug,Eq,PartialEq)]
9pub enum RasterDepth {
10    Depth8,
11    Depth16,
12}
13
14impl<'a> RasterMut<'a> {
15    /// Allocate a new raster for the given destination buffer slice.
16    ///
17    /// # Examples
18    ///
19    /// ```
20    /// const IMG_W: usize = 320;
21    /// const IMG_H: usize = 200;
22    /// let mut buf = [0; 3 * IMG_W * IMG_H];
23    ///
24    /// bayer::RasterMut::new(
25    ///         IMG_W, IMG_H, bayer::RasterDepth::Depth8,
26    ///         &mut buf);
27    /// ```
28    pub fn new(w: usize, h: usize, depth: RasterDepth, buf: &'a mut [u8])
29            -> Self {
30        let bytes_per_pixel = depth.bytes_per_pixel();
31        let stride = w.checked_mul(bytes_per_pixel).expect("overflow");
32        Self::with_offset(0, 0, w, h, stride, depth, buf)
33    }
34
35    /// Allocate a new raster for the given destination buffer slice.
36    /// Stride is in number of bytes.
37    ///
38    /// # Examples
39    ///
40    /// ```
41    /// const IMG_W: usize = 320;
42    /// const IMG_H: usize = 200;
43    /// let mut buf = [0; 3 * IMG_W * IMG_H];
44    ///
45    /// bayer::RasterMut::with_offset(
46    ///         0, 0, IMG_W, IMG_H, 3 * IMG_W, bayer::RasterDepth::Depth8,
47    ///         &mut buf);
48    /// ```
49    pub fn with_offset(
50            x: usize, y: usize, w: usize, h: usize, stride: usize,
51            depth: RasterDepth, buf: &'a mut [u8])
52            -> Self {
53        let x1 = x.checked_add(w).expect("overflow");
54        let y1 = y.checked_add(h).expect("overflow");
55        let bytes_per_pixel = depth.bytes_per_pixel();
56        assert!(x < x1 && x1.checked_mul(bytes_per_pixel).expect("overflow") <= stride && h > 0);
57        assert!(stride.checked_mul(y1).expect("overflow") <= buf.len());
58        assert_eq!(stride % bytes_per_pixel, 0);
59
60        RasterMut {
61            x, y, w, h, stride, depth, buf,
62        }
63    }
64
65    /// Borrow a mutable u8 row slice.
66    ///
67    /// # Panics
68    ///
69    /// Panics if the raster is not 8-bpp.
70    pub fn borrow_row_u8_mut(&mut self, y: usize)
71            -> &mut [u8] {
72        assert!(self.depth == RasterDepth::Depth8);
73        assert!(y < self.h);
74
75        let bytes_per_pixel = 3;
76        let start = self.stride * (self.y + y) + bytes_per_pixel * self.x;
77        let end = start + bytes_per_pixel * self.w;
78        &mut self.buf[start..end]
79    }
80
81    /// Borrow a mutable u16 row slice.
82    ///
83    /// # Panics
84    ///
85    /// Panics if the raster is not 16-bpp.
86    pub fn borrow_row_u16_mut(&mut self, y: usize)
87            -> &mut [u16] {
88        assert!(self.depth == RasterDepth::Depth16);
89        assert!(y < self.h);
90
91        let bytes_per_pixel = 6;
92        let start = self.stride * (self.y + y) + bytes_per_pixel * self.x;
93        let end = start + bytes_per_pixel * self.w;
94        let s = &mut self.buf[start..end];
95
96        unsafe {
97            slice::from_raw_parts_mut(s.as_mut_ptr() as *mut u16, 3 * self.w)
98        }
99    }
100}
101
102impl RasterDepth {
103    /// The number of bytes per pixel for a raster of the given depth.
104    fn bytes_per_pixel(self) -> usize {
105        match self {
106            RasterDepth::Depth8 => 3,
107            RasterDepth::Depth16 => 6,
108        }
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use ::RasterMut;
115    use super::RasterDepth;
116
117    #[test]
118    #[should_panic]
119    fn test_raster_mut_overflow() {
120        let mut buf = [0; 1];
121        let _ = RasterMut::new(
122                ::std::usize::MAX, ::std::usize::MAX, RasterDepth::Depth8, &mut buf);
123    }
124
125    #[test]
126    fn test_borrow_row_u16_mut() {
127        let expected = [
128            0x00,0x00, 0x01,0x01, 0x02,0x02,
129            0x03,0x03, 0x04,0x04, 0x05,0x05,
130            0x06,0x06, 0x07,0x07, 0x08,0x08,
131            0x09,0x09, 0x0A,0x0A, 0x0B,0x0B ];
132
133        const IMG_W: usize = 4;
134        const IMG_H: usize = 1;
135        let mut buf = [0u8; 6 * IMG_W * IMG_H];
136
137        {
138            let mut dst = RasterMut::new(
139                    IMG_W, IMG_H, RasterDepth::Depth16, &mut buf);
140            let row = dst.borrow_row_u16_mut(0);
141
142            for (i, elt) in row.iter_mut().enumerate() {
143                // Work around different endians.
144                let i = i as u16;
145                *elt = (i << 8) | i;
146            }
147        }
148
149        assert_eq!(&buf[0..6 * IMG_W * IMG_H], &expected[..]);
150    }
151}