|
1 |
| -#![allow(deprecated)] |
2 |
| - |
3 | 1 | use egui::{load::SizedTexture, mutex::Mutex, ColorImage, TextureOptions, Vec2};
|
4 | 2 |
|
5 | 3 | #[cfg(feature = "svg")]
|
6 | 4 | use egui::SizeHint;
|
7 | 5 |
|
8 |
| -/// An image to be shown in egui. |
9 |
| -/// |
10 |
| -/// Load once, and save somewhere in your app state. |
11 |
| -/// |
12 |
| -/// Use the `svg` and `image` features to enable more constructors. |
13 |
| -/// |
14 |
| -/// ⚠ This type is deprecated: Consider using [`egui::Image`] instead. |
15 |
| -#[deprecated = "consider using `egui::Image` instead"] |
16 |
| -pub struct RetainedImage { |
17 |
| - debug_name: String, |
18 |
| - |
19 |
| - /// Texel size. |
20 |
| - /// |
21 |
| - /// Same as [`Self.image`]`.size` |
22 |
| - texel_size: [usize; 2], |
23 |
| - |
24 |
| - /// Original SVG size (if this is an SVG), or same as [`Self::texel_size`]. |
25 |
| - source_size: Vec2, |
26 |
| - |
27 |
| - /// Cleared once [`Self::texture`] has been loaded. |
28 |
| - image: Mutex<ColorImage>, |
29 |
| - |
30 |
| - /// Lazily loaded when we have an egui context. |
31 |
| - texture: Mutex<Option<egui::TextureHandle>>, |
32 |
| - |
33 |
| - options: TextureOptions, |
34 |
| -} |
35 |
| - |
36 |
| -impl RetainedImage { |
37 |
| - pub fn from_color_image(debug_name: impl Into<String>, image: ColorImage) -> Self { |
38 |
| - Self { |
39 |
| - debug_name: debug_name.into(), |
40 |
| - texel_size: image.size, |
41 |
| - source_size: image.source_size, |
42 |
| - image: Mutex::new(image), |
43 |
| - texture: Default::default(), |
44 |
| - options: Default::default(), |
45 |
| - } |
46 |
| - } |
47 |
| - |
48 |
| - /// Load a (non-svg) image. |
49 |
| - /// |
50 |
| - /// `image_bytes` should be the raw contents of an image file (`.png`, `.jpg`, …). |
51 |
| - /// |
52 |
| - /// Requires the "image" feature. You must also opt-in to the image formats you need |
53 |
| - /// with e.g. `image = { version = "0.25", features = ["jpeg", "png"] }`. |
54 |
| - /// |
55 |
| - /// # Errors |
56 |
| - /// On invalid image or unsupported image format. |
57 |
| - #[cfg(feature = "image")] |
58 |
| - pub fn from_image_bytes( |
59 |
| - debug_name: impl Into<String>, |
60 |
| - image_bytes: &[u8], |
61 |
| - ) -> Result<Self, String> { |
62 |
| - Ok(Self::from_color_image( |
63 |
| - debug_name, |
64 |
| - load_image_bytes(image_bytes).map_err(|err| err.to_string())?, |
65 |
| - )) |
66 |
| - } |
67 |
| - |
68 |
| - /// Pass in the bytes of an SVG that you've loaded. |
69 |
| - /// |
70 |
| - /// # Errors |
71 |
| - /// On invalid image |
72 |
| - #[cfg(feature = "svg")] |
73 |
| - pub fn from_svg_bytes( |
74 |
| - debug_name: impl Into<String>, |
75 |
| - svg_bytes: &[u8], |
76 |
| - options: &resvg::usvg::Options<'_>, |
77 |
| - ) -> Result<Self, String> { |
78 |
| - Self::from_svg_bytes_with_size(debug_name, svg_bytes, Default::default(), options) |
79 |
| - } |
80 |
| - |
81 |
| - /// Pass in the str of an SVG that you've loaded. |
82 |
| - /// |
83 |
| - /// # Errors |
84 |
| - /// On invalid image |
85 |
| - #[cfg(feature = "svg")] |
86 |
| - pub fn from_svg_str( |
87 |
| - debug_name: impl Into<String>, |
88 |
| - svg_str: &str, |
89 |
| - options: &resvg::usvg::Options<'_>, |
90 |
| - ) -> Result<Self, String> { |
91 |
| - Self::from_svg_bytes_with_size(debug_name, svg_str.as_bytes(), Default::default(), options) |
92 |
| - } |
93 |
| - |
94 |
| - /// Pass in the bytes of an SVG that you've loaded |
95 |
| - /// and the scaling option to resize the SVG with. |
96 |
| - /// |
97 |
| - /// # Errors |
98 |
| - /// On invalid image |
99 |
| - #[cfg(feature = "svg")] |
100 |
| - pub fn from_svg_bytes_with_size( |
101 |
| - debug_name: impl Into<String>, |
102 |
| - svg_bytes: &[u8], |
103 |
| - size_hint: SizeHint, |
104 |
| - options: &resvg::usvg::Options<'_>, |
105 |
| - ) -> Result<Self, String> { |
106 |
| - Ok(Self::from_color_image( |
107 |
| - debug_name, |
108 |
| - load_svg_bytes_with_size(svg_bytes, size_hint, options)?, |
109 |
| - )) |
110 |
| - } |
111 |
| - |
112 |
| - /// Set the texture filters to use for the image. |
113 |
| - /// |
114 |
| - /// **Note:** If the texture has already been uploaded to the GPU, this will require |
115 |
| - /// re-uploading the texture with the updated filter. |
116 |
| - /// |
117 |
| - /// # Example |
118 |
| - /// ```rust |
119 |
| - /// # use egui_extras::RetainedImage; |
120 |
| - /// # use egui::{Color32, epaint::{ColorImage, textures::TextureOptions}}; |
121 |
| - /// # let pixels = vec![Color32::BLACK]; |
122 |
| - /// # let color_image = ColorImage::new([1, 1], pixels); |
123 |
| - /// # |
124 |
| - /// // Upload a pixel art image without it getting blurry when resized |
125 |
| - /// let image = RetainedImage::from_color_image("my_image", color_image) |
126 |
| - /// .with_options(TextureOptions::NEAREST); |
127 |
| - /// ``` |
128 |
| - #[inline] |
129 |
| - pub fn with_options(mut self, options: TextureOptions) -> Self { |
130 |
| - self.options = options; |
131 |
| - |
132 |
| - // If the texture has already been uploaded, this will force it to be re-uploaded with the |
133 |
| - // updated filter. |
134 |
| - *self.texture.lock() = None; |
135 |
| - |
136 |
| - self |
137 |
| - } |
138 |
| - |
139 |
| - /// The size of the image data (number of pixels wide/high). |
140 |
| - pub fn texel_size(&self) -> [usize; 2] { |
141 |
| - self.texel_size |
142 |
| - } |
143 |
| - |
144 |
| - /// The size of the original SVG image (if any). |
145 |
| - /// |
146 |
| - /// Note that this can differ from [`Self::texel_size`] if the SVG was rasterized at a different |
147 |
| - /// resolution than the size of the original SVG. |
148 |
| - pub fn source_size(&self) -> Vec2 { |
149 |
| - self.source_size |
150 |
| - } |
151 |
| - |
152 |
| - #[deprecated = "use `texel_size` or `source_size` instead"] |
153 |
| - pub fn size(&self) -> [usize; 2] { |
154 |
| - self.texel_size |
155 |
| - } |
156 |
| - |
157 |
| - /// The width of the image. |
158 |
| - #[deprecated = "use `texel_size` or `source_size` instead"] |
159 |
| - pub fn width(&self) -> usize { |
160 |
| - self.texel_size[0] |
161 |
| - } |
162 |
| - |
163 |
| - /// The height of the image. |
164 |
| - #[deprecated = "use `texel_size` or `source_size` instead"] |
165 |
| - pub fn height(&self) -> usize { |
166 |
| - self.texel_size[1] |
167 |
| - } |
168 |
| - |
169 |
| - /// The size of the image data (number of pixels wide/high). |
170 |
| - #[deprecated = "use `texel_size` or `source_size` instead"] |
171 |
| - pub fn size_vec2(&self) -> egui::Vec2 { |
172 |
| - let [w, h] = self.texel_size; |
173 |
| - egui::vec2(w as f32, h as f32) |
174 |
| - } |
175 |
| - |
176 |
| - /// The debug name of the image, e.g. the file name. |
177 |
| - pub fn debug_name(&self) -> &str { |
178 |
| - &self.debug_name |
179 |
| - } |
180 |
| - |
181 |
| - /// The texture id for this image. |
182 |
| - pub fn texture_id(&self, ctx: &egui::Context) -> egui::TextureId { |
183 |
| - self.texture |
184 |
| - .lock() |
185 |
| - .get_or_insert_with(|| { |
186 |
| - let image: &mut ColorImage = &mut self.image.lock(); |
187 |
| - let image = std::mem::take(image); |
188 |
| - ctx.load_texture(&self.debug_name, image, self.options) |
189 |
| - }) |
190 |
| - .id() |
191 |
| - } |
192 |
| - |
193 |
| - /// Show the image with the given maximum size. |
194 |
| - pub fn show_max_size(&self, ui: &mut egui::Ui, max_size: egui::Vec2) -> egui::Response { |
195 |
| - let mut desired_size = self.source_size(); |
196 |
| - desired_size *= (max_size.x / desired_size.x).min(1.0); |
197 |
| - desired_size *= (max_size.y / desired_size.y).min(1.0); |
198 |
| - self.show_size(ui, desired_size) |
199 |
| - } |
200 |
| - |
201 |
| - /// Show the image with the original size (one image pixel = one gui point). |
202 |
| - pub fn show(&self, ui: &mut egui::Ui) -> egui::Response { |
203 |
| - self.show_size(ui, self.source_size()) |
204 |
| - } |
205 |
| - |
206 |
| - /// Show the image with the given scale factor (1.0 = original size). |
207 |
| - pub fn show_scaled(&self, ui: &mut egui::Ui, scale: f32) -> egui::Response { |
208 |
| - self.show_size(ui, self.source_size() * scale) |
209 |
| - } |
210 |
| - |
211 |
| - /// Show the image with the given size. |
212 |
| - pub fn show_size(&self, ui: &mut egui::Ui, desired_size: egui::Vec2) -> egui::Response { |
213 |
| - // We need to convert the SVG to a texture to display it: |
214 |
| - // Future improvement: tell backend to do mip-mapping of the image to |
215 |
| - // make it look smoother when downsized. |
216 |
| - ui.image(SizedTexture::new(self.texture_id(ui.ctx()), desired_size)) |
217 |
| - } |
218 |
| -} |
219 |
| - |
220 | 6 | // ----------------------------------------------------------------------------
|
221 | 7 |
|
222 | 8 | /// Load a (non-svg) image.
|
|
0 commit comments