refactor + big performance improvements
This commit is contained in:
parent
82ae18ce43
commit
d114cba193
1 changed files with 48 additions and 59 deletions
107
src/main.rs
107
src/main.rs
|
|
@ -7,8 +7,8 @@ use std::{env, time::*};
|
|||
use anyhow::Context;
|
||||
|
||||
use image::codecs::gif::GifDecoder;
|
||||
use image::{AnimationDecoder, Delay, Frame, RgbImage};
|
||||
use image::{DynamicImage, ImageFormat, ImageReader, imageops::FilterType};
|
||||
use image::{AnimationDecoder, Frame, RgbaImage};
|
||||
use image::{ImageFormat, ImageReader};
|
||||
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::event::WindowEvent;
|
||||
|
|
@ -21,8 +21,7 @@ use softbuffer::Surface;
|
|||
struct App {
|
||||
window: Option<Rc<Window>>,
|
||||
surface: Option<Surface<OwnedDisplayHandle, Rc<Window>>>,
|
||||
image: DynamicImage,
|
||||
resized_image: RgbImage,
|
||||
image: RgbaImage,
|
||||
|
||||
// animated images stuff
|
||||
animation: Option<Animation>,
|
||||
|
|
@ -31,8 +30,6 @@ struct App {
|
|||
#[derive(Default)]
|
||||
struct Animation {
|
||||
frames: Vec<Frame>,
|
||||
resized_frames: Vec<Option<RgbImage>>,
|
||||
frame_dur: Vec<Delay>,
|
||||
//current frame
|
||||
frame: usize,
|
||||
last_update: Option<Instant>,
|
||||
|
|
@ -45,17 +42,8 @@ impl ApplicationHandler for App {
|
|||
let context = softbuffer::Context::new(event_loop.owned_display_handle()).unwrap();
|
||||
let surface = Surface::new(&context, window.clone()).unwrap();
|
||||
|
||||
let size = window.inner_size();
|
||||
|
||||
self.resized_image = self
|
||||
.image
|
||||
.resize(size.width, size.height, FilterType::Nearest)
|
||||
.to_rgb8();
|
||||
|
||||
if let Some(anim) = self.animation.as_mut() {
|
||||
anim.frame_dur = anim.frames.iter().map(|frame| frame.delay()).collect();
|
||||
anim.last_update = Some(Instant::now());
|
||||
anim.resized_frames = vec![None; anim.frames.len()];
|
||||
}
|
||||
|
||||
self.surface = Some(surface);
|
||||
|
|
@ -79,44 +67,61 @@ impl ApplicationHandler for App {
|
|||
.expect("redraw request without a surface");
|
||||
|
||||
let size = window.inner_size();
|
||||
|
||||
if let Some(anim) = self.animation.as_mut() {
|
||||
let curr_frame = anim.frame;
|
||||
match anim.resized_frames[curr_frame].as_ref() {
|
||||
Some(frame) => {
|
||||
self.resized_image = frame.clone();
|
||||
}
|
||||
None => {
|
||||
let original_buffer = anim.frames[curr_frame].buffer().clone();
|
||||
let resized_frame = DynamicImage::ImageRgba8(original_buffer)
|
||||
.resize(size.width, size.height, FilterType::Nearest)
|
||||
.into_rgb8();
|
||||
anim.resized_frames[curr_frame] = Some(resized_frame);
|
||||
self.resized_image = anim.resized_frames[curr_frame].clone().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut buffer = surface.buffer_mut().unwrap();
|
||||
|
||||
let x_offset = ((size.width - self.resized_image.width()) / 2) as usize;
|
||||
let y_offset = ((size.height - self.resized_image.height()) / 2) as usize;
|
||||
let mut img_ref = &self.image;
|
||||
|
||||
if let Some(anim) = self.animation.as_mut() {
|
||||
if anim.last_update.unwrap().elapsed() > anim.frames[anim.frame].delay().into()
|
||||
{
|
||||
anim.last_update = Some(Instant::now());
|
||||
anim.frame += 1;
|
||||
if anim.frame >= anim.frames.len() {
|
||||
anim.frame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
img_ref = anim.frames[anim.frame].buffer();
|
||||
}
|
||||
|
||||
let w_ratio = size.width as f32 / img_ref.width() as f32;
|
||||
let h_ratio = size.height as f32 / img_ref.height() as f32;
|
||||
|
||||
let preferred_size = if w_ratio <= h_ratio {
|
||||
(
|
||||
size.width as f32,
|
||||
(img_ref.height() as f32 * w_ratio).round(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
(img_ref.width() as f32 * h_ratio).round(),
|
||||
size.height as f32,
|
||||
)
|
||||
};
|
||||
|
||||
let x_scaling = img_ref.width() as f32 / preferred_size.0 as f32;
|
||||
let y_scaling = img_ref.height() as f32 / preferred_size.1 as f32;
|
||||
|
||||
let x_offset = ((size.width - preferred_size.0 as u32) / 2) as usize;
|
||||
let y_offset = ((size.height - preferred_size.1 as u32) / 2) as usize;
|
||||
|
||||
for (y, row) in buffer.chunks_exact_mut(size.width as usize).enumerate() {
|
||||
if y < y_offset || y >= y_offset + self.resized_image.height() as usize {
|
||||
if y < y_offset || y >= y_offset + preferred_size.1 as usize {
|
||||
row.fill(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
let old_y = ((y - y_offset) as f32 * y_scaling) as u32;
|
||||
|
||||
for (x, buf_pix) in row.iter_mut().enumerate() {
|
||||
if x < x_offset || x >= x_offset + self.resized_image.width() as usize {
|
||||
if x < x_offset || x >= x_offset + preferred_size.0 as usize {
|
||||
*buf_pix = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
let img_pix = self
|
||||
.resized_image
|
||||
.get_pixel((x - x_offset) as u32, (y - y_offset) as u32);
|
||||
let old_x = ((x - x_offset) as f32 * x_scaling) as u32;
|
||||
|
||||
let img_pix = img_ref.get_pixel(old_x, old_y);
|
||||
|
||||
*buf_pix =
|
||||
u32::from_be_bytes([0, img_pix.0[0], img_pix.0[1], img_pix.0[2]]);
|
||||
|
|
@ -127,15 +132,8 @@ impl ApplicationHandler for App {
|
|||
|
||||
buffer.present().unwrap();
|
||||
|
||||
if let Some(anim) = self.animation.as_mut() {
|
||||
if anim.last_update.unwrap().elapsed() > anim.frame_dur[anim.frame].into() {
|
||||
anim.last_update = Some(Instant::now());
|
||||
anim.frame += 1;
|
||||
if anim.frame >= anim.frames.len() {
|
||||
anim.frame = 0;
|
||||
}
|
||||
}
|
||||
//TODO don't fucking spam redraws
|
||||
if self.animation.is_some() {
|
||||
//TODO DONT SPAM REDRAWS
|
||||
window.request_redraw();
|
||||
}
|
||||
}
|
||||
|
|
@ -151,15 +149,6 @@ impl ApplicationHandler for App {
|
|||
NonZeroU32::new(new_size.height).unwrap(),
|
||||
)
|
||||
.expect("surface resize gone wrong");
|
||||
|
||||
if let Some(anim) = self.animation.as_mut() {
|
||||
anim.resized_frames = vec![None; anim.frames.len()];
|
||||
} else {
|
||||
self.resized_image = self
|
||||
.image
|
||||
.resize(new_size.width, new_size.height, FilterType::Nearest)
|
||||
.to_rgb8();
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
|
@ -195,7 +184,7 @@ fn main() -> anyhow::Result<()> {
|
|||
app.animation = Some(animation);
|
||||
}
|
||||
_ => {
|
||||
app.image = image.decode().context("Failed to decode image")?;
|
||||
app.image = image.decode().context("Failed to decode image")?.to_rgba8();
|
||||
}
|
||||
};
|
||||
event_loop.run_app(&mut app)?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue