about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGenny <gen@nyble.dev>2022-11-24 19:24:05 -0600
committerGenny <gen@nyble.dev>2022-11-24 19:24:05 -0600
commit18c92c66e96be3751fd5457f222b3a2842ed0433 (patch)
tree67e1a1f56513f85a99b8bd597f4562811866f6b2
parentbd597fc165994d7cfb203cede3170639d0afc454 (diff)
downloadgifed-18c92c66e96be3751fd5457f222b3a2842ed0433.tar.gz
gifed-18c92c66e96be3751fd5457f222b3a2842ed0433.zip
Rename some things
-rw-r--r--gifed/src/block/imagedescriptor.rs19
-rw-r--r--gifed/src/block/indexedimage.rs71
-rw-r--r--gifed/src/block/mod.rs16
-rw-r--r--gifed/src/gif.rs11
-rw-r--r--gifed/src/reader/mod.rs62
-rw-r--r--gifed/src/writer/gifbuilder.rs4
-rw-r--r--gifed/src/writer/mod.rs17
7 files changed, 113 insertions, 87 deletions
diff --git a/gifed/src/block/imagedescriptor.rs b/gifed/src/block/imagedescriptor.rs
index 6bc0792..ce20240 100644
--- a/gifed/src/block/imagedescriptor.rs
+++ b/gifed/src/block/imagedescriptor.rs
@@ -2,6 +2,7 @@ use std::convert::TryInto;
 
 use super::{packed::ImagePacked, Palette};
 
+#[derive(Clone, Debug)]
 pub struct ImageDescriptor {
 	pub left: u16,
 	pub top: u16,
@@ -32,20 +33,18 @@ impl ImageDescriptor {
 	pub fn color_table_size(&self) -> usize {
 		crate::packed_to_color_table_length(self.packed.color_table_size())
 	}
-}
 
-impl From<&ImageDescriptor> for Box<[u8]> {
-	fn from(desc: &ImageDescriptor) -> Self {
+	pub fn as_bytes(&self) -> Vec<u8> {
 		let mut vec = vec![];
 
 		vec.push(0x2C); // Image Seperator
-		vec.extend_from_slice(&desc.left.to_le_bytes());
-		vec.extend_from_slice(&desc.top.to_le_bytes());
-		vec.extend_from_slice(&desc.width.to_le_bytes());
-		vec.extend_from_slice(&desc.height.to_le_bytes());
-		vec.push(desc.packed.raw);
+		vec.extend_from_slice(&self.left.to_le_bytes());
+		vec.extend_from_slice(&self.top.to_le_bytes());
+		vec.extend_from_slice(&self.width.to_le_bytes());
+		vec.extend_from_slice(&self.height.to_le_bytes());
+		vec.push(self.packed.raw);
 
-		vec.into_boxed_slice()
+		vec
 	}
 }
 
@@ -66,5 +65,3 @@ impl From<[u8; 9]> for ImageDescriptor {
 		}
 	}
 }
-
-//TODO: Impl to allow changing the packed field easier
diff --git a/gifed/src/block/indexedimage.rs b/gifed/src/block/indexedimage.rs
index 4e72ea0..ab8077f 100644
--- a/gifed/src/block/indexedimage.rs
+++ b/gifed/src/block/indexedimage.rs
@@ -1,10 +1,9 @@
-use std::convert::TryFrom;
-
 use weezl::encode::Encoder;
 
 use super::{ImageDescriptor, Palette};
-use crate::LZW;
+use crate::writer::EncodeError;
 
