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
// Copyright (c) 2017, Marty Mills <daggerbot@gmail.com>
// This software is available under the terms of the zlib license.
// See COPYING.md for more information.

use dvec::Vec2;
use try_from::TryFrom;

use ::Coord;
use bounds::Size2;
use image::{Image, Render};

/// Buffered image backed by a `Vec`.
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct VecImage2<T> {
    bounds: Size2<Coord>,
    buf: Vec<T>,
}

impl<T> VecImage2<T> {
    pub fn buf (&self) -> &[T] { self.buf.as_ref() }
    pub fn buf_mut (&mut self) -> &mut [T] { self.buf.as_mut() }
    pub fn height (&self) -> Coord { self.bounds.height }
    pub fn into_buf (self) -> Vec<T> { self.buf }

    pub fn row (&self, y: Coord) -> &[T] {
        let start = y.checked_mul(self.bounds.width).expect("bad row index");
        let end = start.checked_add(self.bounds.width).expect("bad row index");
        &self.buf[start as usize..end as usize]
    }

    pub fn size (&self) -> Vec2<Coord> { self.bounds.as_vec() }
    pub fn width (&self) -> Coord { self.bounds.width }
}

impl<'a, T: 'a> Image<'a> for VecImage2<T> {
    type Bounds = Size2<Coord>;
    type Index = Vec2<Coord>;
    type Pixel = &'a T;

    fn bounds (&'a self) -> &'a Size2<Coord> { &self.bounds }

    fn pixel (&'a self, pt: Vec2<Coord>) -> &'a T {
        assert!(pt.x >= 0 && pt.x < self.bounds.width && pt.y >= 0 && pt.y < self.bounds.height);

        unsafe {
            self.buf.get_unchecked((pt.y * self.bounds.width + pt.x) as usize)
        }
    }
}

impl<'a, I, T> Render<'a, I> for VecImage2<T>
    where I: Image<'a, Bounds = Size2<Coord>, Index = Vec2<Coord>, Pixel = T>,
          T: 'a
{
    fn render_from (image: &'a I) -> VecImage2<T> {
        let bounds = *image.bounds();
        let width = usize::try_from(bounds.width).expect("bad image width");
        let height = usize::try_from(bounds.height).expect("bad image height");
        let mut buf = Vec::with_capacity(width * height);

        for y in 0..bounds.height {
            for x in 0..bounds.width {
                buf.push(image.pixel(Vec2::new(x, y)));
            }
        }

        VecImage2 {
            bounds: bounds,
            buf: buf,
        }
    }
}