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}