aseprite_loader/binary/
palette.rs1use thiserror::Error;
2
3use super::{
4 chunk::Chunk,
5 chunks::{old_palette::OldPaletteChunk, palette::PaletteChunk},
6 header::Header,
7 raw_frame::RawFrame,
8 scalars::Color,
9};
10
11#[derive(Debug)]
12pub struct Palette {
13 pub colors: [Color; 256],
14}
15
16impl Default for Palette {
17 fn default() -> Self {
18 Palette {
19 colors: [Color::default(); 256],
20 }
21 }
22}
23
24pub fn create_palette(header: &Header, frames: &[RawFrame<'_>]) -> Result<Palette, PaletteError> {
25 let mut palette = Palette::default();
26 let palette_chunks: Vec<_> = frames
27 .iter()
28 .flat_map(|frame| {
29 frame.chunks.iter().filter_map(|chunk| {
30 if let Chunk::Palette(palette) = chunk {
31 Some(palette)
32 } else {
33 None
34 }
35 })
36 })
37 .collect();
38 if !palette_chunks.is_empty() {
39 process_palette_chunks(header.transparent_index, &palette_chunks, &mut palette)?;
40 return Ok(palette);
41 }
42 let palette0004_chunks: Vec<_> = frames
43 .iter()
44 .flat_map(|frame| {
45 frame.chunks.iter().filter_map(|chunk| {
46 if let Chunk::Palette0004(palette) = chunk {
47 Some(palette)
48 } else {
49 None
50 }
51 })
52 })
53 .collect();
54 if !palette0004_chunks.is_empty() {
55 process_old_palette_chunks(header.transparent_index, &palette0004_chunks, &mut palette)?;
56 return Ok(palette);
57 }
58 let palette0011_chunks: Vec<_> = frames
59 .iter()
60 .flat_map(|frame| {
61 frame.chunks.iter().filter_map(|chunk| {
62 if let Chunk::Palette0011(palette) = chunk {
63 Some(palette)
64 } else {
65 None
66 }
67 })
68 })
69 .collect();
70 if !palette0011_chunks.is_empty() {
71 process_old_palette_chunks(header.transparent_index, &palette0011_chunks, &mut palette)?;
72 return Ok(palette);
73 }
74 Err(PaletteError::Missing)
75}
76
77fn process_palette_chunks(
78 transparent_index: u8,
79 chunks: &[&PaletteChunk<'_>],
80 palette: &mut Palette,
81) -> Result<(), PaletteError> {
82 let mut ok = false;
83 for chunk in chunks.iter() {
84 for (entry, color_idx) in chunk.entries.iter().zip(chunk.indices.clone()) {
88 palette.colors[usize::from(color_idx)] = entry.color;
89 ok = true;
90 }
91 }
92 if ok {
93 palette.colors[usize::from(transparent_index)].alpha = 0;
94 Ok(())
95 } else {
96 Err(PaletteError::Empty)
97 }
98}
99
100fn process_old_palette_chunks(
101 transparent_index: u8,
102 chunks: &[&OldPaletteChunk],
103 palette: &mut Palette,
104) -> Result<(), PaletteError> {
105 let mut ok = false;
106 for chunk in chunks.iter() {
107 let mut color_idx = 0usize;
108 for packet in &chunk.packets {
109 color_idx += usize::from(packet.entries_to_skip);
110 if color_idx + packet.colors.len() > 256 {
111 return Err(PaletteError::IndexOutOfBounds);
112 }
113 for color in &packet.colors {
114 palette.colors[color_idx] = Color {
115 red: color.red,
116 green: color.green,
117 blue: color.blue,
118 alpha: 255,
119 };
120 color_idx += 1;
121 ok = true;
122 }
123 }
124 }
125 if ok {
126 palette.colors[usize::from(transparent_index)].alpha = 0;
127 Ok(())
128 } else {
129 Err(PaletteError::Empty)
130 }
131}
132
133#[derive(Debug, Copy, Clone, Error)]
134pub enum PaletteError {
135 #[error("Palette is missing")]
136 Missing,
137 #[error("Palette is empty")]
138 Empty,
139 #[error("First color index not in range 0..255")]
140 FirstColorIndexOutOfBounds,
141 #[error("Last color index not in range 0..255")]
142 LastColorIndexOutOfBounds,
143 #[error("First color index > last color index")]
144 FirstColorIndexGreaterThanLastColorIndex,
145 #[error("Palette index out of bounds")]
146 IndexOutOfBounds,
147}