about summary refs log tree commit diff
path: root/src/writer/imagebuilder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/writer/imagebuilder.rs')
-rw-r--r--src/writer/imagebuilder.rs165
1 files changed, 20 insertions, 145 deletions
diff --git a/src/writer/imagebuilder.rs b/src/writer/imagebuilder.rs
index cd96908..0636bb3 100644
--- a/src/writer/imagebuilder.rs
+++ b/src/writer/imagebuilder.rs
@@ -1,13 +1,11 @@
-use crate::common::Color;
-use super::OutVec;
-use super::LZW;
+use crate::components::{ColorTable, Image, ImageDescriptor};
 
 pub struct ImageBuilder {
 	left_offset: u16,
 	top_offset: u16,
 	width: u16,
 	height: u16,
-	color_table: Option<Vec<Color>>,
+	color_table: Option<ColorTable>,
 	indicies: Vec<u8>
 }
 
@@ -39,13 +37,8 @@ impl ImageBuilder {
 		self
 	}
 
-	pub fn color_table(mut self, vec: Vec<Color>) -> Self {
-		if vec.len() == 0 || vec.len() > 256 {
-			//TODO: Throw error instead of panic
-			panic!("Color table has to be less than or 256 colors in size, and at least one");
-		}
-
-		self.color_table = Some(vec);
+	pub fn color_table(mut self, table: ColorTable) -> Self {
+		self.color_table = Some(table);
 
 		self
 	}
@@ -55,142 +48,24 @@ impl ImageBuilder {
 		self
 	}
 
-	//TODO: Make lzw_minimum_code_size optional. ONly needed with global color tables
-	pub fn write_to_vec(&self, lzw_minimum_code_size: u8) -> Vec<u8> {
-		let mut out = OutVec::new();
-
-		self.write_image_descriptor(&mut out)
-			.write_color_table(&mut out)
-			.write_image_data(&mut out, lzw_minimum_code_size);
-
-		out.vec()
-	}
-
-	fn write_image_descriptor(&self, out: &mut OutVec) -> &Self {
-		// Image seperator. At the start of every image descriptor
-		out.push_u8(0x2C)
-		.push_u16(self.left_offset)
-		.push_u16(self.top_offset)
-		.push_u16(self.width)
-		.push_u16(self.height);
-
-		// Taken from gifbuilder.rs
-		//TODO: deduplciate code
-		let mut packed: u8 = 0;
-		if let Some(ct) = &self.color_table {
-			packed |= 0b1000_0000; // Set the color table flag
-
-			let size = (ct.len() as f32).log2().ceil() - 1f32;
-			
-			packed |= size as u8;
+	pub fn build(self) -> Image {
+		let mut imgdesc = ImageDescriptor {
+			left: self.left_offset,
+			top: self.top_offset,
+			width: self.width,
+			height: self.height,
+			packed: 0 // Set later
+		};
+
+		if let Some(lct) = &self.color_table {
+			imgdesc.color_table_present(true);
+			imgdesc.color_table_size(lct.packed_len());
 		}
-		//TODO: Interlace and Sort flags in packed
-		out.push_u8(packed);
-
-		self
-	}
 
-	fn write_color_table(&self, out: &mut OutVec) -> &Self {
-		if let Some(ct) = &self.color_table {
-			out.push_colors(&ct);
+		Image {
+			image_descriptor: imgdesc,
+			local_color_table: self.color_table,
+			indicies: self.indicies
 		}
-
-		self
-	}
-
-	fn write_image_data(&self, out: &mut OutVec, minimum_code_size: u8) -> &Self {
-		let mut mcs = minimum_code_size;
-
-		//TODO: Deduplicate color table size code
-		if let Some(ct) = &self.color_table {
-			mcs = ((ct.len() as f32).log2().ceil() - 1f32) as u8;
-		}
-
-		if mcs < 2 {
-			// Must always be true: 2 <= mcs <= 8
-			mcs = 2;
-		}
-
-		// First write out the MCS
-		out.push_u8(mcs);
-
-		let compressed = LZW::encode(mcs, &self.indicies);
-		
-		for chunk in compressed.chunks(255) {
-			out.push_u8(chunk.len() as u8);
-			out.push_slice(chunk);
-		}
-		// Data block length 0 to indicate an end
-		out.push_u8(0x00);
-
-		self
 	}
 }
-
-#[cfg(test)]
-mod imagebuilder_test {
-	use super::*;
-
-	#[test]
-	fn write_to_vec() {
-		let colortable = vec![
-			Color::new(0, 0, 0),
-			Color::new(128, 0, 255)
-		];
-		let indicies = vec![0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0];
-
-		let expected_out = vec![
-			0x2C, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0b1000_0000, // Image Descriptor
-			0, 0, 0, 128, 0, 255, // Color Table
-			0x02, 0x05, 0x84, 0x1D, 0x81, 0x7A, 0x50, 0x00 // Image Data
-		];
-		let actual_out = ImageBuilder::new(4, 4)
-			.color_table(colortable)
-			.indicies(indicies)
-			.write_to_vec(0);
-
-		assert_eq!(actual_out, expected_out);
-	}
-
-	#[test]
-	fn write_image_descriptor() {
-		let mut out = OutVec::new();
-		ImageBuilder::new(16, 16).offsets(1, 6).write_image_descriptor(&mut out);
-
-		assert_eq!(out.vec(), vec![0x2C, 0x01, 0x00, 0x06, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00]);
-
-		let mut out = OutVec::new();
-		ImageBuilder::new(16, 16)
-			.offsets(1, 6)
-			.color_table(vec![Color::new(0, 0, 0)])
-			.write_image_descriptor(&mut out);
-
-		assert_eq!(out.vec(), vec![0x2C, 0x01, 0x00, 0x06, 0x00, 0x10, 0x00, 0x10, 0x00, 0b1000_0000]);
-	}
-
-	#[test]
-	fn write_color_table() {
-		let mut out = OutVec::new();
-		ImageBuilder::new(16, 16)
-			.color_table(vec![Color::new(1, 2, 3), Color::new(253, 254, 255)])
-			.write_color_table(&mut out);
-
-		assert_eq!(out.vec(), vec![0x01, 0x02, 0x03, 0xFD, 0xFE, 0xFF]);
-	}
-
-	#[test]
-	fn write_image_data() {
-		#[test]
-		fn encode() {
-			let indicies = vec![0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0];
-			let output = vec![0x02, 0x05, 0x84, 0x1D, 0x81, 0x7A, 0x50, 0x00];
-
-			let mut out = OutVec::new();
-			ImageBuilder::new(16, 16)
-				.indicies(indicies)
-				.write_image_data(&mut out, 2);
-	
-			assert_eq!(out.vec(), output);
-		}
-	}
-}
\ No newline at end of file