Skip to main content

fast_webp/
bytes.rs

1use crate::error::WebpError;
2#[cfg(feature = "image-codecs")]
3use crate::image_api::encode_dynamic_image;
4use crate::options::WebpOptions;
5
6pub(crate) const PNG_SIG: &[u8; 8] = b"\x89PNG\r\n\x1a\n";
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub enum InputFormat {
10    Jpeg,
11    Png,
12}
13
14pub fn detect_format(input: &[u8]) -> Option<InputFormat> {
15    if input.starts_with(PNG_SIG) {
16        Some(InputFormat::Png)
17    } else if input.len() >= 3 && input[0] == 0xff && input[1] == 0xd8 && input[2] == 0xff {
18        Some(InputFormat::Jpeg)
19    } else {
20        None
21    }
22}
23
24pub fn convert_bytes_to_webp(input: &[u8], options: WebpOptions) -> Result<Vec<u8>, WebpError> {
25    convert_bytes_to_webp_impl(input, options)
26}
27
28#[cfg(feature = "image-codecs")]
29fn convert_bytes_to_webp_impl(input: &[u8], options: WebpOptions) -> Result<Vec<u8>, WebpError> {
30    let image_format = match detect_format(input).ok_or(WebpError::UnsupportedFormat)? {
31        InputFormat::Jpeg => image::ImageFormat::Jpeg,
32        InputFormat::Png => image::ImageFormat::Png,
33    };
34    let image =
35        image::load_from_memory_with_format(input, image_format).map_err(
36            |err| match image_format {
37                image::ImageFormat::Jpeg => WebpError::DecodeJpeg(err.to_string()),
38                image::ImageFormat::Png => WebpError::DecodePng(err.to_string()),
39                _ => WebpError::UnsupportedFormat,
40            },
41        )?;
42
43    encode_dynamic_image(&image, options)
44}
45
46#[cfg(not(feature = "image-codecs"))]
47fn convert_bytes_to_webp_impl(_input: &[u8], _options: WebpOptions) -> Result<Vec<u8>, WebpError> {
48    Err(WebpError::UnsupportedFormat)
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn detects_formats() {
57        assert_eq!(detect_format(PNG_SIG), Some(InputFormat::Png));
58        assert_eq!(
59            detect_format(&[0xff, 0xd8, 0xff, 0xdb]),
60            Some(InputFormat::Jpeg)
61        );
62        assert_eq!(detect_format(b"not an image"), None);
63    }
64}