about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDevon Sawatsky <novedevo@gmail.com>2023-12-31 16:13:34 -0800
committerDevon Sawatsky <novedevo@gmail.com>2023-12-31 16:13:34 -0800
commitac3d9ffd2a913da2f578cc0dd908962ce23246bc (patch)
tree23185548c244b6767074b728597f68a6da8c369b
parent85f008479a1994486acd96b27fb5502839e6e893 (diff)
downloadgifed-ac3d9ffd2a913da2f578cc0dd908962ce23246bc.tar.gz
gifed-ac3d9ffd2a913da2f578cc0dd908962ce23246bc.zip
rewrite the gif builder API to actually work
-rw-r--r--gifed/src/gif_builder.rs82
1 files changed, 31 insertions, 51 deletions
diff --git a/gifed/src/gif_builder.rs b/gifed/src/gif_builder.rs
index b376bf7..323e63c 100644
--- a/gifed/src/gif_builder.rs
+++ b/gifed/src/gif_builder.rs
@@ -1,14 +1,14 @@
-use std::convert::TryFrom;
-
-#[cfg(feature = "colorsquash")]
-use colorsquash::Squasher;
-
 use crate::{
 	block::{Palette, ScreenDescriptor, Version},
 	writer::ImageBuilder,
-	Color, EncodeError, Gif,
+	EncodeError, Gif,
 };
 
+use colorsquash::Squasher;
+use rgb::{ComponentBytes, RGB8};
+
+use std::convert::TryFrom;
+
 pub struct GifBuilder {
 	width: u16,
 	height: u16,
@@ -51,7 +51,7 @@ impl GifBuilder {
 		let images = frames.into_iter().map(|frame| {
 			let Frame {
 				interval,
-				image,
+				image_indices,
 				palette,
 			} = frame;
 
@@ -59,23 +59,12 @@ impl GifBuilder {
 				.map(|interval| interval * 10)
 				.or(framerate.map(|fr| 100 / fr))
 				.unwrap_or(10);
-			let image_indicies = image
-				.into_iter()
-				.flat_map(|row| {
-					row.into_iter().map(|c| {
-						//if there is a palette for this frame, use that to encode the
-						palette
-							.or(global_palette)
-							.map(|p| p.from_color(c)) //TODO: this is wrong. don't do this
-							.flatten()
-					})
-				})
-				.collect::<Vec<_>>();
-			let mut ib = ImageBuilder::new(width, height).delay(delay);
-			if let Some(p) = palette {
-				ib = ib.palette(p);
-			}
-			ib.build(image_indicies)?.image.compress(None)
+			ImageBuilder::new(width, height)
+				.delay(delay)
+				.palette(palette)
+				.build(image_indices)?
+				.image
+				.compress(None)
 		});
 
 		for compressed_image in images {
@@ -96,48 +85,39 @@ impl Default for GifBuilder {
 			height: 256,
 			framerate: Some(15),
 			frames: vec![],
+			global_palette: None,
 		}
 	}
 }
 
 pub struct Frame {
-	image: Vec<Vec<Color>>, //row-major
-	interval: Option<u16>,
+	///indices into the palette
+	image_indices: Vec<u8>,
 	///in hundredths of a second
-	palette: Option<Palette>,
+	interval: Option<u16>,
+	palette: Palette,
 }
 
-impl From<Vec<Vec<Color>>> for Frame {
-	fn from(image: Vec<Vec<Color>>) -> Self {
+impl From<Vec<Vec<RGB8>>> for Frame {
+	/// image: row-major ordering
+	fn from(image: Vec<Vec<RGB8>>) -> Self {
+		let flat = image.concat();
+
+		let squasher = Squasher::new(255u8, flat.as_slice());
+
+		let mut image_indices = vec![0; flat.len()];
+		squasher.map_unsafe(flat.as_bytes(), &mut image_indices);
+		let palette = Palette::try_from(squasher.palette_bytes().as_slice()).unwrap();
 		Self {
-			image,
+			image_indices,
 			interval: None,
-			palette: None,
+			palette,
 		}
 	}
 }
 
 impl Frame {
-	#[cfg(feature = "colorsquash")]
-	pub fn optimize_palette(&mut self) {
-		#[cfg(feature = "rgb")]
-		let image_bytes = self.image.clone().into_iter().flatten().collect::<Vec<_>>();
-		#[cfg(not(feature = "rgb"))]
-		let image_bytes = self
-			.image
-			.iter()
-			.flat_map(|row| row.iter().flat_map(|color| [color.r, color.g, color.b]))
-			.collect::<Vec<_>>();
-		#[cfg(feature = "rgb")]
-		let squasher = Squasher::new(255u8, image_bytes.as_slice());
-		#[cfg(not(feature = "rgb"))]
-		let squasher = Squasher::new_raw(255u8, image_bytes.as_slice());
-		let pal = Palette::try_from(squasher.palette_bytes().as_slice()).unwrap();
-		self.set_palette(pal)
-	}
-	pub fn set_palette(&mut self, palette: Palette) {
-		self.palette = Some(palette)
-	}
+	///
 	pub fn set_interval(&mut self, interval_hundredths: u16) {
 		self.interval = Some(interval_hundredths);
 	}