aseprite_loader/binary/chunks/
cel.rs1use nom::bytes::complete::take;
2use strum::FromRepr;
3
4use crate::binary::{
5 errors::ParseResult,
6 image::Image,
7 scalars::{byte, dword, short, word, Byte, Dword, Short, Word},
8};
9
10#[derive(Debug)]
11pub struct CelChunk<'a> {
12 pub layer_index: Word,
14 pub x: Short,
16 pub y: Short,
18 pub opacity: Byte,
20 pub z_index: Short,
22 pub content: CelContent<'a>,
24}
25
26#[derive(Debug, FromRepr)]
27
28enum CelType {
29 RawImageData,
31 LinkedCel,
33 CompressedImage,
35 CompressedTilemap,
37 Unknown(Word),
38}
39
40impl From<Word> for CelType {
41 fn from(word: Word) -> Self {
42 CelType::from_repr(word.into()).unwrap_or(Self::Unknown(word))
43 }
44}
45
46#[derive(Debug)]
47pub enum CelContent<'a> {
48 Image(Image<'a>),
49 LinkedCel {
50 frame_position: Word,
52 },
53 CompressedTilemap {
54 width: Word,
56 height: Word,
58 bits_per_tile: Word,
60 bitmask_tile_id: Dword,
62 bitmask_x_flip: Dword,
64 bitmask_y_flip: Dword,
66 bitmask_diagonal_flip: Dword,
68 data: &'a [u8],
71 },
72 Unknown {
73 cel_type: Word,
74 data: &'a [u8],
75 },
76}
77
78pub fn parse_cel_chunk(input: &[u8]) -> ParseResult<'_, CelChunk<'_>> {
79 let (input, layer_index) = word(input)?;
80 let (input, x) = short(input)?;
81 let (input, y) = short(input)?;
82 let (input, opacity) = byte(input)?;
83 let (input, cel_type) = word(input)?;
84 let cel_type = CelType::from(cel_type);
85 let (input, z_index) = short(input)?;
86 let (input, _) = take(5usize)(input)?;
87 let content = match cel_type {
88 CelType::RawImageData => {
89 let (input, width) = word(input)?;
90 let (input, height) = word(input)?;
91 CelContent::Image(Image {
92 width,
93 height,
94 data: input,
95 compressed: false,
96 })
97 }
98 CelType::LinkedCel => {
99 let (_, frame_position) = word(input)?;
100 CelContent::LinkedCel { frame_position }
101 }
102 CelType::CompressedImage => {
103 let (input, width) = word(input)?;
104 let (input, height) = word(input)?;
105 CelContent::Image(Image {
106 width,
107 height,
108 data: input,
109 compressed: true,
110 })
111 }
112 CelType::CompressedTilemap => {
113 let (input, width) = word(input)?;
114 let (input, height) = word(input)?;
115 let (input, bits_per_tile) = word(input)?;
116 let (input, bitmask_tile_id) = dword(input)?;
117 let (input, bitmask_y_flip) = dword(input)?;
118 let (input, bitmask_x_flip) = dword(input)?;
119 let (input, bitmask_diagonal_flip) = dword(input)?;
120 let (input, _) = take(10usize)(input)?;
121 CelContent::CompressedTilemap {
122 width,
123 height,
124 bits_per_tile,
125 bitmask_tile_id,
126 bitmask_x_flip,
127 bitmask_y_flip,
128 bitmask_diagonal_flip,
129 data: input,
130 }
131 }
132 CelType::Unknown(cel_type) => CelContent::Unknown {
133 cel_type,
134 data: input,
135 },
136 };
137 Ok((
138 &input[input.len()..],
139 CelChunk {
140 layer_index,
141 x,
142 y,
143 opacity,
144 z_index,
145 content,
146 },
147 ))
148}