Skip to content

Commit 793c34e

Browse files
committed
Fix gif encoder to handle stride padding
1 parent 8f3d6d7 commit 793c34e

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

imageflow_core/src/codecs/gif.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,14 @@ impl Encoder for GifEncoder{
132132
pix[0] = pix[2];
133133
pix[2] = a;
134134
}
135-
f = ::gif::Frame::from_rgb(frame.w as u16, frame.h as u16, &mut pixels);
135+
f = from_rgb_with_stride(frame.w as u16, frame.h as u16, &mut pixels, frame.stride as usize);
136136
}else {
137137
for pix in pixels.chunks_mut(4) {
138138
let a = pix[0];
139139
pix[0] = pix[2];
140140
pix[2] = a;
141141
}
142-
f = ::gif::Frame::from_rgba(frame.w as u16, frame.h as u16, &mut pixels);
142+
f = from_rgba_with_stride(frame.w as u16, frame.h as u16, &mut pixels, frame.stride as usize);
143143
}
144144

145145
let mut encoder = ::gif::Encoder::new(io, frame.w as u16, frame.h as u16, &[]).unwrap();
@@ -159,3 +159,22 @@ impl Encoder for GifEncoder{
159159
}
160160
}
161161

162+
163+
fn remove_padding(width: u16, pixels: &[u8], stride: usize) -> Vec<u8>{
164+
pixels.chunks(stride).flat_map(|s| s[0..width as usize * 4].iter().map(|v| *v)).collect()
165+
}
166+
/// Creates a frame from pixels in RGBA format.
167+
///
168+
/// *Note: This method is not optimized for speed.*
169+
pub fn from_rgba_with_stride(width: u16, height: u16, pixels: &mut [u8], stride: usize) -> ::gif::Frame<'static> {
170+
let mut without_padding = remove_padding(width, pixels, stride);
171+
::gif::Frame::from_rgba(width, height, &mut without_padding)
172+
}
173+
174+
/// Creates a frame from pixels in RGB format.
175+
///
176+
/// *Note: This method is not optimized for speed.*
177+
pub fn from_rgb_with_stride(width: u16, height: u16, pixels: &[u8], stride: usize) -> ::gif::Frame<'static> {
178+
let mut without_padding = remove_padding(width, pixels, stride);
179+
::gif::Frame::from_rgb(width, height, &mut without_padding)
180+
}

imageflow_core/tests/visuals.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,41 @@ fn test_jpeg_rotation() {
285285
}
286286

287287
}
288+
//
289+
//#[test]
290+
//fn test_gif_ir4(){
291+
// let matched = compare(Some(s::IoEnum::Url("https://s3-us-west-2.amazonaws.com/imageflow-resources/test_inputs/waterhouse.jpg".to_owned())), 500,
292+
// "Read".to_owned(), true, DEBUG_GRAPH, vec![
293+
// s::Node::CommandString{
294+
// kind: s::CommandStringKind::ImageResizer4,
295+
// value: "width=200&height=200&format=gif".to_owned(),
296+
// decode: Some(0),
297+
// encode: None //Some(1)
298+
// }
299+
// ]
300+
// );
301+
// assert!(matched);
302+
//
303+
//}
304+
305+
#[test]
306+
fn smoke_test_gif_ir4(){
307+
308+
let steps = vec![
309+
s::Node::CommandString{
310+
kind: s::CommandStringKind::ImageResizer4,
311+
value: "width=200&height=200&format=gif".to_owned(),
312+
decode: Some(0),
313+
encode: Some(1)
314+
}
315+
];
316+
317+
smoke_test(Some(s::IoEnum::Url("https://s3-us-west-2.amazonaws.com/imageflow-resources/test_inputs/waterhouse.jpg".to_owned())),
318+
Some(s::IoEnum::OutputBuffer),
319+
DEBUG_GRAPH,
320+
steps,
321+
);
322+
}
288323

289324

290325
#[test]

0 commit comments

Comments
 (0)