1use super::RGB;
2use super::{Error, Result};
3use std::ops::{Index, IndexMut};
4use std::path::Path;
5#[derive(Clone, Debug, PartialEq)]
7pub struct Img<P> {
8 buf: Vec<P>,
9 width: u32,
10}
11
12impl<P> Img<P> {
13 pub fn new(buf: impl IntoIterator<Item = P>, width: u32) -> Option<Self> {
15 let buf: Vec<P> = buf.into_iter().collect();
16 if width == 0 || buf.len() % width as usize != 0 {
17 None
18 } else {
19 Some(Img { buf, width })
20 }
21 }
22 pub const unsafe fn from_raw_buf(buf: Vec<P>, width: u32) -> Self {
31 Img { buf, width }
32 }
33
34 pub fn into_vec(self) -> Vec<P> {
40 self.buf
41 }
42
43 pub fn width(&self) -> u32 {
49 self.width
50 }
51 pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
53 self.into_iter()
54 }
55
56 pub fn iter_mut(&mut self) -> <&mut Self as IntoIterator>::IntoIter {
58 self.buf.iter_mut()
59 }
60 pub fn height(&self) -> u32 {
66 self.len() as u32 / self.width
67 }
68 pub fn convert_with<Q>(self, convert: impl Fn(P) -> Q) -> Img<Q> {
77 let Img { buf, width } = self;
78 Img {
79 buf: buf.into_iter().map(convert).collect(),
80 width,
81 }
82 }
83 #[inline]
84 fn idx(&self, (x, y): (u32, u32)) -> usize {
85 ((y * self.width) + x) as usize
86 }
87 pub fn len(&self) -> usize {
89 self.buf.len()
90 }
91
92 pub fn is_empty(&self) -> bool {
93 self.len() == 0
94 }
95
96 pub fn get(&self, (x, y): (u32, u32)) -> Option<&P> {
98 self.buf.get(self.idx((x, y)))
99 }
100 pub fn size(&self) -> (u32, u32) {
102 (self.width, self.len() as u32 / self.width as u32)
103 }
104}
105
106impl<N: From<u8>> Img<RGB<N>> {
107 pub fn load(path: impl AsRef<Path>) -> Result<Self> {
114 match image::open(&path).and_then(|img| Ok(img.to_rgb())) {
115 Err(err) => Err(Error::input(err, path.as_ref())),
116 Ok(img) => Ok(Img {
117 buf: img.pixels().map(|p| RGB::from(p.0)).collect(),
118 width: img.width(),
119 }),
120 }
121 }
122}
123
124impl Img<RGB<u8>> {
125 pub fn save(self, path: &Path) -> Result<()> {
128 let (width, height) = self.size();
129 let buf = image::RgbImage::from_raw(width, height, self.raw_buf()).unwrap();
130 if let Err(err) = buf.save(path) {
131 Err(Error::output(err, path))
132 } else {
133 Ok(())
134 }
135 }
136 pub fn raw_buf(self) -> Vec<u8> {
143 let mut raw_buf = Vec::with_capacity(self.len() * 3);
144 for RGB(r, g, b) in self.buf {
145 raw_buf.push(r);
146 raw_buf.push(g);
147 raw_buf.push(b);
148 }
149 raw_buf
150 }
151}
152
153impl<P> Index<(u32, u32)> for Img<P> {
154 type Output = P;
155 fn index(&self, (x, y): (u32, u32)) -> &P {
156 &self.buf[self.idx((x, y))]
157 }
158}
159
160impl<P> IndexMut<(u32, u32)> for Img<P> {
161 fn index_mut(&mut self, (x, y): (u32, u32)) -> &mut P {
162 let i = self.idx((x, y));
163 &mut self.buf[i]
164 }
165}
166
167impl<P> IntoIterator for Img<P> {
168 type Item = P;
169 type IntoIter = std::vec::IntoIter<P>;
170 fn into_iter(self) -> Self::IntoIter {
171 self.buf.into_iter()
172 }
173}
174
175impl<'a, P> IntoIterator for &'a Img<P> {
176 type Item = &'a P;
177 type IntoIter = std::slice::Iter<'a, P>;
178 fn into_iter(self) -> Self::IntoIter {
179 (&self.buf).iter()
180 }
181}
182
183impl<'a, P> IntoIterator for &'a mut Img<P> {
184 type Item = &'a mut P;
185 type IntoIter = std::slice::IterMut<'a, P>;
186 fn into_iter(self) -> Self::IntoIter {
187 (&mut self.buf).iter_mut()
188 }
189}