Wrap image load panic in scope thread

This is done to avoid a panic of the whole program
Only the given thread is going to panic and the main thread can continue
This commit is contained in:
Philip Kristoffersen
2022-08-21 15:09:48 +02:00
parent 6749a3db00
commit 05cd76d552
4 changed files with 68 additions and 14 deletions
+6
View File
@@ -0,0 +1,6 @@
[InternetShortcut]
URL=https://codecombat.com/play/dungeon
IDList=
HotKey=0
IconFile=C:\Users\Philip\AppData\Local\Mozilla\Firefox\Profiles\hiiy2fz7.default-release\shortcutCache\gEyfJTfj4BiLoP3VBBQI1A==.ico
IconIndex=0
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

+62 -14
View File
@@ -11,7 +11,10 @@ pub mod ui_colors {
} }
pub mod ui_images { pub mod ui_images {
use std::path::Path; use std::{
path::Path,
thread::{self, Thread},
};
use eframe::IconData; use eframe::IconData;
use egui::{ColorImage, ImageData}; use egui::{ColorImage, ImageData};
@@ -46,7 +49,11 @@ pub mod ui_images {
pub fn load_image_from_path(path: &Path) -> Option<ColorImage> { pub fn load_image_from_path(path: &Path) -> Option<ColorImage> {
if path.exists() { if path.exists() {
if let Ok(data) = std::fs::read(path) { if let Ok(data) = std::fs::read(path) {
return load_image_from_memory(&data).ok(); let load_result = load_image_from_memory(&data);
if load_result.is_err() {
eprintln!("Could not load image at path {:?}", path);
}
return load_result.ok();
} }
} }
None None
@@ -57,17 +64,58 @@ pub mod ui_images {
let size = [image.width() as _, image.height() as _]; let size = [image.width() as _, image.height() as _];
let image_buffer = image.to_rgba8(); let image_buffer = image.to_rgba8();
let pixels = image_buffer.as_flat_samples(); let pixels = image_buffer.as_flat_samples();
let rgba = pixels.as_slice(); thread::scope(|s| {
let is_valid = size[0] * size[1] * 4 == rgba.len(); let rgba = pixels.as_slice();
if is_valid { let is_valid = size[0] * size[1] * 4 == rgba.len();
Ok(ColorImage::from_rgba_unmultiplied(size, rgba)) if is_valid {
} else { //Wrapping this in a thread, since it has a tendency to panic
Err(image::ImageError::Decoding( let thread_handle = s
image::error::DecodingError::new( .spawn(move || ColorImage::from_rgba_unmultiplied(size, rgba))
image::error::ImageFormatHint::Unknown, .join();
"Image did not have right amount of pixels", match thread_handle {
), Ok(value) => Ok(value),
)) Err(e) => {
} println!("Error loading image {:?}", e);
Err(image::ImageError::Decoding(
image::error::DecodingError::new(
image::error::ImageFormatHint::Unknown,
"Could not load image, it panicked while trying",
),
))
}
}
} else {
Err(image::ImageError::Decoding(
image::error::DecodingError::new(
image::error::ImageFormatHint::Unknown,
"Image did not have right amount of pixels",
),
))
}
})
}
}
#[cfg(test)]
mod tests {
use super::ui_images::load_image_from_path;
#[test]
pub fn test_image_load_that_is_broken() {
let res = load_image_from_path(std::path::Path::new("src/testdata/brokenimage.webp"));
assert!(res.is_none());
}
#[test]
pub fn test_image_load_that_works_png() {
let res = load_image_from_path(std::path::Path::new("src/testdata/smallpng.png"));
assert!(res.is_some());
}
#[test]
pub fn test_image_load_that_works_webp() {
let res = load_image_from_path(std::path::Path::new("src/testdata/spider.webp"));
assert!(res.is_some());
} }
} }