use crate::once::OnceBox;
use crate::tables::astc::G_ETC1_TO_ASTC;
use crate::tables::astc_0_255::G_ETC1_TO_ASTC_0_255;
use crate::tables::solution::Etc1ToSolution;
use alloc::boxed::Box;
pub static SELECTOR_RANGES: [[u8; 2]; 6] = [[0, 3], [1, 3], [0, 2], [1, 2], [2, 3], [0, 1]];
pub const NUM_SELECTOR_RANGES: usize = 6;
pub const NUM_SELECTOR_MAPPINGS: usize = 10;
pub static SELECTOR_MAPPINGS: [[u8; 4]; NUM_SELECTOR_MAPPINGS] = [
[0, 0, 1, 1],
[0, 0, 1, 2],
[0, 0, 1, 3],
[0, 0, 2, 3],
[0, 1, 1, 1],
[0, 1, 2, 2],
[0, 1, 2, 3],
[0, 2, 3, 3],
[1, 2, 2, 2],
[1, 2, 3, 3],
];
pub fn build_ise_to_unquant() -> [u32; 48] {
let mut t = [0u32; 48];
for trit in 0..3u32 {
for bit in 0..16u32 {
let a = if bit & 1 != 0 { 511 } else { 0 };
let b = (bit >> 1) | ((bit >> 1) << 6);
let c = 22u32;
let d = trit;
let mut unq = d * c + b;
unq ^= a;
unq = (a & 0x80) | (unq >> 2);
t[(bit | (trit << 4)) as usize] = unq;
}
}
t
}
pub fn build_selector_range_index() -> [[u32; 4]; 4] {
let mut t = [[0u32; 4]; 4];
for (i, r) in SELECTOR_RANGES.iter().enumerate() {
t[r[0] as usize][r[1] as usize] = i as u32;
}
t
}
fn build_best_grayscale_mapping(
table: &[Etc1ToSolution],
) -> Box<[[[u8; NUM_SELECTOR_RANGES]; 8]; 32]> {
let mut out = Box::new([[[0u8; NUM_SELECTOR_RANGES]; 8]; 32]);
for base in 0..32usize {
for inten in 0..8usize {
for range in 0..NUM_SELECTOR_RANGES {
let base_idx = (inten * 32 + base) * (NUM_SELECTOR_RANGES * NUM_SELECTOR_MAPPINGS)
+ range * NUM_SELECTOR_MAPPINGS;
let mut best_mapping = 0u8;
let mut best_err = u32::MAX;
for m in 0..NUM_SELECTOR_MAPPINGS {
let err = table[base_idx + m].m_err as u32;
if err < best_err {
best_err = err;
best_mapping = m as u8;
}
}
out[base][inten][range] = best_mapping;
}
}
}
out
}
pub fn build_best_grayscale_mapping_47() -> Box<[[[u8; NUM_SELECTOR_RANGES]; 8]; 32]> {
build_best_grayscale_mapping(&G_ETC1_TO_ASTC)
}
pub fn build_best_grayscale_mapping_0_255() -> Box<[[[u8; NUM_SELECTOR_RANGES]; 8]; 32]> {
build_best_grayscale_mapping(&G_ETC1_TO_ASTC_0_255)
}
pub fn build_single_color_encoding_1(ise: &[u32; 48]) -> [[u8; 2]; 256] {
let mut t = [[0u8; 2]; 256];
for (i, e) in t.iter_mut().enumerate() {
let mut lowest_e = i32::MAX;
for (lo, &lo_u) in ise.iter().enumerate() {
let lo_v = lo_u as i32;
for (hi, &hi_u) in ise.iter().enumerate() {
let hi_v = hi_u as i32;
let l = lo_v | (lo_v << 8);
let h = hi_v | (hi_v << 8);
let v = ((l * (64 - 21) + h * 21 + 32) / 64) >> 8;
let err = (v - i as i32).abs();
if err < lowest_e {
e[0] = lo as u8; e[1] = hi as u8; lowest_e = err;
}
}
}
}
t
}
pub fn selector_range_index() -> &'static [[u32; 4]; 4] {
static T: OnceBox<[[u32; 4]; 4]> = OnceBox::new();
T.get_or_init(|| Box::new(build_selector_range_index()))
}
pub fn best_grayscale_mapping_0_255() -> &'static [[[u8; NUM_SELECTOR_RANGES]; 8]; 32] {
static T: OnceBox<[[[u8; NUM_SELECTOR_RANGES]; 8]; 32]> = OnceBox::new();
T.get_or_init(build_best_grayscale_mapping_0_255)
}
pub fn best_grayscale_mapping_47() -> &'static [[[u8; NUM_SELECTOR_RANGES]; 8]; 32] {
static T: OnceBox<[[[u8; NUM_SELECTOR_RANGES]; 8]; 32]> = OnceBox::new();
T.get_or_init(build_best_grayscale_mapping_47)
}
pub fn ise_to_unquant() -> &'static [u32; 48] {
static T: OnceBox<[u32; 48]> = OnceBox::new();
T.get_or_init(|| Box::new(build_ise_to_unquant()))
}
pub fn single_color_encoding_0() -> &'static [u8; 256] {
static T: OnceBox<[u8; 256]> = OnceBox::new();
T.get_or_init(|| Box::new(build_single_color_encoding_0(ise_to_unquant())))
}
pub fn single_color_encoding_1() -> &'static [[u8; 2]; 256] {
static T: OnceBox<[[u8; 2]; 256]> = OnceBox::new();
T.get_or_init(|| Box::new(build_single_color_encoding_1(ise_to_unquant())))
}
pub fn build_single_color_encoding_0(ise: &[u32; 48]) -> [u8; 256] {
let mut t = [0u8; 256];
for (i, e) in t.iter_mut().enumerate() {
let mut lowest_e = i32::MAX;
for (lo, &lo_u) in ise.iter().enumerate() {
let err = (lo_u as i32 - i as i32).abs();
if err < lowest_e {
*e = lo as u8;
lowest_e = err;
}
}
}
t
}