about summary refs log tree commit diff
path: root/src/components/gif.rs
blob: 2709fe86f959962ed25ed5b932dc4693400fcb4e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use super::{ColorTable, Image, LogicalScreenDescriptor, Version};

pub struct Gif {
	pub header: Version,
	pub logical_screen_descriptor: LogicalScreenDescriptor,
	pub global_color_table: Option<ColorTable>,
	pub images: Vec<Image>
	// Trailer at the end of this struct is 0x3B //
}

impl Gif {
	pub fn to_vec(&self) -> Vec<u8> {
		let mut out = vec![];

		out.extend_from_slice((&self.header).into());
		
		let mut boxed: Box<[u8]> = (&self.logical_screen_descriptor).into();
		out.extend_from_slice(&*boxed);

		// While we output the color table, grab it's length to use when
		// outputting the image, or 0 if we don't have a GCT
		let mcs = if let Some(gct) = &self.global_color_table {
			boxed = gct.into();
			out.extend_from_slice(&*boxed);

			gct.packed_len()
		} else {
			0
		};

		for image in self.images.iter() {
			boxed = image.as_boxed_slice(mcs);
			out.extend_from_slice(&*boxed);
		}

		// Write Trailer
		out.push(0x3B);

		out
	}
}

#[cfg(test)]
pub mod gif {
	use crate::Color;
	use crate::writer::{GifBuilder, ImageBuilder};
	use super::*;

	#[test]
	fn to_vec() {
		let gct = vec![
			Color::new(1, 2, 3), Color::new(253, 254, 255)
		];
		let colortable = vec![
			Color::new(0, 0, 0), Color::new(128, 0, 255)
		];
		let indicies = vec![0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0];

		let expected_out = vec![
			0x47, 0x49, 0x46, 0x38, 0x37, 0x61, // Version - GIF87a
			0x04, 0x00, 0x04, 0x00, 0b1000_0000, 0x00, 0x00, // Logical Screen Descriptor
			1, 2, 3, 253, 254, 255, // Global Color Table
			0x2C, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0b1000_0000, // Image Descriptor 1
			0, 0, 0, 128, 0, 255, // Color Table
			0x02, 0x05, 0x84, 0x1D, 0x81, 0x7A, 0x50, 0x00, // Image Data 1
			0x2C, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0b0000_0000, // Image Descriptor 2
			0x02, 0x05, 0x84, 0x1D, 0x81, 0x7A, 0x50, 0x00, // Image Data 2
			0x3B // Trailer
		];

		let actual_out = GifBuilder::new(Version::Gif87a, 4, 4)
			.global_color_table(gct.into())
			.image(ImageBuilder::new(4, 4)
				.color_table(colortable.into())
				.indicies(indicies.clone())
			).image(ImageBuilder::new(4, 4)
				.indicies(indicies)
			).build().to_vec();

		assert_eq!(actual_out, expected_out);
	}
}