use alloc::vec::Vec;
pub const HASH_BITS: u32 = 18;
pub const HASH_SIZE: usize = 1 << HASH_BITS;
pub const MAX_LENGTH_BITS: u32 = 12;
pub const WINDOW_SIZE_BITS: u32 = 20;
pub const MAX_LENGTH: usize = (1 << MAX_LENGTH_BITS) - 1;
pub const WINDOW_SIZE: usize = (1 << WINDOW_SIZE_BITS) - 120;
pub const MIN_LENGTH: usize = 4;
pub const NUM_LITERAL_CODES: usize = 256;
pub const NUM_LENGTH_CODES: usize = 24;
pub const NUM_DISTANCE_CODES: usize = 40;
pub const ALPHABET_SIZE_GREEN: usize = NUM_LITERAL_CODES + NUM_LENGTH_CODES; pub const ALPHABET_SIZE_RED: usize = 256;
pub const ALPHABET_SIZE_BLUE: usize = 256;
pub const ALPHABET_SIZE_ALPHA: usize = 256;
pub const ALPHABET_SIZE_DISTANCE: usize = NUM_DISTANCE_CODES;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Vp8lQuality {
pub quality: u8,
pub method: u8,
}
impl Default for Vp8lQuality {
fn default() -> Self {
Self {
quality: 75,
method: 4,
}
}
}
impl Vp8lQuality {
pub fn max_iters(&self) -> usize {
8 + (self.quality as usize * self.quality as usize) / 128
}
pub fn window_size(&self, width: usize) -> usize {
let max = if self.quality > 75 {
WINDOW_SIZE
} else if self.quality > 50 {
width << 8
} else if self.quality > 25 {
width << 6
} else {
width << 4
};
max.min(WINDOW_SIZE)
}
}
#[derive(Debug, Clone)]
pub struct Vp8lConfig {
pub quality: Vp8lQuality,
pub cache_bits: Option<u8>,
pub near_lossless: u8,
pub use_predictor: bool,
pub use_cross_color: bool,
pub use_subtract_green: bool,
pub use_palette: bool,
pub use_meta_huffman: bool,
pub predictor_bits: u8,
pub cross_color_bits: u8,
}
impl Default for Vp8lConfig {
fn default() -> Self {
Self {
quality: Vp8lQuality::default(),
cache_bits: None, near_lossless: 100, use_predictor: true,
use_cross_color: true, use_subtract_green: true,
use_palette: true,
use_meta_huffman: true, predictor_bits: 0, cross_color_bits: 0, }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PixOrCopy {
Literal(u32),
CacheIdx(u16),
Copy {
len: u16,
dist: u32,
},
}
impl PixOrCopy {
#[inline]
pub fn literal(argb: u32) -> Self {
Self::Literal(argb)
}
#[inline]
pub fn cache_idx(idx: u16) -> Self {
Self::CacheIdx(idx)
}
#[inline]
pub fn copy(len: u16, dist: u32) -> Self {
Self::Copy { len, dist }
}
#[inline]
pub fn is_literal(&self) -> bool {
matches!(self, Self::Literal(_))
}
#[inline]
pub fn is_cache(&self) -> bool {
matches!(self, Self::CacheIdx(_))
}
#[inline]
pub fn is_copy(&self) -> bool {
matches!(self, Self::Copy { .. })
}
#[inline]
pub fn copy_len(&self) -> u16 {
match self {
Self::Copy { len, .. } => *len,
_ => 0,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct BackwardRefs {
pub tokens: Vec<PixOrCopy>,
}
impl BackwardRefs {
pub fn new() -> Self {
Self { tokens: Vec::new() }
}
pub fn with_capacity(cap: usize) -> Self {
Self {
tokens: Vec::with_capacity(cap),
}
}
#[inline]
pub fn push(&mut self, token: PixOrCopy) {
self.tokens.push(token);
}
pub fn clear(&mut self) {
self.tokens.clear();
}
pub fn len(&self) -> usize {
self.tokens.len()
}
pub fn is_empty(&self) -> bool {
self.tokens.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &PixOrCopy> {
self.tokens.iter()
}
}
#[inline]
pub const fn argb_alpha(argb: u32) -> u8 {
(argb >> 24) as u8
}
#[inline]
pub const fn argb_red(argb: u32) -> u8 {
(argb >> 16) as u8
}
#[inline]
pub const fn argb_green(argb: u32) -> u8 {
(argb >> 8) as u8
}
#[inline]
pub const fn argb_blue(argb: u32) -> u8 {
argb as u8
}
#[inline]
pub const fn make_argb(a: u8, r: u8, g: u8, b: u8) -> u32 {
((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32)
}
#[inline]
pub const fn subsample_size(size: u32, bits: u8) -> u32 {
(size + (1 << bits) - 1) >> bits
}