about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gifed/src/block/mod.rs18
-rw-r--r--gifed/src/block/palette.rs9
-rw-r--r--gifed/src/gif.rs32
-rw-r--r--gifed/src/lib.rs4
-rw-r--r--gifed/src/writer/mod.rs34
5 files changed, 70 insertions, 27 deletions
diff --git a/gifed/src/block/mod.rs b/gifed/src/block/mod.rs
index 3a18a07..46738ed 100644
--- a/gifed/src/block/mod.rs
+++ b/gifed/src/block/mod.rs
@@ -102,3 +102,21 @@ fn encode_extension(block: &Block) -> Vec<u8> {
 
 	vec
 }
+
+impl From<GraphicControl> for Block {
+	fn from(gce: GraphicControl) -> Self {
+		Block::GraphicControlExtension(gce)
+	}
+}
+
+impl From<Application> for Block {
+	fn from(app: Application) -> Self {
+		Block::ApplicationExtension(app)
+	}
+}
+
+impl From<LoopCount> for Block {
+	fn from(count: LoopCount) -> Self {
+		Block::LoopingExtension(count)
+	}
+}
diff --git a/gifed/src/block/palette.rs b/gifed/src/block/palette.rs
index 8a06883..3cbcaaa 100644
--- a/gifed/src/block/palette.rs
+++ b/gifed/src/block/palette.rs
@@ -15,15 +15,8 @@ impl Palette {
 		Self { table: vec![] }
 	}
 
