use std::{
fs::File,
io::{BufWriter, Write},
ops::Deref,
path::Path,
};
use crate::{
buffer::Buffer,
color,
encoder::{self, Encoder},
error::{self, Error},
format::Format,
pixel,
};
#[inline]
pub fn to<P, C, D, W>(output: W, buffer: &Buffer<P, C, D>) -> error::Result<()>
where
P: Into<color::Rgb> + Into<color::Rgba> + Into<color::Luma> + Into<color::Lumaa>,
P: pixel::Read<C>,
C: pixel::Channel,
D: Deref<Target = [C]>,
W: Write,
{
with_format(output, Format::Png, buffer)
}
#[inline]
pub fn to_path<P, C, D, W>(path: W, buffer: &Buffer<P, C, D>) -> error::Result<()>
where
P: Into<color::Rgb> + Into<color::Rgba> + Into<color::Luma> + Into<color::Lumaa>,
P: pixel::Read<C>,
C: pixel::Channel,
D: Deref<Target = [C]>,
W: AsRef<Path>,
{
let path = path.as_ref();
let extension = path.extension().and_then(|p| p.to_str()).map(|p| p.to_lowercase());
let format = match extension.as_ref().map(|p| p.as_ref()) {
Some("png") => Format::Png,
Some("jpg") | Some("jpeg") => Format::Jpeg,
Some("bmp") => Format::Bmp,
Some("tga") => Format::Tga,
Some("gif") => Format::Gif,
_ => return Err(Error::Unsupported("unsupported image format".into())),
};
with_format(BufWriter::new(File::create(path)?), format, buffer)
}
#[inline]
pub fn with_format<P, C, D, W>(output: W, format: Format, buffer: &Buffer<P, C, D>) -> error::Result<()>
where
P: Into<color::Rgb> + Into<color::Rgba> + Into<color::Luma> + Into<color::Lumaa>,
P: pixel::Read<C>,
C: pixel::Channel,
D: Deref<Target = [C]>,
W: Write,
{
match format {
#[cfg(feature = "png")]
Format::Png => png(output, buffer, |_| {}),
#[cfg(feature = "bmp")]
Format::Bmp => bmp(output, buffer, |_| {}),
#[cfg(feature = "tga")]
Format::Tga => tga(output, buffer, |_| {}),
#[cfg(feature = "gif")]
Format::Gif => gif(output, buffer, |_| {}),
_ => Err(Error::Unsupported("unsupported image format".into())),
}
}
#[cfg(feature = "png")]
#[inline]
pub fn png<P, C, D, F, W>(output: W, buffer: &Buffer<P, C, D>, func: F) -> error::Result<()>
where
P: Into<color::Rgb> + Into<color::Rgba> + Into<color::Luma> + Into<color::Lumaa>,
P: pixel::Read<C>,
C: pixel::Channel,
D: Deref<Target = [C]>,
F: FnOnce(&mut encoder::png::Encoder<W>),
W: Write,
{
let mut encoder = encoder::png::Encoder::new(output);
func(&mut encoder);
encoder.frame(buffer)
}
#[cfg(feature = "bmp")]
#[inline]
pub fn bmp<P, C, D, F, W>(output: W, buffer: &Buffer<P, C, D>, func: F) -> error::Result<()>
where
P: Into<color::Rgb> + Into<color::Rgba>,
P: pixel::Read<C>,
C: pixel::Channel,
D: Deref<Target = [C]>,
F: FnOnce(&mut encoder::bmp::Encoder<W>),
W: Write,
{
let mut encoder = encoder::bmp::Encoder::new(output);
func(&mut encoder);
encoder.frame(buffer)
}
#[cfg(feature = "tga")]
#[inline]
pub fn tga<P, C, D, F, W>(output: W, buffer: &Buffer<P, C, D>, func: F) -> error::Result<()>
where
P: Into<color::Rgb> + Into<color::Rgba> + Into<color::Luma> + Into<color::Lumaa>,
P: pixel::Read<C>,
C: pixel::Channel,
D: Deref<Target = [C]>,
F: FnOnce(&mut encoder::tga::Encoder<W>),
W: Write,
{
let mut encoder = encoder::tga::Encoder::new(output);
func(&mut encoder);
encoder.frame(buffer)
}
#[cfg(feature = "gif")]
#[inline]
pub fn gif<P, C, D, F, W>(output: W, buffer: &Buffer<P, C, D>, func: F) -> error::Result<()>
where
P: Into<color::Rgb> + Into<color::Rgba> + Into<color::Luma> + Into<color::Lumaa>,
P: pixel::Read<C>,
C: pixel::Channel,
D: Deref<Target = [C]>,
F: FnOnce(&mut encoder::gif::Encoder<W>),
W: Write,
{
let mut encoder = encoder::gif::Encoder::new(output);
func(&mut encoder);
encoder.frame(buffer)
}