#![forbid(unsafe_code)]
use crate::c_types::{ColorMapObject, GifColorType, GifPixelType, SavedImage};
use core::ffi::c_int;
impl ColorMapObject {
pub fn bit_size(n: c_int) -> c_int {
(1..=8).find(|&i| (1 << i) >= n).unwrap_or(9)
}
pub fn union_with(
&self,
other: &ColorMapObject,
trans: &mut [GifPixelType],
) -> Option<ColorMapObject> {
let c1_colors = self.colors();
let c2_colors = other.colors();
let max_count = self.ColorCount.max(other.ColorCount).checked_mul(2)?;
let mut color_union = ColorMapObject::new(max_count).ok()?;
let mut cu_colors = color_union.colors_mut();
cu_colors[..c1_colors.len()].copy_from_slice(c1_colors);
let mut crnt_slot = c1_colors
.iter()
.rposition(|c| c.Red != 0 || c.Green != 0 || c.Blue != 0)
.map_or(0, |i| i + 1);
for (i, c2_color) in c2_colors.iter().enumerate() {
if crnt_slot >= max_count as usize {
break;
}
if let Some(j) = c1_colors.iter().position(|c| {
c.Red == c2_color.Red && c.Green == c2_color.Green && c.Blue == c2_color.Blue
}) {
trans[i] = j as GifPixelType;
} else {
cu_colors[crnt_slot] = *c2_color;
trans[i] = crnt_slot as GifPixelType;
crnt_slot += 1;
}
}
if crnt_slot > max_count as usize {
return None;
}
let new_bit_size = Self::bit_size(crnt_slot as c_int);
let round_up_to = 1usize << new_bit_size;
if round_up_to > max_count as usize {
return None;
}
let zero = GifColorType { Red: 0, Green: 0, Blue: 0 };
cu_colors[crnt_slot..round_up_to].fill(zero);
if round_up_to != max_count as usize {
let mut result = ColorMapObject::from_slice(&cu_colors[..round_up_to]).ok()?;
result.BitsPerPixel = new_bit_size;
return Some(result);
}
drop(cu_colors);
color_union.ColorCount = round_up_to as c_int;
color_union.BitsPerPixel = new_bit_size;
Some(color_union)
}
}
impl SavedImage {
pub fn apply_translation(&mut self, translation: &[GifPixelType; 256]) {
for pixel in self.raster_bits_mut() {
*pixel = translation[*pixel as usize];
}
}
}