aseprite_loader/binary/
file.rs1use itertools::Itertools;
2
3use super::{
4 chunk::Chunk,
5 chunks::{cel::CelChunk, layer::LayerChunk, slice::SliceChunk, tags::Tag},
6 color_depth::ColorDepth,
7 errors::ParseError,
8 frame::Frame,
9 header::Header,
10 palette::{create_palette, Palette},
11 raw_file::parse_raw_file,
12 scalars::Word,
13};
14
15#[derive(Debug)]
16pub struct File<'a> {
17 pub header: Header,
18 pub palette: Option<Palette>,
19 pub layers: Vec<LayerChunk<'a>>,
20 pub frames: Vec<Frame<'a>>,
21 pub tags: Vec<Tag<'a>>,
22 pub slices: Vec<SliceChunk<'a>>,
23}
24
25pub fn parse_file(input: &[u8]) -> Result<File<'_>, nom::Err<ParseError<'_>>> {
26 let raw_file = parse_raw_file(input)?;
27 let palette = match raw_file.header.color_depth {
28 ColorDepth::Indexed => Some(
29 create_palette(&raw_file.header, &raw_file.frames)
30 .map_err(|e| nom::Err::Failure(ParseError::PaletteError(e)))?,
31 ),
32 _ => None,
33 };
34 let mut frames = Vec::<(Word, Vec<CelChunk<'_>>)>::new();
35 let mut layers = Vec::<LayerChunk<'_>>::new();
36 let mut tags = Vec::<Tag<'_>>::new();
37 let mut slices = Vec::<SliceChunk<'_>>::new();
38 for raw_frame in raw_file.frames {
39 let mut cels = Vec::<CelChunk<'_>>::new();
40 for chunk in raw_frame.chunks {
41 match chunk {
42 Chunk::Palette0004(_) => {}
43 Chunk::Palette0011(_) => {}
44 Chunk::Layer(layer) => layers.push(layer),
45 Chunk::Cel(cel) => cels.push(cel),
46 Chunk::CelExtra(_) => {}
47 Chunk::ColorProfile(_) => {}
48 Chunk::ExternalFiles(_) => {}
49 Chunk::Mask(_) => {}
50 Chunk::Path => {}
51 Chunk::Tags(tags_chunk) => tags.extend(tags_chunk.tags),
52 Chunk::Palette(_) => {}
53 Chunk::UserData(_) => {}
54 Chunk::Slice(slice) => slices.push(slice),
55 Chunk::Tileset(_) => {}
56 Chunk::Unsupported(_) => {}
57 }
58 }
59 frames.push((raw_frame.duration, cels));
60 }
61 let frames = frames
62 .into_iter()
63 .map(|(duration, frame_cels)| {
64 Ok(Frame {
65 duration,
66 cels: {
67 let mut cels: Vec<Option<CelChunk<'_>>> = Vec::with_capacity(layers.len());
70 for _ in 0..layers.len() {
71 cels.push(None);
72 }
73 for cel in frame_cels {
74 let layer_index: usize = cel.layer_index.into();
75 if layer_index > layers.len() {
76 return Err(nom::Err::Failure(ParseError::LayerIndexOutOfBounds));
77 }
78 cels[layer_index] = Some(cel);
79 }
80 cels
81 },
82 })
83 })
84 .try_collect()?;
85 Ok(File {
86 header: raw_file.header,
87 palette,
88 layers,
89 frames,
90 tags,
91 slices,
92 })
93}
94
95#[test]
96fn test_parse_file() {
97 let input = std::fs::read("./tests/default.aseprite").unwrap();
98 let file = parse_file(&input).unwrap();
99 assert_eq!(file.frames.len(), 1);
100 assert_eq!(file.frames[0].duration, 100);
101}
102
103#[test]
104fn test_palette() {
105 use crate::binary::scalars::Color;
106 let input = std::fs::read("./tests/indexed.aseprite").unwrap();
107 let file = parse_file(&input).unwrap();
108 assert_eq!(file.header.color_depth, ColorDepth::Indexed);
109 let palette = file.palette.unwrap();
110 assert_eq!(
111 palette.colors[27],
112 Color {
113 red: 172,
114 green: 50,
115 blue: 50,
116 alpha: 255
117 }
118 );
119 assert_eq!(
120 palette.colors[10],
121 Color {
122 red: 106,
123 green: 190,
124 blue: 48,
125 alpha: 255
126 }
127 );
128 assert_eq!(
129 palette.colors[17],
130 Color {
131 red: 91,
132 green: 110,
133 blue: 225,
134 alpha: 255
135 }
136 );
137}