From ca82163ce8c2d542a7e2ff34e11a295407f9678e Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 5 Jun 2024 12:18:12 +0100 Subject: [PATCH] Quick'n'dirty bounce option Fixes #332 --- README.md | 2 +- src/bin/gifski.rs | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 90eeb1c..dadf504 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Note that `*` is a special wildcard character, and it won't work when placed ins You can also resize frames (with `-W ` option). If the input was ever encoded using a lossy video codec it's recommended to at least halve size of the frames to hide compression artefacts and counter chroma subsampling that was done by the video codec. -See `gifski -h` for more options. +See `gifski --help` for more options. ### Tips for smaller GIF files diff --git a/src/bin/gifski.rs b/src/bin/gifski.rs index 57c847c..91e74e6 100644 --- a/src/bin/gifski.rs +++ b/src/bin/gifski.rs @@ -159,6 +159,12 @@ fn bin_main() -> BinResult<()> { .num_args(1) .value_parser(value_parser!(i16)) .value_name("num")) + .arg(Arg::new("bounce") + .long("bounce") + .num_args(0) + .action(ArgAction::SetTrue) + .hide_short_help(true) + .help("Make animation play forwards then backwards")) .arg(Arg::new("fixed-color") .long("fixed-color") .help("Always include this color in the palette") @@ -182,10 +188,11 @@ fn bin_main() -> BinResult<()> { }); let mut frames: Vec<&str> = matches.get_many::("FILES").ok_or("?")?.map(|s| s.as_str()).collect(); + let bounce = matches.get_flag("bounce"); if !matches.get_flag("nosort") && frames.len() > 1 { frames.sort_by(|a, b| natord::compare(a, b)); } - let frames: Vec<_> = frames.into_iter().map(PathBuf::from).collect(); + let mut frames: Vec<_> = frames.into_iter().map(PathBuf::from).collect(); let output_path = DestPath::new(matches.get_one::("output").ok_or("?")?); let width = matches.get_one::("width").copied(); @@ -268,6 +275,9 @@ fn bin_main() -> BinResult<()> { let decode_thread = thread::Builder::new().name("decode".into()).spawn_scoped(scope, move || { let mut decoder = if let [path] = &frames[..] { + if bounce { + eprintln!("warning: the bounce flag is supported only for individual files, not pipe or video"); + } let mut src = if path.as_os_str() == "-" { let fd = stdin().lock(); if fd.is_terminal() { @@ -291,6 +301,10 @@ fn bin_main() -> BinResult<()> { other_type => get_video_decoder(other_type, src, rate, settings)?, } } else { + if bounce { + let mut extra: Vec<_> = frames.iter().skip(1).rev().cloned().collect(); + frames.append(&mut extra); + } if speed != 1.0 { eprintln!("warning: --fast-forward option is for videos. It doesn't make sense for images. Use --fps only."); }