1#![allow(clippy::while_let_loop)]
29
30use std::io::{self, BufRead, Cursor, Read, Seek, Write};
31use std::marker::PhantomData;
32use std::mem;
33
34use gif::ColorOutput;
35use gif::{DisposalMethod, Frame};
36
37use crate::animation::{self, Ratio};
38use crate::color::{ColorType, Rgba};
39use crate::error::LimitError;
40use crate::error::LimitErrorKind;
41use crate::error::{
42 DecodingError, EncodingError, ImageError, ImageResult, ParameterError, ParameterErrorKind,
43 UnsupportedError, UnsupportedErrorKind,
44};
45use crate::image::{AnimationDecoder, ImageDecoder, ImageFormat};
46use crate::traits::Pixel;
47use crate::ExtendedColorType;
48use crate::ImageBuffer;
49use crate::Limits;
50
51pub struct GifDecoder<R: Read> {
53 reader: gif::Decoder<R>,
54 limits: Limits,
55}
56
57impl<R: Read> GifDecoder<R> {
58 pub fn new(r: R) -> ImageResult<GifDecoder<R>> {
60 let mut decoder = gif::DecodeOptions::new();
61 decoder.set_color_output(ColorOutput::RGBA);
62
63 Ok(GifDecoder {
64 reader: decoder.read_info(r).map_err(ImageError::from_decoding)?,
65 limits: Limits::no_limits(),
66 })
67 }
68}
69
70#[allow(dead_code)]
72#[deprecated]
73pub struct GifReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
74#[allow(deprecated)]
75impl<R> Read for GifReader<R> {
76 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
77 self.0.read(buf)
78 }
79 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
80 if self.0.position() == 0 && buf.is_empty() {
81 mem::swap(buf, self.0.get_mut());
82 Ok(buf.len())
83 } else {
84 self.0.read_to_end(buf)
85 }
86 }
87}
88
89impl<R: BufRead + Seek> ImageDecoder for GifDecoder<R> {
90 fn dimensions(&self) -> (u32, u32) {
91 (
92 u32::from(self.reader.width()),
93 u32::from(self.reader.height()),
94 )
95 }
96
97 fn color_type(&self) -> ColorType {
98 ColorType::Rgba8
99 }
100
101 fn set_limits(&mut self, limits: Limits) -> ImageResult<()> {
102 limits.check_support(&crate::LimitSupport::default())?;
103
104 let (width, height) = self.dimensions();
105 limits.check_dimensions(width, height)?;
106
107 self.limits = limits;
108
109 Ok(())
110 }
111
112 fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> {
113 assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));
114
115 let frame = match self
116 .reader
117 .next_frame_info()
118 .map_err(ImageError::from_decoding)?
119 {
120 Some(frame) => FrameInfo::new_from_frame(frame),
121 None => {
122 return Err(ImageError::Parameter(ParameterError::from_kind(
123 ParameterErrorKind::NoMoreData,
124 )))
125 }
126 };
127
128 let (width, height) = self.dimensions();
129
130 if frame.left == 0
131 && frame.width == width
132 && (u64::from(frame.top) + u64::from(frame.height) <= u64::from(height))
133 {
134 let line_length = usize::try_from(width)
138 .unwrap()
139 .checked_mul(self.color_type().bytes_per_pixel() as usize)
140 .unwrap();
141
142 let (blank_top, rest) =
145 buf.split_at_mut(line_length.checked_mul(frame.top as usize).unwrap());
146 let (buf, blank_bottom) =
147 rest.split_at_mut(line_length.checked_mul(frame.height as usize).unwrap());
148
149 debug_assert_eq!(buf.len(), self.reader.buffer_size());
150
151 for b in blank_top {
153 *b = 0;
154 }
155 self.reader
157 .read_into_buffer(buf)
158 .map_err(ImageError::from_decoding)?;
159 for b in blank_bottom {
161 *b = 0;
162 }
163 } else {
164 let buffer_size = (frame.width as usize)
167 .checked_mul(frame.height as usize)
168 .and_then(|s| s.checked_mul(4))
169 .ok_or(ImageError::Limits(LimitError::from_kind(
170 LimitErrorKind::InsufficientMemory,
171 )))?;
172
173 self.limits.reserve_usize(buffer_size)?;
174 let mut frame_buffer = vec![0; buffer_size];
175 self.limits.free_usize(buffer_size);
176
177 self.reader
178 .read_into_buffer(&mut frame_buffer[..])
179 .map_err(ImageError::from_decoding)?;
180
181 let frame_buffer = ImageBuffer::from_raw(frame.width, frame.height, frame_buffer);
182 let image_buffer = ImageBuffer::from_raw(width, height, buf);
183
184 if frame_buffer.is_none() || image_buffer.is_none() {
188 return Err(ImageError::Unsupported(
189 UnsupportedError::from_format_and_kind(
190 ImageFormat::Gif.into(),
191 UnsupportedErrorKind::GenericFeature(format!(
192 "Image dimensions ({}, {}) are too large",
193 frame.width, frame.height
194 )),
195 ),
196 ));
197 }
198
199 let frame_buffer = frame_buffer.unwrap();
200 let mut image_buffer = image_buffer.unwrap();
201
202 for (x, y, pixel) in image_buffer.enumerate_pixels_mut() {
203 let frame_x = x.wrapping_sub(frame.left);
204 let frame_y = y.wrapping_sub(frame.top);
205
206 if frame_x < frame.width && frame_y < frame.height {
207 *pixel = *frame_buffer.get_pixel(frame_x, frame_y);
208 } else {
209 *pixel = Rgba([0, 0, 0, 0]);
211 }
212 }
213 }
214
215 Ok(())
216 }
217
218 fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()> {
219 (*self).read_image(buf)
220 }
221}
222
223struct GifFrameIterator<R: Read> {
224 reader: gif::Decoder<R>,
225
226 width: u32,
227 height: u32,
228
229 non_disposed_frame: Option<ImageBuffer<Rgba<u8>, Vec<u8>>>,
230 limits: Limits,
231}
232
233impl<R: BufRead + Seek> GifFrameIterator<R> {
234 fn new(decoder: GifDecoder<R>) -> GifFrameIterator<R> {
235 let (width, height) = decoder.dimensions();
236 let limits = decoder.limits.clone();
237
238 GifFrameIterator {
241 reader: decoder.reader,
242 width,
243 height,
244 non_disposed_frame: None,
245 limits,
246 }
247 }
248}
249
250impl<R: Read> Iterator for GifFrameIterator<R> {
251 type Item = ImageResult<animation::Frame>;
252
253 fn next(&mut self) -> Option<ImageResult<animation::Frame>> {
254 const COLOR_TYPE: ColorType = ColorType::Rgba8;
256
257 if self.non_disposed_frame.is_none() {
261 if let Err(e) = self
262 .limits
263 .reserve_buffer(self.width, self.height, COLOR_TYPE)
264 {
265 return Some(Err(e));
266 }
267 self.non_disposed_frame = Some(ImageBuffer::from_pixel(
268 self.width,
269 self.height,
270 Rgba([0, 0, 0, 0]),
271 ));
272 }
273 let non_disposed_frame = self.non_disposed_frame.as_mut().unwrap();
275
276 let frame = match self.reader.next_frame_info() {
279 Ok(frame_info) => {
280 if let Some(frame) = frame_info {
281 FrameInfo::new_from_frame(frame)
282 } else {
283 return None;
285 }
286 }
287 Err(err) => return Some(Err(ImageError::from_decoding(err))),
288 };
289
290 let mut local_limits = self.limits.clone();
295
296 if let Err(e) = local_limits.reserve_buffer(frame.width, frame.height, COLOR_TYPE) {
298 return Some(Err(e));
299 }
300 let mut vec = vec![0; self.reader.buffer_size()];
302 if let Err(err) = self.reader.read_into_buffer(&mut vec) {
303 return Some(Err(ImageError::from_decoding(err)));
304 }
305
306 let mut frame_buffer = match ImageBuffer::from_raw(frame.width, frame.height, vec) {
312 Some(frame_buffer) => frame_buffer,
313 None => {
314 return Some(Err(ImageError::Unsupported(
315 UnsupportedError::from_format_and_kind(
316 ImageFormat::Gif.into(),
317 UnsupportedErrorKind::GenericFeature(format!(
318 "Image dimensions ({}, {}) are too large",
319 frame.width, frame.height
320 )),
321 ),
322 )))
323 }
324 };
325
326 fn blend_and_dispose_pixel(
329 dispose: DisposalMethod,
330 previous: &mut Rgba<u8>,
331 current: &mut Rgba<u8>,
332 ) {
333 let pixel_alpha = current.channels()[3];
334 if pixel_alpha == 0 {
335 *current = *previous;
336 }
337
338 match dispose {
339 DisposalMethod::Any | DisposalMethod::Keep => {
340 *previous = *current;
345 }
346 DisposalMethod::Background => {
347 *previous = Rgba([0, 0, 0, 0]);
350 }
351 DisposalMethod::Previous => {
352 }
355 }
356 }
357
358 let image_buffer = if (frame.left, frame.top) == (0, 0)
362 && (self.width, self.height) == frame_buffer.dimensions()
363 {
364 for (x, y, pixel) in frame_buffer.enumerate_pixels_mut() {
365 let previous_pixel = non_disposed_frame.get_pixel_mut(x, y);
366 blend_and_dispose_pixel(frame.disposal_method, previous_pixel, pixel);
367 }
368 frame_buffer
369 } else {
370 if let Err(e) = local_limits.reserve_buffer(self.width, self.height, COLOR_TYPE) {
372 return Some(Err(e));
373 }
374 ImageBuffer::from_fn(self.width, self.height, |x, y| {
375 let frame_x = x.wrapping_sub(frame.left);
376 let frame_y = y.wrapping_sub(frame.top);
377 let previous_pixel = non_disposed_frame.get_pixel_mut(x, y);
378
379 if frame_x < frame_buffer.width() && frame_y < frame_buffer.height() {
380 let mut pixel = *frame_buffer.get_pixel(frame_x, frame_y);
381 blend_and_dispose_pixel(frame.disposal_method, previous_pixel, &mut pixel);
382 pixel
383 } else {
384 *previous_pixel
386 }
387 })
388 };
389
390 Some(Ok(animation::Frame::from_parts(
391 image_buffer,
392 0,
393 0,
394 frame.delay,
395 )))
396 }
397}
398
399impl<'a, R: BufRead + Seek + 'a> AnimationDecoder<'a> for GifDecoder<R> {
400 fn into_frames(self) -> animation::Frames<'a> {
401 animation::Frames::new(Box::new(GifFrameIterator::new(self)))
402 }
403}
404
405struct FrameInfo {
406 left: u32,
407 top: u32,
408 width: u32,
409 height: u32,
410 disposal_method: DisposalMethod,
411 delay: animation::Delay,
412}
413
414impl FrameInfo {
415 fn new_from_frame(frame: &Frame) -> FrameInfo {
416 FrameInfo {
417 left: u32::from(frame.left),
418 top: u32::from(frame.top),
419 width: u32::from(frame.width),
420 height: u32::from(frame.height),
421 disposal_method: frame.dispose,
422 delay: animation::Delay::from_ratio(Ratio::new(u32::from(frame.delay) * 10, 1)),
424 }
425 }
426}
427
428#[derive(Clone, Copy, Debug)]
430pub enum Repeat {
431 Finite(u16),
433 Infinite,
435}
436
437impl Repeat {
438 pub(crate) fn to_gif_enum(self) -> gif::Repeat {
439 match self {
440 Repeat::Finite(n) => gif::Repeat::Finite(n),
441 Repeat::Infinite => gif::Repeat::Infinite,
442 }
443 }
444}
445
446pub struct GifEncoder<W: Write> {
448 w: Option<W>,
449 gif_encoder: Option<gif::Encoder<W>>,
450 speed: i32,
451 repeat: Option<Repeat>,
452}
453
454impl<W: Write> GifEncoder<W> {
455 pub fn new(w: W) -> GifEncoder<W> {
457 Self::new_with_speed(w, 1)
458 }
459
460 pub fn new_with_speed(w: W, speed: i32) -> GifEncoder<W> {
464 assert!(
465 (1..=30).contains(&speed),
466 "speed needs to be in the range [1, 30]"
467 );
468 GifEncoder {
469 w: Some(w),
470 gif_encoder: None,
471 speed,
472 repeat: None,
473 }
474 }
475
476 pub fn set_repeat(&mut self, repeat: Repeat) -> ImageResult<()> {
478 if let Some(ref mut encoder) = self.gif_encoder {
479 encoder
480 .set_repeat(repeat.to_gif_enum())
481 .map_err(ImageError::from_encoding)?;
482 }
483 self.repeat = Some(repeat);
484 Ok(())
485 }
486
487 pub fn encode(
489 &mut self,
490 data: &[u8],
491 width: u32,
492 height: u32,
493 color: ExtendedColorType,
494 ) -> ImageResult<()> {
495 let (width, height) = self.gif_dimensions(width, height)?;
496 match color {
497 ExtendedColorType::Rgb8 => self.encode_gif(Frame::from_rgb(width, height, data)),
498 ExtendedColorType::Rgba8 => {
499 self.encode_gif(Frame::from_rgba(width, height, &mut data.to_owned()))
500 }
501 _ => Err(ImageError::Unsupported(
502 UnsupportedError::from_format_and_kind(
503 ImageFormat::Gif.into(),
504 UnsupportedErrorKind::Color(color),
505 ),
506 )),
507 }
508 }
509
510 pub fn encode_frame(&mut self, img_frame: animation::Frame) -> ImageResult<()> {
512 let frame = self.convert_frame(img_frame)?;
513 self.encode_gif(frame)
514 }
515
516 pub fn encode_frames<F>(&mut self, frames: F) -> ImageResult<()>
519 where
520 F: IntoIterator<Item = animation::Frame>,
521 {
522 for img_frame in frames {
523 self.encode_frame(img_frame)?;
524 }
525 Ok(())
526 }
527
528 pub fn try_encode_frames<F>(&mut self, frames: F) -> ImageResult<()>
532 where
533 F: IntoIterator<Item = ImageResult<animation::Frame>>,
534 {
535 for img_frame in frames {
536 self.encode_frame(img_frame?)?;
537 }
538 Ok(())
539 }
540
541 pub(crate) fn convert_frame(
542 &mut self,
543 img_frame: animation::Frame,
544 ) -> ImageResult<Frame<'static>> {
545 let frame_delay = img_frame.delay().into_ratio().to_integer();
547 let mut rbga_frame = img_frame.into_buffer();
549 let (width, height) = self.gif_dimensions(rbga_frame.width(), rbga_frame.height())?;
550
551 let mut frame = Frame::from_rgba_speed(width, height, &mut rbga_frame, self.speed);
553 frame.delay = (frame_delay / 10).try_into().unwrap_or(u16::MAX);
558
559 Ok(frame)
560 }
561
562 fn gif_dimensions(&self, width: u32, height: u32) -> ImageResult<(u16, u16)> {
563 fn inner_dimensions(width: u32, height: u32) -> Option<(u16, u16)> {
564 let width = u16::try_from(width).ok()?;
565 let height = u16::try_from(height).ok()?;
566 Some((width, height))
567 }
568
569 inner_dimensions(width, height).ok_or_else(|| {
571 ImageError::Parameter(ParameterError::from_kind(
572 ParameterErrorKind::DimensionMismatch,
573 ))
574 })
575 }
576
577 pub(crate) fn encode_gif(&mut self, mut frame: Frame) -> ImageResult<()> {
578 let gif_encoder;
579 if let Some(ref mut encoder) = self.gif_encoder {
580 gif_encoder = encoder;
581 } else {
582 let writer = self.w.take().unwrap();
583 let mut encoder = gif::Encoder::new(writer, frame.width, frame.height, &[])
584 .map_err(ImageError::from_encoding)?;
585 if let Some(ref repeat) = self.repeat {
586 encoder
587 .set_repeat(repeat.to_gif_enum())
588 .map_err(ImageError::from_encoding)?;
589 }
590 self.gif_encoder = Some(encoder);
591 gif_encoder = self.gif_encoder.as_mut().unwrap();
592 }
593
594 frame.dispose = DisposalMethod::Background;
595
596 gif_encoder
597 .write_frame(&frame)
598 .map_err(ImageError::from_encoding)
599 }
600}
601
602impl ImageError {
603 fn from_decoding(err: gif::DecodingError) -> ImageError {
604 use gif::DecodingError::*;
605 match err {
606 err @ Format(_) => {
607 ImageError::Decoding(DecodingError::new(ImageFormat::Gif.into(), err))
608 }
609 Io(io_err) => ImageError::IoError(io_err),
610 }
611 }
612
613 fn from_encoding(err: gif::EncodingError) -> ImageError {
614 use gif::EncodingError::*;
615 match err {
616 err @ Format(_) => {
617 ImageError::Encoding(EncodingError::new(ImageFormat::Gif.into(), err))
618 }
619 Io(io_err) => ImageError::IoError(io_err),
620 }
621 }
622}
623
624#[cfg(test)]
625mod test {
626 use super::*;
627
628 #[test]
629 fn frames_exceeding_logical_screen_size() {
630 let data = vec![
632 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x0A, 0x00, 0x0A, 0x00, 0xF0, 0x00, 0x00, 0x00,
633 0x00, 0x00, 0x0E, 0xFF, 0x1F, 0x21, 0xF9, 0x04, 0x09, 0x64, 0x00, 0x00, 0x00, 0x2C,
634 0x06, 0x00, 0x06, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x02, 0x23, 0x84, 0x8F, 0xA9,
635 0xBB, 0xE1, 0xE8, 0x42, 0x8A, 0x0F, 0x50, 0x79, 0xAE, 0xD1, 0xF9, 0x7A, 0xE8, 0x71,
636 0x5B, 0x48, 0x81, 0x64, 0xD5, 0x91, 0xCA, 0x89, 0x4D, 0x21, 0x63, 0x89, 0x4C, 0x09,
637 0x77, 0xF5, 0x6D, 0x14, 0x00, 0x3B,
638 ];
639
640 let decoder = GifDecoder::new(Cursor::new(data)).unwrap();
641 let mut buf = vec![0u8; decoder.total_bytes() as usize];
642
643 assert!(decoder.read_image(&mut buf).is_ok());
644 }
645}