tinyvg_rs/
color_table.rs

1use std::io::Cursor;
2use byteorder::{LittleEndian, ReadBytesExt};
3use crate::{TinyVgParseError};
4use crate::header::{ColorEncoding, TinyVgHeader};
5#[derive(Debug, Copy, Clone, PartialEq)]
6pub struct RgbaF32(pub f32, pub f32, pub f32, pub f32);
7
8pub type ColorTable = Vec<RgbaF32>;
9
10pub(crate) fn parse_color_table(cursor: &mut Cursor<&[u8]>, header: &TinyVgHeader) -> Result<ColorTable, TinyVgParseError> {
11    let mut color_table_rgba_f32 = Vec::with_capacity(header.color_count as usize);
12
13    for _ in 0..header.color_count {
14        match header.color_encoding {
15            ColorEncoding::Rgba8888 => {
16                let r = cursor.read_u8().map_err(|_| TinyVgParseError::InvalidColorTable)? as f32;
17                let g = cursor.read_u8().map_err(|_| TinyVgParseError::InvalidColorTable)? as f32;
18                let b = cursor.read_u8().map_err(|_| TinyVgParseError::InvalidColorTable)? as f32;
19                let a = cursor.read_u8().map_err(|_| TinyVgParseError::InvalidColorTable)? as f32;
20                color_table_rgba_f32.push(RgbaF32(r / 255.0, g / 255.0, b / 255.0, a / 255.0));
21            }
22            ColorEncoding::Rgb565 => {
23                let color = cursor.read_u16::<LittleEndian>().map_err(|_| TinyVgParseError::InvalidColorTable)?;
24                const FIVE_BIT_MASK: u16 = 31;
25                const SIX_BIT_MASK: u16 = 63;
26                // Red color channel between 0 and 100% intensity, mapped to integer values 0 to 31.
27                let red: u8 = (color & FIVE_BIT_MASK) as u8;
28                // Green color channel between 0 and 100% intensity, mapped to integer values 0 to 63.
29                let green: u8 = ((color >> 5) & SIX_BIT_MASK) as u8;
30                // Blue color channel between 0 and 100% intensity, mapped to integer values 0 to 31.
31                let blue: u8 = ((color >> 11) & FIVE_BIT_MASK) as u8;
32                color_table_rgba_f32.push(RgbaF32(red as f32 / 31.0, green as f32 / 63.0, blue as f32 / 31.0, 1.0));
33            }
34            ColorEncoding::RgbaF32 => {
35                let r = cursor.read_f32::<LittleEndian>().map_err(|_| TinyVgParseError::InvalidColorTable)?;
36                let g = cursor.read_f32::<LittleEndian>().map_err(|_| TinyVgParseError::InvalidColorTable)?;
37                let b = cursor.read_f32::<LittleEndian>().map_err(|_| TinyVgParseError::InvalidColorTable)?;
38                let a = cursor.read_f32::<LittleEndian>().map_err(|_| TinyVgParseError::InvalidColorTable)?;
39
40                color_table_rgba_f32.push(RgbaF32(r, g, b, a));
41            }
42            ColorEncoding::Custom => unreachable!("Custom color encoding not supported.")
43
44        }
45    }
46
47    Ok(color_table_rgba_f32)
48}