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 anyhow::Context;
|
||||||
|
|
||||||
use image::codecs::gif::GifDecoder;
|
use image::codecs::gif::GifDecoder;
|
||||||
use image::{AnimationDecoder, Delay, Frame, RgbImage};
|
use image::{AnimationDecoder, Frame, RgbaImage};
|
||||||
use image::{DynamicImage, ImageFormat, ImageReader, imageops::FilterType};
|
use image::{ImageFormat, ImageReader};
|
||||||
|
|
||||||
use winit::application::ApplicationHandler;
|
use winit::application::ApplicationHandler;
|
||||||
use winit::event::WindowEvent;
|
use winit::event::WindowEvent;
|
||||||
|
|
@ -21,8 +21,7 @@ use softbuffer::Surface;
|
||||||
struct App {
|
struct App {
|
||||||
window: Option<Rc<Window>>,
|
window: Option<Rc<Window>>,
|
||||||
surface: Option<Surface<OwnedDisplayHandle, Rc<Window>>>,
|
surface: Option<Surface<OwnedDisplayHandle, Rc<Window>>>,
|
||||||
image: DynamicImage,
|
image: RgbaImage,
|
||||||
resized_image: RgbImage,
|
|
||||||
|
|
||||||
// animated images stuff
|
// animated images stuff
|
||||||
animation: Option<Animation>,
|
animation: Option<Animation>,
|
||||||
|
|
@ -31,8 +30,6 @@ struct App {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Animation {
|
struct Animation {
|
||||||
frames: Vec<Frame>,
|
frames: Vec<Frame>,
|
||||||
resized_frames: Vec<Option<RgbImage>>,
|
|
||||||
frame_dur: Vec<Delay>,
|
|
||||||
//current frame
|
//current frame
|
||||||
frame: usize,
|
frame: usize,
|
||||||
last_update: Option<Instant>,
|
last_update: Option<Instant>,
|
||||||
|
|
@ -45,17 +42,8 @@ impl ApplicationHandler for App {
|
||||||
let context = softbuffer::Context::new(event_loop.owned_display_handle()).unwrap();
|
let context = softbuffer::Context::new(event_loop.owned_display_handle()).unwrap();
|
||||||
let surface = Surface::new(&context, window.clone()).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() {
|
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.last_update = Some(Instant::now());
|
||||||
anim.resized_frames = vec![None; anim.frames.len()];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.surface = Some(surface);
|
self.surface = Some(surface);
|
||||||
|
|
@ -79,44 +67,61 @@ impl ApplicationHandler for App {
|
||||||
.expect("redraw request without a surface");
|
.expect("redraw request without a surface");
|
||||||
|
|
||||||
let size = window.inner_size();
|
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 mut buffer = surface.buffer_mut().unwrap();
|
||||||
|
|
||||||
let x_offset = ((size.width - self.resized_image.width()) / 2) as usize;
|
let mut img_ref = &self.image;
|
||||||
let y_offset = ((size.height - self.resized_image.height()) / 2) as usize;
|
|
||||||
|
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() {
|
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);
|
row.fill(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let old_y = ((y - y_offset) as f32 * y_scaling) as u32;
|
||||||
|
|
||||||
for (x, buf_pix) in row.iter_mut().enumerate() {
|
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;
|
*buf_pix = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let img_pix = self
|
let old_x = ((x - x_offset) as f32 * x_scaling) as u32;
|
||||||
.resized_image
|
|
||||||
.get_pixel((x - x_offset) as u32, (y - y_offset) as u32);
|
let img_pix = img_ref.get_pixel(old_x, old_y);
|
||||||
|
|
||||||
*buf_pix =
|
*buf_pix =
|
||||||
u32::from_be_bytes([0, img_pix.0[0], img_pix.0[1], img_pix.0[2]]);
|
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();
|
buffer.present().unwrap();
|
||||||
|
|
||||||
if let Some(anim) = self.animation.as_mut() {
|
if self.animation.is_some() {
|
||||||
if anim.last_update.unwrap().elapsed() > anim.frame_dur[anim.frame].into() {
|
//TODO DONT SPAM REDRAWS
|
||||||
anim.last_update = Some(Instant::now());
|
|
||||||
anim.frame += 1;
|
|
||||||
if anim.frame >= anim.frames.len() {
|
|
||||||
anim.frame = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//TODO don't fucking spam redraws
|
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,15 +149,6 @@ impl ApplicationHandler for App {
|
||||||
NonZeroU32::new(new_size.height).unwrap(),
|
NonZeroU32::new(new_size.height).unwrap(),
|
||||||
)
|
)
|
||||||
.expect("surface resize gone wrong");
|
.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.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)?;
|
event_loop.run_app(&mut app)?;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue