diff --git a/src/decoder.rs b/src/decoder.rs index c60a71d..c840ef8 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -175,12 +175,16 @@ where previous_sample = sample; - if !progress_update((progress as f32) / (step * 10) as f32, img.clone()) { - return Ok(()); + if progress % LINES_PER_SECOND == 0 { + if !progress_update((progress as f32) / (step * 10) as f32, img.clone()) { + return Ok(()); + } } } println!(""); + progress_update(1.0, img.clone()); + img.save_with_format(&Path::new(output_file), image::ImageFormat::Png) .map_err(|err| format!("Could not save outputfile: {}", err))?; diff --git a/src/ui.rs b/src/ui.rs index 2c6a092..f6ccaf7 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -17,7 +17,7 @@ enum DecoderRunState { struct DecoderJobState { progress: f32, - image: image::GrayImage, + image: Option, run_state: DecoderRunState, } @@ -31,7 +31,7 @@ impl Default for DecoderJobState { fn default() -> Self { Self { progress: 0.0, - image: image::GrayImage::new(1, 1), + image: None, run_state: DecoderRunState::DONE, } } @@ -41,6 +41,7 @@ pub struct DecoderApp { input_path: String, output_path: String, decoding_state: Arc>, + texture: Option<(egui::TextureId, egui::Vec2)>, } impl Default for DecoderApp { @@ -50,6 +51,7 @@ impl Default for DecoderApp { input_path: "input.wav".to_owned(), output_path: "output.png".to_owned(), decoding_state: Arc::new(Mutex::new(DecoderJobState::default())), + texture: None, } } } @@ -75,6 +77,7 @@ impl epi::App for DecoderApp { input_path, output_path, decoding_state, + texture, } = self; { @@ -135,10 +138,12 @@ impl epi::App for DecoderApp { std::thread::spawn(move || { decoder::decode(&input_path, &output_path, |progress, image| { let mut state = decoding_state.lock().unwrap(); + state.progress = progress; - state.image = image; + state.image = Some(image); frame.request_repaint(); + return state.is_running(); }) .unwrap(); @@ -163,16 +168,28 @@ impl epi::App for DecoderApp { ui.separator(); - let size = [state.image.width() as _, state.image.height() as _]; - let image_buffer = - image::DynamicImage::ImageLuma8(state.image.clone()).into_rgba8(); - let pixels = image_buffer.as_flat_samples(); - let epi_img = epi::Image::from_rgba_unmultiplied(size, pixels.as_slice()); + if let Some(image) = state.image.take() { + let image = image::DynamicImage::ImageLuma8(image); + let size = [image.width() as _, image.height() as _]; + let pixels = image.into_rgba8(); + let epi_img = epi::Image::from_rgba_unmultiplied( + size, + pixels.as_flat_samples().as_slice(), + ); + let size = egui::Vec2::new(size[0] as f32, size[1] as f32); - let texture = frame.alloc_texture(epi_img); - let size = egui::Vec2::new(size[0] as f32, size[1] as f32); + if let Some((old_texture, _)) = texture { + frame.free_texture(*old_texture); + } - ui.image(texture, size); + *texture = Some((frame.alloc_texture(epi_img), size)); + + state.image = None; + } + + if let Some((texture, size)) = texture { + ui.image(*texture, *size); + } }); } }