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 adjusted_ra = self.ra.as_ref().map(|ra| RA {
110 pan: ra.pan,
111 pad: ra.pad,
112 ph: Some(width),
113 pv: Some(height),
114 });
115 let sixel_serializer =
116 SixelSerializer::new(&self.dcs, &adjusted_ra, &self.color_registers, &self.pixels);
117 let serialized_image =
118 sixel_serializer.serialize_range(start_x_index, start_y_index, width, height);
119 serialized_image
120 }
121 pub fn cut_out(
125 &mut self,
126 start_x_index: usize,
127 start_y_index: usize,
128 width: usize,
129 height: usize,
130 ) {
131 for row in self.pixels.iter_mut().skip(start_y_index).take(height) {
132 for pixel in row.iter_mut().skip(start_x_index).take(width) {
133 pixel.on = false;
134 }
135 }
136 }
137}
138
139#[derive(Clone, Copy)]
140pub struct Pixel {
141 pub on: bool,
142 pub color: u16,
143}
144
145impl fmt::Debug for Pixel {
146 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147 if self.on {
148 write!(f, "{}", self.color)
149 } else {
150 write!(f, "x")
151 }
152 }
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
156pub enum SixelColor {
157 Rgb(u8, u8, u8), Hsl(u16, u8, u8), }
160
161impl From<ColorCoordinateSystem> for SixelColor {
162 fn from(item: ColorCoordinateSystem) -> Self {
163 match item {
164 ColorCoordinateSystem::HLS(x, y, z) => SixelColor::Hsl(x as u16, y as u8, z as u8),
165 ColorCoordinateSystem::RGB(x, y, z) => SixelColor::Rgb(x as u8, y as u8, z as u8),
166 }
167 }
168}
169
170#[cfg(test)]
171mod tests;