gif_dispose/
disposal.rs

1use gif::DisposalMethod;
2use imgref::{ImgRef, ImgRefMut};
3use rgb::RGBA8;
4
5enum SavedState {
6    Previous(Vec<RGBA8>),
7    Background,
8    Keep,
9}
10
11pub struct Disposal {
12    saved: SavedState,
13    left: u16, top: u16,
14    width: u16, height: u16,
15}
16
17impl Default for Disposal {
18    fn default() -> Self {
19        Disposal {
20           saved: SavedState::Keep,
21           top: 0, left: 0, width: 0, height: 0,
22       }
23   }
24}
25
26impl Disposal {
27    pub fn dispose(&self, mut pixels: ImgRefMut<'_, RGBA8>) {
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 = RGBA8::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
45    pub fn new(method: gif::DisposalMethod, left: u16, top: u16, width: u16, height: u16, pixels: ImgRef<'_, RGBA8>) -> 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}