use core::num::NonZeroU16;
use crate::parser::{FromData, LazyArray16, Offset, Offset32, Stream};
use crate::RgbaColor;
#[derive(Clone, Copy, Debug)]
pub struct Table<'a> {
color_indices: LazyArray16<'a, u16>,
colors: LazyArray16<'a, BgraColor>,
}
impl<'a> Table<'a> {
pub fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let version = s.read::<u16>()?;
if version > 1 {
return None;
}
s.skip::<u16>(); let num_palettes = s.read::<u16>()?;
if num_palettes == 0 {
return None; }
let num_colors = s.read::<u16>()?;
let color_records_offset = s.read::<Offset32>()?;
let color_indices = s.read_array16::<u16>(num_palettes)?;
let colors = Stream::new_at(data, color_records_offset.to_usize())?
.read_array16::<BgraColor>(num_colors)?;
Some(Self {
color_indices,
colors,
})
}
pub fn palettes(&self) -> NonZeroU16 {
NonZeroU16::new(self.color_indices.len()).unwrap()
}
pub fn get(&self, palette_index: u16, palette_entry: u16) -> Option<RgbaColor> {
let index = self
.color_indices
.get(palette_index)?
.checked_add(palette_entry)?;
self.colors.get(index).map(|c| c.to_rgba())
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
struct BgraColor {
blue: u8,
green: u8,
red: u8,
alpha: u8,
}
impl BgraColor {
#[inline]
fn to_rgba(self) -> RgbaColor {
RgbaColor::new(self.red, self.green, self.blue, self.alpha)
}
}
impl FromData for BgraColor {
const SIZE: usize = 4;
fn parse(data: &[u8]) -> Option<Self> {
let mut s = Stream::new(data);
Some(Self {
blue: s.read::<u8>()?,
green: s.read::<u8>()?,
red: s.read::<u8>()?,
alpha: s.read::<u8>()?,
})
}
}