1mod sixel_deserializer;
27mod sixel_serializer;
28
29pub use sixel_deserializer::SixelDeserializer;
30pub use sixel_serializer::SixelSerializer;
31
32use sixel_tokenizer::{ColorCoordinateSystem, Parser};
33use std::collections::BTreeMap;
34use std::fmt;
35
36#[derive(Debug, Clone)]
37pub struct SixelImage {
38 pub color_registers: BTreeMap<u16, SixelColor>,
39 pub pixels: Vec<Vec<Pixel>>,
40 dcs: DCS,
41 ra: Option<RA>,
42}
43
44#[derive(Debug, Clone)]
45pub struct DCS {
46 macro_parameter: u8,
47 transparent_bg: bool,
48}
49
50impl Default for DCS {
51 fn default() -> Self {
52 DCS {
53 macro_parameter: 0,
54 transparent_bg: false,
55 }
56 }
57}
58
59#[derive(Debug, Clone)]
60pub struct RA {
61 pan: usize,
62 pad: usize,
63 ph: Option<usize>,
64 pv: Option<usize>,
65}
66
67impl SixelImage {
68 pub fn new(bytes: &[u8]) -> Result<Self, &'static str> {
70 let mut parser = Parser::new();
71 let mut sixel_deserializer = SixelDeserializer::new();
72 for byte in bytes {
73 let mut handle_result = Ok(());
74 parser.advance(&byte, |sixel_event| {
75 handle_result = sixel_deserializer.handle_event(sixel_event);
76 });
77 handle_result?
78 }
79 let sixel_image = sixel_deserializer.create_image();
80 sixel_image
81 }
82 pub fn pixel_size(&self) -> (usize, usize) {
84 let width = self
86 .pixels
87 .first()
88 .map(|first_line| first_line.len())
89 .unwrap_or(0);
90 let height = self.pixels.len();
91 (height, width)
92 }
93 pub fn serialize(&self) -> String {
95 let sixel_serializer =
96 SixelSerializer::new(&self.dcs, &self.ra, &self.color_registers, &self.pixels);
97 let serialized_image = sixel_serializer.serialize();
98 serialized_image
99 }
100 pub fn serialize_range(
103 &self,
104 start_x_index: usize,
105 start_y_index: usize,
106 width: usize,
107 height: usize,
108 ) -> String {
109 let sixel_serializer =
110 SixelSerializer::new(&self.dcs, &self.ra, &self.color_registers, &self.pixels);
111 let serialized_image =
112 sixel_serializer.serialize_range(start_x_index, start_y_index, width, height);
113 serialized_image
114 }
115 pub fn cut_out(
119 &mut self,
120 start_x_index: usize,
121 start_y_index: usize,
122 width: usize,
123 height: usize,
124 ) {
125 for row in self.pixels.iter_mut().skip(start_y_index).take(height) {
126 for pixel in row.iter_mut().skip(start_x_index).take(width) {
127 pixel.on = false;
128 }
129 }
130 }
131}
132
133#[derive(Clone, Copy)]
134pub struct Pixel {
135 pub on: bool,
136 pub color: u16,
137}
138
139impl fmt::Debug for Pixel {
140 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 if self.on {
142 write!(f, "{}", self.color)
143 } else {
144 write!(f, "x")
145 }
146 }
147}
148
149#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
150pub enum SixelColor {
151 Rgb(u8, u8, u8), Hsl(u16, u8, u8), }
154
155impl From<ColorCoordinateSystem> for SixelColor {
156 fn from(item: ColorCoordinateSystem) -> Self {
157 match item {
158 ColorCoordinateSystem::HLS(x, y, z) => SixelColor::Hsl(x as u16, y as u8, z as u8),
159 ColorCoordinateSystem::RGB(x, y, z) => SixelColor::Rgb(x as u8, y as u8, z as u8),
160 }
161 }
162}
163
164#[cfg(test)]
165mod tests;