diff options
author | gennyble <gen@nyble.dev> | 2023-11-21 16:38:54 -0600 |
---|---|---|
committer | gennyble <gen@nyble.dev> | 2023-11-21 16:38:54 -0600 |
commit | fd8922dbb80095ec58bc5e4b78b10eeab7e23f43 (patch) | |
tree | abc95af050c622a1497b6adff84af5c10dc05613 | |
parent | 077e8385c9bb4bb0ac5dfe2279903d4dab11d063 (diff) | |
download | gifed-fd8922dbb80095ec58bc5e4b78b10eeab7e23f43.tar.gz gifed-fd8922dbb80095ec58bc5e4b78b10eeab7e23f43.zip |
api improvements
-rw-r--r-- | gifed/src/block/mod.rs | 18 | ||||
-rw-r--r-- | gifed/src/block/palette.rs | 9 | ||||
-rw-r--r-- | gifed/src/gif.rs | 32 | ||||
-rw-r--r-- | gifed/src/lib.rs | 4 | ||||
-rw-r--r-- | gifed/src/writer/mod.rs | 34 |
5 files changed, 70 insertions, 27 deletions
diff --git a/gifed/src/block/mod.rs b/gifed/src/block/mod.rs index 3a18a07..46738ed 100644 --- a/gifed/src/block/mod.rs +++ b/gifed/src/block/mod.rs @@ -102,3 +102,21 @@ fn encode_extension(block: &Block) -> Vec<u8> { vec } + +impl From<GraphicControl> for Block { + fn from(gce: GraphicControl) -> Self { + Block::GraphicControlExtension(gce) + } +} + +impl From<Application> for Block { + fn from(app: Application) -> Self { + Block::ApplicationExtension(app) + } +} + +impl From<LoopCount> for Block { + fn from(count: LoopCount) -> Self { + Block::LoopingExtension(count) + } +} diff --git a/gifed/src/block/palette.rs b/gifed/src/block/palette.rs index 8a06883..3cbcaaa 100644 --- a/gifed/src/block/palette.rs +++ b/gifed/src/block/palette.rs @@ -15,15 +15,8 @@ impl Palette { Self { table: vec![] } } - //FIXME: gen- Second paragraph is incorrect - /// Returns the number of colors in the color table as used by the packed - /// fields in the Logical Screen Descriptor and Image Descriptor. You can - /// get the actual size with the [`len`](struct.ColorTable.html#method.len) method. - /// - /// This value is equal to `log2([Palette::len]) - 1`. In other words, 2^(n + 1) will - /// give you the same value as [Palette::len]. (where `n` is the value returned) pub fn packed_len(&self) -> u8 { - ((self.table.len() as f32).log2().ceil() - 1f32) as u8 + crate::color_table_len_to_packed(self.len()) } pub fn lzw_code_size(&self) -> u8 { diff --git a/gifed/src/gif.rs b/gifed/src/gif.rs index 81aea28..5b1cfd7 100644 --- a/gifed/src/gif.rs +++ b/gifed/src/gif.rs @@ -1,9 +1,13 @@ use std::{fs::File, io::Write, path::Path, time::Duration}; -use crate::block::{ - encode_block, - extension::{DisposalMethod, GraphicControl}, - Block, CompressedImage, IndexedImage, Palette, ScreenDescriptor, Version, +use crate::{ + block::{ + encode_block, + extension::{DisposalMethod, GraphicControl}, + Block, CompressedImage, IndexedImage, Palette, ScreenDescriptor, Version, + }, + writer::EncodeBlock, + EncodeError, }; #[derive(Clone, Debug)] @@ -74,6 +78,26 @@ impl Gif { File::create(path.as_ref())?.write_all(&self.as_bytes()) } + pub fn push<I: Into<EncodeBlock>>(&mut self, image: I) { + match image.into() { + EncodeBlock::Block(block) => self.blocks.push(block), + EncodeBlock::CompressedImage(ci) => self.blocks.push(Block::CompressedImage(ci)), + EncodeBlock::IndexedImage(indexed) => { + let lzw_code_size = self.palette.as_ref().map(|p| p.lzw_code_size()); + + //TODO: remove unwrap + let compressed = indexed.compress(lzw_code_size).unwrap(); + self.blocks.push(Block::CompressedImage(compressed)); + } + EncodeBlock::BuiltImage(built) => { + if let Some(gce) = built.gce { + self.push(gce); + } + self.push(built.image) + } + } + } + /// An iterator over the discrete images in the gif. pub fn images(&self) -> ImageIterator<'_> { ImageIterator { diff --git a/gifed/src/lib.rs b/gifed/src/lib.rs index cfb124f..438ab79 100644 --- a/gifed/src/lib.rs +++ b/gifed/src/lib.rs @@ -19,6 +19,10 @@ pub(crate) fn packed_to_color_table_length(packed: u8) -> usize { 1 << (packed + 1) } +pub(crate) fn color_table_len_to_packed(len: usize) -> u8 { + ((len as f32).log2().ceil() - 1f32) as u8 +} + //TODO: Be sure to check that fields in LSD and Img. Desc. that were reserved //in 87a aren't set if version is 87a, or that we return a warning, etc. Just //remember about this. diff --git a/gifed/src/writer/mod.rs b/gifed/src/writer/mod.rs index e115ce8..661156d 100644 --- a/gifed/src/writer/mod.rs +++ b/gifed/src/writer/mod.rs @@ -58,24 +58,20 @@ impl<W: Write> Writer<W> { .map_err(|error| EncodeError::IoError { error }) } - pub fn block(&mut self, block: Block) -> Result<(), EncodeError> { - self.write_all(&encode_block(&block)) - } - pub fn repeat(&mut self, count: LoopCount) -> Result<(), EncodeError> { self.write_all(&encode_block(&Block::LoopingExtension(count))) } - pub fn image<I: Into<EncodeImage>>(&mut self, image: I) -> Result<(), EncodeError> { + pub fn push<I: Into<EncodeBlock>>(&mut self, image: I) -> Result<(), EncodeError> { match image.into() { - EncodeImage::CompressedImage(compressed) => self.write_all(&compressed.as_bytes()), - EncodeImage::IndexedImage(indexed) => { + EncodeBlock::CompressedImage(compressed) => self.write_all(&compressed.as_bytes()), + EncodeBlock::IndexedImage(indexed) => { let lzw_code_size = self.global_palette.as_ref().map(|p| p.lzw_code_size()); let compressed = indexed.compress(lzw_code_size)?; self.write_all(&compressed.as_bytes()) } - EncodeImage::BuiltImage(built) => { + EncodeBlock::BuiltImage(built) => { if let Some(gce) = built.gce { self.write_all(&encode_block(&Block::GraphicControlExtension(gce)))?; } @@ -85,6 +81,7 @@ impl<W: Write> Writer<W> { let compressed = built.image.compress(lzw_code_size)?; self.write_all(&compressed.as_bytes()) } + EncodeBlock::Block(block) => self.write_all(&encode_block(&block)), } } @@ -125,26 +122,33 @@ impl From<std::io::Error> for EncodeError { } } -pub enum EncodeImage { +pub enum EncodeBlock { CompressedImage(CompressedImage), IndexedImage(IndexedImage), BuiltImage(BuiltImage), + Block(Block), } -impl From<CompressedImage> for EncodeImage { +impl From<CompressedImage> for EncodeBlock { fn from(ci: CompressedImage) -> Self { - EncodeImage::CompressedImage(ci) + EncodeBlock::CompressedImage(ci) } } -impl From<IndexedImage> for EncodeImage { +impl From<IndexedImage> for EncodeBlock { fn from(ii: IndexedImage) -> Self { - EncodeImage::IndexedImage(ii) + EncodeBlock::IndexedImage(ii) } } -impl From<BuiltImage> for EncodeImage { +impl From<BuiltImage> for EncodeBlock { fn from(bi: BuiltImage) -> Self { - EncodeImage::BuiltImage(bi) + EncodeBlock::BuiltImage(bi) + } +} + +impl<T: Into<Block>> From<T> for EncodeBlock { + fn from(ib: T) -> Self { + EncodeBlock::Block(ib.into()) } } |