Skip to content

Commit

Permalink
feat: added webp decoder
Browse files Browse the repository at this point in the history
  • Loading branch information
SalOne22 committed Mar 15, 2024
1 parent b64b931 commit 3916d28
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 0 deletions.
77 changes: 77 additions & 0 deletions src/codecs/webp/decoder/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use std::{io::Read, marker::PhantomData};

use webp::{AnimDecoder, DecodeAnimImage};
use zune_core::{bit_depth::BitDepth, bytestream::ZReaderTrait, colorspace::ColorSpace};
use zune_image::{errors::ImageErrors, frame::Frame, image::Image, traits::DecoderTrait};

pub struct WebPDecoder<R: Read> {
inner: DecodeAnimImage,
phantom: PhantomData<R>,
}

impl<R: Read> WebPDecoder<R> {
pub fn try_new(mut source: R) -> Result<WebPDecoder<R>, ImageErrors> {
let mut buf = Vec::new();
source.read_to_end(&mut buf)?;

let decoder = AnimDecoder::new(&buf);
let img = decoder
.decode()
.map_err(|e| ImageErrors::ImageDecodeErrors(e))?;

Ok(WebPDecoder {
inner: img,
phantom: PhantomData,
})
}
}

impl<R, T> DecoderTrait<T> for WebPDecoder<R>
where
R: Read,
T: ZReaderTrait,
{
fn decode(&mut self) -> Result<Image, ImageErrors> {
let (width, height) = <WebPDecoder<R> as DecoderTrait<T>>::dimensions(self).unwrap();
let color = <WebPDecoder<R> as DecoderTrait<T>>::out_colorspace(self);

let frames = self
.inner
.into_iter()
.enumerate()
.map(|(idx, frame)| {
Frame::from_u8(frame.get_image(), color, idx, frame.get_time_ms() as usize)
})
.collect::<Vec<_>>();

Ok(Image::new_frames(
frames,
BitDepth::Eight,
width,
height,
color,
))
}

fn dimensions(&self) -> Option<(usize, usize)> {
let frame = self.inner.get_frame(0).unwrap();

Some((frame.width() as usize, frame.height() as usize))
}

fn out_colorspace(&self) -> ColorSpace {
let frame = self.inner.get_frame(0).unwrap();

match frame.get_layout() {
webp::PixelLayout::Rgb => ColorSpace::RGB,
webp::PixelLayout::Rgba => ColorSpace::RGBA,
}
}

fn name(&self) -> &'static str {
"webp"
}
}

#[cfg(test)]
mod tests;
20 changes: 20 additions & 0 deletions src/codecs/webp/decoder/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::fs::read;

use zune_core::bytestream::ZByteReader;

use super::*;

#[test]
fn decode() {
let file_content = read("tests/files/webp/f1t.webp").unwrap();

let reader = ZByteReader::new(file_content);

let mut decoder = WebPDecoder::try_new(reader).unwrap();

let img =
<WebPDecoder<ZByteReader<Vec<u8>>> as DecoderTrait<Vec<u8>>>::decode(&mut decoder).unwrap();

assert_eq!(img.dimensions(), (48, 80));
assert_eq!(img.colorspace(), ColorSpace::RGBA);
}
2 changes: 2 additions & 0 deletions src/codecs/webp/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod decoder;
mod encoder;

pub use decoder::*;
pub use encoder::*;

0 comments on commit 3916d28

Please sign in to comment.