//! GIF (first frame) and BMP via the `image` crate's pure-Rust decoders. use crate::convert::{Buf, Meta, Model, Raw, check_size, finish}; use crate::{DecodeOptions, Decoded, Error, Format, Result}; use image::{DynamicImage, ImageDecoder}; pub(crate) fn decode(bytes: &[u8], format: Format, opts: &DecodeOptions) -> Result { let err = |e: image::ImageError| Error::Malformed(format, e.to_string()); let cursor = std::io::Cursor::new(bytes); let (img, icc) = match format { Format::Gif => { let mut d = image::codecs::gif::GifDecoder::new(cursor).map_err(err)?; let (w, h) = d.dimensions(); check_size(format, w as u64, h as u64, opts)?; let icc = d.icc_profile().ok().flatten(); (DynamicImage::from_decoder(d).map_err(err)?, icc) } Format::Bmp => { let mut d = image::codecs::bmp::BmpDecoder::new(cursor).map_err(err)?; let (w, h) = d.dimensions(); check_size(format, w as u64, h as u64, opts)?; let icc = d.icc_profile().ok().flatten(); (DynamicImage::from_decoder(d).map_err(err)?, icc) } _ => return Err(Error::Unsupported(format, "not handled by this decoder")), }; let (w, h) = (img.width(), img.height()); let alpha = img.color().has_alpha(); let gray = !img.color().has_color(); let (model, alpha, buf) = match (gray, alpha) { (true, false) => (Model::Gray, false, img.into_luma8().into_raw()), (true, true) => (Model::Gray, true, img.into_luma_alpha8().into_raw()), (false, false) => (Model::Rgb, false, img.into_rgb8().into_raw()), (false, true) => (Model::Rgb, true, img.into_rgba8().into_raw()), }; let raw = Raw { width: w as usize, height: h as usize, model, alpha, premultiplied: false, buf: Buf::U8(buf), bit_depth: 8 }; finish(format, raw, Meta { icc, ..Default::default() }, (w, h), opts) }