about summary refs log tree commit diff
path: root/gifcheck/src/fix.rs
diff options
context:
space:
mode:
authorgennyble <gen@nyble.dev>2023-10-09 17:45:19 -0500
committergennyble <gen@nyble.dev>2023-10-09 17:45:19 -0500
commit25b78bb991fa96864558cccd651519c296af1e91 (patch)
tree417eb3c94b4dd8477d6971b4d3401af5ebfd928e /gifcheck/src/fix.rs
parentfa2943a6a4bc1d276b458fefae48b28cd78cdb9c (diff)
downloadgifed-25b78bb991fa96864558cccd651519c296af1e91.tar.gz
gifed-25b78bb991fa96864558cccd651519c296af1e91.zip
changes
Diffstat (limited to 'gifcheck/src/fix.rs')
-rw-r--r--gifcheck/src/fix.rs103
1 files changed, 103 insertions, 0 deletions
diff --git a/gifcheck/src/fix.rs b/gifcheck/src/fix.rs
new file mode 100644
index 0000000..95f7ef2
--- /dev/null
+++ b/gifcheck/src/fix.rs
@@ -0,0 +1,103 @@
+use gifed::{
+	block::{Block, Palette},
+	Color, Gif,
+};
+
+use crate::PaletteReport;
+
+pub fn palette_errors(gif: &Gif, report: PaletteReport) -> Option<Gif> {
+	if report.local_matching_indicies {
+		let mut new = gif.clone();
+
+		for block in new.blocks.iter_mut() {
+			if let Block::CompressedImage(comp) = block {
+				comp.image_descriptor.packed.set_color_table(false);
+				comp.image_descriptor.packed.set_color_table_size(0);
+
+				if let Some(plt) = comp.local_color_table.take() {
+					new.global_color_table.get_or_insert(plt);
+				}
+			}
+		}
+
+		Some(new)
+	} else {
+		None
+	}
+}
+
+pub fn images_match_exactly(gifa: &Gif, gifb: &Gif) -> bool {
+	let mut a_buf = vec![0; gifa.width() * gifa.height() * 4];
+	let mut b_buf = vec![0; gifb.width() * gifb.height() * 4];
+
+	for (a, b) in gifa.images().zip(gifb.images()) {
+		if a.width() != b.width() || a.height() != b.height() {
+			return false;
+		}
+
+		if a.left() != b.left() || a.top() != b.top() {
+			return false;
+		}
+
+		let a_decomp = a.decompess();
+		let b_decomp = b.decompess();
+
+		let a_size = deindex(
+			&a_decomp.indicies,
+			a.palette(),
+			a.transparent_index(),
+			&mut a_buf,
+		);
+
+		let b_size = deindex(
+			&b_decomp.indicies,
+			b.palette(),
+			b.transparent_index(),
+			&mut b_buf,
+		);
+
+		match (a_size, b_size) {
+			(None, _) | (_, None) => return false,
+			(Some(asize), Some(bsize)) => {
+				if asize != bsize {
+					return false;
+				}
+
+				if a_buf[..asize] != b_buf[..bsize] {
+					return false;
+				}
+			}
+		}
+	}
+
+	true
+}
+
+fn deindex(indicies: &[u8], plt: &Palette, trns: Option<u8>, buffer: &mut [u8]) -> Option<usize> {
+	let mut rgba = |idx: usize, clr: Option<Color>| match clr {
+		None => {
+			buffer[idx] = 0;
+			buffer[idx + 1] = 0;
+			buffer[idx + 2] = 0;
+			buffer[idx + 3] = 0;
+		}
+		Some(clr) => {
+			buffer[idx] = clr.r;
+			buffer[idx + 1] = clr.g;
+			buffer[idx + 2] = clr.b;
+			buffer[idx + 3] = 255;
+		}
+	};
+
+	for (idx, color_idx) in indicies.iter().enumerate() {
+		match (trns, plt.get(*color_idx)) {
+			(Some(trns_idx), _) if trns_idx == *color_idx => rgba(idx * 4, None),
+			(_, Some(color)) => rgba(idx * 4, Some(color)),
+			(Some(_) | None, None) => {
+				return None;
+			}
+		}
+	}
+
+	Some(indicies.len() * 4)
+}