#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::marker::PhantomData;
use crate::lossless::EncoderConfig;
use crate::lossy::{LossyConfig, Quality};
use crate::{Effort, Image, ImageRef, Metadata, MetadataPolicy, Result};
mod sealed {
pub trait Codec {}
}
#[derive(Debug, Clone, Copy)]
pub struct Lossless(());
#[derive(Debug, Clone, Copy)]
pub struct Lossy(());
impl sealed::Codec for Lossless {}
impl sealed::Codec for Lossy {}
#[derive(Debug, Clone)]
pub struct Encoder<C> {
effort: Effort,
metadata: Metadata,
policy: MetadataPolicy,
quality: Quality,
_codec: PhantomData<C>,
}
impl<C: sealed::Codec> Encoder<C> {
fn new() -> Self {
Self {
effort: Effort::default(),
metadata: Metadata::none(),
policy: MetadataPolicy::default(),
quality: Quality::default(),
_codec: PhantomData,
}
}
#[must_use]
pub const fn effort(mut self, effort: Effort) -> Self {
self.effort = effort;
self
}
#[must_use]
pub fn metadata(mut self, metadata: Metadata) -> Self {
self.metadata = metadata;
self
}
#[must_use]
pub const fn metadata_policy(mut self, policy: MetadataPolicy) -> Self {
self.policy = policy;
self
}
}
impl Encoder<Lossless> {
#[must_use]
pub fn lossless() -> Self {
Self::new()
}
#[cfg(feature = "alloc")]
pub fn encode(&self, image: &Image) -> Result<Vec<u8>> {
crate::lossless::encode_image(image, &self.config())
}
#[cfg(feature = "alloc")]
pub fn encode_ref(&self, image: ImageRef<'_>) -> Result<Vec<u8>> {
crate::lossless::encode(image, &self.config())
}
#[cfg(feature = "std")]
pub fn encode_to<W: std::io::Write>(&self, image: &Image, mut writer: W) -> Result<()> {
writer.write_all(&self.encode(image)?)?;
Ok(())
}
fn config(&self) -> EncoderConfig {
EncoderConfig::new()
.with_effort(self.effort)
.with_metadata(self.metadata.clone())
.with_metadata_policy(self.policy)
}
}
impl Encoder<Lossy> {
#[must_use]
pub fn lossy() -> Self {
Self::new()
}
#[must_use]
pub const fn quality(mut self, quality: u8) -> Self {
self.quality = Quality::new(quality);
self
}
#[cfg(feature = "alloc")]
pub fn encode(&self, image: &Image) -> Result<Vec<u8>> {
crate::lossy::encode_image(image, &self.config())
}
#[cfg(feature = "alloc")]
pub fn encode_ref(&self, image: ImageRef<'_>) -> Result<Vec<u8>> {
crate::lossy::encode(image, &self.config())
}
#[cfg(feature = "std")]
pub fn encode_to<W: std::io::Write>(&self, image: &Image, mut writer: W) -> Result<()> {
writer.write_all(&self.encode(image)?)?;
Ok(())
}
fn config(&self) -> LossyConfig {
LossyConfig::new()
.with_quality(self.quality.get())
.with_effort(self.effort)
.with_metadata(self.metadata.clone())
.with_metadata_policy(self.policy)
}
}