1 use gif::DisposalMethod;
2 use imgref::*;
3 use std::default::Default;
4 
5 enum SavedState<Pixel> {
6     Previous(Vec<Pixel>),
7     Background,
8     Keep,
9 }
10 
11 pub struct Disposal<Pixel> {
12     saved: SavedState<Pixel>,
13     left: u16, top: u16,
14     width: u16, height: u16,
15 }
16 
17 impl<Pixel: Copy + Default> Default for Disposal<Pixel> {
default() -> Self18     fn default() -> Self {
19         Disposal {
20            saved: SavedState::Keep,
21            top: 0, left: 0, width: 0, height: 0,
22        }
23    }
24 }
25 
26 impl<Pixel: Copy + Default> Disposal<Pixel> {
dispose(&self, mut pixels: ImgRefMut<'_, Pixel>)27     pub fn dispose(&self, mut pixels: ImgRefMut<'_, Pixel>) {
28         if self.width == 0 || self.height == 0 {
29             return;
30         }
31 
32         let mut dest = pixels.sub_image_mut(self.left.into(), self.top.into(), self.width.into(), self.height.into());
33         match &self.saved {
34             SavedState::Background => {
35                 let bg = Pixel::default();
36                 for px in dest.pixels_mut() { *px = bg; }
37             },
38             SavedState::Previous(saved) => {
39                 for (px, &src) in dest.pixels_mut().zip(saved.iter()) { *px = src; }
40             },
41             SavedState::Keep => {},
42         }
43     }
44 
new(method: gif::DisposalMethod, left: u16, top: u16, width: u16, height: u16, pixels: ImgRef<'_, Pixel>) -> Self45     pub fn new(method: gif::DisposalMethod, left: u16, top: u16, width: u16, height: u16, pixels: ImgRef<'_, Pixel>) -> Self {
46         Disposal {
47             saved: match method {
48                 DisposalMethod::Previous => SavedState::Previous(pixels.sub_image(left.into(), top.into(), width.into(), height.into()).pixels().collect()),
49                 DisposalMethod::Background => SavedState::Background,
50                 _ => SavedState::Keep,
51             },
52             left, top, width, height,
53         }
54     }
55 }
56