libsixel_rs/device_control_string/
sixel_char.rs1use super::constants::{SIXEL_CHAR_END, SIXEL_CHAR_START};
2use crate::std::fmt;
3
4pub type RgbBytes = [u8; 3];
6pub type RgbSixelBytes = [RgbBytes; 6];
8pub type SixelPlane = [u8; 6];
10
11#[repr(C)]
25#[derive(Clone, Copy, Debug, PartialEq)]
26pub struct SixelChar(u8);
27
28impl SixelChar {
29 pub const fn new() -> Self {
31 Self(SIXEL_CHAR_START)
32 }
33
34 pub const fn full() -> Self {
36 Self(SIXEL_CHAR_END)
37 }
38
39 pub fn from_plane(plane: &RgbSixelBytes, six_idx: usize, hits: &[u8], threshold: u8) -> Self {
46 if six_idx < plane.len() && six_idx < hits.len() && (1..=threshold).contains(&hits[six_idx])
47 {
48 (1u8 << six_idx).into()
49 } else {
50 Self::new()
51 }
52 }
53
54 pub fn from_index(six_idx: usize) -> Self {
61 (1u8 << six_idx).into()
62 }
63}
64
65impl Default for SixelChar {
66 fn default() -> Self {
67 Self::new()
68 }
69}
70
71impl From<&SixelChar> for u8 {
72 fn from(val: &SixelChar) -> Self {
73 val.0
74 }
75}
76
77impl From<SixelChar> for u8 {
78 fn from(val: SixelChar) -> Self {
79 (&val).into()
80 }
81}
82
83impl From<u8> for SixelChar {
84 fn from(val: u8) -> Self {
85 if val < SIXEL_CHAR_START {
86 Self(SIXEL_CHAR_START + val)
87 } else if (SIXEL_CHAR_START..=SIXEL_CHAR_END).contains(&val) {
88 Self(val)
89 } else {
90 Self((val % SIXEL_CHAR_START) + SIXEL_CHAR_START)
91 }
92 }
93}
94
95impl From<&SixelChar> for char {
96 fn from(val: &SixelChar) -> Self {
97 val.0 as char
98 }
99}
100
101impl From<SixelChar> for char {
102 fn from(val: SixelChar) -> Self {
103 (&val).into()
104 }
105}
106
107impl From<char> for SixelChar {
108 fn from(val: char) -> Self {
109 (val as u8).into()
110 }
111}
112
113impl From<&RgbSixelBytes> for SixelChar {
114 fn from(val: &RgbSixelBytes) -> Self {
115 let mut sorted = *val;
117 sorted.sort();
118
119 (((sorted[0] <= val[0] && val[0] < sorted[5]) as u8
126 | (((sorted[0] <= val[1] && val[1] < sorted[5]) as u8) << 1)
127 | (((sorted[0] <= val[2] && val[2] < sorted[5]) as u8) << 2)
128 | (((sorted[0] <= val[3] && val[3] < sorted[5]) as u8) << 3)
129 | (((sorted[0] <= val[4] && val[4] < sorted[5]) as u8) << 4)
130 | (((sorted[0] <= val[5] && val[5] < sorted[5]) as u8) << 5))
131 + SIXEL_CHAR_START)
132 .into()
133 }
134}
135
136impl From<RgbSixelBytes> for SixelChar {
137 fn from(val: RgbSixelBytes) -> Self {
138 (&val).into()
139 }
140}
141
142impl fmt::Display for SixelChar {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 write!(f, "{}", char::from(self))
145 }
146}