about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGenevieve Alfirevic <gen@nyble.dev>2022-04-05 00:56:10 -0500
committerGenevieve Alfirevic <gen@nyble.dev>2022-04-05 00:56:10 -0500
commit8395c74a9706e5d180a917b633af57a3fe1ad400 (patch)
tree8e91ac111a6b73d40198c0f81a8c24ea8dcd542a
parent5e4c832053635b6900044b2c48771788856b5244 (diff)
downloadgifed-8395c74a9706e5d180a917b633af57a3fe1ad400.tar.gz
gifed-8395c74a9706e5d180a917b633af57a3fe1ad400.zip
gifed: Add packed struct for image descriptor
-rw-r--r--gifed/examples/read.rs2
-rw-r--r--gifed/src/block/colortable.rs10
-rw-r--r--gifed/src/block/imagedescriptor.rs39
-rw-r--r--gifed/src/block/packed.rs78
-rw-r--r--gifed/src/color.rs6
-rw-r--r--gifed/src/gif.rs3
-rw-r--r--gifed/src/reader/mod.rs2
-rw-r--r--gifed/src/writer/imagebuilder.rs6
8 files changed, 118 insertions, 28 deletions
diff --git a/gifed/examples/read.rs b/gifed/examples/read.rs
index 3c3d611..2c8b08d 100644
--- a/gifed/examples/read.rs
+++ b/gifed/examples/read.rs
@@ -7,7 +7,7 @@ use gifed::{
 };
 
 fn main() {
-	let reader = GifReader::file("examples/simulation.gif").unwrap();
+	let reader = GifReader::file("/home/gen/Downloads/emilia_bar.gif").unwrap();
 
 	// Create the directory we're we'll dump all the PNGs
 	std::fs::create_dir_all("examples/read/").unwrap();
diff --git a/gifed/src/block/colortable.rs b/gifed/src/block/colortable.rs
index b467d64..0d076c9 100644
--- a/gifed/src/block/colortable.rs
+++ b/gifed/src/block/colortable.rs
@@ -36,9 +36,9 @@ impl ColorTable {
 		self.table.get(index as usize).map(|v| v.clone())
 	}
 
-	pub fn from_color(&self, color: Color) -> Option<u8> {
+	pub fn from_color<C: AsRef<Color>>(&self, color: C) -> Option<u8> {
 		for (i, &c) in self.table.iter().enumerate() {
-			if c == color {
+			if c == *color.as_ref() {
 				return Some(i as u8);
 			}
 		}
@@ -63,6 +63,12 @@ impl Deref for ColorTable {
 	}
 }
 
+impl AsRef<ColorTable> for ColorTable {
+	fn as_ref(&self) -> &ColorTable {
+		self
+	}
+}
+
 impl From<&ColorTable> for Box<[u8]> {
 	fn from(table: &ColorTable) -> Self {
 		let mut vec = vec![];
diff --git a/gifed/src/block/imagedescriptor.rs b/gifed/src/block/imagedescriptor.rs
index 25567b2..76efe6c 100644
--- a/gifed/src/block/imagedescriptor.rs
+++ b/gifed/src/block/imagedescriptor.rs
@@ -1,39 +1,36 @@
 use std::convert::TryInto;
 
+use super::{packed::ImagePacked, ColorTable};
+
 pub struct ImageDescriptor {
-	// Image Seperator 0x2C is the first byte //
 	pub left: u16,
 	pub top: u16,
 	pub width: u16,
 	pub height: u16,
-	pub packed: u8,
+	pub packed: ImagePacked,
 }
 
 impl ImageDescriptor {
-	pub fn set_color_table_present(&mut self, is_present: bool) {
-		if is_present {
-			self.packed |= 0b1000_0000;
+	/// This data structure **does not** contain the color table, only a flag to
+	/// indicate if one is present and it's size.
+	pub fn set_color_table_metadata<T: AsRef<ColorTable>>(&mut self, table: Option<T>) {
+		if let Some(table) = table {
+			let table = table.as_ref();
+			self.packed.set_color_table(true);
+			self.packed.set_color_table_size(table.packed_len());
 		} else {
-			self.packed &= 0b0111_1111;
+			self.packed.set_color_table(false);
+			// This is not strictly needed, but we'll clear it anyway
+			self.packed.set_color_table_size(0);
 		}
 	}
 
-	pub fn set_color_table_size(&mut self, size: u8) {
-		// GCT size is calulated by raising two to this number plus one,
-		// so we have to work backwards.
-		let size = (size as f32).log2().ceil() - 1f32;
-		self.packed |= size as u8;
-	}
-
-	//TODO: Setter for sort flag in packed field
-	//TODO: Setter for interlace flag in packed field
-
-	pub fn color_table_present(&self) -> bool {
-		self.packed & 0b1000_0000 != 0
+	pub fn has_color_table(&self) -> bool {
+		self.packed.color_table()
 	}
 
 	pub fn color_table_size(&self) -> usize {
-		crate::packed_to_color_table_length(self.packed & 0b0000_0111)
+		crate::packed_to_color_table_length(self.packed.color_table_size())
 	}
 }
 
@@ -46,7 +43,7 @@ impl From<&ImageDescriptor> for Box<[u8]> {
 		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);
+		vec.push(desc.packed.raw);
 
 		vec.into_boxed_slice()
 	}
@@ -65,7 +62,7 @@ impl From<[u8; 9]> for ImageDescriptor {
 			top,
 			width,
 			height,
-			packed,
+			packed: ImagePacked { raw: packed },
 		}
 	}
 }
diff --git a/gifed/src/block/packed.rs b/gifed/src/block/packed.rs
index 1557fae..a80b807 100644
--- a/gifed/src/block/packed.rs
+++ b/gifed/src/block/packed.rs
@@ -41,6 +41,84 @@ impl GraphicPacked {
 	}
 }
 
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct ImagePacked {
+	pub raw: u8,
+}
+
+impl ImagePacked {
+	pub(crate) fn new(packed: u8) -> Self {
+		Self { raw: packed }
+	}
+
+	pub fn color_table(&self) -> bool {
+		self.raw & 0b1_0_0_00_000 > 0
+	}
+
+	pub fn set_color_table(&mut self, flag: bool) {
+		if flag {
+			self.raw |= 0b1_0_0_00_000;
+		} else {
+			self.raw &= 0b0_1_1_11_111;
+		}
+	}
+
+	pub fn interlaced(&self) -> bool {
+		self.raw & 0b0_1_0_00_000 > 0
+	}
+
+	pub fn set_interlaced(&mut self, flag: bool) {
+		if flag {
+			self.raw |= 0b0_1_0_00_000;
+		} else {
+			self.raw &= 0b1_0_1_11_111;
+		}
+	}
+
+	pub fn sorted(&self) -> bool {
+		self.raw & 0b0_0_1_00_000 > 0
+	}
+
+	pub fn set_sorted(&mut self, flag: bool) {
+		if flag {
+			self.raw |= 0b0_0_1_00_000;
+		} else {
+			self.raw &= 0b1_1_0_11_111;
+		}
+	}
+
+	pub fn reserved_87a(&self) -> u8 {
+		// There was no sort flag in 87a
+		self.raw & 0b0_0_111_000 >> 3
+	}
+
+	pub fn set_reserved_87a(&mut self, reserved: u8) {
+		// We care about the three least significant bits and we want to shift
+		// them so they're three higher. From 0_0_000_111 to 0_0_111_000
+		self.raw = (reserved & 0b0000_0111) << 3;
+	}
+
+	pub fn reserved_89a(&self) -> u8 {
+		self.raw & 0b0_0_0_11_000 >> 3
+	}
+
+	pub fn set_reserved_89a(&mut self, reserved: u8) {
+		// We care about the two least significant bits and we want to shift
+		// them so they're three higher. From 0_0_0_00_011 to 0_0_0_11_000
+		self.raw = (reserved & 0b0000_0011) << 3;
+	}
+
+	pub fn color_table_size(&self) -> u8 {
+		self.raw & 0b0_0_0_00_111
+	}
+
+	pub fn set_color_table_size(&mut self, reserved: u8) {
+		// The color table is the least significant already, don't do anything
+		// except select the bits
+		self.raw = reserved & 0b0_0_0_00_111;
+	}
+}
+
 #[inline]
 fn graphic_reserved(packed: u8) -> u8 {
 	packed & 0b111_000_0_0 >> 5
diff --git a/gifed/src/color.rs b/gifed/src/color.rs
index 29e7feb..4b6e22a 100644
--- a/gifed/src/color.rs
+++ b/gifed/src/color.rs
@@ -11,6 +11,12 @@ impl Color {
 	}
 }
 
+impl AsRef<Color> for Color {
+	fn as_ref(&self) -> &Color {
+		self
+	}
+}
+
 impl From<[u8; 3]> for Color {
 	fn from(arr: [u8; 3]) -> Self {
 		Self {
diff --git a/gifed/src/gif.rs b/gifed/src/gif.rs
index dff3123..c4fb66c 100644
--- a/gifed/src/gif.rs
+++ b/gifed/src/gif.rs
@@ -4,6 +4,7 @@ use crate::{
 	block::{
 		encode_block,
 		extension::{DisposalMethod, GraphicControl},
+		packed::ImagePacked,
 		Block, ColorTable, ScreenDescriptor, Version,
 	},
 	colorimage::{RgbImage, RgbaImage},
@@ -113,6 +114,7 @@ impl<'a> Iterator for ImageIterator<'a> {
 			height: img.image_descriptor.height,
 			left_offset: img.image_descriptor.left,
 			top_offset: img.image_descriptor.top,
+			packed: img.image_descriptor.packed,
 			palette,
 			indicies: &img.indicies,
 			blocks: &self.gif.blocks[starting_block..self.block_index],
@@ -125,6 +127,7 @@ pub struct Image<'a> {
 	pub height: u16,
 	pub left_offset: u16,
 	pub top_offset: u16,
+	pub packed: ImagePacked,
 	pub palette: &'a ColorTable,
 	pub indicies: &'a [u8],
 	pub blocks: &'a [Block],
diff --git a/gifed/src/reader/mod.rs b/gifed/src/reader/mod.rs
index 1b2e34a..68e15c4 100644
--- a/gifed/src/reader/mod.rs
+++ b/gifed/src/reader/mod.rs
@@ -135,7 +135,7 @@ impl GifReader {
 			.ok_or(DecodingError::UnexpectedEof)?;
 		let descriptor = ImageDescriptor::from(buffer);
 
-		let color_table = if descriptor.color_table_present() {
+		let color_table = if descriptor.has_color_table() {
 			let size = descriptor.color_table_size() * 3;
 			Some(Self::read_color_table(&mut reader, size)?)
 		} else {
diff --git a/gifed/src/writer/imagebuilder.rs b/gifed/src/writer/imagebuilder.rs
index f5c9e2b..c2ffd1a 100644
--- a/gifed/src/writer/imagebuilder.rs
+++ b/gifed/src/writer/imagebuilder.rs
@@ -1,6 +1,7 @@
 use crate::{
 	block::{
 		extension::{DisposalMethod, GraphicControl},
+		packed::ImagePacked,
 		ColorTable, ImageDescriptor, IndexedImage, Version,
 	},
 	EncodingError,
@@ -116,12 +117,11 @@ impl ImageBuilder {
 			top: self.top_offset,
 			width: self.width,
 			height: self.height,
-			packed: 0, // Set later
+			packed: ImagePacked { raw: 0 }, // Set later
 		};
 
 		if let Some(lct) = &self.color_table {
-			imgdesc.set_color_table_present(true);
-			imgdesc.set_color_table_size(lct.packed_len());
+			imgdesc.set_color_table_metadata(Some(lct));
 		}
 
 		Ok(IndexedImage {