about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gifed/Cargo.toml8
-rw-r--r--gifed/src/gif.rs10
-rw-r--r--gifed/src/gif_builder.rs124
-rw-r--r--gifed/src/lib.rs2
4 files changed, 65 insertions, 79 deletions
diff --git a/gifed/Cargo.toml b/gifed/Cargo.toml
index ce49947..b4d6322 100644
--- a/gifed/Cargo.toml
+++ b/gifed/Cargo.toml
@@ -9,13 +9,15 @@ repository = "https://github.com/genuinebyte/gifed"
 
 [dependencies]
 bitvec = "1.0.1"
-color_quant = "1.1.0"
-rgb = { version = "0.8", optional = true }
 weezl = "0.1.5"
 
+color_quant = { version = "1.1.0", optional = true }
+rgb = { version = "0.8", optional = true }
+
 [features]
 weezl-encode = []
-default = ["rgb"]
+videoish = ["color_quant", "rgb"]
+default = []
 
 [dev-dependencies]
 rand = "0.8.5"
diff --git a/gifed/src/gif.rs b/gifed/src/gif.rs
index 87a310f..f11694a 100644
--- a/gifed/src/gif.rs
+++ b/gifed/src/gif.rs
@@ -20,6 +20,16 @@ pub struct Gif {
 }
 
 impl Gif {
+	pub fn new(width: u16, height: u16) -> Self {
+		Self {
+			//TODO: gen- select lower when possible
+			version: Version::Gif89a,
+			descriptor: ScreenDescriptor::new(width, height),
+			palette: None,
+			blocks: vec![],
+		}
+	}
+
 	pub fn set_width(&mut self, width: u16) {
 		self.descriptor.width = width;
 	}
diff --git a/gifed/src/gif_builder.rs b/gifed/src/gif_builder.rs
index 9d039bf..53b1929 100644
--- a/gifed/src/gif_builder.rs
+++ b/gifed/src/gif_builder.rs
@@ -1,90 +1,59 @@
-use crate::{
-	block::{Palette, ScreenDescriptor, Version},
-	writer::ImageBuilder,
-	EncodeError, Gif,
-};
+use crate::{block::Palette, writer::ImageBuilder, Color, EncodeError, Gif};
 
 use color_quant::NeuQuant;
-use rgb::{ComponentBytes, FromSlice, RGB8};
+use rgb::{ComponentBytes, FromSlice};
 
 use std::convert::TryFrom;
 
-pub struct GifBuilder {
+pub struct VideoGif {
 	width: u16,
 	height: u16,
 	framerate: Option<u16>,
-	global_palette: Option<Palette>,
 	frames: Vec<Frame>,
 }
 
-impl GifBuilder {
-	pub fn set_resolution(&mut self, width: u16, height: u16) {
-		self.width = width;
-		self.height = height;
+impl VideoGif {
+	pub fn new(width: u16, height: u16) -> Self {
+		Self {
+			width,
+			height,
+			framerate: None,
+			frames: vec![],
+		}
 	}
+
+	/// Set the approximate frames per second.
+	///
+	/// This struct uses a constant framerate and is only precise to hundreths
+	/// of a second, so you might not get exactly what you want.
 	pub fn set_framerate(&mut self, framerate: u16) {
-		self.framerate = Some(framerate)
+		self.framerate = Some(100 / framerate);
 	}
-	pub fn add_frame(&mut self, frame: Frame) {
-		self.frames.push(frame)
-	}
-	pub fn add_global_palette(&mut self, palette: Palette) {
-		self.global_palette = Some(palette)
+
+	pub fn add_frame<F: Into<Frame>>(&mut self, frame: F) {
+		self.frames.push(frame.into())
 	}
+
+	#[rustfmt::skip] // it was doing things i did not like
 	pub fn build(self) -> Result<Gif, EncodeError> {
-		let Self {
-			width,
-			height,
-			framerate,
-			frames,
-			global_palette,
-		} = self;
-
-		let descriptor = ScreenDescriptor::new(width, height);
-		let mut gif = Gif {
-			version: Version::Gif89a,
-			descriptor,
-			palette: global_palette,
-			blocks: vec![],
-		};
-
-		let images = frames.into_iter().map(|frame| {
-			let Frame {
-				interval,
-				image_indices,
-				palette,
-			} = frame;
-
-			let delay = interval
-				.map(|interval| interval)
-				.or(framerate.map(|fr| 100 / fr))
-				.unwrap_or(10);
-			ImageBuilder::new(width, height)
-				.delay(delay)
-				.palette(palette)
-				.build(image_indices)
-		});
-
-		for compressed_image in images {
-			match compressed_image {
-				Ok(img) => gif.push(img),
-				Err(e) => return Err(e),
-			}
-		}
+		let Self { width, height, framerate, frames } = self;
 
-		Ok(gif)
-	}
-}
+		let mut gif = Gif::new(width, height);
 
-impl Default for GifBuilder {
-	fn default() -> Self {
-		Self {
-			width: 256,
-			height: 256,
-			framerate: Some(15),
-			frames: vec![],
-			global_palette: None,
+		for Frame { image_indices, interval, palette } in frames {
+			//TODO: return error instead of defaulting to 10? or print warning?
+			// printing in a library is bad but perhaps so is assuming 10 fps?
+			let delay = interval.or(framerate).unwrap_or(10);
+
+			gif.push(
+				ImageBuilder::new(width, height)
+					.delay(delay)
+					.palette(palette)
+					.build(image_indices)?,
+			)
 		}
+
+		Ok(gif)
 	}
 }
 
@@ -96,13 +65,10 @@ pub struct Frame {
 	palette: Palette,
 }
 
-impl From<Vec<Vec<RGB8>>> for Frame {
-	/// image: row-major ordering
-	fn from(image: Vec<Vec<RGB8>>) -> Self {
-		let flat = image.concat();
-
+impl From<&[Color]> for Frame {
+	fn from(flat: &[Color]) -> Self {
 		let flat_rgba = flat.as_rgba();
-		let quant = NeuQuant::new(1, 256, &flat_rgba.as_bytes());
+		let quant = NeuQuant::new(1, 256, flat_rgba.as_bytes());
 
 		let mut indicies = vec![0; flat.len()];
 		for (image_idx, px) in flat.iter().enumerate() {
@@ -120,8 +86,16 @@ impl From<Vec<Vec<RGB8>>> for Frame {
 	}
 }
 
+impl From<(&[Color], u16)> for Frame {
+	fn from(image_delay: (&[Color], u16)) -> Self {
+		let (flat, delay) = image_delay;
+		let mut this: Frame = flat.into();
+		this.interval = Some(delay);
+		this
+	}
+}
+
 impl Frame {
-	///
 	pub fn set_interval(&mut self, interval_hundredths: u16) {
 		self.interval = Some(interval_hundredths);
 	}
diff --git a/gifed/src/lib.rs b/gifed/src/lib.rs
index 3990e33..7d35dee 100644
--- a/gifed/src/lib.rs
+++ b/gifed/src/lib.rs
@@ -2,7 +2,7 @@ mod gif;
 mod lzw;
 
 pub mod block;
-#[cfg(all(feature = "rgb"))]
+#[cfg(feature = "videoish")]
 pub mod gif_builder;
 pub mod reader;
 pub mod writer;