1use alloc::vec::Vec;
4
5use crate::{config::*, palette::*, pixel_format::PixelFormat, quant::*, Error, Result};
6
7pub mod method;
8
9#[derive(Clone, Debug, Default, PartialEq)]
11#[repr(C)]
12pub struct SixelDither {
13 pub palette: Vec<u8>,
14 pub cache_table: Vec<u16>,
15 pub req_colors: usize,
16 pub ncolors: usize,
17 pub orig_colors: usize,
18 pub optimized: bool,
19 pub optimize_palette: bool,
20 pub complexion: i32,
21 pub body_only: bool,
22 pub method_for_largest: MethodForLargest,
23 pub method_for_rep: MethodForRep,
24 pub method_for_diffuse: MethodForDiffuse,
25 pub quality_mode: QualityMode,
26 pub key_color: i32,
27 pub pixel_format: PixelFormat,
28 pub height: usize,
29 pub width: usize,
30 pub depth: usize,
31}
32
33impl SixelDither {
34 pub const fn new() -> Self {
36 Self {
37 palette: vec![],
38 cache_table: vec![],
39 req_colors: 256,
40 ncolors: 256,
41 orig_colors: 0,
42 key_color: -1,
43 optimized: false,
44 optimize_palette: false,
45 complexion: 1,
46 body_only: false,
47 method_for_largest: MethodForLargest::Norm,
48 method_for_rep: MethodForRep::CenterBox,
49 method_for_diffuse: MethodForDiffuse::Fs,
50 quality_mode: QualityMode::High,
51 pixel_format: PixelFormat::Rgb888,
52 height: 0,
53 width: 0,
54 depth: 0,
55 }
56 }
57
58 pub fn create(mut ncolors: i32) -> Result<Self> {
60 if ncolors == 0 || ncolors > 256 {
61 Err(Error::Dither(format!(
62 "sixel_dither_new: palette colors must be in range [1,256], have: {ncolors}"
63 )))
64 } else {
65 let quality_mode = if ncolors < 0 {
66 ncolors = 256;
67 QualityMode::HighColor
68 } else {
69 QualityMode::Low
70 };
71
72 Ok(Self {
73 palette: vec![],
74 cache_table: vec![],
75 req_colors: ncolors as usize,
76 ncolors: ncolors as usize,
77 orig_colors: 0,
78 key_color: -1,
79 optimized: false,
80 optimize_palette: false,
81 complexion: 1,
82 body_only: false,
83 method_for_largest: MethodForLargest::Norm,
84 method_for_rep: MethodForRep::CenterBox,
85 method_for_diffuse: MethodForDiffuse::Fs,
86 quality_mode,
87 pixel_format: PixelFormat::Rgb888,
88 height: 0,
89 width: 0,
90 depth: 0,
91 })
92 }
93 }
94
95 pub fn get(builtin_dither: BuiltinPalette) -> Result<Self> {
97 let (ncolors, palette, key_color) = match builtin_dither {
98 BuiltinPalette::MonoDark => (2, PAL_MONO_DARK.as_ref(), 0),
99 BuiltinPalette::MonoLight => (2, PAL_MONO_LIGHT.as_ref(), 0),
100 BuiltinPalette::Xterm16 => (16, PAL_XTERM256.as_ref(), -1),
101 BuiltinPalette::Xterm256 => (256, PAL_XTERM256.as_ref(), -1),
102 BuiltinPalette::Vt340Mono => (16, PAL_VT340_MONO.as_ref(), -1),
103 BuiltinPalette::Vt340Color => (16, PAL_VT340_COLOR.as_ref(), -1),
104 BuiltinPalette::G1 => (2, PAL_GRAY_1BIT.as_ref(), -1),
105 BuiltinPalette::G2 => (4, PAL_GRAY_2BIT.as_ref(), -1),
106 BuiltinPalette::G4 => (16, PAL_GRAY_4BIT.as_ref(), -1),
107 BuiltinPalette::G8 => (256, PAL_GRAY_8BIT.as_ref(), -1),
108 };
109
110 let mut dither = Self::create(ncolors)?;
111
112 dither.palette = palette.into();
113 dither.key_color = key_color;
114 dither.optimized = true;
115 dither.optimize_palette = false;
116
117 Ok(dither)
118 }
119
120 pub fn initialize(
122 &mut self,
123 data: &[u8],
124 width: usize,
125 height: usize,
126 palette_config: PaletteConfig,
127 ) -> Result<()> {
128 let mut normalized_pixels = vec![0u8; data.len()];
129
130 self.pixel_format = palette_config.pixel_format;
131
132 let input_pixels = match self.pixel_format {
133 PixelFormat::Rgb888 => data,
134 _ => {
135 self.pixel_format
136 .normalize(normalized_pixels.as_mut(), data, width, height)?;
137
138 normalized_pixels.as_ref()
139 }
140 };
141
142 self.method_for_largest = palette_config.method_for_largest;
143 self.method_for_rep = palette_config.method_for_rep;
144 self.quality_mode = palette_config.quality_mode;
145
146 let buf = self.make_palette(input_pixels)?;
147
148 let palette_len = self.ncolors.saturating_mul(3);
149
150 let dither_palette_len = palette_len;
151 let buf_len = buf.len();
152
153 if palette_len > dither_palette_len || palette_len > buf_len {
154 Err(Error::Dither(format!("invalid palette length, palette: {dither_palette_len}, buffer: {buf_len}, have: {palette_len}")))
155 } else {
156 #[cfg(feature = "std")]
157 println!(
158 "palette len: {}, buf len: {}",
159 self.palette.len(),
160 buf.len()
161 );
162 self.palette[..palette_len].copy_from_slice(&buf[..palette_len]);
163 self.optimized = true;
164
165 if self.orig_colors <= self.ncolors {
166 self.method_for_diffuse = MethodForDiffuse::None;
167 }
168
169 Ok(())
170 }
171 }
172
173 pub fn apply_palette(&mut self, pixels: &[u8], width: usize, height: usize) -> Result<Vec<u8>> {
175 if self.quality_mode == QualityMode::Full {
177 self.optimized = false;
178 }
179
180 if self.cache_table.is_empty()
181 && self.optimized
182 && self.palette != PAL_MONO_DARK
183 && self.palette != PAL_MONO_LIGHT
184 {
185 self.cache_table = vec![0u16; 1 << (3 * 5)];
186 }
187
188 let mut input_pixels: Vec<u8> = if self.pixel_format != PixelFormat::Rgb888 {
189 let mut normalized_pixels = vec![0u8; width * height * 3];
190 self.pixel_format
191 .normalize(normalized_pixels.as_mut(), pixels, width, height)?;
192 normalized_pixels
193 } else {
194 pixels.into()
195 };
196
197 self.width = width;
198 self.height = height;
199 self.depth = 3;
200
201 #[cfg(feature = "std")]
202 println!("pixel len: {}", input_pixels.len());
203
204 self.quant_apply_palette(input_pixels.as_mut())
205 }
206}