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
use std::io::{Read, Write};
use png;
use super::{Bitmap, Gray, RGB};
pub trait PngColorType {
type PngPixelType;
const PNG_COLOR_TYPE: png::ColorType;
}
impl<T> PngColorType for Gray<T> {
type PngPixelType = Gray<u8>;
const PNG_COLOR_TYPE: png::ColorType = png::ColorType::Grayscale;
}
impl<T> PngColorType for RGB<T> {
type PngPixelType = RGB<u8>;
const PNG_COLOR_TYPE: png::ColorType = png::ColorType::RGB;
}
impl<T> Bitmap<T>
where
T: PngColorType + Copy,
T::PngPixelType: From<T>,
{
pub fn write_png(&self, writer: impl Write) -> Result<(), png::EncodingError> {
let mut encoder = png::Encoder::new(
writer, self.width(), self.height(),
);
encoder.set_color(T::PNG_COLOR_TYPE);
encoder.set_depth(png::BitDepth::Eight);
let mut writer = encoder.write_header()?;
let bitmap = Bitmap::<T::PngPixelType>::from(self);
writer.write_image_data(bitmap.raw_pixels())
}
}
impl<T> Bitmap<T>
where
T: PngColorType,
T: From<<T as PngColorType>::PngPixelType>,
T::PngPixelType: Copy,
{
pub fn read_png(reader: impl Read) -> Result<Bitmap<T>, png::DecodingError> {
let decoder = png::Decoder::new(reader);
let (info, mut reader) = decoder.read_info()?;
if info.bit_depth != png::BitDepth::Eight {
return Err(png::DecodingError::Other("Bit depth should be 8".into()));
}
if info.color_type != T::PNG_COLOR_TYPE {
return Err(png::DecodingError::Other("Color type mismatch".into()));
}
let mut bitmap = Bitmap::<T::PngPixelType>::new(info.width, info.height);
reader.next_frame(bitmap.raw_pixels_mut())?;
Ok(Bitmap::<T>::from(&bitmap))
}
}