1use super::image::{Image, PixelFormat};
2use std::io::{self, BufRead, Seek, Write};
3
4impl Image {
5 pub fn read_png<R: BufRead + Seek>(input: R) -> io::Result<Image> {
7 let mut decoder = png::Decoder::new(input);
8 decoder.set_transformations(
9 png::Transformations::STRIP_16 | png::Transformations::EXPAND,
10 );
11 let info = decoder.read_header_info()?;
12 let (width, height) = (info.width, info.height);
13 let mut reader = decoder.read_info()?;
14
15 let (color_type, bit_depth) = reader.output_color_type();
16 assert!(bit_depth == png::BitDepth::Eight);
17 let pixel_format = match color_type {
18 png::ColorType::Rgba => PixelFormat::RGBA,
19 png::ColorType::Rgb => PixelFormat::RGB,
20 png::ColorType::GrayscaleAlpha => PixelFormat::GrayAlpha,
21 png::ColorType::Grayscale => PixelFormat::Gray,
22 _ => unreachable!(), };
24
25 let mut image = Image::new(pixel_format, width, height);
26 assert_eq!(Some(image.data().len()), reader.output_buffer_size());
27 reader.next_frame(image.data_mut())?;
28 reader.finish()?;
29 Ok(image)
30 }
31
32 pub fn write_png<W: Write>(&self, output: W) -> io::Result<()> {
34 let color_type = match self.format {
35 PixelFormat::RGBA => png::ColorType::Rgba,
36 PixelFormat::RGB => png::ColorType::Rgb,
37 PixelFormat::GrayAlpha => png::ColorType::GrayscaleAlpha,
38 PixelFormat::Gray => png::ColorType::Grayscale,
39 PixelFormat::Alpha => {
40 return self
41 .convert_to(PixelFormat::GrayAlpha)
42 .write_png(output);
43 }
44 };
45 let mut encoder = png::Encoder::new(output, self.width, self.height);
46 encoder.set_color(color_type);
47 encoder.set_depth(png::BitDepth::Eight);
48
49 let mut writer = encoder.write_header()?;
50 writer.write_image_data(&self.data)?;
51 Ok(())
52 }
53}