diff options
author | Genny <gen@nyble.dev> | 2022-11-25 19:10:03 -0600 |
---|---|---|
committer | Genny <gen@nyble.dev> | 2022-11-25 19:10:03 -0600 |
commit | f45c0d338f9bd0eac56cbab2ff5b6d7c163e2ed0 (patch) | |
tree | 8caafa654047ff19822e4d1d19d3b36825c4c507 | |
parent | 9c9c04015d1dcc79ac27d1e903ce36a35e5c2dcf (diff) | |
download | gifed-f45c0d338f9bd0eac56cbab2ff5b6d7c163e2ed0.tar.gz gifed-f45c0d338f9bd0eac56cbab2ff5b6d7c163e2ed0.zip |
no more giftool
-rw-r--r-- | README.md | 3 | ||||
-rw-r--r-- | giftool/Cargo.toml | 10 | ||||
-rw-r--r-- | giftool/src/main.rs | 169 |
3 files changed, 0 insertions, 182 deletions
diff --git a/README.md b/README.md index 339407b..444faeb 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,5 @@ These are part of the 89a spec, but are kept separate as they're not "core" to t ## gifprobe Similar to FFMPEG's ffprobe, gifprobe will print details of a gif to stdout. -## giftool -A CLI tool for modifying gif files. - # License gifed, gifprobe, and giftool are licensed under Creative Commons Zero 1.0; they're in the public domain. Attribution is appreciated, but not required. \ No newline at end of file diff --git a/giftool/Cargo.toml b/giftool/Cargo.toml deleted file mode 100644 index 8e5763a..0000000 --- a/giftool/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "giftool" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -gifed = { path = "../gifed" } -png = "0.17.2" \ No newline at end of file diff --git a/giftool/src/main.rs b/giftool/src/main.rs deleted file mode 100644 index 1482185..0000000 --- a/giftool/src/main.rs +++ /dev/null @@ -1,169 +0,0 @@ -use std::{fs::File, ops::Deref, path::PathBuf}; - -fn main() { - let subcommand = std::env::args().nth(1); - - match subcommand.as_ref().map(|s| s.as_str()) { - Some("extract-frames") => extract_frames(), - Some("analyze") => analyze(), - _ => print_usage_and_exit(), - } -} - -fn print_usage_and_exit() -> ! { - println!("usage: giftool <subcommand> <options>\n"); - println!("extract_frames <input_gif> <output_directory>"); - println!("\tExtract each frame of the gif to a png in the output directory."); - println!("analyze <input_gif>"); - println!("\tAnalyze the gif, looking for places to make the image smaller."); - - std::process::exit(0) -} - -fn check_input_gif(igif: Option<PathBuf>) -> PathBuf { - if let Some(igif) = igif { - if !igif.exists() { - println!("The path provided to the gif does not exist"); - std::process::exit(1); - } else if !igif.is_file() { - println!("The path provided to the gif is not a file"); - std::process::exit(1); - } - - igif - } else { - println!("No gif file provided"); - std::process::exit(1); - } -} - -fn extract_frames() { - let input_gif = std::env::args().nth(2).map(PathBuf::from); - let out_dir = std::env::args().nth(3).map(PathBuf::from); - - let input_gif = check_input_gif(input_gif); - - let out_dir = if let Some(odir) = out_dir { - if !odir.exists() { - println!("The output path does not exist"); - std::process::exit(1); - } else if !odir.is_dir() { - println!("The output path is not a directory"); - std::process::exit(1); - } - - odir - } else { - println!("No output directory provided"); - std::process::exit(1); - }; - - let gread = match GifReader::file(&input_gif) { - Ok(gread) => gread, - Err(e) => { - println!( - "Failed to read {} as a gif:\n{}", - input_gif.to_string_lossy(), - e - ); - std::process::exit(1); - } - }; - - for (frame_number, image) in gread.images().enumerate() { - let mut fname = out_dir.clone(); - fname.push(format!("{}.png", frame_number)); - - let file = File::create(fname).unwrap(); - - let mut encoder = png::Encoder::new(file, image.width as u32, image.height as u32); - encoder.set_color(png::ColorType::Indexed); - encoder.set_palette(image.palette.as_bytes()); - - if let Some(trns) = image.png_trns() { - encoder.set_trns(trns); - } - - let mut writer = encoder.write_header().unwrap(); - writer.write_image_data(&image.indicies).unwrap(); - } -} - -fn analyze() { - let input_gif = check_input_gif(std::env::args().nth(2).map(PathBuf::from)); - - //TODO: - // Look at color tables: - // - Can any of them be combined into a global colour table? Can they all be? - // - Can the colour tables be shrank? Is it bigger than it needs to be. (Are all the inidicies used) - - let gread = match GifReader::file(&input_gif) { - Ok(gread) => gread, - Err(e) => { - println!( - "Failed to read {} as a gif:\n{}", - input_gif.to_string_lossy(), - e - ); - std::process::exit(1); - } - }; - - if gread.global_color_table.is_some() { - if analyze_can_be_a_gct(&gread) { - println!("All local colors are in the global, this gif doesn't need locals"); - } - } -} - -/// A gif can be reindexed to not need any local color tables if: -/// - The global color table contains all colors used in the gif -/// OR -/// - The global color table does not contain all colors used in the gif, -/// but it can fit the colors it does not have. -/// OR -/// - There is no global color table, but there are only 256 colors used in -/// the gif, so it can be created. -/// -/// # Returns -/// This function returns `true` if the gif can be reindexed to not need any -/// local tables anymore. -fn analyze_can_be_a_gct(gread: &Gif) -> bool { - let mut gct = if let Some(gct) = gread.global_color_table.as_ref() { - let mut gct = gct.clone().to_vec(); - gct.dedup(); - gct - } else { - vec![] - }; - - let mut gct_contains_all_colors = true; - let mut largest_gct_seen = 0; - let mut gif_has_local_tables = false; - - for image in gread.images() { - if image.packed.color_table() { - gif_has_local_tables = true; - let lct = image.palette; - - for color in lct.deref() { - if !gct.contains(color) { - gct_contains_all_colors = false; - gct.push(color.clone()); - } - } - } else { - for index in image.indicies { - largest_gct_seen = largest_gct_seen.max(*index); - } - } - } - - if gct_contains_all_colors || !gif_has_local_tables { - true - } else if !gct_contains_all_colors && gct.len() <= 256 { - true - } else { - false - } -} |