From 07f12a6b98fab149ad81c15f66557261a5455af8 Mon Sep 17 00:00:00 2001 From: gennyble Date: Mon, 9 Oct 2023 03:13:40 -0500 Subject: output gif using gifed --- .gitignore | 2 ++ Cargo.lock | 14 ++++++++++++++ squash/Cargo.toml | 1 + squash/src/main.rs | 55 ++++++++++++++++++++++++++++++++++++++++-------------- 4 files changed, 58 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 4c7d6ed..ba7f17b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ *.PNG *.jpg *.JPG +*.gif +*.GIF flamegraph.svg perf.data perf.data.old diff --git a/Cargo.lock b/Cargo.lock index 4256a12..fc918c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,13 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "gifed" +version = "0.2.0" +dependencies = [ + "weezl", +] + [[package]] name = "log" version = "0.4.20" @@ -129,10 +136,17 @@ dependencies = [ "anyhow", "camino", "colorsquash", + "gifed", "png", "zune-jpeg", ] +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" + [[package]] name = "zune-core" version = "0.2.14" diff --git a/squash/Cargo.toml b/squash/Cargo.toml index 1b92d38..921f937 100644 --- a/squash/Cargo.toml +++ b/squash/Cargo.toml @@ -14,3 +14,4 @@ camino = "1.1.6" # been released yet, so we're using the git here. the commit we require is e4b4811 png = { git = "https://github.com/image-rs/image-png.git", rev = "f10238a1e886b228e7da5301e5c0f5011316f2d6" } zune-jpeg = "0.3.17" +gifed = { path = "../../gifed/gifed" } diff --git a/squash/src/main.rs b/squash/src/main.rs index da3cfbf..fe7f310 100644 --- a/squash/src/main.rs +++ b/squash/src/main.rs @@ -3,6 +3,7 @@ use std::{fs::File, io::BufWriter}; use anyhow::{anyhow, bail}; use camino::{Utf8Path, Utf8PathBuf}; use colorsquash::Squasher; +use gifed::writer::{GifBuilder, ImageBuilder}; use png::{ColorType, Decoder, Encoder}; use zune_jpeg::{zune_core::colorspace::ColorSpace, JpegDecoder}; @@ -60,17 +61,24 @@ fn main() -> Result<(), anyhow::Error> { color_count ); - // PNG Output - let file = File::create(output_path)?; - let bufw = BufWriter::new(file); - - let mut enc = Encoder::new(bufw, image.width as u32, image.height as u32); - enc.set_color(ColorType::Indexed); - enc.set_depth(png::BitDepth::Eight); - enc.set_palette(squasher.palette_bytes()); - enc.write_header()?.write_image_data(&image.data)?; + match output_path.extension() { + None => { + eprintln!("can't determine output filetype! defaulting to png"); + save_png(image, squasher, output_path) + } + Some("png") => save_png(image, squasher, output_path), + Some("gif") => save_gif(image, squasher, output_path), + Some(ext) => { + eprintln!("unknown filetype '{ext}'!\nSupport output types are: GIF, PNG"); + std::process::exit(1); + } + } +} - Ok(()) +struct Image { + width: usize, + height: usize, + data: Vec, } fn get_png>(path: P) -> Result { @@ -124,8 +132,27 @@ fn get_jpg>(path: P) -> Result { }) } -struct Image { - width: usize, - height: usize, - data: Vec, +fn save_png(image: Image, squasher: Squasher, path: Utf8PathBuf) -> Result<(), anyhow::Error> { + let file = File::create(path)?; + let bufw = BufWriter::new(file); + + let mut enc = Encoder::new(bufw, image.width as u32, image.height as u32); + enc.set_color(ColorType::Indexed); + enc.set_depth(png::BitDepth::Eight); + enc.set_palette(squasher.palette_bytes()); + enc.write_header()?.write_image_data(&image.data)?; + + Ok(()) +} + +fn save_gif(image: Image, squasher: Squasher, path: Utf8PathBuf) -> Result<(), anyhow::Error> { + // I don't think I like this API anymore. It's a builder API, that's fine. + // I should make it so you can mutate the Gif directly. + GifBuilder::new(image.width as u16, image.height as u16) + .palette(squasher.palette_bytes().as_slice().try_into().unwrap()) + .image(ImageBuilder::new(image.width as u16, image.height as u16).build(image.data)?) + .build()? + .save(path)?; + + Ok(()) } -- cgit 1.4.1-3-g733a5