From fd8922dbb80095ec58bc5e4b78b10eeab7e23f43 Mon Sep 17 00:00:00 2001 From: gennyble Date: Tue, 21 Nov 2023 16:38:54 -0600 Subject: api improvements --- gifed/src/block/mod.rs | 18 ++++++++++++++++++ gifed/src/block/palette.rs | 9 +-------- gifed/src/gif.rs | 32 ++++++++++++++++++++++++++++---- gifed/src/lib.rs | 4 ++++ 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 { vec } + +impl From for Block { + fn from(gce: GraphicControl) -> Self { + Block::GraphicControlExtension(gce) + } +} + +impl From for Block { + fn from(app: Application) -> Self { + Block::ApplicationExtension(app) + } +} + +impl From 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>(&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 Writer { .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>(&mut self, image: I) -> Result<(), EncodeError> { + pub fn push>(&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 Writer { 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 for EncodeError { } } -pub enum EncodeImage { +pub enum EncodeBlock { CompressedImage(CompressedImage), IndexedImage(IndexedImage), BuiltImage(BuiltImage), + Block(Block), } -impl From for EncodeImage { +impl From for EncodeBlock { fn from(ci: CompressedImage) -> Self { - EncodeImage::CompressedImage(ci) + EncodeBlock::CompressedImage(ci) } } -impl From for EncodeImage { +impl From for EncodeBlock { fn from(ii: IndexedImage) -> Self { - EncodeImage::IndexedImage(ii) + EncodeBlock::IndexedImage(ii) } } -impl From for EncodeImage { +impl From for EncodeBlock { fn from(bi: BuiltImage) -> Self { - EncodeImage::BuiltImage(bi) + EncodeBlock::BuiltImage(bi) + } +} + +impl> From for EncodeBlock { + fn from(ib: T) -> Self { + EncodeBlock::Block(ib.into()) } } -- cgit 1.4.1-3-g733a5