#![cfg(feature = "qoi")]
use zune_core::bit_depth::BitDepth;
use zune_core::bytestream::ZReaderTrait;
use zune_core::colorspace::ColorSpace;
use zune_core::options::EncoderOptions;
pub use zune_qoi::*;
use crate::codecs::{create_options_for_encoder, ImageFormat};
use crate::errors::{ImageErrors, ImgEncodeErrors};
use crate::image::Image;
use crate::metadata::ImageMetadata;
use crate::traits::{DecodeInto, DecoderTrait, EncoderTrait};
impl<T> DecoderTrait<T> for QoiDecoder<T>
where
T: ZReaderTrait
{
fn decode(&mut self) -> Result<Image, ImageErrors> {
let pixels = self.decode()?;
let colorspace = self.get_colorspace().unwrap();
let (width, height) = self.get_dimensions().unwrap();
let depth = self.get_bit_depth();
let mut image = Image::from_u8(&pixels, width, height, colorspace);
image.metadata.format = Some(ImageFormat::QOI);
Ok(image)
}
fn dimensions(&self) -> Option<(usize, usize)> {
self.get_dimensions()
}
fn out_colorspace(&self) -> ColorSpace {
self.get_colorspace().unwrap()
}
fn name(&self) -> &'static str {
"QOI Decoder"
}
fn is_experimental(&self) -> bool {
true
}
fn read_headers(&mut self) -> Result<Option<ImageMetadata>, crate::errors::ImageErrors> {
self.decode_headers()
.map_err(<QoiErrors as Into<ImageErrors>>::into)?;
let (width, height) = self.get_dimensions().unwrap();
let depth = self.get_bit_depth();
let metadata = ImageMetadata {
format: Some(ImageFormat::QOI),
colorspace: self.get_colorspace().unwrap(),
depth: depth,
width: width,
height: height,
..Default::default()
};
Ok(Some(metadata))
}
}
#[derive(Copy, Clone, Default)]
pub struct QoiEncoder {
options: Option<EncoderOptions>
}
impl QoiEncoder {
pub fn new() -> QoiEncoder {
QoiEncoder::default()
}
pub fn new_with_options(options: EncoderOptions) -> QoiEncoder {
QoiEncoder {
options: Some(options)
}
}
}
impl EncoderTrait for QoiEncoder {
fn name(&self) -> &'static str {
"QOI Encoder"
}
fn encode_inner(&mut self, image: &Image) -> Result<Vec<u8>, ImageErrors> {
let options = create_options_for_encoder(self.options, image);
let data = &image.to_u8()[0];
let mut qoi_encoder = zune_qoi::QoiEncoder::new(data, options);
let data = qoi_encoder
.encode()
.map_err(<QoiEncodeErrors as Into<ImgEncodeErrors>>::into)?;
Ok(data)
}
fn supported_colorspaces(&self) -> &'static [ColorSpace] {
&[ColorSpace::RGBA, ColorSpace::RGB]
}
fn format(&self) -> ImageFormat {
ImageFormat::QOI
}
fn supported_bit_depth(&self) -> &'static [BitDepth] {
&[BitDepth::Eight]
}
fn default_depth(&self, _: BitDepth) -> BitDepth {
BitDepth::Eight
}
fn default_colorspace(&self, colorspace: ColorSpace) -> ColorSpace {
if colorspace.has_alpha() {
ColorSpace::RGBA
} else {
ColorSpace::RGB
}
}
fn set_options(&mut self, opts: EncoderOptions) {
self.options = Some(opts)
}
}
impl From<zune_qoi::QoiErrors> for ImageErrors {
fn from(error: zune_qoi::QoiErrors) -> Self {
let err = format!("qoi: {error:?}");
ImageErrors::ImageDecodeErrors(err)
}
}
impl From<zune_qoi::QoiEncodeErrors> for ImgEncodeErrors {
fn from(error: zune_qoi::QoiEncodeErrors) -> Self {
let err = format!("qoi: {error:?}");
ImgEncodeErrors::Generic(err)
}
}
impl<T> DecodeInto for QoiDecoder<T>
where
T: ZReaderTrait
{
fn decode_into(&mut self, buffer: &mut [u8]) -> Result<(), ImageErrors> {
self.decode_into(buffer)?;
Ok(())
}
fn output_buffer_size(&mut self) -> Result<usize, ImageErrors> {
self.decode_headers()?;
Ok(self.output_buffer_size().unwrap())
}
}