about summary refs log tree commit diff
path: root/gifcheck/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'gifcheck/src/main.rs')
-rw-r--r--gifcheck/src/main.rs103
1 files changed, 102 insertions, 1 deletions
diff --git a/gifcheck/src/main.rs b/gifcheck/src/main.rs
index a30eb95..8eec4c1 100644
--- a/gifcheck/src/main.rs
+++ b/gifcheck/src/main.rs
@@ -1,3 +1,104 @@
+use std::{ops::Deref, path::PathBuf};
+
+use gifed::{reader::Decoder, Gif};
+
+mod fix;
+
 fn main() {
-	println!("Hello, world!");
+	let file = std::env::args().nth(1).unwrap();
+	let arg = std::env::args().nth(2).map(|cmd| cmd.to_lowercase());
+
+	let gif = Decoder::file(&file).unwrap().read_all().unwrap();
+
+	let plt_report = same_palette(&gif);
+	match plt_report {
+		PaletteReport {
+			has_local: true,
+			local_redundant: true,
+			local_matching_indicies,
+		} => {
+			if local_matching_indicies {
+				println!("!!! LOCPLT_NORE. This could've been a global palette");
+			} else {
+				println!("!!  LOCPLT. This gif can be reindexed and have a global palette");
+			}
+		}
+		PaletteReport {
+			has_local: true,
+			local_redundant: false,
+			..
+		} => {
+			println!("    gif has local palettes and they differ");
+		}
+		PaletteReport {
+			has_local: false, ..
+		} => {
+			println!("    gif only has a global palette");
+		}
+	}
+
+	if arg.as_deref() == Some("fix") {
+		if let Some(fix_gif) = fix::palette_errors(&gif, plt_report) {
+			if !fix::images_match_exactly(&gif, &fix_gif) {
+				panic!("fixed images did not exactly match, this is a hard error")
+			}
+
+			println!("--- fixing, writing!");
+			let mut path = PathBuf::from(file);
+			path.set_file_name(format!(
+				"{}_fix",
+				path.file_stem().unwrap().to_string_lossy()
+			));
+
+			fix_gif.save(path).unwrap();
+		}
+	}
+}
+
+pub struct PaletteReport {
+	// Does the gif even contain local color tables?
+	has_local: bool,
+	// ... do those color tables always contain the same colors?
+	local_redundant: bool,
+	// ... and do those colors all have matching inidices, making it possible
+	// to simply set the global palette and remove the locals?
+	local_matching_indicies: bool,
+}
+
+fn same_palette(gif: &Gif) -> PaletteReport {
+	let mut palette = gif.global_color_table.as_ref();
+	let mut report = PaletteReport {
+		has_local: false,
+		local_redundant: true,
+		local_matching_indicies: true,
+	};
+
+	for img in gif.images() {
+		if let Some(local_palette) = img.compressed.palette() {
+			report.has_local = true;
+
+			match palette {
+				None => palette = Some(local_palette),
+				Some(known_palette) => {
+					if !local_palette.eq(known_palette) {
+						// Are the palletes equal, even?
+						report.local_redundant = false;
+						report.local_matching_indicies = false;
+						return report;
+					} else if report.local_matching_indicies {
+						// it's matching, but are the indicies the same?
+						for known_color in known_palette.deref() {
+							for local_color in local_palette.deref() {
+								if known_color != local_color {
+									report.local_matching_indicies = false;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	report
 }