mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 06:40:06 -04:00
Texture loading in egui (#1110)
* Move texture allocation into epaint/egui proper * Add TextureHandle * egui_glow: cast using bytemuck instead of unsafe code * Optimize glium painter * Optimize WebGL * Add example of loading an image from file
This commit is contained in:
@@ -7,7 +7,7 @@ struct Resource {
|
||||
text: Option<String>,
|
||||
|
||||
/// If set, the response was an image.
|
||||
image: Option<epi::Image>,
|
||||
image: Option<egui::ImageData>,
|
||||
|
||||
/// If set, the response was text with some supported syntax highlighting (e.g. ".rs" or ".md").
|
||||
colored_text: Option<ColoredText>,
|
||||
@@ -17,7 +17,7 @@ impl Resource {
|
||||
fn from_response(ctx: &egui::Context, response: ehttp::Response) -> Self {
|
||||
let content_type = response.content_type().unwrap_or_default();
|
||||
let image = if content_type.starts_with("image/") {
|
||||
decode_image(&response.bytes)
|
||||
load_image(&response.bytes).ok().map(|img| img.into())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -112,7 +112,7 @@ impl epi::App for HttpApp {
|
||||
} else if let Some(result) = &self.result {
|
||||
match result {
|
||||
Ok(resource) => {
|
||||
ui_resource(ui, frame, &mut self.tex_mngr, resource);
|
||||
ui_resource(ui, &mut self.tex_mngr, resource);
|
||||
}
|
||||
Err(error) => {
|
||||
// This should only happen if the fetch API isn't available or something similar.
|
||||
@@ -160,7 +160,7 @@ fn ui_url(ui: &mut egui::Ui, frame: &epi::Frame, url: &mut String) -> bool {
|
||||
trigger_fetch
|
||||
}
|
||||
|
||||
fn ui_resource(ui: &mut egui::Ui, frame: &epi::Frame, tex_mngr: &mut TexMngr, resource: &Resource) {
|
||||
fn ui_resource(ui: &mut egui::Ui, tex_mngr: &mut TexMngr, resource: &Resource) {
|
||||
let Resource {
|
||||
response,
|
||||
text,
|
||||
@@ -212,11 +212,10 @@ fn ui_resource(ui: &mut egui::Ui, frame: &epi::Frame, tex_mngr: &mut TexMngr, re
|
||||
}
|
||||
|
||||
if let Some(image) = image {
|
||||
if let Some(texture_id) = tex_mngr.texture(frame, &response.url, image) {
|
||||
let mut size = egui::Vec2::new(image.size[0] as f32, image.size[1] as f32);
|
||||
size *= (ui.available_width() / size.x).min(1.0);
|
||||
ui.image(texture_id, size);
|
||||
}
|
||||
let texture = tex_mngr.texture(ui.ctx(), &response.url, image);
|
||||
let mut size = texture.size_vec2();
|
||||
size *= (ui.available_width() / size.x).min(1.0);
|
||||
ui.image(texture, size);
|
||||
} else if let Some(colored_text) = colored_text {
|
||||
colored_text.ui(ui);
|
||||
} else if let Some(text) = &text {
|
||||
@@ -293,33 +292,32 @@ impl ColoredText {
|
||||
#[derive(Default)]
|
||||
struct TexMngr {
|
||||
loaded_url: String,
|
||||
texture_id: Option<egui::TextureId>,
|
||||
texture: Option<egui::TextureHandle>,
|
||||
}
|
||||
|
||||
impl TexMngr {
|
||||
fn texture(
|
||||
&mut self,
|
||||
frame: &epi::Frame,
|
||||
ctx: &egui::Context,
|
||||
url: &str,
|
||||
image: &epi::Image,
|
||||
) -> Option<egui::TextureId> {
|
||||
if self.loaded_url != url {
|
||||
if let Some(texture_id) = self.texture_id.take() {
|
||||
frame.free_texture(texture_id);
|
||||
}
|
||||
|
||||
self.texture_id = Some(frame.alloc_texture(image.clone()));
|
||||
image: &egui::ImageData,
|
||||
) -> &egui::TextureHandle {
|
||||
if self.loaded_url != url || self.texture.is_none() {
|
||||
self.texture = Some(ctx.load_texture(url, image.clone()));
|
||||
self.loaded_url = url.to_owned();
|
||||
}
|
||||
self.texture_id
|
||||
self.texture.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_image(bytes: &[u8]) -> Option<epi::Image> {
|
||||
use image::GenericImageView;
|
||||
let image = image::load_from_memory(bytes).ok()?;
|
||||
fn load_image(image_data: &[u8]) -> Result<egui::ColorImage, image::ImageError> {
|
||||
use image::GenericImageView as _;
|
||||
let image = image::load_from_memory(image_data)?;
|
||||
let size = [image.width() as _, image.height() as _];
|
||||
let image_buffer = image.to_rgba8();
|
||||
let size = [image.width() as usize, image.height() as usize];
|
||||
let pixels = image_buffer.into_vec();
|
||||
Some(epi::Image::from_rgba_unmultiplied(size, &pixels))
|
||||
let pixels = image_buffer.as_flat_samples();
|
||||
Ok(egui::ColorImage::from_rgba_unmultiplied(
|
||||
size,
|
||||
pixels.as_slice(),
|
||||
))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user