about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gifed/Cargo.toml2
-rw-r--r--gifed/src/block/extension/application.rs4
-rw-r--r--gifed/src/block/extension/graphiccontrol.rs84
-rw-r--r--gifed/src/block/indexedimage.rs2
-rw-r--r--gifed/src/block/mod.rs3
-rw-r--r--gifed/src/colorimage.rs2
-rw-r--r--gifed/src/gif.rs39
-rw-r--r--gifed/src/lzw.rs5
-rw-r--r--gifed/src/reader/mod.rs2
-rw-r--r--gifprobe/Cargo.toml2
-rw-r--r--gifprobe/src/main.rs6
11 files changed, 94 insertions, 57 deletions
diff --git a/gifed/Cargo.toml b/gifed/Cargo.toml
index 08974f5..bf02547 100644
--- a/gifed/Cargo.toml
+++ b/gifed/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "gifed"
 version = "0.1.0"
-authors = ["Genevive Alfirevic <gen@nyble.dev>"]
+authors = ["Genevive <gen@nyble.dev>"]
 edition = "2018"
 license = "CC0-1.0"
 description = "Gif encoding and decoding with fine control"
diff --git a/gifed/src/block/extension/application.rs b/gifed/src/block/extension/application.rs
index 9ec1814..3d46277 100644
--- a/gifed/src/block/extension/application.rs
+++ b/gifed/src/block/extension/application.rs
@@ -1,11 +1,11 @@
 pub struct Application {
-	pub(crate) identifier: String, // max len 8
+	pub(crate) identifier: [u8; 8],
 	pub(crate) authentication_code: [u8; 3],
 	pub(crate) data: Vec<u8>,
 }
 
 impl Application {
-	pub fn identifier(&self) -> &str {
+	pub fn identifier(&self) -> &[u8] {
 		&self.identifier
 	}
 
diff --git a/gifed/src/block/extension/graphiccontrol.rs b/gifed/src/block/extension/graphiccontrol.rs
index 8b62160..a6abbdc 100644
--- a/gifed/src/block/extension/graphiccontrol.rs
+++ b/gifed/src/block/extension/graphiccontrol.rs
@@ -1,9 +1,9 @@
-use std::{convert::TryInto, fmt};
+use std::{convert::TryInto, fmt, time::Duration};
 
 #[derive(Clone, Debug)]
 pub struct GraphicControl {
 	pub(crate) packed: u8,
-	pub(crate) delay_time: u16,
+	pub(crate) delay: u16,
 	pub(crate) transparency_index: u8,
 }
 
@@ -12,22 +12,27 @@ impl GraphicControl {
 		disposal_method: DisposalMethod,
 		user_input_flag: bool,
 		transparency_flag: bool,
-		delay_time: u16,
+		delay: u16,
 		transparency_index: u8,
 	) -> Self {
 		let mut ret = Self {
 			packed: 0,
-			delay_time,
+			delay,
 			transparency_index,
 		};
 
 		ret.set_disposal_method(disposal_method);
 		ret.set_user_input(user_input_flag);
-		ret.transparency(transparency_flag);
+		ret.set_transparent(transparency_flag);
 
 		ret
 	}
 
+	/// Get the disposal method that should be used for the associated image.
+	///
+	/// # Returns
+	/// This method will return `Some([DisposalMethod])` if the disposal method
+	/// is recognized, or None if it was set to a reserved value.
 	pub fn disposal_method(&self) -> Option<DisposalMethod> {
 		match self.packed & 0b000_111_00 {
 			0b000_000_00 => Some(DisposalMethod::NoAction),
@@ -38,6 +43,7 @@ impl GraphicControl {
 		}
 	}
 
+	/// Set the disposal method that shoudl be used for the associated image.
 	pub fn set_disposal_method(&mut self, method: DisposalMethod) {
 		match method {
 			DisposalMethod::NoAction => self.packed &= 0b111_000_1_1,
@@ -47,10 +53,48 @@ impl GraphicControl {
 		};
 	}
 
-	pub fn transparency_index(&self) -> u8 {
+	/// Returns the index that should be replaced by a fully transparent pixel
+	/// if the transparency flag is set, or None if it's not set.
+	pub fn transparent_index(&self) -> Option<u8> {
+		if self.transparent() {
+			Some(self.transparency_index)
+		} else {
+			None
+		}
+	}
+
+	/// Returns the transparency index regardless if the transparency flag is set.
+	/// You probably want [GraphicControl::transparency_index] instead.s
+	pub fn transparent_index_unchecked(&self) -> u8 {
 		self.transparency_index
 	}
 
+	/// Sets the transparent index flag to the value provided. This will change
+	/// the index value in any way and should be used with caution. You probably
+	/// want [GraphicControl::set_transparent_index] instead.
+	pub fn set_transparent(&mut self, flag: bool) {
+		if flag {
+			self.packed |= 0b000_000_0_1;
+		} else {
+			self.packed &= 0b111_111_1_0;
+		}
+	}
+
+	/// Sets the transparent index and flips the flag to indicate a transparent
+	/// index is present.
+	pub fn set_transparent_index(&mut self, index: Option<u8>) {
+		self.set_transparent(index.is_some());
+
+		if let Some(index) = index {
+			self.transparency_index = index;
+		}
+	}
+
+	/// Get the value of the transparency flag
+	pub fn transparent(&self) -> bool {
+		self.packed & 0b000_000_0_1 > 0
+	}
+
 	pub fn user_input(&self) -> bool {
 		self.packed & 0b000_000_1_0 > 0
 	}
@@ -63,36 +107,36 @@ impl GraphicControl {
 		}
 	}
 
-	pub fn transparency(&mut self, flag: bool) {
-		if flag {
-			self.packed |= 0b000_000_0_1;
-		} else {
-			self.packed &= 0b111_111_1_0;
-		}
+	pub fn delay(&self) -> u16 {
+		self.delay
 	}
 
-	pub fn delay_time(&self) -> u16 {
-		self.delay_time
+	pub fn delay_duration(&self) -> Duration {
+		Duration::from_millis(self.delay as u64 * 10)
 	}
 
-	pub fn delay_time_mut(&mut self) -> &mut u16 {
-		&mut self.delay_time
+	pub fn delay_mut(&mut self) -> &mut u16 {
+		&mut self.delay
 	}
 
-	pub fn is_transparent(&self) -> bool {
-		self.packed & 0b000_000_0_1 > 0
+	pub fn packed(&self) -> u8 {
+		self.packed
+	}
+
+	pub fn packed_mut(&mut self) -> &mut u8 {
+		&mut self.packed
 	}
 }
 
 impl From<[u8; 4]> for GraphicControl {
 	fn from(arr: [u8; 4]) -> Self {
 		let packed = arr[0];
-		let delay_time = u16::from_le_bytes(arr[1..3].try_into().unwrap());
+		let delay = u16::from_le_bytes(arr[1..3].try_into().unwrap());
 		let transparency_index = arr[3];
 
 		Self {
 			packed,
-			delay_time,
+			delay,
 			transparency_index,
 		}
 	}
diff --git a/gifed/src/block/indexedimage.rs b/gifed/src/block/indexedimage.rs
index 8ed0319..8834d33 100644
--- a/gifed/src/block/indexedimage.rs
+++ b/gifed/src/block/indexedimage.rs
@@ -37,7 +37,7 @@ impl IndexedImage {
 			boxed = lct.into();
 			out.extend_from_slice(&*boxed);
 
-			lct.packed_len()
+			lct.packed_len() + 1
 		} else {
 			minimum_code_size + 1
 		};
diff --git a/gifed/src/block/mod.rs b/gifed/src/block/mod.rs
index a101600..623b346 100644
--- a/gifed/src/block/mod.rs
+++ b/gifed/src/block/mod.rs
@@ -2,6 +2,7 @@ mod colortable;
 pub mod extension;
 mod imagedescriptor;
 mod indexedimage;
+pub mod packed;
 mod screendescriptor;
 mod version;
 
@@ -57,7 +58,7 @@ fn encode_extension(block: &Block) -> Box<[u8]> {
 			vec.push(0xF9); // Graphic control label
 			vec.push(0x04); // Block size for this extension is always 4
 			vec.push(gce.packed);
-			vec.extend_from_slice(&gce.delay_time.to_le_bytes());
+			vec.extend_from_slice(&gce.delay.to_le_bytes());
 			vec.push(gce.transparency_index);
 		}
 		Block::CommentExtension(comment) => todo!(),
diff --git a/gifed/src/colorimage.rs b/gifed/src/colorimage.rs
index 69dac1e..93314ff 100644
--- a/gifed/src/colorimage.rs
+++ b/gifed/src/colorimage.rs
@@ -49,7 +49,7 @@ impl<'a> TryFrom<Image<'a>> for ColorImage {
 			img.height,
 			img.indicies,
 			img.palette,
-			img.transparent_index,
+			img.trans_index(),
 		)
 	}
 }
diff --git a/gifed/src/gif.rs b/gifed/src/gif.rs
index 5f1bd7a..e8d6150 100644
--- a/gifed/src/gif.rs
+++ b/gifed/src/gif.rs
@@ -71,18 +71,14 @@ impl<'a> Iterator for ImageIterator<'a> {
 	type Item = Image<'a>;
 
 	fn next(&mut self) -> Option<Self::Item> {
-		let mut transparent = None;
+		let mut graphic_control = None;
 
 		let img = loop {
 			match self.veciter.next() {
 				Some(block) => match block {
 					Block::IndexedImage(img) => break img,
 					Block::GraphicControlExtension(gce) => {
-						if gce.is_transparent() {
-							transparent = Some(gce.transparency_index());
-						} else {
-							transparent = None;
-						}
+						graphic_control = Some(gce.clone());
 					}
 					_ => (),
 				},
@@ -97,8 +93,8 @@ impl<'a> Iterator for ImageIterator<'a> {
 				left_offset: img.image_descriptor.left,
 				top_offset: img.image_descriptor.top,
 				palette: &img.local_color_table.as_ref().unwrap(),
-				transparent_index: transparent,
 				indicies: &img.indicies,
+				graphic_control,
 			})
 		} else {
 			Some(Image {
@@ -107,8 +103,8 @@ impl<'a> Iterator for ImageIterator<'a> {
 				left_offset: img.image_descriptor.left,
 				top_offset: img.image_descriptor.top,
 				palette: self.gif.global_color_table.as_ref().unwrap(),
-				transparent_index: transparent,
 				indicies: &img.indicies,
+				graphic_control,
 			})
 		}
 	}
@@ -120,8 +116,8 @@ pub struct Image<'a> {
 	pub left_offset: u16,
 	pub top_offset: u16,
 	pub palette: &'a ColorTable,
-	pub transparent_index: Option<u8>,
 	pub indicies: &'a [u8],
+	pub graphic_control: Option<GraphicControl>,
 }
 
 impl<'a> Image<'a> {
@@ -129,7 +125,7 @@ impl<'a> Image<'a> {
 		let mut rgba = vec![0; self.indicies.len() * 4];
 
 		for (image_index, &color_index) in self.indicies.iter().enumerate() {
-			match self.transparent_index {
+			match self.trans_index() {
 				Some(trans) if trans == color_index => {
 					rgba[image_index as usize * 4] = 0;
 					rgba[image_index * 4 + 1] = 0;
@@ -156,7 +152,7 @@ impl<'a> Image<'a> {
 		let mut rgb = vec![0; self.indicies.len() * 3];
 
 		for (image_index, &color_index) in self.indicies.iter().enumerate() {
-			match self.transparent_index {
+			match self.trans_index() {
 				Some(trans) if trans == color_index => {
 					rgb[image_index as usize * 4] = transparent_replace.r;
 					rgb[image_index * 3 + 1] = transparent_replace.g;
@@ -176,22 +172,13 @@ impl<'a> Image<'a> {
 
 		Some(rgb)
 	}
-}
-
-pub struct FrameIterator<'a> {
-	gif: &'a Gif,
-	veciter: std::slice::Iter<'a, Block>,
-	buffer: Vec<u8>,
-}
 
-pub struct Frame {
-	pub width: u16,
-	pub height: u16,
-	pub palette: ColorTable,
-	pub transparent_index: Option<u8>,
-	pub indicies: Vec<u8>,
-	pub delay_after_draw: u16,
-	pub user_input_flag: bool,
+	pub fn trans_index(&self) -> Option<u8> {
+		self.graphic_control
+			.as_ref()
+			.map(|gce| gce.transparent_index())
+			.flatten()
+	}
 }
 
 #[cfg(test)]
diff --git a/gifed/src/lzw.rs b/gifed/src/lzw.rs
index dce6a5d..9fdfcdd 100644
--- a/gifed/src/lzw.rs
+++ b/gifed/src/lzw.rs
@@ -8,6 +8,8 @@ impl LZW {
 		let cc = 2u16.pow(minimum_size as u32);
 		let eoi = cc + 1;
 
+		println!("mcs {} | cc {}", minimum_size, cc);
+
 		// Fill dictionary with self-descriptive values
 		for value in 0..cc {
 			dictionary.insert(vec![value as u8], value);
@@ -44,6 +46,9 @@ impl LZW {
 					buffer.clear();
 					buffer.push(indicie);
 				} else {
+					println!("indicie is: {}", indicie);
+					println!("buffer is: {:?}", buffer);
+					println!("dictionary: {:?}", dictionary);
 					unreachable!()
 				}
 			}
diff --git a/gifed/src/reader/mod.rs b/gifed/src/reader/mod.rs
index 966ebde..1b2e34a 100644
--- a/gifed/src/reader/mod.rs
+++ b/gifed/src/reader/mod.rs
@@ -113,7 +113,7 @@ impl GifReader {
 			0xFF => {
 				//TODO: error instead of unwraps
 				assert_eq!(Some(11), reader.u8());
-				let identifier = reader.take_lossy_utf8(8).unwrap().to_string();
+				let identifier = TryInto::try_into(reader.take(8).unwrap()).unwrap();
 				let authentication_code: [u8; 3] =
 					TryInto::try_into(reader.take(3).unwrap()).unwrap();
 				let data = reader.take_and_collapse_subblocks();
diff --git a/gifprobe/Cargo.toml b/gifprobe/Cargo.toml
index 75047b8..96e76a5 100644
--- a/gifprobe/Cargo.toml
+++ b/gifprobe/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "gifprobe"
 version = "0.1.0"
-authors = ["Genevive Alfirevic <gen@nyble.dev"]
+authors = ["Genevive <gen@nyble.dev"]
 edition = "2018"
 license = "CC0-1.0"
 description = "Print the details of a gif to stdout; ffprobe for gif"
diff --git a/gifprobe/src/main.rs b/gifprobe/src/main.rs
index 35a137f..a8e3cfd 100644
--- a/gifprobe/src/main.rs
+++ b/gifprobe/src/main.rs
@@ -49,11 +49,11 @@ fn main() {
 				img_count += 1;
 			}
 			Block::GraphicControlExtension(gce) => {
-				hundreths += gce.delay_time() as usize;
+				hundreths += gce.delay() as usize;
 
 				println!(
 					"Graphic Control Extension\n\tDelay Time {}\n\tDispose {}",
-					format!("{}s", gce.delay_time() as f32 / 100.0).yellow(),
+					format!("{}s", gce.delay() as f32 / 100.0).yellow(),
 					gce.disposal_method().unwrap().yellow()
 				)
 			}
@@ -65,7 +65,7 @@ fn main() {
 				let auth = app.authentication_code();
 				println!(
 					"Application Extension\n\tIdentifier {}\n\tAuthentication {:02X} {:02X} {:02X}",
-					app.identifier().yellow(),
+					String::from_utf8_lossy(app.identifier()).yellow(),
 					auth[0].yellow(),
 					auth[1].yellow(),
 					auth[2].yellow()