1use crate::{color::Rgb, std::fmt, Error, Result};
2
3#[repr(i32)]
5#[derive(Copy, Clone, Debug, Default, PartialEq)]
6pub enum FormatType {
7 #[default]
8 Color = 0,
9 Grayscale = 1 << 6,
10 Palette = 1 << 7,
11}
12
13#[repr(i32)]
15#[derive(Copy, Clone, Debug, Default, PartialEq)]
16pub enum PixelFormat {
17 Rgb555 = FormatType::Color as i32 | 0x01,
19 Rgb565 = FormatType::Color as i32 | 0x02,
21 #[default]
23 Rgb888 = FormatType::Color as i32 | 0x03,
24 Bgr555 = FormatType::Color as i32 | 0x04,
26 Bgr565 = FormatType::Color as i32 | 0x05,
28 Bgr888 = FormatType::Color as i32 | 0x06,
30 Argb8888 = FormatType::Color as i32 | 0x10,
32 Rgba8888 = FormatType::Color as i32 | 0x11,
34 Abgr8888 = FormatType::Color as i32 | 0x12,
36 Bgra8888 = FormatType::Color as i32 | 0x13,
38 G1 = FormatType::Grayscale as i32,
40 G2 = FormatType::Grayscale as i32 | 0x01,
42 G4 = FormatType::Grayscale as i32 | 0x02,
44 G8 = FormatType::Grayscale as i32 | 0x03,
46 Ag88 = FormatType::Grayscale as i32 | 0x13,
48 Ga88 = FormatType::Grayscale as i32 | 0x23,
50 Pal1 = FormatType::Palette as i32,
52 Pal2 = FormatType::Palette as i32 | 0x01,
54 Pal4 = FormatType::Palette as i32 | 0x02,
56 Pal8 = FormatType::Palette as i32 | 0x03,
58}
59
60impl PixelFormat {
61 pub const fn new() -> Self {
63 Self::Rgb888
64 }
65
66 pub fn compute_depth(&self) -> usize {
68 match self {
69 Self::Argb8888 | Self::Rgba8888 | Self::Abgr8888 | Self::Bgra8888 => 4,
70 Self::Rgb888 | Self::Bgr888 => 3,
71 Self::Rgb555 | Self::Rgb565 | Self::Bgr555 | Self::Bgr565 | Self::Ag88 | Self::Ga88 => {
72 2
73 }
74 Self::G1
75 | Self::G2
76 | Self::G4
77 | Self::G8
78 | Self::Pal1
79 | Self::Pal2
80 | Self::Pal4
81 | Self::Pal8 => 1,
82 }
83 }
84
85 pub fn rgb(&self, data: &[u8], depth: usize) -> Result<Rgb> {
87 let mut pixels = 0u32;
88
89 let data_len = data.len();
90
91 if depth > data_len {
92 return Err(Error::PixelFormat(format!("invalid RGB depth larger than data length, data length: {data_len}, depth: {depth}")));
93 }
94
95 for &d in data.iter().take(depth) {
96 pixels = d as u32 | pixels << 8;
97 }
98
99 let ret = match self {
100 Self::Rgb555 => Rgb::create(
101 (((pixels >> 10) & 0x1f) << 3) as u8,
102 (((pixels >> 5) & 0x1f) << 3) as u8,
103 ((pixels & 0x1f) << 3) as u8,
104 ),
105 Self::Rgb565 => Rgb::create(
106 (((pixels >> 11) & 0x1f) << 3) as u8,
107 (((pixels >> 5) & 0x3f) << 2) as u8,
108 ((pixels & 0x1f) << 3) as u8,
109 ),
110 Self::Rgb888 => Rgb::create(
111 ((pixels >> 16) & 0xff) as u8,
112 ((pixels >> 8) & 0xff) as u8,
113 (pixels & 0xff) as u8,
114 ),
115 Self::Bgr555 => Rgb::create(
116 ((pixels & 0x1f) << 3) as u8,
117 (((pixels >> 5) & 0x1f) << 3) as u8,
118 (((pixels >> 10) & 0x1f) << 3) as u8,
119 ),
120 Self::Bgr565 => Rgb::create(
121 ((pixels & 0x1f) << 3) as u8,
122 (((pixels >> 5) & 0x3f) << 2) as u8,
123 (((pixels >> 11) & 0x1f) << 3) as u8,
124 ),
125 Self::Bgr888 => Rgb::create(
126 (pixels & 0xff) as u8,
127 ((pixels >> 8) & 0xff) as u8,
128 ((pixels >> 16) & 0xff) as u8,
129 ),
130 Self::Rgba8888 => Rgb::create(
131 ((pixels >> 24) & 0xff) as u8,
132 ((pixels >> 16) & 0xff) as u8,
133 ((pixels >> 8) & 0xff) as u8,
134 ),
135 Self::Argb8888 => Rgb::create(
136 ((pixels >> 16) & 0xff) as u8,
137 ((pixels >> 8) & 0xff) as u8,
138 (pixels & 0xff) as u8,
139 ),
140 Self::Bgra8888 => Rgb::create(
141 ((pixels >> 8) & 0xff) as u8,
142 ((pixels >> 16) & 0xff) as u8,
143 ((pixels >> 24) & 0xff) as u8,
144 ),
145 Self::Abgr8888 => Rgb::create(
146 (pixels & 0xff) as u8,
147 ((pixels >> 8) & 0xff) as u8,
148 ((pixels >> 16) & 0xff) as u8,
149 ),
150 Self::Ga88 => {
151 let color = ((pixels >> 8) & 0xff) as u8;
152 Rgb::create(color, color, color)
153 }
154 Self::G8 | Self::Ag88 => {
155 let color = (pixels & 0xff) as u8;
156 Rgb::create(color, color, color)
157 }
158 _ => Rgb::new(),
159 };
160
161 Ok(ret)
162 }
163
164 pub fn expand_rgb(
166 &self,
167 dst: &mut [u8],
168 src: &[u8],
169 width: usize,
170 height: usize,
171 depth: usize,
172 ) -> Result<()> {
173 let dst_len = dst.len();
174 let src_len = src.len();
175
176 for y in 0..height {
177 for x in 0..width {
178 let src_offset = depth.saturating_mul(y.saturating_mul(width).saturating_add(x));
179 let dst_offset = 3usize.saturating_mul(y.saturating_mul(width).saturating_add(x));
180
181 if src_offset >= src.len() {
182 return Err(Error::PixelFormat(format!(
183 "invalid depth, source length: {src_len}, source offset: {src_offset}"
184 )));
185 }
186
187 let rgb = self.rgb(&src[src_offset..], depth)?;
188
189 if dst_offset + 2 >= dst.len() {
190 return Err(Error::PixelFormat(format!(
191 "invalid RGB depth, destination length: {dst_len}, destination offset: {}",
192 dst_offset + 2
193 )));
194 }
195
196 dst[dst_offset] = rgb.r();
197 dst[dst_offset + 1] = rgb.g();
198 dst[dst_offset + 2] = rgb.b();
199 }
200 }
201
202 Ok(())
203 }
204
205 pub fn expand_palette(
207 &self,
208 dst: &mut [u8],
209 src: &[u8],
210 width: usize,
211 height: usize,
212 ) -> Result<()> {
213 let mut bpp = 0;
215
216 let mut dst_view = dst;
217 let mut src_view = src;
218
219 match self {
220 PixelFormat::Pal1 | PixelFormat::G1 => {
221 bpp = 1;
222 }
223 PixelFormat::Pal2 | PixelFormat::G2 => {
224 bpp = 2;
225 }
226 PixelFormat::Pal4 | PixelFormat::G4 => {
227 bpp = 4;
228 }
229 PixelFormat::Pal8 | PixelFormat::G8 => {
230 let offset = width.saturating_mul(height).saturating_sub(1);
231 let (dst_len, src_len) = (dst_view.len(), src_view.len());
232
233 if offset >= dst_len || offset >= src_len {
234 return Err(Error::PixelFormat(format!("width and height outside the bounds of the palette buffers, dst len: {dst_len}, src len: {src_len}, offset: {offset}")));
235 }
236
237 dst_view = &mut dst_view[offset..];
238 src_view = &src_view[offset..];
239 }
240 _ => {
241 return Err(Error::PixelFormat(format!("invalid pixel format: {self}")));
242 }
243 }
244
245 for _y in 0..height {
246 let upper_bound = width.saturating_mul(bpp).saturating_div(8);
247 for _x in 0..upper_bound {
248 for i in 0..8usize.saturating_div(bpp) {
249 dst_view = &mut dst_view[1..];
250
251 let shift = 8usize
252 .saturating_div(bpp)
253 .saturating_sub(1)
254 .saturating_sub(i);
255 let tail_shift = 1u32.overflowing_shl(bpp as u32).0.saturating_sub(1);
256
257 dst_view[0] = ((src[0] as u32)
258 .overflowing_shr(shift as u32)
259 .0
260 .saturating_mul(bpp as u32)
261 & tail_shift) as u8;
262 }
263 src_view = &src_view[1..];
264 }
265
266 let x = width - upper_bound.saturating_mul(8).saturating_div(bpp);
267
268 if x > 0 {
269 for i in 0..x {
270 dst_view = &mut dst_view[1..];
271
272 let shift = 8usize.saturating_sub(i + 1).saturating_mul(bpp);
273 let tail_shift = 1u32.overflowing_shl(bpp as u32).0.saturating_sub(1);
274
275 dst_view[0] =
276 ((src_view[0] as u32).overflowing_shr(shift as u32).0 & tail_shift) as u8;
277 }
278
279 src_view = &src_view[1..];
280 }
281 }
282
283 Ok(())
284 }
285
286 pub fn normalize(
288 &mut self,
289 dst: &mut [u8],
290 src: &[u8],
291 width: usize,
292 height: usize,
293 ) -> Result<()> {
294 let format = match self {
295 PixelFormat::G8 => {
296 self.expand_rgb(dst, src, width, height, 1)?;
297
298 PixelFormat::Rgb888
299 }
300 PixelFormat::Rgb565
301 | PixelFormat::Rgb555
302 | PixelFormat::Bgr565
303 | PixelFormat::Bgr555
304 | PixelFormat::Ga88
305 | PixelFormat::Ag88 => {
306 self.expand_rgb(dst, src, width, height, 2)?;
307
308 PixelFormat::Rgb888
309 }
310 PixelFormat::Rgb888 | PixelFormat::Bgr888 => {
311 self.expand_rgb(dst, src, width, height, 3)?;
312
313 PixelFormat::Rgb888
314 }
315 PixelFormat::Rgba8888
316 | PixelFormat::Argb8888
317 | PixelFormat::Bgra8888
318 | PixelFormat::Abgr8888 => {
319 self.expand_rgb(dst, src, width, height, 4)?;
320
321 PixelFormat::Rgb888
322 }
323 PixelFormat::Pal1 | PixelFormat::Pal2 | PixelFormat::Pal4 => {
324 self.expand_palette(dst, src, width, height)?;
325
326 PixelFormat::Pal8
327 }
328 PixelFormat::G1 | PixelFormat::G2 | PixelFormat::G4 => {
329 self.expand_palette(dst, src, width, height)?;
330
331 PixelFormat::G8
332 }
333 PixelFormat::Pal8 => {
334 let len = width.saturating_mul(height);
335 dst[..len].copy_from_slice(src[..len].as_ref());
336
337 *self
338 }
339 };
340
341 *self = format;
342
343 Ok(())
344 }
345}
346
347impl From<i32> for PixelFormat {
348 fn from(val: i32) -> Self {
349 match val {
350 pf if pf == Self::Rgb555 as i32 => Self::Rgb555,
351 pf if pf == Self::Rgb565 as i32 => Self::Rgb565,
352 pf if pf == Self::Rgb888 as i32 => Self::Rgb888,
353 pf if pf == Self::Bgr555 as i32 => Self::Bgr555,
354 pf if pf == Self::Bgr565 as i32 => Self::Bgr565,
355 pf if pf == Self::Bgr888 as i32 => Self::Bgr888,
356 pf if pf == Self::Argb8888 as i32 => Self::Argb8888,
357 pf if pf == Self::Rgba8888 as i32 => Self::Rgba8888,
358 pf if pf == Self::Abgr8888 as i32 => Self::Abgr8888,
359 pf if pf == Self::Bgra8888 as i32 => Self::Bgra8888,
360 pf if pf == Self::G1 as i32 => Self::G1,
361 pf if pf == Self::G2 as i32 => Self::G2,
362 pf if pf == Self::G4 as i32 => Self::G4,
363 pf if pf == Self::G8 as i32 => Self::G8,
364 pf if pf == Self::Ag88 as i32 => Self::Ag88,
365 pf if pf == Self::Ga88 as i32 => Self::Ga88,
366 pf if pf == Self::Pal1 as i32 => Self::Pal1,
367 pf if pf == Self::Pal2 as i32 => Self::Pal2,
368 pf if pf == Self::Pal4 as i32 => Self::Pal4,
369 pf if pf == Self::Pal8 as i32 => Self::Pal8,
370 _ => Self::Rgb888,
371 }
372 }
373}
374
375impl From<PixelFormat> for i32 {
376 fn from(val: PixelFormat) -> Self {
377 val as i32
378 }
379}
380
381impl From<PixelFormat> for &'static str {
382 fn from(val: PixelFormat) -> Self {
383 match val {
384 PixelFormat::Rgb555 => "RGB555",
385 PixelFormat::Rgb565 => "RGB565",
386 PixelFormat::Rgb888 => "RGB888",
387 PixelFormat::Bgr555 => "BGR555",
388 PixelFormat::Bgr565 => "BGR565",
389 PixelFormat::Bgr888 => "BGR888",
390 PixelFormat::Argb8888 => "ARGB8888",
391 PixelFormat::Rgba8888 => "RGBA8888",
392 PixelFormat::Abgr8888 => "ABGR8888",
393 PixelFormat::Bgra8888 => "BGRA8888",
394 PixelFormat::G1 => "G1",
395 PixelFormat::G2 => "G2",
396 PixelFormat::G4 => "G4",
397 PixelFormat::G8 => "G8",
398 PixelFormat::Ag88 => "AG88",
399 PixelFormat::Ga88 => "GA88",
400 PixelFormat::Pal1 => "PAL1",
401 PixelFormat::Pal2 => "PAL2",
402 PixelFormat::Pal4 => "PAL4",
403 PixelFormat::Pal8 => "PAL8",
404 }
405 }
406}
407
408impl From<&PixelFormat> for &'static str {
409 fn from(val: &PixelFormat) -> Self {
410 (*val).into()
411 }
412}
413
414impl fmt::Display for PixelFormat {
415 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
416 write!(f, "{}", <&str>::from(self))
417 }
418}
419
420#[cfg(test)]
421mod tests {
422 use super::*;
423
424 #[test]
425 fn test_1() -> Result<()> {
426 let mut dst = [0u8; 3];
427 let src = [0x46, 0xf3, 0xe5];
428
429 let exp_pixel_fmt = PixelFormat::Rgb888;
430 let mut pixel_fmt = PixelFormat::Rgb888;
431
432 pixel_fmt.normalize(dst.as_mut(), src.as_ref(), 1, 1)?;
433
434 assert_eq!(pixel_fmt, exp_pixel_fmt);
435 assert_eq!(dst, src);
436
437 Ok(())
438 }
439
440 #[test]
441 fn test_2() -> Result<()> {
442 let mut dst = [0u8; 3];
443 let src = [0x47, 0x9c];
444
445 let exp_pixel_fmt = PixelFormat::Rgb888;
446 let mut pixel_fmt = PixelFormat::Rgb555;
447
448 pixel_fmt.normalize(dst.as_mut(), src.as_ref(), 1, 1)?;
449
450 assert_eq!(pixel_fmt, exp_pixel_fmt);
451 assert_eq!(
452 ((dst[0] as u32 >> 3) << 10) | ((dst[1] as u32 >> 3) << 5) | (dst[2] as u32 >> 3),
453 (src[0] as u32) << 8 | src[1] as u32,
454 );
455
456 Ok(())
457 }
458
459 #[test]
460 fn test_3() -> Result<()> {
461 let mut dst = [0u8; 3];
462 let src = [0x47, 0x9c];
463
464 let exp_pixel_fmt = PixelFormat::Rgb888;
465 let mut pixel_fmt = PixelFormat::Rgb565;
466
467 pixel_fmt.normalize(dst.as_mut(), src.as_ref(), 1, 1)?;
468
469 assert_eq!(pixel_fmt, exp_pixel_fmt);
470 assert_eq!(
471 ((dst[0] as u32 >> 3) << 11) | ((dst[1] as u32 >> 2) << 5) | (dst[2] as u32 >> 3),
472 (src[0] as u32) << 8 | src[1] as u32,
473 );
474
475 Ok(())
476 }
477
478 #[test]
479 fn test_4() -> Result<()> {
480 let mut dst = [0u8; 3];
481 let src = [0x46, 0xf3, 0xe5];
482
483 let exp_pixel_fmt = PixelFormat::Rgb888;
484 let mut pixel_fmt = PixelFormat::Bgr888;
485
486 pixel_fmt.normalize(dst.as_mut(), src.as_ref(), 1, 1)?;
487
488 assert_eq!(pixel_fmt, exp_pixel_fmt);
489 assert_eq!(
490 ((dst[2] as u32) << 16) | ((dst[1] as u32) << 8) | (dst[0] as u32),
491 ((src[0] as u32) << 16) | ((src[1] as u32) << 8) | (src[2] as u32),
492 );
493
494 Ok(())
495 }
496
497 #[test]
498 fn test_5() -> Result<()> {
499 let mut dst = [0u8; 3];
500 let src = [0x23, 0xc8];
501
502 let exp_pixel_fmt = PixelFormat::Rgb888;
503 let mut pixel_fmt = PixelFormat::Bgr555;
504
505 pixel_fmt.normalize(dst.as_mut(), src.as_ref(), 1, 1)?;
506
507 assert_eq!(pixel_fmt, exp_pixel_fmt);
508 assert_eq!(
509 ((dst[2] as u32 >> 3) << 10) | ((dst[1] as u32 >> 3) << 5) | (dst[0] as u32 >> 3),
510 (src[0] as u32) << 8 | src[1] as u32,
511 );
512
513 Ok(())
514 }
515
516 #[test]
517 fn test_6() -> Result<()> {
518 let mut dst = [0u8; 3];
519 let src = [0x47, 0x88];
520
521 let exp_pixel_fmt = PixelFormat::Rgb888;
522 let mut pixel_fmt = PixelFormat::Bgr565;
523
524 pixel_fmt.normalize(dst.as_mut(), src.as_ref(), 1, 1)?;
525
526 assert_eq!(pixel_fmt, exp_pixel_fmt);
527 assert_eq!(
528 ((dst[2] as u32 >> 3) << 11) | ((dst[1] as u32 >> 2) << 5) | (dst[0] as u32 >> 3),
529 (src[0] as u32) << 8 | src[1] as u32,
530 );
531
532 Ok(())
533 }
534
535 #[test]
536 fn test_7() -> Result<()> {
537 let mut dst = [0u8; 3];
538 let src = [0x47, 0x88];
539
540 let exp_pixel_fmt = PixelFormat::Rgb888;
541 let mut pixel_fmt = PixelFormat::Ag88;
542
543 pixel_fmt.normalize(dst.as_mut(), src.as_ref(), 1, 1)?;
544
545 assert_eq!(pixel_fmt, exp_pixel_fmt);
546 assert_eq!(dst[0], src[1]);
547
548 Ok(())
549 }
550
551 #[test]
552 fn test_8() -> Result<()> {
553 let mut dst = [0u8; 3];
554 let src = [0x47, 0x88];
555
556 let exp_pixel_fmt = PixelFormat::Rgb888;
557 let mut pixel_fmt = PixelFormat::Ga88;
558
559 pixel_fmt.normalize(dst.as_mut(), src.as_ref(), 1, 1)?;
560
561 assert_eq!(pixel_fmt, exp_pixel_fmt);
562 assert_eq!(dst[0], src[0]);
563
564 Ok(())
565 }
566
567 #[test]
568 fn test_9() -> Result<()> {
569 let mut dst = [0u8; 3];
570 let src = [0x46, 0xf3, 0xe5, 0xf0];
571
572 let exp_pixel_fmt = PixelFormat::Rgb888;
573 let mut pixel_fmt = PixelFormat::Rgba8888;
574
575 pixel_fmt.normalize(dst.as_mut(), src.as_ref(), 1, 1)?;
576
577 assert_eq!(pixel_fmt, exp_pixel_fmt);
578 assert_eq!(dst.as_ref(), &src[..3]);
579
580 Ok(())
581 }
582
583 #[test]
584 fn test_10() -> Result<()> {
585 let mut dst = [0u8; 3];
586 let src = [0x46, 0xf3, 0xe5, 0xf0];
587
588 let exp_pixel_fmt = PixelFormat::Rgb888;
589 let mut pixel_fmt = PixelFormat::Argb8888;
590
591 pixel_fmt.normalize(dst.as_mut(), src.as_ref(), 1, 1)?;
592
593 assert_eq!(pixel_fmt, exp_pixel_fmt);
594 assert_eq!(dst.as_ref(), &src[1..]);
595
596 Ok(())
597 }
598}