1use std::{
2 any::Any,
3 fmt::Debug,
4 io,
5 path::{Path, PathBuf},
6 sync::{Arc, Weak},
7};
8
9use glam::Vec2;
10
11#[macro_export]
12macro_rules! include_image {
13 ($($tt:tt)*) => {
14 $crate::ImageData::from_bytes(include_bytes!($($tt)*))
15 };
16}
17
18#[derive(Debug)]
19pub enum ImageLoadError {
20 Io(io::Error),
21 Image(image::ImageError),
22}
23
24impl From<io::Error> for ImageLoadError {
25 fn from(err: io::Error) -> Self {
26 Self::Io(err)
27 }
28}
29
30impl From<image::ImageError> for ImageLoadError {
31 fn from(err: image::ImageError) -> Self {
32 Self::Image(err)
33 }
34}
35
36#[derive(Clone, Debug, PartialEq, Eq, Hash)]
37pub enum ImageSource {
38 Path(PathBuf),
39 Data(ImageData),
40}
41
42impl Default for ImageSource {
43 fn default() -> Self {
44 Self::Data(ImageData::default())
45 }
46}
47
48impl From<PathBuf> for ImageSource {
49 fn from(path: PathBuf) -> Self {
50 Self::Path(path)
51 }
52}
53
54impl From<&Path> for ImageSource {
55 fn from(path: &Path) -> Self {
56 Self::Path(path.into())
57 }
58}
59
60impl From<String> for ImageSource {
61 fn from(path: String) -> Self {
62 Self::Path(path.into())
63 }
64}
65
66impl From<&str> for ImageSource {
67 fn from(path: &str) -> Self {
68 Self::Path(path.into())
69 }
70}
71
72impl From<ImageData> for ImageSource {
73 fn from(image: ImageData) -> Self {
74 Self::Data(image)
75 }
76}
77
78impl From<&[u8]> for ImageSource {
79 fn from(bytes: &[u8]) -> Self {
80 Self::Data(ImageData::from_bytes(bytes))
81 }
82}
83
84impl ImageSource {
85 pub fn try_load(&self) -> Result<ImageData, ImageLoadError> {
86 match self {
87 Self::Path(path) => Ok(ImageData::try_load(path)?),
88 Self::Data(image) => Ok(image.clone()),
89 }
90 }
91
92 pub fn load(&self) -> ImageData {
93 match self {
94 Self::Path(path) => ImageData::load(path),
95 Self::Data(image) => image.clone(),
96 }
97 }
98}
99
100#[derive(Clone, PartialEq, Eq, Hash)]
101pub struct ImageData {
102 width: u32,
103 height: u32,
104 pixels: Arc<[u8]>,
105}
106
107impl ImageData {
108 pub fn new(width: u32, height: u32, pixels: impl Into<Arc<[u8]>>) -> Self {
109 Self {
110 width,
111 height,
112 pixels: pixels.into(),
113 }
114 }
115
116 pub fn try_load(path: impl AsRef<Path>) -> image::ImageResult<Self> {
117 let image = image::open(path)?;
118 let width = image.width();
119 let height = image.height();
120 let pixels = image.into_rgba8().into_raw();
121
122 Ok(Self {
123 width,
124 height,
125 pixels: pixels.into(),
126 })
127 }
128
129 pub fn load(path: impl AsRef<Path>) -> Self {
130 match Self::try_load(path) {
131 Ok(image) => image,
132 Err(err) => {
133 tracing::error!("Failed to load image: {}", err);
134 Self::default()
135 }
136 }
137 }
138
139 pub fn try_from_bytes(bytes: &[u8]) -> image::ImageResult<Self> {
140 let image = image::load_from_memory(bytes)?;
141 let width = image.width();
142 let height = image.height();
143 let pixels = image.into_rgba8().into_raw();
144
145 Ok(Self {
146 width,
147 height,
148 pixels: pixels.into(),
149 })
150 }
151
152 pub fn from_bytes(bytes: &[u8]) -> Self {
153 match Self::try_from_bytes(bytes) {
154 Ok(image) => image,
155 Err(err) => {
156 tracing::error!("Failed to load image: {}", err);
157 Self::default()
158 }
159 }
160 }
161
162 pub fn width(&self) -> u32 {
163 self.width
164 }
165
166 pub fn height(&self) -> u32 {
167 self.height
168 }
169
170 pub fn size(&self) -> Vec2 {
171 Vec2::new(self.width as f32, self.height as f32)
172 }
173
174 pub fn pixels(&self) -> &[u8] {
175 &self.pixels
176 }
177}
178
179impl Default for ImageData {
180 fn default() -> Self {
181 Self {
182 width: 1,
183 height: 1,
184 pixels: vec![0, 0, 0, 0].into(),
185 }
186 }
187}
188
189impl Debug for ImageData {
190 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191 f.debug_struct("ImageData")
192 .field("width", &self.width)
193 .field("height", &self.height)
194 .field("pixels", &Arc::as_ptr(&self.pixels))
195 .finish()
196 }
197}
198
199#[derive(Clone, Debug)]
200pub struct ImageHandle {
201 width: u32,
202 height: u32,
203 handle: Arc<dyn Any + Send + Sync>,
204}
205
206impl ImageHandle {
207 pub fn new<T: Any + Send + Sync>(handle: T, width: u32, height: u32) -> Self {
208 Self {
209 width,
210 height,
211 handle: Arc::new(handle),
212 }
213 }
214
215 pub fn downgrade(&self) -> WeakImageHandle {
216 WeakImageHandle {
217 width: self.width,
218 height: self.height,
219 handle: Arc::downgrade(&self.handle),
220 }
221 }
222
223 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
224 self.handle.downcast_ref()
225 }
226
227 pub fn downcast_arc<T: Any + Send + Sync>(self) -> Option<Arc<T>> {
228 Arc::downcast(self.handle).ok()
229 }
230
231 pub fn width(&self) -> u32 {
232 self.width
233 }
234
235 pub fn height(&self) -> u32 {
236 self.height
237 }
238
239 pub fn size(&self) -> Vec2 {
240 Vec2::new(self.width as f32, self.height as f32)
241 }
242}
243
244#[derive(Clone, Debug)]
245pub struct WeakImageHandle {
246 width: u32,
247 height: u32,
248 handle: Weak<dyn Any + Send + Sync>,
249}
250
251impl WeakImageHandle {
252 pub fn upgrade(&self) -> Option<ImageHandle> {
253 Some(ImageHandle {
254 width: self.width,
255 height: self.height,
256 handle: self.handle.upgrade()?,
257 })
258 }
259
260 pub fn is_alive(&self) -> bool {
261 self.handle.strong_count() > 0
262 }
263
264 pub fn width(&self) -> u32 {
265 self.width
266 }
267
268 pub fn height(&self) -> u32 {
269 self.height
270 }
271
272 pub fn size(&self) -> Vec2 {
273 Vec2::new(self.width as f32, self.height as f32)
274 }
275}