Skip to content

Commit

Permalink
Upgrade to new gif crate
Browse files Browse the repository at this point in the history
  • Loading branch information
kornelski committed Jan 23, 2024
1 parent 5bf8b1a commit c6a6975
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 62 deletions.
74 changes: 37 additions & 37 deletions Cargo.lock

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

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ license = "AGPL-3.0-or-later"
name = "gifski"
readme = "README.md"
repository = "https://github.com/ImageOptim/gifski"
version = "1.14.0"
version = "1.14.1"
autobins = false
edition = "2021"
rust-version = "1.65"
Expand All @@ -22,9 +22,9 @@ required-features = ["binary"]

[dependencies]
clap = { version = "4.3.24", features = ["cargo"], optional = true }
gif = { version = "0.13.0-beta.1", default-features = false, features = ["std", "raii_no_panic"] }
gif-dispose = "5.0.0-beta.1"
imgref = "1.10.0"
gif = { version = "0.13", default-features = false, features = ["std", "raii_no_panic"] }
gif-dispose = "5.0.0-beta.2"
imagequant = "4.3.0"
lodepng = { version = "3.10.1", optional = true }
pbr = { version = "1.1.1", optional = true }
Expand All @@ -48,7 +48,7 @@ default-features = false
features = ["codec", "format", "filter", "software-resampling", "software-scaling"]

[dev-dependencies]
lodepng = "3.9.3"
lodepng = "3.10.1"

