cog_task/resource/
image.rs1use eframe::egui::mutex::RwLock;
2use eframe::egui::{ColorImage, ImageData, TextureFilter, Vec2};
3use eframe::{egui, epaint};
4use egui::TextureId;
5use eyre::{eyre, Context, Result};
6use std::fs;
7use std::path::Path;
8use std::sync::Arc;
9
10pub fn image_from_file(
11 tex_manager: Arc<RwLock<epaint::TextureManager>>,
12 path: &Path,
13) -> Result<(TextureId, Vec2)> {
14 let bytes = fs::read(path).wrap_err_with(|| format!("Failed to read image file: {path:?}"))?;
15 image_from_bytes(tex_manager, &bytes, path)
16}
17
18#[inline]
19pub fn image_from_bytes(
20 tex_manager: Arc<RwLock<epaint::TextureManager>>,
21 bytes: &[u8],
22 path: &Path,
23) -> Result<(TextureId, Vec2)> {
24 let image = image::load_from_memory(bytes)
25 .wrap_err_with(|| format!("Failed to decode image: {path:?}"))?;
26 let size = [image.width() as _, image.height() as _];
27 let image_buffer = image.to_rgba8();
28 let pixels = image_buffer.as_flat_samples();
29 let image = ColorImage::from_rgba_unmultiplied(size, pixels.as_slice());
30
31 Ok((
32 tex_manager.write().alloc(
33 path.to_str().unwrap().to_owned(),
34 ImageData::Color(image),
35 TextureFilter::Nearest,
36 ),
37 Vec2::new(size[0] as _, size[1] as _),
38 ))
39}
40
41pub fn svg_from_file(
42 tex_manager: Arc<RwLock<epaint::TextureManager>>,
43 path: &Path,
44) -> Result<(TextureId, Vec2)> {
45 let bytes = fs::read(path).wrap_err_with(|| format!("Failed to read image file: {path:?}"))?;
46 svg_from_bytes(tex_manager, &bytes, path)
47}
48
49#[inline]
50pub fn svg_from_bytes(
51 tex_manager: Arc<RwLock<epaint::TextureManager>>,
52 bytes: &[u8],
53 path: &Path,
54) -> Result<(TextureId, Vec2)> {
55 let mut opt = usvg::Options::default();
56 opt.fontdb.load_system_fonts();
57
58 let rtree = usvg::Tree::from_data(bytes, &opt.to_ref())
59 .wrap_err_with(|| format!("Failed to decode SVG: {path:?}"))?;
60 let orig_size = rtree.svg_node().size;
61
62 let [width, height] = [1920, 1080];
63 let scale = (width as f64 / orig_size.width()).min(height as f64 / orig_size.height());
64 let [width, height] = [
65 (scale * orig_size.width() as f64).round() as _,
66 (scale * orig_size.height() as f64).round() as _,
67 ];
68
69 let mut pixmap = tiny_skia::Pixmap::new(width, height)
70 .ok_or_else(|| eyre!("Failed to create SVG Pixmap of size {width}x{height}: {path:?}"))?;
71
72 resvg::render(
73 &rtree,
74 usvg::FitTo::Size(width, height),
75 Default::default(),
76 pixmap.as_mut(),
77 )
78 .ok_or_else(|| eyre!("Failed to decode SVG: {path:?}"))?;
79
80 let image = ColorImage::from_rgba_unmultiplied([width as _, height as _], pixmap.data());
81
82 Ok((
83 tex_manager.write().alloc(
84 path.to_str().unwrap().to_owned(),
85 ImageData::Color(image),
86 TextureFilter::Nearest,
87 ),
88 Vec2::new(orig_size.width() as _, orig_size.height() as _),
89 ))
90}