about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gifed/src/gif.rs41
1 files changed, 39 insertions, 2 deletions
diff --git a/gifed/src/gif.rs b/gifed/src/gif.rs
index 06cf0b8..06e03a8 100644
--- a/gifed/src/gif.rs
+++ b/gifed/src/gif.rs
@@ -6,7 +6,8 @@ use crate::{
 		extension::{DisposalMethod, GraphicControl},
 		Block, CompressedImage, IndexedImage, Palette, ScreenDescriptor, Version,
 	},
-	writer::EncodeBlock,
+	writer::{EncodeBlock, ImageBuilder},
+	Color, EncodeError,
 };
 
 #[derive(Clone, Debug)]
@@ -30,6 +31,42 @@ impl Gif {
 		}
 	}
 
+	/// Create a new GIF with a single frame.
+	///
+	/// `data` should be a buffer of RGB data with a length of width * height * 3.
+	///
+	/// ## Errors
+	/// [EncodeError::TooManyColors] if the number of unique colors in the RGB
+	/// image are greater than 256.
+	pub fn from_rgb(width: u16, height: u16, mut data: Vec<u8>) -> Result<Self, EncodeError> {
+		let mut pal = Palette::new();
+		for idx in 0..data.len() / 3 {
+			let raw = &data[idx * 3..idx * 3 + 3];
+			let clr = Color::new(raw[0], raw[1], raw[2]);
+
+			match pal.from_color(clr) {
+				Some(clr_idx) => data[idx] = clr_idx,
+				None => {
+					if pal.len() == 256 {
+						// Error if we're already at max size
+						return Err(EncodeError::TooManyColors);
+					} else {
+						// Set as the next index, then fill that index in the palette
+						data[idx] = pal.len() as u8;
+						pal.push(clr);
+					}
+				}
+			}
+		}
+		data.resize(width as usize * height as usize, 0);
+
+		let mut gif = Gif::new(width, height);
+		let img = ImageBuilder::new(width, height).palette(pal).build(data)?;
+		gif.push(img);
+
+		Ok(gif)
+	}
+
 	pub fn set_width(&mut self, width: u16) {
 		self.descriptor.width = width;
 	}
@@ -246,7 +283,7 @@ impl<'a> Image<'a> {
 	}
 
 	/// Clones the CompressedImage and decompresses it.
-	pub fn decompess(&self) -> IndexedImage {
+	pub fn decompress(&self) -> IndexedImage {
 		//FIXME: remove unwrap
 		self.compressed.clone().decompress().unwrap()
 	}