about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGenevieve Alfirevic <gen@nyble.dev>2022-04-04 22:15:49 -0500
committerGenevieve Alfirevic <gen@nyble.dev>2022-04-04 22:15:49 -0500
commit90119b61130a7475ad743e512f41110d1b50ed99 (patch)
tree5a307bda029ba44ede58474f2593e7e4150360d0
parentc60d5e8efdd6208968250e397d9e2676d6e347fc (diff)
downloadgifed-90119b61130a7475ad743e512f41110d1b50ed99.tar.gz
gifed-90119b61130a7475ad743e512f41110d1b50ed99.zip
giftool: Add extract-frames subcommand
-rw-r--r--giftool/Cargo.toml10
-rw-r--r--giftool/src/main.rs88
2 files changed, 98 insertions, 0 deletions
diff --git a/giftool/Cargo.toml b/giftool/Cargo.toml
new file mode 100644
index 0000000..8e5763a
--- /dev/null
+++ b/giftool/Cargo.toml
@@ -0,0 +1,10 @@
+[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
new file mode 100644
index 0000000..a835112
--- /dev/null
+++ b/giftool/src/main.rs
@@ -0,0 +1,88 @@
+use std::{fs::File, path::PathBuf};
+
+use gifed::reader::GifReader;
+
+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.");
+
+	std::process::exit(0)
+}
+
+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 = if let Some(igif) = input_gif {
+		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);
+	};
+
+	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() {}