use crate::{wan_read_raw_4, WanError};
use binwrite::BinWrite;
use byteorder::{ReadBytesExt, LE};
use std::io::{Read, Seek, SeekFrom, Write};
#[derive(PartialEq, Eq, Debug, Default)]
pub struct Palette {
pub palette: Vec<[u8; 4]>,
}
impl Palette {
pub fn new_from_bytes<F: Read + Seek>(file: &mut F) -> Result<Palette, WanError> {
let mut palette = Vec::new();
let pointer_palette_start = file.read_u32::<LE>()? as u64;
trace!("start of palette : {}", pointer_palette_start);
file.read_u16::<LE>()?;
let nb_color = file.read_u16::<LE>()?;
wan_read_raw_4(file)?;
trace!(
"palette_start: {}, nb_color: {}",
pointer_palette_start,
nb_color
);
if file.read_u32::<LE>()? != 0 {
return Err(WanError::PaletteDontEndWithZero);
};
file.seek(SeekFrom::Start(pointer_palette_start))?;
for _ in 0..nb_color {
let red = file.read_u8()?;
let green = file.read_u8()?;
let blue = file.read_u8()?;
let alpha = file.read_u8()?;
palette.push([red, green, blue, alpha]);
}
Ok(Palette { palette })
}
pub fn get(&self, id: u8, palette_id: u16) -> Option<[u8; 4]> {
let id = (id as usize).saturating_add(palette_id as usize * 16);
if id >= self.palette.len() {
return None;
};
Some(self.palette[id])
}
#[allow(dead_code)]
pub fn color_id(&self, target_color: [u8; 4], palette_id: u16) -> Result<usize, WanError> {
for color_id in (palette_id as usize) * 16..(palette_id as usize) * 16 + self.palette.len()
{
if self.palette[color_id] == target_color {
return Ok(color_id);
}
}
error!("impossible to find the palette {:?}", target_color);
error!("tried :");
for color in &self.palette {
error!("{:?}", color);
}
Err(WanError::CantFindColorInPalette)
}
pub fn write<F: Write + Seek>(&self, file: &mut F) -> Result<u64, WanError> {
let start_offset = file.seek(SeekFrom::Current(0))?;
for color in &self.palette {
color.write(file)?;
}
let header_offset = file.seek(SeekFrom::Current(0))?;
(
start_offset as u32,
0u16, self.palette.len() as u16,
(0xFF << 16) as u32, 0u32, )
.write(file)?;
Ok(header_offset)
}
}