use super::{Bitmap, Gray, Rgb, Rgba};
use std::io::{Read, Write};
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> PngColorType for Rgba<T> {
type PngPixelType = Rgba<u8>;
const PNG_COLOR_TYPE: png::ColorType = png::ColorType::Rgba;
}
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 mut reader = decoder.read_info()?;
let info = reader.info();
let mut bitmap = Bitmap::<T::PngPixelType>::new(info.width, info.height);
reader.next_frame(bitmap.raw_pixels_mut())?;
Ok(Bitmap::<T>::from(&bitmap))
}
}