-	//FIXME: gen- Second paragraph is incorrect
-	/// Returns the number of colors in the color table as used by the packed
-	/// fields in the Logical Screen Descriptor and Image Descriptor. You can
-	/// get the actual size with the [`len`](struct.ColorTable.html#method.len) method.
-	///
-	/// This value is equal to `log2([Palette::len]) - 1`. In other words, 2^(n + 1) will
-	/// give you the same value as [Palette::len]. (where `n` is the value returned)
 	pub fn packed_len(&self) -> u8 {
-		((self.table.len() as f32).log2().ceil() - 1f32) as u8
+		crate::color_table_len_to_packed(self.len())
 	}
 
 	pub fn lzw_code_size(&self) -> u8 {
diff --git a/gifed/src/gif.rs b/gifed/src/gif.rs
index 81aea28..5b1cfd7 100644
--- a/gifed/src/gif.rs
+++ b/gifed/src/gif.rs
@@ -1,9 +1,13 @@
 use std::{fs::File, io::Write, path::Path, time::Duration};
 
-use crate::block::{
-	encode_block,
-	extension::{DisposalMethod, GraphicControl},
-	Block, CompressedImage, IndexedImage, Palette, ScreenDescriptor, Version,
+use crate::{
+	block::{
+		encode_block,
+		extension::{DisposalMethod, GraphicControl},
+		Block, CompressedImage, IndexedImage, Palette, ScreenDescriptor, Version,
+	},
+	writer::EncodeBlock,
+	EncodeError,
 };
 
 #[derive(Clone, Debug)]
@@ -74,6 +78,26 @@ impl Gif {
 		File::create(path.as_ref())?.write_all(&self.as_bytes())
 	}
 
+	pub fn push<I: Into<EncodeBlock>>(&mut self, image: I) {
+		match image.into() {
+			EncodeBlock::Block(block) => self.blocks.push(block),
+			EncodeBlock::CompressedImage(ci) => self.blocks.push(Block::CompressedImage(ci)),
+			EncodeBlock::IndexedImage(indexed) => {
+				let lzw_code_size = self.palette.as_ref().map(|p| p.lzw_code_size());
+
+				//TODO: remove unwrap
+				let compressed = indexed.compress(lzw_code_size).unwrap();
+				self.blocks.push(Block::CompressedImage(compressed));
+			}
+			EncodeBlock::BuiltImage(built) => {
+				if let Some(gce) = built.gce {
+					self.push(gce);
+				}
+				self.push(built.image)
+			}
+		}
+	}
+
 	/// An iterator over the discrete images in the gif.
 	pub fn images(&self) -> ImageIterator<'_> {
 		ImageIterator {
diff --git a/gifed/src/lib.rs b/gifed/src/lib.rs
index cfb124f..438ab79 100644
--- a/gifed/src/lib.rs
+++ b/gifed/src/lib.rs
@@ -19,6 +19,10 @@ pub(crate) fn packed_to_color_table_length(packed: u8) -> usize {
 	1 << (packed + 1)
 }
 
+pub(crate) fn color_table_len_to_packed(len: usize) -> u8 {
+	((len as f32).log2().ceil() - 1f32) as u8
+}
+
 //TODO: Be sure to check that fields in LSD and Img. Desc. that were reserved
 //in 87a aren't set if version is 87a, or that we return a warning, etc. Just
 //remember about this.
diff --git a/gifed/src/writer/mod.rs b/gifed/src/writer/mod.rs
index e115ce8..661156d 100644
--- a/gifed/src/writer/mod.rs
+++ b/gifed/src/writer/mod.rs
@@ -58,24 +58,20 @@ impl<W: Write> Writer<W> {
 			.map_err(|error| EncodeError::IoError { error })
 	}
 
-	pub fn block(&mut self, block: Block) -> Result<(), EncodeError> {
-		self.write_all(&encode_block(&block))
-	}
-
 	pub fn repeat(&mut self, count: LoopCount) -> Result<(), EncodeError> {
 		self.write_all(&encode_block(&Block::LoopingExtension(count)))
 	}
 
-	pub fn image<I: Into<EncodeImage>>(&mut self, image: I) -> Result<(), EncodeError> {
+	pub fn push<I: Into<EncodeBlock>>(&mut self, image: I) -> Result<(), EncodeError> {
 		match image.into() {
-			EncodeImage::CompressedImage(compressed) => self.write_all(&compressed.as_bytes()),
-			EncodeImage::IndexedImage(indexed) => {
+			EncodeBlock::CompressedImage(compressed) => self.write_all(&compressed.as_bytes()),
+			EncodeBlock::IndexedImage(indexed) => {
 				let lzw_code_size = self.global_palette.as_ref().map(|p| p.lzw_code_size());
 
 				let compressed = indexed.compress(lzw_code_size)?;
 				self.write_all(&compressed.as_bytes())
 			}
-			EncodeImage::BuiltImage(built) => {
+			EncodeBlock::BuiltImage(built) => {
 				if let Some(gce) = built.gce {
 					self.write_all(&encode_block(&Block::GraphicControlExtension(gce)))?;
 				}
@@ -85,6 +81,7 @@ impl<W: Write> Writer<W> {
 				let compressed = built.image.compress(lzw_code_size)?;
 				self.write_all(&compressed.as_bytes())
 			}
+			EncodeBlock::Block(block) => self.write_all(&encode_block(&block)),
 		}
 	}
 
@@ -125,26 +122,33 @@ impl From<std::io::Error> for EncodeError {
 	}
 }
 
-pub enum EncodeImage {
+pub enum EncodeBlock {
 	CompressedImage(CompressedImage),
 	IndexedImage(IndexedImage),
 	BuiltImage(BuiltImage),
+	Block(Block),
 }
 
-impl From<CompressedImage> for EncodeImage {
+impl From<CompressedImage> for EncodeBlock {
 	fn from(ci: CompressedImage) -> Self {
-		EncodeImage::CompressedImage(ci)
+		EncodeBlock::CompressedImage(ci)
 	}
 }
 
-impl From<IndexedImage> for EncodeImage {
+impl From<IndexedImage> for EncodeBlock {
 	fn from(ii: IndexedImage) -> Self {
-		EncodeImage::IndexedImage(ii)
+		EncodeBlock::IndexedImage(ii)
 	}
 }
 
-impl From<BuiltImage> for EncodeImage {
+impl From<BuiltImage> for EncodeBlock {
 	fn from(bi: BuiltImage) -> Self {
-		EncodeImage::BuiltImage(bi)
+		EncodeBlock::BuiltImage(bi)
+	}
+}
+
+impl<T: Into<Block>> From<T> for EncodeBlock {
+	fn from(ib: T) -> Self {
+		EncodeBlock::Block(ib.into())
 	}
 }