+#[derive(Clone, Debug)]
 pub struct IndexedImage {
 	pub image_descriptor: ImageDescriptor,
 	pub local_color_table: Option<Palette>,
@@ -28,48 +27,62 @@ impl IndexedImage {
 		self.image_descriptor.height
 	}
 
-	pub fn as_boxed_slice(&self, minimum_code_size: u8) -> Box<[u8]> {
-		let mut out = vec![];
-
-		let mut boxed: Box<[u8]> = (&self.image_descriptor).into();
-		out.extend_from_slice(&*boxed);
-
-		// Get the mcs while we write out the color table
-		let mut mcs = if let Some(lct) = &self.local_color_table {
-			out.extend_from_slice(&lct.as_bytes());
-
-			lct.packed_len() + 1
-		} else {
-			minimum_code_size + 1
+	/// The `lzw_code_size` should be None if there is a local color table present. If
+	/// this image is using the Global Color Table, you must provide an
+	/// LZW Minimum Code Size here. It is equal to the value of [Palette::packed_len], but
+	/// must also be at least 2.
+	pub fn compress(self, lzw_code_size: Option<u8>) -> Result<CompressedImage, EncodeError> {
+		//TODO: gen- The old code had a +1 here. Why?
+		let mcs = match lzw_code_size {
+			Some(mcs) => mcs,
+			None => match self.local_color_table.as_ref() {
+				None => return Err(EncodeError::InvalidCodeSize { lzw_code_size: 0 }),
+				Some(lct) => lct.packed_len(),
+			},
 		};
 
-		if mcs < 2 {
-			mcs = 2; // Must be true: 0 <= mcs <= 8
-		}
-
-		// First write out the MCS
-		out.push(mcs);
-
 		//FIXME: gen- This seems  broken
 		//let compressed = LZW::encode(mcs, &self.indicies);
 		let compressed = Encoder::new(weezl::BitOrder::Lsb, mcs)
 			.encode(&self.indicies)
 			.unwrap();
 
+		let mut blocks = vec![];
 		for chunk in compressed.chunks(255) {
-			out.push(chunk.len() as u8);
-			out.extend_from_slice(chunk);
+			blocks.push(chunk.to_vec());
 		}
-		// Data block length 0 to indicate an end
-		out.push(0x00);
 
-		out.into_boxed_slice()
+		Ok(CompressedImage {
+			image_descriptor: self.image_descriptor,
+			local_color_table: self.local_color_table,
+			lzw_code_size: mcs,
+			blocks,
+		})
 	}
 }
 
 pub struct CompressedImage {
 	pub image_descriptor: ImageDescriptor,
 	pub local_color_table: Option<Palette>,
-	pub lzw_minimum_code_size: u8,
+	pub lzw_code_size: u8,
 	pub blocks: Vec<Vec<u8>>,
 }
+
+impl CompressedImage {
+	pub fn as_bytes(&self) -> Vec<u8> {
+		let mut ret = vec![];
+
+		ret.extend_from_slice(&self.image_descriptor.as_bytes());
+		ret.push(self.lzw_code_size);
+
+		for block in &self.blocks {
+			ret.push(block.len() as u8);
+			ret.extend_from_slice(block);
+		}
+
+		// A zero length block indicates the end of the data stream
+		ret.push(0x00);
+
+		ret
+	}
+}
diff --git a/gifed/src/block/mod.rs b/gifed/src/block/mod.rs
index 06f3d9a..99075cf 100644
--- a/gifed/src/block/mod.rs
+++ b/gifed/src/block/mod.rs
@@ -19,7 +19,7 @@ use self::extension::Application;
 use self::extension::GraphicControl;
 
 pub enum Block {
-	IndexedImage(IndexedImage),
+	CompressedImage(CompressedImage),
 	//TODO: Extension(Extension),
 	GraphicControlExtension(GraphicControl),
 	CommentExtension(Vec<u8>),
@@ -38,9 +38,9 @@ pub enum LoopCount {
 	Number(u16),
 }
 
-pub(crate) fn encode_block(mcs: u8, block: &Block) -> Box<[u8]> {
+pub(crate) fn encode_block(mcs: u8, block: &Block) -> Vec<u8> {
 	match block {
-		Block::IndexedImage(img) => img.as_boxed_slice(mcs),
+		Block::CompressedImage(img) => img.as_bytes(),
 		Block::GraphicControlExtension(_) => encode_extension(block),
 		Block::CommentExtension(_) => encode_extension(block),
 		Block::ApplicationExtension(_) => encode_extension(block),
@@ -48,12 +48,12 @@ pub(crate) fn encode_block(mcs: u8, block: &Block) -> Box<[u8]> {
 	}
 }
 
-fn encode_extension(block: &Block) -> Box<[u8]> {
+fn encode_extension(block: &Block) -> Vec<u8> {
 	let mut vec = vec![];
 	vec.push(0x21); // Extension Introducer
 
 	match block {
-		Block::IndexedImage(_) => unreachable!(),
+		Block::CompressedImage(_) => unreachable!(),
 		Block::GraphicControlExtension(gce) => {
 			vec.push(0xF9); // Graphic control label
 			vec.push(0x04); // Block size for this extension is always 4
@@ -87,6 +87,8 @@ fn encode_extension(block: &Block) -> Box<[u8]> {
 		}
 	}
 
-	vec.push(0x00); // Zero length sub-block indicates end of extension
-	vec.into_boxed_slice()
+	// Zero length sub-block indicates end of extension
+	vec.push(0x00);
+
+	vec
 }
diff --git a/gifed/src/gif.rs b/gifed/src/gif.rs
index d9af572..816b10b 100644
--- a/gifed/src/gif.rs
+++ b/gifed/src/gif.rs
@@ -7,7 +7,7 @@ use crate::{
 		packed::ImagePacked,
 		Block, Palette, ScreenDescriptor, Version,
 	},
-	reader::DecodingError,
+	reader::DecodeError,
 	writer::GifBuilder,
 	Color,
 };
@@ -42,8 +42,7 @@ impl Gif {
 		};
 
 		for block in self.blocks.iter() {
-			boxed = encode_block(mcs, block);
-			out.extend_from_slice(&*boxed);
+			out.extend_from_slice(&encode_block(mcs, block));
 		}
 
 		// Write Trailer
@@ -78,7 +77,7 @@ impl<'a> Iterator for ImageIterator<'a> {
 		let img = loop {
 			match self.gif.blocks.get(self.block_index) {
 				Some(block) => match block {
-					Block::IndexedImage(img) => {
+					Block::CompressedImage(img) => {
 						// Step over this image so we don't hit it next time
 						self.block_index += 1;
 
@@ -104,7 +103,7 @@ impl<'a> Iterator for ImageIterator<'a> {
 			top_offset: img.image_descriptor.top,
 			packed: img.image_descriptor.packed,
 			palette,
-			indicies: &img.indicies,
+			image_blocks: &img.blocks,
 			blocks: &self.gif.blocks[starting_block..self.block_index],
 		})
 	}
@@ -117,7 +116,7 @@ pub struct Image<'a> {
 	pub top_offset: u16,
 	pub packed: ImagePacked,
 	pub palette: &'a Palette,
-	pub indicies: &'a [u8],
+	pub image_blocks: &'a [Vec<u8>],
 	pub blocks: &'a [Block],
 }
 
diff --git a/gifed/src/reader/mod.rs b/gifed/src/reader/mod.rs
index bd7d08a..68226f9 100644
--- a/gifed/src/reader/mod.rs
+++ b/gifed/src/reader/mod.rs
@@ -4,22 +4,22 @@ use std::{
 	error::Error,
 	fmt,
 	fs::File,
-	io::{BufRead, BufReader, Read},
+	io::Read,
 	path::Path,
 };
 
 use crate::{
 	block::{
 		extension::{Application, GraphicControl},
-		Block, CompressedImage, ImageDescriptor, IndexedImage, Palette, ScreenDescriptor, Version,
+		Block, CompressedImage, ImageDescriptor, Palette, ScreenDescriptor, Version,
 	},
-	color, Gif,
+	Gif,
 };
 
 pub struct GifReader {}
 
 impl GifReader {
-	pub fn file<P: AsRef<Path>>(path: P) -> Result<Gif, DecodingError> {
+	pub fn file<P: AsRef<Path>>(path: P) -> Result<Gif, DecodeError> {
 		let mut file = File::open(path)?;
 		let mut reader = SmartReader {
 			inner: vec![],
@@ -42,17 +42,17 @@ impl GifReader {
 		}
 	}
 
-	fn read_required(reader: &mut SmartReader) -> Result<Gif, DecodingError> {
+	fn read_required(reader: &mut SmartReader) -> Result<Gif, DecodeError> {
 		let version = match reader.take_lossy_utf8(6).as_deref() {
 			Some("GIF87a") => Version::Gif87a,
 			Some("GIF89a") => Version::Gif89a,
-			_ => return Err(DecodingError::UnknownVersionString),
+			_ => return Err(DecodeError::UnknownVersionString),
 		};
 
 		let mut lsd_buffer: [u8; 7] = [0; 7];
 		reader
 			.read_exact(&mut lsd_buffer)
-			.ok_or(DecodingError::UnexpectedEof)?;
+			.ok_or(DecodeError::UnexpectedEof)?;
 
 		let lsd = ScreenDescriptor::from(lsd_buffer);
 
@@ -64,17 +64,17 @@ impl GifReader {
 		})
 	}
 
-	fn read_color_table(reader: &mut SmartReader, size: usize) -> Result<Palette, DecodingError> {
+	fn read_color_table(reader: &mut SmartReader, size: usize) -> Result<Palette, DecodeError> {
 		let buffer = reader
 			.take(size as usize)
-			.ok_or(DecodingError::UnexpectedEof)?;
+			.ok_or(DecodeError::UnexpectedEof)?;
 
 		// We get the size from the screen descriptor. This should never return Err
 		Ok(Palette::try_from(&buffer[..]).unwrap())
 	}
 
-	fn read_block(reader: &mut SmartReader) -> Result<Option<Block>, DecodingError> {
-		let block_id = reader.u8().ok_or(DecodingError::UnexpectedEof)?;
+	fn read_block(reader: &mut SmartReader) -> Result<Option<Block>, DecodeError> {
+		let block_id = reader.u8().ok_or(DecodeError::UnexpectedEof)?;
 
 		//TODO: remove panic
 		match block_id {
@@ -88,7 +88,7 @@ impl GifReader {
 		}
 	}
 
-	fn read_extension(reader: &mut SmartReader) -> Result<Block, DecodingError> {
+	fn read_extension(reader: &mut SmartReader) -> Result<Block, DecodeError> {
 		let extension_id = reader.u8().expect("File ended early");
 
 		match extension_id {
@@ -97,7 +97,7 @@ impl GifReader {
 				let mut data = [0u8; 4];
 				reader
 					.read_exact(&mut data)
-					.ok_or(DecodingError::UnexpectedEof)?;
+					.ok_or(DecodeError::UnexpectedEof)?;
 				reader.skip(1); // Skip block terminator
 
 				Ok(Block::GraphicControlExtension(GraphicControl::from(data)))
@@ -124,11 +124,11 @@ impl GifReader {
 		}
 	}
 
-	fn read_image(mut reader: &mut SmartReader) -> Result<Block, DecodingError> {
+	fn read_image(mut reader: &mut SmartReader) -> Result<Block, DecodeError> {
 		let mut buffer = [0u8; 9];
 		reader
 			.read_exact(&mut buffer)
-			.ok_or(DecodingError::UnexpectedEof)?;
+			.ok_or(DecodeError::UnexpectedEof)?;
 		let descriptor = ImageDescriptor::from(buffer);
 
 		let color_table = if descriptor.has_color_table() {
@@ -138,42 +138,38 @@ impl GifReader {
 			None
 		};
 
-		let lzw_csize = reader.u8().ok_or(DecodingError::UnexpectedEof)?;
+		let lzw_csize = reader.u8().ok_or(DecodeError::UnexpectedEof)?;
+		let compressed_data = reader.take_data_subblocks();
 
-		let compressed_data = reader.take_and_collapse_subblocks();
-
-		let mut decompress = weezl::decode::Decoder::new(weezl::BitOrder::Lsb, lzw_csize);
-		//TODO: remove unwrap
-		let mut decompressed_data = decompress.decode(&compressed_data).unwrap();
-
-		Ok(Block::IndexedImage(IndexedImage {
+		Ok(Block::CompressedImage(CompressedImage {
 			image_descriptor: descriptor,
 			local_color_table: color_table,
-			indicies: decompressed_data,
+			lzw_code_size: lzw_csize,
+			blocks: compressed_data,
 		}))
 	}
 }
 
 #[derive(Debug)]
-pub enum DecodingError {
+pub enum DecodeError {
 	IoError(std::io::Error),
 	UnknownVersionString,
 	UnexpectedEof,
 	ColorIndexOutOfBounds,
 }
 
-impl Error for DecodingError {}
-impl fmt::Display for DecodingError {
+impl Error for DecodeError {}
+impl fmt::Display for DecodeError {
 	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 		match self {
-			DecodingError::IoError(error) => write!(f, "{}", error),
-			DecodingError::UnknownVersionString => {
+			DecodeError::IoError(error) => write!(f, "{}", error),
+			DecodeError::UnknownVersionString => {
 				write!(f, "File did not start with a valid header")
 			}
-			DecodingError::UnexpectedEof => {
+			DecodeError::UnexpectedEof => {
 				write!(f, "Found the end of the data at a weird spot")
 			}
-			DecodingError::ColorIndexOutOfBounds => {
+			DecodeError::ColorIndexOutOfBounds => {
 				write!(
 					f,
 					"The image contained an index not found in the color table"
@@ -183,9 +179,9 @@ impl fmt::Display for DecodingError {
 	}
 }
 
-impl From<std::io::Error> for DecodingError {
+impl From<std::io::Error> for DecodeError {
 	fn from(ioerror: std::io::Error) -> Self {
-		DecodingError::IoError(ioerror)
+		DecodeError::IoError(ioerror)
 	}
 }
 
diff --git a/gifed/src/writer/gifbuilder.rs b/gifed/src/writer/gifbuilder.rs
index f02862b..a6f5604 100644
--- a/gifed/src/writer/gifbuilder.rs
+++ b/gifed/src/writer/gifbuilder.rs
@@ -59,10 +59,12 @@ impl GifBuilder {
 			self.blocks.push(Block::GraphicControlExtension(gce));
 		}
 
+		//FIXME
+		/*
 		match ib.build() {
 			Ok(image) => self.blocks.push(Block::IndexedImage(image)),
 			Err(e) => self.error = Some(e),
-		}
+		}*/
 
 		self
 	}
diff --git a/gifed/src/writer/mod.rs b/gifed/src/writer/mod.rs
index 88311fc..4a12a76 100644
--- a/gifed/src/writer/mod.rs
+++ b/gifed/src/writer/mod.rs
@@ -1,5 +1,22 @@
 mod gifbuilder;
 mod imagebuilder;
 
+use std::fmt;
+
 pub use gifbuilder::GifBuilder;
 pub use imagebuilder::ImageBuilder;
+
+pub enum EncodeError {
+	InvalidCodeSize { lzw_code_size: u8 },
+}
+
+impl fmt::Display for EncodeError {
+	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+		match self {
+			//TODO: better error
+			EncodeError::InvalidCodeSize { lzw_code_size } => {
+				write!(f, "InvalidCodeSize => {lzw_code_size}")
+			}
+		}
+	}
+}