-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added an example to save plot to image (#2769)
* implement save_plot * fix for check.sh * clippy * add save_plot to Cargo.lock * adapted for PR #2676 (removes unsafe code) * add some comments * implemented the comments from emilk * update comments in code * rustfmt * remove picked_path * add more comments * removed unused import * use `inner.response.rect` as the plot position * remove plot_location from MyApp members * sort entries * Update examples/save_plot/src/main.rs Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com> * use env_logger instead of tracing subscriber * use env_logger instead of tracing subscriber and combine if let --------- Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
- Loading branch information
Showing
4 changed files
with
130 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[package] | ||
name = "save_plot" | ||
version = "0.1.0" | ||
authors = ["hacknus <l_stoeckli@bluewin.ch>"] | ||
license = "MIT OR Apache-2.0" | ||
edition = "2021" | ||
rust-version = "1.65" | ||
publish = false | ||
|
||
[dependencies] | ||
eframe = { path = "../../crates/eframe", features = [ | ||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO | ||
] } | ||
image = { version = "0.24", default-features = false, features = ["png"] } | ||
rfd = "0.11.0" | ||
env_logger = "0.10" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
This example shows that you can save a plot in egui as a png. | ||
|
||
```sh | ||
cargo run -p save_plot | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release | ||
|
||
use eframe::egui; | ||
use eframe::egui::plot::{Legend, Line, Plot, PlotPoints}; | ||
use eframe::egui::ColorImage; | ||
|
||
fn main() -> Result<(), eframe::Error> { | ||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`). | ||
|
||
let options = eframe::NativeOptions { | ||
initial_window_size: Some(egui::vec2(350.0, 400.0)), | ||
..Default::default() | ||
}; | ||
eframe::run_native( | ||
"My egui App with a plot", | ||
options, | ||
Box::new(|_cc| Box::new(MyApp::default())), | ||
) | ||
} | ||
|
||
#[derive(Default)] | ||
struct MyApp { | ||
screenshot: Option<ColorImage>, | ||
} | ||
|
||
impl eframe::App for MyApp { | ||
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { | ||
let mut plot_rect = None; | ||
egui::CentralPanel::default().show(ctx, |ui| { | ||
// these are just some dummy variables for the example, | ||
// such that the plot is not at position (0,0) | ||
let height = 200.0; | ||
let border_x = 11.0; | ||
let border_y = 18.0; | ||
let width = 300.0; | ||
|
||
ui.heading("My egui Application"); | ||
|
||
// add some whitespace in y direction | ||
ui.add_space(border_y); | ||
|
||
if ui.button("Save Plot").clicked() { | ||
frame.request_screenshot(); | ||
} | ||
|
||
// add some whitespace in y direction | ||
ui.add_space(border_y); | ||
|
||
ui.horizontal(|ui| { | ||
// add some whitespace in x direction | ||
ui.add_space(border_x); | ||
|
||
let my_plot = Plot::new("My Plot") | ||
.height(height) | ||
.width(width) | ||
.legend(Legend::default()); | ||
|
||
// let's create a dummy line in the plot | ||
let graph: Vec<[f64; 2]> = vec![[0.0, 1.0], [2.0, 3.0], [3.0, 2.0]]; | ||
let inner = my_plot.show(ui, |plot_ui| { | ||
plot_ui.line(Line::new(PlotPoints::from(graph)).name("curve")); | ||
}); | ||
// Remember the position of the plot | ||
plot_rect = Some(inner.response.rect); | ||
}); | ||
|
||
// add some whitespace in y direction | ||
ui.add_space(border_y); | ||
}); | ||
|
||
if let (Some(screenshot), Some(plot_location)) = (self.screenshot.take(), plot_rect) { | ||
if let Some(mut path) = rfd::FileDialog::new().save_file() { | ||
path.set_extension("png"); | ||
|
||
// for a full size application, we should put this in a different thread, | ||
// so that the GUI doesn't lag during saving | ||
|
||
let pixels_per_point = frame.info().native_pixels_per_point; | ||
let plot = screenshot.region(&plot_location, pixels_per_point); | ||
// save the plot to png | ||
image::save_buffer( | ||
&path, | ||
plot.as_raw(), | ||
plot.width() as u32, | ||
plot.height() as u32, | ||
image::ColorType::Rgba8, | ||
) | ||
.unwrap(); | ||
} | ||
} | ||
} | ||
|
||
fn post_rendering(&mut self, _screen_size_px: [u32; 2], frame: &eframe::Frame) { | ||
// this is inspired by the Egui screenshot example | ||
if let Some(screenshot) = frame.screenshot() { | ||
self.screenshot = Some(screenshot); | ||
} | ||
} | ||
} |