diff options
author | Genevieve Alfirevic <gen@nyble.dev> | 2022-04-05 00:56:10 -0500 |
---|---|---|
committer | Genevieve Alfirevic <gen@nyble.dev> | 2022-04-05 00:56:10 -0500 |
commit | 8395c74a9706e5d180a917b633af57a3fe1ad400 (patch) | |
tree | 8e91ac111a6b73d40198c0f81a8c24ea8dcd542a | |
parent | 5e4c832053635b6900044b2c48771788856b5244 (diff) | |
download | gifed-8395c74a9706e5d180a917b633af57a3fe1ad400.tar.gz gifed-8395c74a9706e5d180a917b633af57a3fe1ad400.zip |
gifed: Add packed struct for image descriptor
-rw-r--r-- | gifed/examples/read.rs | 2 | ||||
-rw-r--r-- | gifed/src/block/colortable.rs | 10 | ||||
-rw-r--r-- | gifed/src/block/imagedescriptor.rs | 39 | ||||
-rw-r--r-- | gifed/src/block/packed.rs | 78 | ||||
-rw-r--r-- | gifed/src/color.rs | 6 | ||||
-rw-r--r-- | gifed/src/gif.rs | 3 | ||||
-rw-r--r-- | gifed/src/reader/mod.rs | 2 | ||||
-rw-r--r-- | gifed/src/writer/imagebuilder.rs | 6 |
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 { |