sixel_image/
sixel_deserializer.rs1use sixel_tokenizer::SixelEvent;
2use std::collections::BTreeMap;
3use std::iter;
4
5use crate::{Pixel, SixelColor, SixelImage, DCS, RA};
6
7#[derive(Debug, Clone)]
8pub struct SixelDeserializer {
9 dcs: DCS,
10 ra: Option<RA>,
11 color_registers: BTreeMap<u16, SixelColor>,
12 current_color: u16,
13 sixel_cursor_y: usize,
14 sixel_cursor_x: usize,
15 pixels: Vec<Vec<Pixel>>,
16 max_height: Option<usize>,
17 stop_parsing: bool,
18 got_dcs: bool,
19}
20
21impl SixelDeserializer {
22 pub fn new() -> Self {
23 SixelDeserializer {
24 dcs: DCS {
25 macro_parameter: 0,
26 transparent_bg: false,
27 },
28 ra: None,
29 color_registers: BTreeMap::new(),
30 current_color: 0, sixel_cursor_y: 0,
32 sixel_cursor_x: 0,
33 pixels: vec![vec![]], max_height: None,
35 stop_parsing: false,
36 got_dcs: false,
37 }
38 }
39 pub fn max_height(mut self, max_height: usize) -> Self {
42 self.max_height = Some(max_height);
43 self
44 }
45 pub fn create_image(&mut self) -> Result<SixelImage, &'static str> {
47 if !self.got_dcs {
48 return Err("Corrupted image sequence");
49 }
50 let dcs = std::mem::take(&mut self.dcs);
51 let ra = std::mem::take(&mut self.ra);
52 let pixels = std::mem::take(&mut self.pixels);
53 let color_registers = std::mem::take(&mut self.color_registers);
54 Ok(SixelImage {
55 dcs,
56 ra,
57 pixels,
58 color_registers,
59 })
60 }
61 pub fn handle_event(&mut self, event: SixelEvent) -> Result<(), &'static str> {
63 if !self.got_dcs && !matches!(event, SixelEvent::Dcs { .. }) {
64 return Err("Corrupted image sequence");
65 }
66 if self.stop_parsing {
67 return Ok(());
68 }
69 match event {
70 SixelEvent::ColorIntroducer {
71 color_coordinate_system,
72 color_number,
73 } => {
74 match color_coordinate_system {
75 Some(color_coordinate_system) => {
76 let color = SixelColor::from(color_coordinate_system);
78 self.color_registers.insert(color_number, color);
79 }
80 None => {
81 self.current_color = color_number;
83 }
84 }
85 }
86 SixelEvent::RasterAttribute { pan, pad, ph, pv } => {
87 if !self.dcs.transparent_bg {
88 if let Some(pv) = pv {
89 self.pad_lines_vertically(pv);
90 }
91 if let Some(ph) = ph {
92 self.pad_lines_horizontally(ph);
93 }
94 }
95 self.ra = Some(RA { pan, pad, ph, pv });
96 }
97 SixelEvent::Data { byte } => {
98 self.make_sure_six_lines_exist_after_cursor();
99 self.add_sixel_byte(byte, 1);
100 self.sixel_cursor_x += 1;
101 }
102 SixelEvent::Repeat {
103 repeat_count,
104 byte_to_repeat,
105 } => {
106 self.make_sure_six_lines_exist_after_cursor();
107 self.add_sixel_byte(byte_to_repeat, repeat_count);
108 self.sixel_cursor_x += repeat_count;
109 }
110 SixelEvent::Dcs {
111 macro_parameter,
112 transparent_background,
113 horizontal_pixel_distance: _,
114 } => {
115 self.got_dcs = true;
116 if let Some(mp) = macro_parameter {
117 self.dcs.macro_parameter = mp;
118 }
119 if transparent_background == Some(1) {
120 self.dcs.transparent_bg = true;
121 }
122 }
123 SixelEvent::GotoBeginningOfLine => {
124 self.sixel_cursor_x = 0;
125 }
126 SixelEvent::GotoNextLine => {
127 if let Some(max_height) = self.max_height {
128 if self.sixel_cursor_y + 12 > max_height {
129 self.stop_parsing = true;
131 return Ok(());
132 }
133 }
134 self.sixel_cursor_y += 6;
135 self.sixel_cursor_x = 0;
136 }
137 SixelEvent::UnknownSequence(_) => {
138 return Err("Corrupted Sixel sequence");
139 }
140 SixelEvent::End => {}
141 }
142 Ok(())
143 }
144 fn make_sure_six_lines_exist_after_cursor(&mut self) {
145 let lines_to_add = (self.sixel_cursor_y + 6).saturating_sub(self.pixels.len());
146 for _ in 0..lines_to_add {
147 self.pixels.push(vec![]);
148 }
149 }
150 fn add_sixel_byte(&mut self, byte: u8, repeat_count: usize) {
151 let mut pixel_line_index_in_sixel = 0;
152 for bit in SixelPixelIterator::new(byte.saturating_sub(63)) {
153 let current_line = self
154 .pixels
155 .get_mut(self.sixel_cursor_y + pixel_line_index_in_sixel)
156 .unwrap();
157 let new_pixel = Pixel {
158 on: bit,
159 color: self.current_color,
160 };
161 for i in 0..repeat_count {
162 match current_line.get_mut(self.sixel_cursor_x + i) {
163 Some(pixel_in_current_position) if bit => {
164 let _ = std::mem::replace(pixel_in_current_position, new_pixel);
165 }
166 None => {
167 current_line.push(new_pixel);
168 }
169 _ => {} }
171 }
172 pixel_line_index_in_sixel += 1;
173 }
174 }
175 fn pad_lines_vertically(&mut self, pad_until: usize) {
176 let empty_pixel = Pixel {
177 on: true,
178 color: self.current_color,
179 };
180 if self.pixels.len() < pad_until {
181 let empty_line = vec![empty_pixel; pad_until];
182 let lines_to_pad = pad_until - self.pixels.len();
183 let line_padding = iter::repeat(empty_line).take(lines_to_pad);
184 self.pixels.extend(line_padding);
185 }
186 }
187 fn pad_lines_horizontally(&mut self, pad_until: usize) {
188 let empty_pixel = Pixel {
189 on: true,
190 color: self.current_color,
191 };
192 for pixel_line in self.pixels.iter_mut() {
193 if pixel_line.len() < pad_until {
194 let pixel_count_to_pad = pad_until - pixel_line.len();
195 let pixel_padding = iter::repeat(empty_pixel).take(pixel_count_to_pad);
196 pixel_line.extend(pixel_padding);
197 }
198 }
199 }
200}
201
202#[derive(Debug, Clone, Copy)]
203struct SixelPixelIterator {
204 sixel_byte: u8,
205 current_mask: u8,
206}
207impl SixelPixelIterator {
208 pub fn new(sixel_byte: u8) -> Self {
209 SixelPixelIterator {
210 sixel_byte,
211 current_mask: 1,
212 }
213 }
214}
215impl Iterator for SixelPixelIterator {
216 type Item = bool;
217 fn next(&mut self) -> Option<Self::Item> {
218 let bit = self.sixel_byte & self.current_mask == self.current_mask;
221 self.current_mask <<= 1;
222 if self.current_mask == 128 {
223 None
224 } else {
225 Some(bit)
226 }
227 }
228}