diff options
author | Genevieve Alfirevic <gen@nyble.dev> | 2022-04-05 04:48:36 -0500 |
---|---|---|
committer | Genevieve Alfirevic <gen@nyble.dev> | 2022-04-05 04:48:36 -0500 |
commit | 6e12de4faa129ebe0f0e46ede46c1780bb23a315 (patch) | |
tree | 756a48b368300edaceff926951050e4aa3515765 | |
parent | 4849e9cd5dca472997b239a4dcd697a829196070 (diff) | |
download | gifed-6e12de4faa129ebe0f0e46ede46c1780bb23a315.tar.gz gifed-6e12de4faa129ebe0f0e46ede46c1780bb23a315.zip |
Add screenpacked abstraction over u8
-rw-r--r-- | gifed/src/block/extension/graphiccontrol.rs | 6 | ||||
-rw-r--r-- | gifed/src/block/packed.rs | 111 | ||||
-rw-r--r-- | gifed/src/block/screendescriptor.rs | 41 | ||||
-rw-r--r-- | gifed/src/reader/mod.rs | 2 | ||||
-rw-r--r-- | gifed/src/writer/gifbuilder.rs | 6 | ||||
-rw-r--r-- | gifprobe/src/main.rs | 2 |
6 files changed, 86 insertions, 82 deletions
diff --git a/gifed/src/block/extension/graphiccontrol.rs b/gifed/src/block/extension/graphiccontrol.rs index 04086a6..5806884 100644 --- a/gifed/src/block/extension/graphiccontrol.rs +++ b/gifed/src/block/extension/graphiccontrol.rs @@ -25,7 +25,7 @@ impl GraphicControl { ret.set_disposal_method(disposal_method); ret.packed.set_user_input(user_input_flag); - ret.packed.set_transparent_color(transparency_flag); + ret.packed.set_transparent_flag(transparency_flag); ret } @@ -61,7 +61,7 @@ impl GraphicControl { /// 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.packed.transparent_color() { + if self.packed.transparent_flag() { Some(self.transparency_index) } else { None @@ -77,7 +77,7 @@ impl GraphicControl { /// Sets the transparent index and flips the flag to indicate a transparent /// index is present if `index` is `Some`. pub fn set_transparent_index(&mut self, index: Option<u8>) { - self.packed.set_transparent_color(index.is_some()); + self.packed.set_transparent_flag(index.is_some()); if let Some(index) = index { self.transparency_index = index; diff --git a/gifed/src/block/packed.rs b/gifed/src/block/packed.rs index a80b807..f091fb3 100644 --- a/gifed/src/block/packed.rs +++ b/gifed/src/block/packed.rs @@ -9,35 +9,47 @@ impl GraphicPacked { } pub fn reserved(&self) -> u8 { - graphic_reserved(self.raw) + self.raw & 0b111_000_0_0 >> 5 } pub fn set_reserved(&mut self, reserved: u8) { - set_graphic_reserved(&mut self.raw, reserved) + // We care about the three least significant bits and we want to shift + // them so they're at the top, five away. From 000_001_1_1 to 111_000_0_0 + self.raw = (reserved & 0b0000_0111) << 5; } pub fn disposal_method(&self) -> u8 { - disposal_method(self.raw) + self.raw & 0b000_111_0_0 >> 2 } pub fn set_disposal_method(&mut self, disposal: u8) { - set_disposal_method(&mut self.raw, disposal) + // Care about 3 least significant bits and we want them three from the top + // from 000_001_1_1 into 000_111_0_0 + self.raw = (disposal & 0b0000_0111) << 2; } pub fn user_input(&self) -> bool { - user_input(self.raw) + self.raw & 0b000_000_1_0 > 0 } pub fn set_user_input(&mut self, flag: bool) { - set_user_input(&mut self.raw, flag) + if flag { + self.raw |= 0b000_000_1_0; + } else { + self.raw &= 0b111_111_0_1; + } } - pub fn transparent_color(&self) -> bool { - transparent_color(self.raw) + pub fn transparent_flag(&self) -> bool { + self.raw & 0b000_000_0_1 > 0 } - pub fn set_transparent_color(&mut self, flag: bool) { - set_transparent_flag(&mut self.raw, flag) + pub fn set_transparent_flag(&mut self, flag: bool) { + if flag { + self.raw |= 0b000_000_0_1; + } else { + self.raw &= 0b111_111_1_0; + } } } @@ -112,61 +124,56 @@ impl ImagePacked { self.raw & 0b0_0_0_00_111 } - pub fn set_color_table_size(&mut self, reserved: u8) { + pub fn set_color_table_size(&mut self, size: 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; + self.raw = size & 0b0_0_0_00_111; } } -#[inline] -fn graphic_reserved(packed: u8) -> u8 { - packed & 0b111_000_0_0 >> 5 +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct ScreenPacked { + pub raw: u8, } -#[inline] -fn disposal_method(packed: u8) -> u8 { - packed & 0b000_111_0_0 >> 2 -} +impl ScreenPacked { + pub fn color_table(&self) -> bool { + self.raw & 0b1_000_0_000 > 0 + } -#[inline] -fn user_input(packed: u8) -> bool { - packed & 0b000_000_1_0 > 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; + } + } -#[inline] -fn transparent_color(packed: u8) -> bool { - packed & 0b000_000_0_1 > 0 -} + pub fn color_resolution(&self) -> u8 { + (self.raw & 0b0_111_0_000) >> 4 + } -#[inline] -fn set_graphic_reserved(packed: &mut u8, reserved: u8) { - // We care about the three least significant bits and we want to shift - // them so they're at the top, five away. From 000_001_1_1 to 111_000_0_0 - *packed = (reserved & 0b0000_0111) << 5; -} + pub fn set_color_resolution(&mut self, resolution: u8) { + self.raw = (resolution & 0b0000_0111) << 4; + } -#[inline] -fn set_disposal_method(packed: &mut u8, disposal: u8) { - // Care about 3 least significant bits and we want them three from the top - // from 000_001_1_1 into 000_111_0_0 - *packed = (disposal & 0b0000_0111) << 2; -} + pub fn sorted(&self) -> bool { + self.raw & 0b0_000_1_000 > 0 + } -#[inline] -fn set_user_input(packed: &mut u8, flag: bool) { - if flag { - *packed |= 0b000_000_1_0; - } else { - *packed &= 0b111_111_0_1; + pub fn set_sorted(&mut self, flag: bool) { + if flag { + self.raw |= 0b0_000_1_000; + } else { + self.raw &= 0b1_111_0_111; + } + } + + pub fn color_table_size(&self) -> u8 { + self.raw & 0b0_0_0_00_111 } -} -#[inline] -fn set_transparent_flag(packed: &mut u8, flag: bool) { - if flag { - *packed |= 0b000_000_0_1; - } else { - *packed &= 0b111_111_1_0; + pub fn set_color_table_size(&mut self, size: u8) { + self.raw = size & 0b0_0_0_00_111; } } diff --git a/gifed/src/block/screendescriptor.rs b/gifed/src/block/screendescriptor.rs index dc0257d..6b318b5 100644 --- a/gifed/src/block/screendescriptor.rs +++ b/gifed/src/block/screendescriptor.rs @@ -1,9 +1,11 @@ use std::convert::TryInto; +use super::{packed::ScreenPacked, ColorTable}; + pub struct ScreenDescriptor { pub width: u16, pub height: u16, - pub packed: u8, + pub packed: ScreenPacked, pub background_color_index: u8, pub pixel_aspect_ratio: u8, } @@ -13,37 +15,32 @@ impl ScreenDescriptor { Self { width, height, - packed: 0, + packed: ScreenPacked { raw: 0 }, background_color_index: 0, pixel_aspect_ratio: 0, } } - 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) { - println!("scts: {}", size); - // 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 color resolution 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_len(&self) -> usize { - crate::packed_to_color_table_length(self.packed & 0b0000_0111) + crate::packed_to_color_table_length(self.packed.color_table_size()) } } @@ -52,7 +49,7 @@ impl From<&ScreenDescriptor> for Box<[u8]> { let mut vec = vec![]; vec.extend_from_slice(&lsd.width.to_le_bytes()); vec.extend_from_slice(&lsd.height.to_le_bytes()); - vec.push(lsd.packed); + vec.push(lsd.packed.raw); vec.push(lsd.background_color_index); vec.push(lsd.pixel_aspect_ratio); @@ -71,7 +68,7 @@ impl From<[u8; 7]> for ScreenDescriptor { Self { width, height, - packed, + packed: ScreenPacked { raw: packed }, background_color_index, pixel_aspect_ratio, } diff --git a/gifed/src/reader/mod.rs b/gifed/src/reader/mod.rs index 68e15c4..e852d26 100644 --- a/gifed/src/reader/mod.rs +++ b/gifed/src/reader/mod.rs @@ -30,7 +30,7 @@ impl GifReader { let mut gif = Self::read_required(&mut reader)?; - if gif.screen_descriptor.color_table_present() { + if gif.screen_descriptor.has_color_table() { let gct_size = gif.screen_descriptor.color_table_len() * 3; gif.global_color_table = Some(Self::read_color_table(&mut reader, gct_size)?); } diff --git a/gifed/src/writer/gifbuilder.rs b/gifed/src/writer/gifbuilder.rs index 337e404..2141fc7 100644 --- a/gifed/src/writer/gifbuilder.rs +++ b/gifed/src/writer/gifbuilder.rs @@ -1,5 +1,6 @@ use std::convert::TryInto; +use crate::block::packed::ScreenPacked; use crate::block::{Block, ColorTable, LoopCount, ScreenDescriptor, Version}; use crate::writer::ImageBuilder; use crate::{EncodingError, Gif}; @@ -84,15 +85,14 @@ impl GifBuilder { let mut lsd = ScreenDescriptor { width: self.width, height: self.height, - packed: 0, // Set later + packed: ScreenPacked { raw: 0 }, // Set later background_color_index: self.background_color_index, pixel_aspect_ratio: 0, //TODO: Allow configuring }; if let Some(gct) = &self.global_color_table { println!("build {}", gct.len()); - lsd.set_color_table_present(true); - lsd.set_color_table_size((gct.len() - 1) as u8); + lsd.set_color_table_metadata(Some(gct)); } Ok(Gif { diff --git a/gifprobe/src/main.rs b/gifprobe/src/main.rs index c6bc0f8..241c421 100644 --- a/gifprobe/src/main.rs +++ b/gifprobe/src/main.rs @@ -24,7 +24,7 @@ fn main() { gif.screen_descriptor.height.yellow() ); - if gif.screen_descriptor.color_table_present() { + if gif.screen_descriptor.has_color_table() { println!( "\tGlobal Color Table Present {}\n\tGlobal Color Table Size {}", "Yes".green(), |