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
use png;
use std::io::{self, Read, Write};
use image::{Image, PixelFormat};

impl Image {

    /// Reads an image from a PNG file.
    pub fn read_png<R: Read>(input: R) -> io::Result<Image> {
        let decoder = png::Decoder::new(input);
        let (info, mut reader) = decoder.read_info()?;
        let pixel_format = match info.color_type {
            png::ColorType::RGBA => PixelFormat::RGBA,
            png::ColorType::RGB => PixelFormat::RGB,
            png::ColorType::GrayscaleAlpha => PixelFormat::GrayAlpha,
            png::ColorType::Grayscale => PixelFormat::Gray,
            _ => {
                // TODO: Support other color types.
                return Err(io::Error::new(io::ErrorKind::InvalidData,
                                          format!("unsupported PNG color \
                                                   type: {:?}",
                                                  info.color_type)));
            }
        };
        if info.bit_depth != png::BitDepth::Eight {
            // TODO: Support other bit depths.
            return Err(io::Error::new(io::ErrorKind::InvalidData,
                                      format!("unsupported PNG bit depth: \
                                               {:?}",
                                              info.bit_depth)));

        }
        let mut image = Image::new(pixel_format, info.width, info.height);
        assert_eq!(image.data().len(), info.buffer_size());
        reader.next_frame(image.data_mut())?;
        Ok(image)
    }

    /// Writes the image to a PNG file.
    pub fn write_png<W: Write>(&self, output: W) -> io::Result<()> {
        let color_type = match self.format {
            PixelFormat::RGBA => png::ColorType::RGBA,
            PixelFormat::RGB => png::ColorType::RGB,
            PixelFormat::GrayAlpha => png::ColorType::GrayscaleAlpha,
            PixelFormat::Gray => png::ColorType::Grayscale,
            PixelFormat::Alpha => {
                return self.convert_to(PixelFormat::GrayAlpha)
                    .write_png(output);
            }
        };
        let mut encoder = png::Encoder::new(output, self.width, self.height);
        encoder.set_color(color_type);
        encoder.set_depth(png::BitDepth::Eight);
        let mut writer = encoder.write_header()?;
        writer.write_image_data(&self.data).map_err(|err| match err {
            png::EncodingError::IoError(err) => err,
            png::EncodingError::Format(msg) => {
                io::Error::new(io::ErrorKind::InvalidData, msg.into_owned())
            }
        })
    }
}