imagepipe/
buffer.rs

1extern crate rayon;
2use self::rayon::prelude::*;
3
4#[derive(Debug, Clone, PartialEq)]
5pub struct OpBuffer {
6  pub width: usize,
7  pub height: usize,
8  pub colors: usize,
9  pub monochrome: bool,
10  pub data: Vec<f32>,
11}
12
13impl OpBuffer {
14  pub fn default() -> OpBuffer {
15    OpBuffer {
16      width: 0,
17      height: 0,
18      colors: 0,
19      monochrome: false,
20      data: Vec::new(),
21    }
22  }
23
24  pub fn new(width: usize, height: usize, colors: usize, monochrome: bool) -> OpBuffer {
25    OpBuffer {
26      width: width,
27      height: height,
28      colors: colors,
29      monochrome,
30      data: vec![0.0; width*height*(colors as usize)],
31    }
32  }
33
34  pub fn mutate_lines<F>(&mut self, closure: &F)
35    where F : Fn(&mut [f32], usize)+Sync {
36
37    self.data.par_chunks_mut(self.width*self.colors).enumerate().for_each(|(row, line)| {
38      closure(line, row);
39    });
40  }
41
42  pub fn mutate_lines_copying<F>(&self, closure: &F) -> OpBuffer
43    where F : Fn(&mut [f32], usize)+Sync {
44
45    let mut buf = self.clone();
46    buf.data.par_chunks_mut(self.width*self.colors).enumerate().for_each(|(row, line)| {
47      closure(line, row);
48    });
49    buf
50  }
51
52  pub fn process_into_new<F>(&self, colors: usize, closure: &F) -> OpBuffer
53    where F : Fn(&mut [f32], &[f32])+Sync {
54
55    let mut out = OpBuffer::new(self.width, self.height, colors, self.monochrome);
56    out.data.par_chunks_mut(out.width*out.colors).enumerate().for_each(|(row, line)| {
57      closure(line, &self.data[self.width*self.colors*row..]);
58    });
59    out
60  }
61
62  pub fn transform(&self,
63    topleft: (isize, isize),
64    topright: (isize, isize),
65    bottomleft: (isize, isize),
66    width: usize,
67    height: usize) -> OpBuffer {
68
69    let newdata = crate::scaling::transform_buffer(&self.data, self.width, self.height,
70      topleft, topright, bottomleft, width, height, self.colors, None);
71
72    Self {
73      width,
74      height,
75      colors: self.colors,
76      monochrome: self.monochrome,
77      data: newdata,
78    }
79  }
80
81  /// Helper function to allow human readable creation of `OpBuffer` instances
82  pub fn from_rgb_str_vec(data: Vec<&str>) -> OpBuffer {
83    let width = data.first().expect("Invalid data for rgb helper function").len();
84    let height = data.len();
85    let colors = 3;
86
87    let mut pixel_data: Vec<f32> = Vec::with_capacity(width * height * colors);
88    for row in data {
89      for col in row.chars() {
90        let (r, g, b) = match col {
91            'R' => (1.0, 0.0, 0.0),
92            'G' => (0.0, 1.0, 0.0),
93            'B' => (0.0, 0.0, 1.0),
94            'O' => (1.0, 1.0, 1.0),
95            ' ' => (0.0, 0.0, 0.0),
96            c @ _ => panic!(
97              "Invalid color '{}' sent to rgb expected any of 'RGBO '", c),
98        };
99
100        pixel_data.push(r);
101        pixel_data.push(g);
102        pixel_data.push(b);
103      }
104    }
105
106    OpBuffer {
107      width: width,
108      height: height,
109      colors: colors,
110      monochrome: false,
111      data: pixel_data,
112    }
113  }
114}