Skip to content

Commit 533b358

Browse files
committed
cli: ability to drop gif frames depending on FPS option
This provides no smoothing, only dropping. This means some stuttering in some cases, because some frames will be displayed for twice as long, but it should help match a given target. Fixes #361
1 parent 011bc7c commit 533b358

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

src/bin/gif_source.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
//! This is for reading GIFs as an input for re-encoding as another GIF
22
3-
use crate::source::{Fps, Source};
3+
use crate::source::{Fps, Source, DEFAULT_FPS};
44
use crate::{BinResult, SrcPath};
55
use gif::Decoder;
66
use gifski::Collector;
77
use std::io::Read;
88

99
pub struct GifDecoder {
10+
fps: Option<f32>,
1011
speed: f32,
1112
decoder: Decoder<Box<dyn Read>>,
1213
screen: gif_dispose::Screen,
@@ -27,6 +28,7 @@ impl GifDecoder {
2728
let screen = gif_dispose::Screen::new_decoder(&decoder);
2829

2930
Ok(Self {
31+
fps: fps.fps,
3032
speed: fps.speed,
3133
decoder,
3234
screen,
@@ -39,13 +41,20 @@ impl Source for GifDecoder {
3941
fn collect(&mut self, c: &mut Collector) -> BinResult<()> {
4042
let mut idx = 0;
4143
let mut delay_ts = 0;
44+
let skip_frames = self.fps.is_some();
45+
let wanted_frame_time = 1. / f64::from(self.fps.unwrap_or(DEFAULT_FPS));
46+
let mut wanted_presentation_timestamp = 0.;
4247
while let Some(frame) = self.decoder.read_next_frame()? {
4348
self.screen.blit_frame(frame)?;
4449
let pixels = self.screen.pixels_rgba().map_buf(|b| b.to_owned());
4550
let presentation_timestamp = f64::from(delay_ts) * (1. / (100. * f64::from(self.speed)));
51+
delay_ts += u32::from(frame.delay);
52+
if skip_frames && presentation_timestamp < wanted_presentation_timestamp {
53+
continue
54+
}
55+
wanted_presentation_timestamp += wanted_frame_time;
4656
c.add_frame_rgba(idx, pixels, presentation_timestamp)?;
4757
idx += 1;
48-
delay_ts += u32::from(frame.delay);
4958
}
5059
Ok(())
5160
}

src/bin/gifski.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ fn bin_main() -> BinResult<()> {
8181
kept.\nIf video is used, it will be resampled to \
8282
this constant rate by dropping and/or duplicating \
8383
frames.\nDefault is 20 for videos. No effect for \
84-
GIF or PNG input.")
84+
PNG input. For GIF input, it will be used to drop \
85+
frames if present.")
8586
.value_parser(value_parser!(f32))
8687
.value_name("num"))
8788
.arg(Arg::new("fast-forward")

0 commit comments

Comments
 (0)