[features]
# `cargo build` will skip the binaries with missing `required-features`
Expand Down
2 changes: 1 addition & 1 deletion src/bin/gif.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl Source for GifDecoder {
let mut delay_ts = 0;
while let Some(frame) = self.decoder.read_next_frame()? {
self.screen.blit_frame(frame)?;
let pixels = self.screen.pixels.clone();
let pixels = self.screen.pixels_rgba().map_buf(|b| b.to_owned());
let presentation_timestamp = f64::from(delay_ts) * (f64::from(self.speed) / 100.);
c.add_frame_rgba(idx, pixels, presentation_timestamp)?;
idx += 1;
Expand Down
11 changes: 7 additions & 4 deletions src/encoderust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use rgb::ComponentBytes;
use rgb::RGB8;
use std::cell::Cell;
use std::io::Write;
use std::iter::repeat;
use std::rc::Rc;

#[cfg(feature = "gifsicle")]
Expand Down Expand Up @@ -53,11 +54,13 @@ impl<W: Write> RustEncoder<W> {

let (buffer, width, height) = image.into_contiguous_buf();

let mut pal_rgb = Vec::with_capacity(3 * pal.len());
for p in &pal {
pal_rgb.extend_from_slice([p.rgb()].as_bytes());
let mut pal_rgb = pal.as_bytes().to_vec();
// Palette should be power-of-two sized
if pal.len() != 256 {
let needed_size = 3 * pal.len().max(2).next_power_of_two();
pal_rgb.extend(repeat([115,107,105,46,103,105,102]).flat_map(|x| x).take(needed_size - pal_rgb.len()));
debug_assert_eq!(needed_size, pal_rgb.len());
}

let mut frame = gif::Frame {
delay: 1, // TBD
dispose,
Expand Down
32 changes: 17 additions & 15 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ struct GIFFrame {
left: u16,
top: u16,
image: ImgVec<u8>,
pal: Vec<RGBA8>,
pal: Vec<RGB8>,
dispose: DisposalMethod,
transparent_index: Option<u8>,
}
Expand Down Expand Up @@ -424,7 +424,8 @@ impl Writer {
};
liq.set_quality(0, quality)?;
if self.settings.s.quality < 50 {
liq.set_max_colors(u32::from(self.settings.s.quality * 2).max(16).next_power_of_two())?;
let min_colors = 5 + self.fixed_colors.len() as u32;
liq.set_max_colors(u32::from(self.settings.s.quality * 2).max(min_colors).next_power_of_two().min(256))?;
}
let (buf, width, height) = image.into_contiguous_buf();
let mut img = liq.new_image(buf, width, height, 0.)?;
Expand Down Expand Up @@ -759,23 +760,24 @@ impl Writer {
fn remap_frames(&self, mut inputs: OrdQueueIter<RemapMessage>, write_queue: Sender<FrameMessage>) -> CatResult<()> {
let mut frame_index = 0;
let first_frame = inputs.next().ok_or(Error::NoFrames)?;
let mut screen = gif_dispose::Screen::new(first_frame.liq_image.width(), first_frame.liq_image.height(), RGBA8::new(0, 0, 0, 0), None);
let mut screen = gif_dispose::Screen::new(first_frame.liq_image.width(), first_frame.liq_image.height(), None);

let mut next_frame = Some(first_frame);
while let Some(RemapMessage {ordinal_frame_number, end_pts, dispose, liq, remap, liq_image, out_buf, has_next_frame}) = next_frame {
let screen_width = screen.pixels.width() as u16;
let screen_height = screen.pixels.height() as u16;
let mut screen_after_dispose = screen.dispose();
let pixels = screen.pixels_rgba();
let screen_width = pixels.width() as u16;
let screen_height = pixels.height() as u16;
let mut screen_after_dispose = screen.dispose_only();

let (mut image8, mut image8_pal) = {
let bg = if frame_index != 0 { Some(screen_after_dispose.pixels()) } else { None };
let (mut image8, image8_pal) = {
let bg = if frame_index != 0 { Some(screen_after_dispose.pixels_rgba()) } else { None };
self.remap(liq, remap, liq_image, bg, out_buf)?
};

let transparent_index = transparent_index_from_palette(&mut image8_pal, image8.as_mut());
let (image8_pal, transparent_index) = transparent_index_from_palette(image8_pal, image8.as_mut());

let (left, top) = if frame_index != 0 && has_next_frame {
let (left, top, new_width, new_height) = trim_image(image8.as_ref(), &image8_pal, transparent_index, dispose, screen_after_dispose.pixels())
let (left, top, new_width, new_height) = trim_image(image8.as_ref(), &image8_pal, transparent_index, dispose, screen_after_dispose.pixels_rgba())
.unwrap_or((0, 0, 1, 1));
if new_width != image8.width() || new_height != image8.height() {
let new_buf = image8.sub_image(left.into(), top.into(), new_width, new_height).to_contiguous_buf().0.into_owned();
Expand Down Expand Up @@ -811,12 +813,12 @@ impl Writer {
}
}

fn transparent_index_from_palette(image8_pal: &mut [RGBA<u8>], mut image8: ImgRefMut<u8>) -> Option<u8> {
fn transparent_index_from_palette(mut image8_pal: Vec<RGBA8>, mut image8: ImgRefMut<u8>) -> (Vec<RGB8>, Option<u8>) {
// Palette may have multiple transparent indices :(
let mut transparent_index = None;
for (i, p) in image8_pal.iter_mut().enumerate() {
if p.a <= 128 {
p.a = 0;
*p = RGBA8::new(71,80,76,0);
let new_index = i as u8;
if let Some(old_index) = transparent_index {
image8.pixels_mut().filter(|px| **px == new_index).for_each(|px| *px = old_index);
Expand All @@ -831,7 +833,7 @@ fn transparent_index_from_palette(image8_pal: &mut [RGBA<u8>], mut image8: ImgRe
Some(idx as u8) == transparent_index || color.a > 128 || !image8.pixels().any(|px| px == idx as u8)
}));

transparent_index
(image8_pal.into_iter().map(|r| r.rgb()).collect(), transparent_index)
}

/// When one thread unexpectedly fails, all other threads fail with Aborted, but that Aborted isn't the relevant cause
Expand All @@ -847,7 +849,7 @@ fn combine_res(res1: Result<(), Error>, res2: Result<(), Error>) -> Result<(), E
}
}

fn trim_image(mut image_trimmed: ImgRef<u8>, image8_pal: &[RGBA8], transparent_index: Option<u8>, dispose: DisposalMethod, mut screen: ImgRef<RGBA8>) -> Option<(u16, u16, usize, usize)> {
fn trim_image(mut image_trimmed: ImgRef<u8>, image8_pal: &[RGB8], transparent_index: Option<u8>, dispose: DisposalMethod, mut screen: ImgRef<RGBA8>) -> Option<(u16, u16, usize, usize)> {
let is_matching_pixel = move |px: u8, bg: RGBA8| -> bool {
if Some(px) == transparent_index {
if dispose == DisposalMethod::Keep {
Expand All @@ -858,7 +860,7 @@ fn trim_image(mut image_trimmed: ImgRef<u8>, image8_pal: &[RGBA8], transparent_i
bg.a == 0
}
} else {
image8_pal.get(px as usize).copied().unwrap_or_default() == bg
image8_pal.get(px as usize).map(|px| px.alpha(255)).unwrap_or_default() == bg
}
};

Expand Down
2 changes: 1 addition & 1 deletion tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ fn for_each_frame(mut gif_data: &[u8], mut cb: impl FnMut(&gif::Frame, ImgRef<RG

while let Some(frame) = decoder.read_next_frame().unwrap() {
screen.blit_frame(frame).unwrap();
cb(frame, screen.pixels.as_ref());
cb(frame, screen.pixels_rgba());
}
}

Expand Down

0 comments on commit c6a6975

Please sign in to comment.