From 9b4ed6eb620a4363f09999729a8bfafd97662251 Mon Sep 17 00:00:00 2001 From: Luke D Jones Date: Tue, 6 Apr 2021 22:03:06 +1200 Subject: [PATCH] anime: discard frames if specified --- rog-anime/src/anime_gif.rs | 47 ++++++++++++++++++++++++++++---------- rog-anime/src/lib.rs | 6 +++-- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/rog-anime/src/anime_gif.rs b/rog-anime/src/anime_gif.rs index 5bc209b8..79c38b22 100644 --- a/rog-anime/src/anime_gif.rs +++ b/rog-anime/src/anime_gif.rs @@ -1,8 +1,8 @@ +use glam::Vec2; use serde_derive::{Deserialize, Serialize}; use std::{fs::File, path::Path, time::Duration}; -use glam::Vec2; -use crate::{AniMeDataBuffer, AniMeDiagonal, AniMeImage, error::AnimeError, Pixel}; +use crate::{error::AnimeError, AniMeDataBuffer, AniMeDiagonal, AniMeImage, Pixel}; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct AniMeFrame { @@ -27,7 +27,6 @@ pub struct AniMeGif(Vec); impl AniMeGif { pub fn create_diagonal_gif(file_name: &Path, brightness: f32) -> Result { - let mut frames = Vec::new(); let mut matrix = AniMeDiagonal::new(); let mut decoder = gif::DecodeOptions::new(); @@ -37,8 +36,12 @@ impl AniMeGif { let file = File::open(file_name)?; let mut decoder = decoder.read_info(file)?; + let mut frames = Vec::with_capacity(decoder.buffer_size()); while let Some(frame) = decoder.read_next_frame()? { let wait = frame.delay * 10; + if matches!(frame.dispose, gif::DisposalMethod::Background) { + frames = Vec::new(); + } for (y, row) in frame.buffer.chunks(frame.width as usize * 4).enumerate() { for (x, px) in row.chunks(4).enumerate() { if px[3] != 255 { @@ -68,25 +71,45 @@ impl AniMeGif { let file = File::open(file_name)?; let mut decoder = decoder.read_info(file)?; + let height = decoder.height(); let width = decoder.width(); - let pixels: Vec = vec![Pixel::default(); (decoder.width() as u32 * decoder.height() as u32) as usize]; - let mut image = AniMeImage::new(Vec2::new(1.0, 1.0), 0.0, Vec2::new(0.0, 0.0), - brightness, pixels, decoder.width() as u32); + let pixels: Vec = + vec![Pixel::default(); (decoder.width() as u32 * decoder.height() as u32) as usize]; + let mut image = AniMeImage::new( + Vec2::new(1.0, 1.0), + 0.0, + Vec2::new(0.0, 0.0), + brightness, + pixels, + decoder.width() as u32, + ); while let Some(frame) = decoder.read_next_frame()? { let wait = frame.delay * 10; + if matches!(frame.dispose, gif::DisposalMethod::Background) { + let pixels: Vec = + vec![Pixel::default(); (width as u32 * height as u32) as usize]; + image = AniMeImage::new( + Vec2::new(1.0, 1.0), + 0.0, + Vec2::new(0.0, 0.0), + brightness, + pixels, + width as u32, + ); + } for (y, row) in frame.buffer.chunks(frame.width as usize * 4).enumerate() { for (x, px) in row.chunks(4).enumerate() { if px[3] != 255 { // should be t but not in some gifs? What, ASUS, what? continue; } - let pos = (x + frame.left as usize) + ((y + frame.top as usize) * width as usize); - image.get_mut()[pos] = - Pixel { - color: ((px[0] as u32 + px[1] as u32 + px[2] as u32) / 3), - alpha: 1.0, - }; + let pos = + (x + frame.left as usize) + ((y + frame.top as usize) * width as usize); + image.get_mut()[pos] = Pixel { + color: ((px[0] as u32 + px[1] as u32 + px[2] as u32) / 3), + alpha: 1.0, + }; } } image.update(); diff --git a/rog-anime/src/lib.rs b/rog-anime/src/lib.rs index cd62bad6..b25abe33 100644 --- a/rog-anime/src/lib.rs +++ b/rog-anime/src/lib.rs @@ -55,11 +55,13 @@ impl AniMeSequence { Ok(Self::Image(Box::new(data))) } - pub fn png_gif(file: &Path, + pub fn png_gif( + file: &Path, // scale: Vec2, // angle: f32, // translation: Vec2, - brightness: f32,) -> Result { + brightness: f32, + ) -> Result { let frames = AniMeGif::create_png_gif(file, brightness)?; Ok(Self::Animation(frames)) }