Skip to content

Commit

Permalink
WIP on replacing gif stuff with gif / gif-dispose crates. Probably ne…
Browse files Browse the repository at this point in the history
…ed gifski due to animated+transparent re-encoding complexity. To solve #653
  • Loading branch information
lilith committed Dec 4, 2024
1 parent 0a4f30a commit 7dedd98
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 17 deletions.
16 changes: 14 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions imageflow_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ slotmap = "1"
base64 = "0.22"
hex = "0.4"
gif = "0.13.1"
gif-dispose = "5.0.1"
rgb = { version = "0.8", features = ["argb"] }
imagequant = "4"
lodepng = "3"
Expand Down
36 changes: 21 additions & 15 deletions imageflow_core/src/codecs/gif/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,49 @@ use crate::ffi::BitmapBgra;
use imageflow_types::collections::AddRemoveSet;
use crate::io::IoProxy;
use uuid::Uuid;
use imageflow_types::{IoDirection, PixelLayout};
use imageflow_types::{FrameSizeLimit, IoDirection, PixelLayout};
use super::*;
use std::any::Any;
mod disposal;
mod subimage;
mod screen;
mod bgra;
use self::bgra::BGRA8;
use self::screen::Screen;

use rgb::alt::BGRA8;
use gif_dispose::Screen;
use crate::gif::Frame;
use std::rc::Rc;
use lcms2_sys::cmsAllocProfileSequenceDescription;
use crate::io::IoProxyProxy;
use crate::io::IoProxyRef;
use crate::graphics::bitmaps::{BitmapKey, ColorSpace, BitmapCompositing};


pub struct GifDecoder{
reader: ::gif::Decoder<IoProxy>,
screen: Screen,
buffer: Option<Vec<u8>>,
last_frame: Option<Frame<'static>>,
next_frame: Option<Frame<'static>>
next_frame: Option<Frame<'static>>,
state: Option<gif_dispose::TempDisposedStateScreen<'static>>
}

impl GifDecoder {
pub fn create(c: &Context, io: IoProxy, io_id: i32) -> Result<GifDecoder> {

let max_pixels = c.security.max_frame_size.clone().or(Some(FrameSizeLimit{ w: 8000, h: 8000, megapixels: 16f32 })).unwrap().megapixels * 1000f32 * 1000f32;

let mut options = ::gif::Decoder::<IoProxy>::build();
options.allow_unknown_blocks(true);
options.set_memory_limit(::gif::MemoryLimit::Bytes(std::num::NonZeroU64::new(8000*8000).unwrap()));
options.set_memory_limit(::gif::MemoryLimit::Bytes(std::num::NonZeroU64::new(max_pixels as u64).unwrap()));
options.set_color_output(::gif::ColorOutput::Indexed); // Important


let reader = options.read_info(io)
.map_err(|e| FlowError::from(e).at(here!()))?;

let screen = Screen::new(&reader);
let screen = Screen::new_decoder(&reader);

Ok(GifDecoder{
reader,
screen,
state: None,
buffer: None,
last_frame: None,
next_frame: None
Expand All @@ -65,14 +66,13 @@ impl GifDecoder {
fn create_bitmap_from_screen(&self, c: &Context) -> Result<BitmapKey>{
// Create output bitmap and copy to it
unsafe {
let w = self.screen.width;
let h = self.screen.height;
let w = self.screen.width();
let h = self.screen.height();

let mut bitmaps = c.borrow_bitmaps_mut()
.map_err(|e| e.at(here!()))?;

let bitmap_key = bitmaps.create_bitmap_u8(w as u32,
h as u32,
let bitmap_key = bitmaps.create_bitmap_u8(w as u32, h as u32,
PixelLayout::BGRA,
false,
true,
Expand All @@ -89,8 +89,14 @@ impl GifDecoder {
let copy_mut = &mut copy;

for row in 0..h{
let row_bytes = bitmap.get_window_u8().unwrap().row_mut(row as u32).unwrap();

let row_pixels = bytemuck::cast_mut::<[u8],BGRA8>(row_bytes);
self.screen.
rgb
let to_row: &mut [BGRA8] = std::slice::from_raw_parts_mut(copy_mut.pixels.offset(copy_mut.stride as isize * row as isize) as *mut BGRA8, w as usize);
to_row.copy_from_slice(&self.screen.pixels[row * w..(row + 1) * w]);
self.screen.
to_row.copy_from_slice(&self.screen.pixels_rgba()[row * w..(row + 1) * w]);
}
Ok(bitmap_key)
}
Expand Down
10 changes: 10 additions & 0 deletions imageflow_core/tests/visuals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,16 @@ fn test_read_gif_eof() {
}


#[test]
fn test_read_animated_transparent_gif() {
let matched = compare(Some(IoTestEnum::Url("https://s3-us-west-2.amazonaws.com/imageflow-resources/test_inputs/transparent-animated.gif".to_owned())), 500,
"transparent-animated.gif", POPULATE_CHECKSUMS, DEBUG_GRAPH, vec![
Node::Decode {io_id: 0, commands: None}
]
);
assert!(matched);
}




Expand Down
1 change: 1 addition & 0 deletions imageflow_core/tests/visuals/checksums.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"test_rot_90_and_red_dot_command_string": "0C790C6600AFBBADA_0AE4839D1D9B04C57",
"test_round_corners_command_string": "05218274046A5989B_0BF80F0AE71CD9A63",
"test_webp_to_webp_quality": "0AFEF1F4539220FD1.webp",
"transparent-animated.gif": "0B4DF2CB7EDFEC674_0BF7B7FA413ED3B60",
"transparent_png_to_jpeg": "0DC709F50C5148224.jpg",
"transparent_png_to_jpeg_constrained": "0D6B7D34193494A6C.jpg",
"transparent_png_to_png": "0A839287BD1939BE8.png",
Expand Down

0 comments on commit 7dedd98

Please sign in to comment.