mirror of
https://github.com/emilk/egui.git
synced 2026-08-30 05:10:03 -04:00
Support loading images with weird urls and improve error message (#5431)
* Closes #5341 * [x] I have followed the instructions in the PR template
This commit is contained in:
@@ -7,7 +7,7 @@ use egui::{
|
||||
use image::ImageFormat;
|
||||
use std::{mem::size_of, path::Path, sync::Arc};
|
||||
|
||||
type Entry = Result<Arc<ColorImage>, String>;
|
||||
type Entry = Result<Arc<ColorImage>, LoadError>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ImageCrateLoader {
|
||||
@@ -31,9 +31,14 @@ fn is_supported_uri(uri: &str) -> bool {
|
||||
.any(|format_ext| ext == *format_ext)
|
||||
}
|
||||
|
||||
fn is_unsupported_mime(mime: &str) -> bool {
|
||||
fn is_supported_mime(mime: &str) -> bool {
|
||||
// This is the default mime type for binary files, so this might actually be a valid image,
|
||||
// let's relay on image's format guessing
|
||||
if mime == "application/octet-stream" {
|
||||
return true;
|
||||
}
|
||||
// Uses only the enabled image crate features
|
||||
!ImageFormat::all()
|
||||
ImageFormat::all()
|
||||
.filter(ImageFormat::reading_enabled)
|
||||
.map(|fmt| fmt.to_mime_type())
|
||||
.any(|format_mime| mime == format_mime)
|
||||
@@ -46,12 +51,12 @@ impl ImageLoader for ImageCrateLoader {
|
||||
|
||||
fn load(&self, ctx: &egui::Context, uri: &str, _: SizeHint) -> ImageLoadResult {
|
||||
// three stages of guessing if we support loading the image:
|
||||
// 1. URI extension
|
||||
// 1. URI extension (only done for files)
|
||||
// 2. Mime from `BytesPoll::Ready`
|
||||
// 3. image::guess_format
|
||||
// 3. image::guess_format (used internally by image::load_from_memory)
|
||||
|
||||
// (1)
|
||||
if !is_supported_uri(uri) {
|
||||
if uri.starts_with("file://") && !is_supported_uri(uri) {
|
||||
return Err(LoadError::NotSupported);
|
||||
}
|
||||
|
||||
@@ -59,26 +64,26 @@ impl ImageLoader for ImageCrateLoader {
|
||||
if let Some(entry) = cache.get(uri).cloned() {
|
||||
match entry {
|
||||
Ok(image) => Ok(ImagePoll::Ready { image }),
|
||||
Err(err) => Err(LoadError::Loading(err)),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
} else {
|
||||
match ctx.try_load_bytes(uri) {
|
||||
Ok(BytesPoll::Ready { bytes, mime, .. }) => {
|
||||
// (2 and 3)
|
||||
if mime.as_deref().is_some_and(is_unsupported_mime)
|
||||
|| image::guess_format(&bytes).is_err()
|
||||
{
|
||||
return Err(LoadError::NotSupported);
|
||||
// (2)
|
||||
if let Some(mime) = mime {
|
||||
if !is_supported_mime(&mime) {
|
||||
return Err(LoadError::FormatNotSupported {
|
||||
detected_format: Some(mime),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// (3)
|
||||
log::trace!("started loading {uri:?}");
|
||||
let result = crate::image::load_image_bytes(&bytes).map(Arc::new);
|
||||
log::trace!("finished loading {uri:?}");
|
||||
cache.insert(uri.into(), result.clone());
|
||||
match result {
|
||||
Ok(image) => Ok(ImagePoll::Ready { image }),
|
||||
Err(err) => Err(LoadError::Loading(err)),
|
||||
}
|
||||
result.map(|image| ImagePoll::Ready { image })
|
||||
}
|
||||
Ok(BytesPoll::Pending { size }) => Ok(ImagePoll::Pending { size }),
|
||||
Err(err) => Err(err),
|
||||
@@ -100,7 +105,7 @@ impl ImageLoader for ImageCrateLoader {
|
||||
.values()
|
||||
.map(|result| match result {
|
||||
Ok(image) => image.pixels.len() * size_of::<egui::Color32>(),
|
||||
Err(err) => err.len(),
|
||||
Err(err) => err.byte_size(),
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user