azul_layout/image/
decode.rs

1use core::fmt;
2
3use azul_core::app_resources::{RawImage, RawImageFormat};
4use azul_css::{impl_result, impl_result_inner, U8Vec};
5use image::{
6    error::{ImageError, LimitError, LimitErrorKind},
7    DynamicImage,
8};
9
10#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
11#[repr(C)]
12pub enum DecodeImageError {
13    InsufficientMemory,
14    DimensionError,
15    UnsupportedImageFormat,
16    Unknown,
17}
18
19impl fmt::Display for DecodeImageError {
20    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21        match self {
22            DecodeImageError::InsufficientMemory => write!(
23                f,
24                "Error decoding image: Not enough memory available to perform encoding operation"
25            ),
26            DecodeImageError::DimensionError => {
27                write!(f, "Error decoding image: Wrong dimensions")
28            }
29            DecodeImageError::UnsupportedImageFormat => {
30                write!(f, "Error decoding image: Invalid data format")
31            }
32            DecodeImageError::Unknown => write!(f, "Error decoding image: Unknown error"),
33        }
34    }
35}
36
37fn translate_image_error_decode(i: ImageError) -> DecodeImageError {
38    match i {
39        ImageError::Limits(l) => match l.kind() {
40            LimitErrorKind::InsufficientMemory => DecodeImageError::InsufficientMemory,
41            LimitErrorKind::DimensionError => DecodeImageError::DimensionError,
42            _ => DecodeImageError::Unknown,
43        },
44        _ => DecodeImageError::Unknown,
45    }
46}
47
48impl_result!(
49    RawImage,
50    DecodeImageError,
51    ResultRawImageDecodeImageError,
52    copy = false,
53    [Debug, Clone]
54);
55
56pub fn decode_raw_image_from_any_bytes(image_bytes: &[u8]) -> ResultRawImageDecodeImageError {
57    use azul_core::app_resources::RawImageData;
58
59    let image_format = match image::guess_format(image_bytes) {
60        Ok(o) => o,
61        Err(e) => {
62            return ResultRawImageDecodeImageError::Err(translate_image_error_decode(e));
63        }
64    };
65
66    let decoded = match image::load_from_memory_with_format(image_bytes, image_format) {
67        Ok(o) => o,
68        Err(e) => {
69            return ResultRawImageDecodeImageError::Err(translate_image_error_decode(e));
70        }
71    };
72
73    let ((width, height), data_format, pixels) = match decoded {
74        DynamicImage::ImageLuma8(i) => (
75            i.dimensions(),
76            RawImageFormat::R8,
77            RawImageData::U8(i.into_vec().into()),
78        ),
79        DynamicImage::ImageLumaA8(i) => (
80            i.dimensions(),
81            RawImageFormat::RG8,
82            RawImageData::U8(i.into_vec().into()),
83        ),
84        DynamicImage::ImageRgb8(i) => (
85            i.dimensions(),
86            RawImageFormat::RGB8,
87            RawImageData::U8(i.into_vec().into()),
88        ),
89        DynamicImage::ImageRgba8(i) => (
90            i.dimensions(),
91            RawImageFormat::RGBA8,
92            RawImageData::U8(i.into_vec().into()),
93        ),
94        DynamicImage::ImageLuma16(i) => (
95            i.dimensions(),
96            RawImageFormat::R16,
97            RawImageData::U16(i.into_vec().into()),
98        ),
99        DynamicImage::ImageLumaA16(i) => (
100            i.dimensions(),
101            RawImageFormat::RG16,
102            RawImageData::U16(i.into_vec().into()),
103        ),
104        DynamicImage::ImageRgb16(i) => (
105            i.dimensions(),
106            RawImageFormat::RGB16,
107            RawImageData::U16(i.into_vec().into()),
108        ),
109        DynamicImage::ImageRgba16(i) => (
110            i.dimensions(),
111            RawImageFormat::RGBA16,
112            RawImageData::U16(i.into_vec().into()),
113        ),
114        DynamicImage::ImageRgb32F(i) => (
115            i.dimensions(),
116            RawImageFormat::RGBF32,
117            RawImageData::F32(i.into_vec().into()),
118        ),
119        DynamicImage::ImageRgba32F(i) => (
120            i.dimensions(),
121            RawImageFormat::RGBAF32,
122            RawImageData::F32(i.into_vec().into()),
123        ),
124        _ => {
125            return ResultRawImageDecodeImageError::Err(DecodeImageError::Unknown);
126        }
127    };
128
129    ResultRawImageDecodeImageError::Ok(RawImage {
130        tag: Vec::new().into(),
131        pixels,
132        width: width as usize,
133        height: height as usize,
134        premultiplied_alpha: false,
135        data_format,
136    })
137}