Skip to content

Commit

Permalink
Upgrade libgifski to 1.3.3 (#227)
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Feb 8, 2021
1 parent 4aea424 commit b7c8a4e
Show file tree
Hide file tree
Showing 13 changed files with 109 additions and 90 deletions.
31 changes: 16 additions & 15 deletions gifski-api/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 11 additions & 6 deletions gifski-api/Cargo.toml
Expand Up @@ -10,7 +10,7 @@ license = "AGPL-3.0+"
name = "gifski"
readme = "README.md"
repository = "https://github.com/ImageOptim/gifski"
version = "1.3.1"
version = "1.3.3"
autobins = false
edition = "2018"

Expand All @@ -23,11 +23,11 @@ gifsicle = { version = "1.92.4", optional = true }
clap = "2.33.3"
gif = "0.11.1"
gif-dispose = "3.1.1"
imagequant = "3.0.2"
imagequant = "3.0.3"
imgref = "1.7.1"
lodepng = "3.4.2"
lodepng = "3.4.3"
pbr = "1.0.4"
resize = "0.5.5"
resize = "0.6.1"
rgb = "0.8.25"
wild = "2.0.4"
natord = "1.0.9"
Expand All @@ -53,8 +53,13 @@ video-static = ["video", "ffmpeg/build"]
path = "src/lib.rs"
crate-type = ["lib", "staticlib", "cdylib"]

[profile.dev.package.imagequant]
opt-level = 3
[profile.dev]
debug = 1
opt-level = 1

[profile.dev.package.'*']
opt-level = 2
debug = false

[profile.release]
panic = "abort"
Expand Down
2 changes: 2 additions & 0 deletions gifski-api/README.md
Expand Up @@ -34,6 +34,8 @@ gifski -o anim.gif frame*.png

You can also resize frames (with `-W <width in pixels>` 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.

Adding `--quality=90` may reduce file sizes a bit, but expect to lose a lot of quality for little gain. GIF just isn't that good at compressing, no matter how much you compromise.

See `gifski -h` for more options.

## Building
Expand Down
36 changes: 15 additions & 21 deletions gifski-api/src/bin/ffmpeg_source.rs
@@ -1,9 +1,9 @@
use crate::source::*;
use crate::BinResult;
use gifski::Collector;
use gifski::Settings;
use imgref::*;
use rgb::*;
use crate::source::*;
use std::path::Path;

pub struct FfmpegDecoder {
Expand Down Expand Up @@ -89,43 +89,37 @@ impl FfmpegDecoder {
let mut filt_frame = ffmpeg::util::frame::Video::empty();
let mut i = 0;
let mut pts_last_packet = 0;
let mut delayed_frames = 0;
let pts_frame_step = 1.0 / self.rate.fps as f64;

loop {
let (packet, packet_is_empty) = if let Some((s, packet)) = packets.next() {
let (packet, no_more_packets) = if let Some((s, packet)) = packets.next() {
if s.index() != stream_index {
// ignore irrelevant streams
continue;
}
pts_last_packet = packet.pts().ok_or("ffmpeg format error")? + packet.duration();
(packet, false)
} else {
(ffmpeg::Packet::empty(), true)
};

let decoded = decoder.decode(&packet, &mut vid_frame)?;
if !decoded || 0 == vid_frame.width() {
if packet_is_empty {
if delayed_frames == 0 {
break;
}
} else {
delayed_frames += 1;
if decoded {
filter.get("in").ok_or("ffmpeg format error")?.source().add(&vid_frame)?;
let mut out = filter.get("out").ok_or("ffmpeg format error")?;
let mut out = out.sink();
while let Ok(..) = out.frame(&mut filt_frame) {
add_frame(&filt_frame, pts_frame_step * i as f64, i)?;
i += 1;
}
continue;
}
if packet_is_empty {
delayed_frames -= 1;
}

filter.get("in").ok_or("ffmpeg format error")?.source().add(&vid_frame)?;
let mut out = filter.get("out").ok_or("ffmpeg format error")?;
let mut out = out.sink();
while let Ok(..) = out.frame(&mut filt_frame) {
add_frame(&filt_frame, pts_frame_step * i as f64, i)?;
i += 1;
// loop to flush decoder's buffer
if no_more_packets && !decoded {
break;
}
}

// now flush filter's buffer
filter.get("in").ok_or("ffmpeg format error")?.source().close(pts_last_packet)?;
let mut out = filter.get("out").ok_or("ffmpeg format error")?;
let mut out = out.sink();
Expand Down
21 changes: 9 additions & 12 deletions gifski-api/src/bin/gifski.rs
Expand Up @@ -2,8 +2,6 @@

use std::ffi::OsStr;
use gifski::{Settings, Repeat};
use natord;
use wild;

#[cfg(feature = "video")]
mod ffmpeg_source;
Expand All @@ -19,16 +17,16 @@ use clap::{App, AppSettings, Arg};

use std::env;
use std::fmt;
use std::io;
use std::fs::File;
use std::io;
use std::path::{Path, PathBuf};
use std::thread;
use std::time::Duration;

#[cfg(feature = "video")]
const VIDEO_FRAMES_ARG_HELP: &'static str = "one video file supported by FFmpeg, or multiple PNG image files";
const VIDEO_FRAMES_ARG_HELP: &str = "one video file supported by FFmpeg, or multiple PNG image files";
#[cfg(not(feature = "video"))]
const VIDEO_FRAMES_ARG_HELP: &'static str = "PNG image files";
const VIDEO_FRAMES_ARG_HELP: &str = "PNG image files";

fn main() {
if let Err(e) = bin_main() {
Expand All @@ -40,8 +38,9 @@ fn main() {
}
}

#[allow(clippy::float_cmp)]
fn bin_main() -> BinResult<()> {
let matches = App::new(crate_name!())
let matches = App::new(crate_name!())
.version(crate_version!())
.about("https://gif.ski by Kornel Lesiński")
.setting(AppSettings::UnifiedHelpMessage)
Expand Down Expand Up @@ -71,7 +70,7 @@ fn bin_main() -> BinResult<()> {
.long("fast-forward")
.help("Multiply speed of video by a factor\n(no effect when using PNG files as input)")
.empty_values(false)
.value_name("num")
.value_name("x")
.default_value("1"))
.arg(Arg::with_name("fast")
.long("fast")
Expand Down Expand Up @@ -118,7 +117,7 @@ fn bin_main() -> BinResult<()> {
if !matches.is_present("nosort") {
frames.sort_by(|a, b| natord::compare(a, b));
}
let frames: Vec<_> = frames.into_iter().map(|s| PathBuf::from(s)).collect();
let frames: Vec<_> = frames.into_iter().map(PathBuf::from).collect();

let output_path = DestPath::new(matches.value_of_os("output").ok_or("Missing output")?);
let width = parse_opt(matches.value_of("width")).map_err(|_| "Invalid width")?;
Expand All @@ -142,10 +141,7 @@ fn bin_main() -> BinResult<()> {
let fps: f32 = matches.value_of("fps").ok_or("Missing fps")?.parse().map_err(|_| "FPS must be a number")?;
let speed: f32 = matches.value_of("fast-forward").ok_or("Missing speed")?.parse().map_err(|_| "Speed must be a number")?;

let rate = source::Fps {
speed,
fps,
};
let rate = source::Fps { speed, fps };

if settings.quality < 20 {
if settings.quality < 1 {
Expand Down Expand Up @@ -265,6 +261,7 @@ fn get_video_decoder(path: &Path, fps: source::Fps, settings: Settings) -> BinRe
}

#[cfg(not(feature = "video"))]
#[cold]
fn get_video_decoder(_: &Path, _: source::Fps, _: Settings) -> BinResult<Box<dyn Source + Send>> {
Err(r"Video support is permanently disabled in this executable.
Expand Down
2 changes: 1 addition & 1 deletion gifski-api/src/bin/png.rs
@@ -1,5 +1,5 @@
use crate::source::Source;
use crate::source::Fps;
use crate::source::Source;
use crate::BinResult;
use gifski::Collector;
use std::path::PathBuf;
Expand Down
1 change: 1 addition & 0 deletions gifski-api/src/c_api.rs
@@ -1,3 +1,4 @@
#![allow(clippy::missing_safety_doc)]
//! How to use from C
//!
//! ```c
Expand Down
4 changes: 4 additions & 0 deletions gifski-api/src/c_api/c_api_error.rs
Expand Up @@ -26,6 +26,7 @@ pub enum GifskiError {
}

impl Into<io::Error> for GifskiError {
#[cold]
fn into(self) -> io::Error {
use std::io::ErrorKind as EK;
use GifskiError::*;
Expand All @@ -45,6 +46,7 @@ impl Into<io::Error> for GifskiError {
}

impl From<c_int> for GifskiError {
#[cold]
fn from(res: c_int) -> Self {
use GifskiError::*;
match res {
Expand All @@ -69,6 +71,7 @@ impl From<c_int> for GifskiError {
}

impl From<CatResult<()>> for GifskiError {
#[cold]
fn from(res: CatResult<()>) -> Self {
use crate::error::Error::*;
match res {
Expand All @@ -85,6 +88,7 @@ impl From<CatResult<()>> for GifskiError {
}

impl From<io::ErrorKind> for GifskiError {
#[cold]
fn from(res: io::ErrorKind) -> Self {
use std::io::ErrorKind as EK;
match res {
Expand Down
8 changes: 4 additions & 4 deletions gifski-api/src/encodegifsicle.rs
@@ -1,7 +1,7 @@
use crate::error::*;
use crate::{Encoder, Repeat};
use crate::GIFFrame;
use crate::Settings;
use crate::{Encoder, Repeat};
use gifsicle::*;
use std::io::Write;
use std::ptr;
Expand Down Expand Up @@ -86,7 +86,7 @@ impl Encoder for Gifsicle<'_> {
unsafe {
self.gif_writer = Gif_IncrementalWriteFileInit(gfs, &self.info, ptr::null_mut());
if self.gif_writer.is_null() {
Err(Error::Gifsicle)?;
return Err(Error::Gifsicle);
}
}
}
Expand Down Expand Up @@ -123,12 +123,12 @@ impl Encoder for Gifsicle<'_> {
unsafe {
if 0 == Gif_SetUncompressedImage(g, image.buf().as_ptr() as *mut u8, None, 0) {
Gif_DeleteImage(g);
Err(Error::Gifsicle)?;
return Err(Error::Gifsicle);
}
let res = Gif_IncrementalWriteImage(self.gif_writer, self.gfs, g);
Gif_DeleteImage(g);
if 0 == res {
Err(Error::Gifsicle)?;
return Err(Error::Gifsicle);
}
self.flush_writer()?;
}
Expand Down
2 changes: 1 addition & 1 deletion gifski-api/src/encoderust.rs
@@ -1,7 +1,7 @@
use crate::error::CatResult;
use crate::{Encoder, Repeat};
use crate::GIFFrame;
use crate::Settings;
use crate::{Encoder, Repeat};
use rgb::*;
use std::io::Write;

Expand Down

0 comments on commit b7c8a4e

Please sign in to comment.