use super::amf::ApproxMoveToFront;
use super::decoder::BitwiseDecoder;
use super::huffman::HuffmanDecodingTable;
use crate::color::Color32;
use crate::etc::block::DecoderEtcBlock;
use crate::etc::tables::SELECTOR_INDEX_TO_ETC1;
use alloc::vec::Vec;
const COLOR5_PAL0_PREV_HI: i32 = 9;
const COLOR5_PAL1_PREV_HI: i32 = 21;
#[inline]
fn mul_8(v: u32, q: u32) -> u32 {
let v = v * q + 128;
(v + (v >> 8)) >> 8
}
const ENDPOINT_PRED_REPEAT_LAST_SYMBOL: u32 = (4 * 4 * 4 * 4 + 1) - 1;
const ENDPOINT_PRED_MIN_REPEAT_COUNT: u32 = 3;
const ENDPOINT_PRED_COUNT_VLC_BITS: u32 = 4;
const SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH: u32 = 3;
const SELECTOR_HISTORY_BUF_RLE_COUNT_TOTAL: u32 = 1 << 6;
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug)]
pub struct Endpoint {
pub color5: Color32,
pub inten5: u8,
}
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug)]
pub struct Selector {
pub selectors: [u8; 4],
pub bytes: [u8; 4],
pub lo_selector: u8,
pub hi_selector: u8,
pub num_unique_selectors: u8,
}
impl Selector {
pub fn get_selector(&self, x: u32, y: u32) -> u32 {
((self.selectors[y as usize] >> (x * 2)) & 3) as u32
}
pub fn set_selector(&mut self, x: u32, y: u32, val: u32) {
self.selectors[y as usize] &= !(3 << (x * 2));
self.selectors[y as usize] |= (val << (x * 2)) as u8;
let etc1_bit_index = x * 4 + y;
let pi = (3 - (etc1_bit_index >> 3)) as usize;
let byte_bit_ofs = etc1_bit_index & 7;
let mask = 1u8 << byte_bit_ofs;
let etc1_val = SELECTOR_INDEX_TO_ETC1[val as usize] as u32;
let lsb = (etc1_val & 1) as u8;
let msb = (etc1_val >> 1) as u8;
self.bytes[pi] &= !mask;
self.bytes[pi] |= lsb << byte_bit_ofs;
self.bytes[pi - 2] &= !mask;
self.bytes[pi - 2] |= msb << byte_bit_ofs;
}
pub fn init_flags(&mut self) {
let mut hist = [0u32; 4];
for y in 0..4 {
for x in 0..4 {
hist[self.get_selector(x, y) as usize] += 1;
}
}
self.lo_selector = 3;
self.hi_selector = 0;
self.num_unique_selectors = 0;
for i in 0..4u8 {
if hist[i as usize] != 0 {
self.num_unique_selectors += 1;
if i < self.lo_selector {
self.lo_selector = i;
}
if i > self.hi_selector {
self.hi_selector = i;
}
}
}
}
}
pub fn convert_etc1s_to_etc1(ep: &Endpoint, sel: &Selector) -> [u8; 8] {
let mut blk = DecoderEtcBlock::new();
blk.set_flip_bit(false);
blk.set_diff_bit(true);
blk.set_base5_color(DecoderEtcBlock::pack_color5_unscaled(ep.color5));
blk.set_inten_table(0, ep.inten5 as u32);
blk.set_inten_table(1, ep.inten5 as u32);
let mut out = [0u8; 8];
out[0..4].copy_from_slice(&blk.m_bytes[0..4]);
out[4..8].copy_from_slice(&sel.bytes);
out
}
pub const MAX_PREV_FRAME_LEVELS: usize = 16;
#[derive(Default)]
pub struct VideoState {
prev_frame_indices: [[Vec<u32>; MAX_PREV_FRAME_LEVELS]; 2],
}
impl VideoState {
pub fn new() -> Self {
Self::default()
}
pub fn reset(&mut self) {
for per_level in &mut self.prev_frame_indices {
for v in per_level {
v.clear();
}
}
}
pub(crate) fn slots(
&mut self,
level: usize,
total_blocks: usize,
) -> (&mut Vec<u32>, &mut Vec<u32>) {
let [color, alpha] = &mut self.prev_frame_indices;
let (c, a) = (&mut color[level], &mut alpha[level]);
if c.len() < total_blocks {
c.resize(total_blocks, 0);
}
if a.len() < total_blocks {
a.resize(total_blocks, 0);
}
(c, a)
}
}
#[derive(Default)]
pub struct Etc1sTranscoder {
pub endpoints: Vec<Endpoint>,
pub selectors: Vec<Selector>,
pub endpoint_pred_model: HuffmanDecodingTable,
pub delta_endpoint_model: HuffmanDecodingTable,
pub selector_model: HuffmanDecodingTable,
pub selector_history_buf_rle_model: HuffmanDecodingTable,
pub selector_history_buf_size: u32,
}
impl Etc1sTranscoder {
pub fn new() -> Self {
Self::default()
}
pub fn with_global_codebook(
endpoints: Vec<Endpoint>,
selectors: Vec<Selector>,
tables: &[u8],
) -> Option<Self> {
let mut dec = Self {
endpoints,
selectors,
..Self::default()
};
dec.decode_tables(tables).then_some(dec)
}
pub fn decode_palettes(
&mut self,
num_endpoints: u32,
endpoints_data: &[u8],
num_selectors: u32,
selectors_data: &[u8],
) -> bool {
let mut sym = BitwiseDecoder::new(endpoints_data);
let (mut m0, mut m1, mut m2, mut im) = (
HuffmanDecodingTable::new(),
HuffmanDecodingTable::new(),
HuffmanDecodingTable::new(),
HuffmanDecodingTable::new(),
);
if !sym.read_huffman_table(&mut m0)
|| !sym.read_huffman_table(&mut m1)
|| !sym.read_huffman_table(&mut m2)
|| !sym.read_huffman_table(&mut im)
{
return false;
}
if !m0.is_valid() || !m1.is_valid() || !m2.is_valid() || !im.is_valid() {
return false;
}
let grayscale = sym.get_bits(1) != 0;
self.endpoints = vec![Endpoint::default(); num_endpoints as usize];
let mut prev_color5 = Color32::new(16, 16, 16, 0);
let mut prev_inten = 0u32;
for e in self.endpoints.iter_mut() {
let inten_delta = sym.decode_huffman(&im);
e.inten5 = ((inten_delta + prev_inten) & 7) as u8;
prev_inten = e.inten5 as u32;
let nc = if grayscale { 1 } else { 3 };
for c in 0..nc {
let prev = prev_color5[c] as i32;
let delta = if prev <= COLOR5_PAL0_PREV_HI {
sym.decode_huffman(&m0)
} else if prev <= COLOR5_PAL1_PREV_HI {
sym.decode_huffman(&m1)
} else {
sym.decode_huffman(&m2)
};
let v = ((prev + delta as i32) & 31) as u8;
e.color5[c] = v;
prev_color5[c] = v;
}
if grayscale {
e.color5[1] = e.color5[0];
e.color5[2] = e.color5[0];
}
}
let mut sym = BitwiseDecoder::new(selectors_data);
self.selectors = vec![Selector::default(); num_selectors as usize];
if sym.get_bits(1) == 1 {
return false; }
if sym.get_bits(1) == 1 {
return false; }
let used_raw = sym.get_bits(1) == 1;
if used_raw {
for s in self.selectors.iter_mut() {
for j in 0..4u32 {
let cur = sym.get_bits(8);
for k in 0..4u32 {
s.set_selector(k, j, (cur >> (k * 2)) & 3);
}
}
s.init_flags();
}
} else {
let mut dm = HuffmanDecodingTable::new();
if !sym.read_huffman_table(&mut dm) {
return false;
}
if num_selectors > 1 && !dm.is_valid() {
return false;
}
let mut prev_bytes = [0u8; 4];
for (i, s) in self.selectors.iter_mut().enumerate() {
if i == 0 {
for j in 0..4u32 {
let cur = sym.get_bits(8);
prev_bytes[j as usize] = cur as u8;
for k in 0..4u32 {
s.set_selector(k, j, (cur >> (k * 2)) & 3);
}
}
s.init_flags();
continue;
}
for j in 0..4u32 {
let delta_byte = sym.decode_huffman(&dm);
let cur = delta_byte ^ prev_bytes[j as usize] as u32;
prev_bytes[j as usize] = cur as u8;
for k in 0..4u32 {
s.set_selector(k, j, (cur >> (k * 2)) & 3);
}
}
s.init_flags();
}
}
true
}
pub(crate) fn decode_slice_indices(
&self,
slice_data: &[u8],
num_blocks_x: u32,
num_blocks_y: u32,
mut video: Option<&mut Vec<u32>>,
) -> Option<Vec<(u16, u16)>> {
let total_blocks = num_blocks_x * num_blocks_y;
if self.endpoints.is_empty() || self.selectors.is_empty() {
return None;
}
let n_end = self.endpoints.len() as u32;
let n_sel = self.selectors.len() as u32;
let mut sym = BitwiseDecoder::new(slice_data);
let mut selector_history_buf =
ApproxMoveToFront::new(self.selector_history_buf_size as usize);
let mut cur_selector_rle_count = 0u32;
let mut preds: [Vec<(u8, u16)>; 2] = [
vec![(0u8, 0u16); num_blocks_x as usize],
vec![(0u8, 0u16); num_blocks_x as usize],
];
let mut cur_pred_bits = 0u32;
let mut prev_endpoint_pred_sym = 0u32;
let mut endpoint_pred_repeat_count = 0u32;
let mut prev_endpoint_index = 0u32;
let selector_rle_sym = self.selector_history_buf_size + n_sel;
let mut indices = vec![(0u16, 0u16); total_blocks as usize];
for block_y in 0..num_blocks_y {
let cur = (block_y & 1) as usize;
for block_x in 0..num_blocks_x {
let bx = block_x as usize;
if block_x & 1 == 0 {
if block_y & 1 == 0 {
if endpoint_pred_repeat_count != 0 {
endpoint_pred_repeat_count -= 1;
cur_pred_bits = prev_endpoint_pred_sym;
} else {
cur_pred_bits = sym.decode_huffman(&self.endpoint_pred_model);
if cur_pred_bits == ENDPOINT_PRED_REPEAT_LAST_SYMBOL {
endpoint_pred_repeat_count = sym
.decode_vlc(ENDPOINT_PRED_COUNT_VLC_BITS)
+ ENDPOINT_PRED_MIN_REPEAT_COUNT
- 1;
cur_pred_bits = prev_endpoint_pred_sym;
} else {
prev_endpoint_pred_sym = cur_pred_bits;
}
}
preds[cur ^ 1][bx].0 = (cur_pred_bits >> 4) as u8;
} else {
cur_pred_bits = preds[cur][bx].0 as u32;
}
}
let pred = cur_pred_bits & 3;
cur_pred_bits >>= 2;
let mut cr_selector: Option<u32> = None;
let endpoint_index = match pred {
0 => {
if block_x == 0 {
return None;
}
prev_endpoint_index
}
1 => {
if block_y == 0 {
return None;
}
preds[cur ^ 1][bx].1 as u32
}
2 => {
if let Some(prev) = video.as_deref_mut() {
let v = prev[(block_x + block_y * num_blocks_x) as usize];
cr_selector = Some(v >> 16);
v & 0xFFFF
} else {
if block_x == 0 || block_y == 0 {
return None;
}
preds[cur ^ 1][bx - 1].1 as u32
}
}
_ => {
let delta = sym.decode_huffman(&self.delta_endpoint_model);
let mut ei = delta + prev_endpoint_index;
if ei >= n_end {
ei -= n_end;
}
ei
}
};
preds[cur][bx].1 = endpoint_index as u16;
prev_endpoint_index = endpoint_index;
let selector_index = if let Some(si) = cr_selector {
si
} else {
let mut selector_sym: u32;
if cur_selector_rle_count > 0 {
cur_selector_rle_count -= 1;
selector_sym = n_sel;
} else {
selector_sym = sym.decode_huffman(&self.selector_model);
if selector_sym == selector_rle_sym {
let run_sym = sym.decode_huffman(&self.selector_history_buf_rle_model);
cur_selector_rle_count =
if run_sym == SELECTOR_HISTORY_BUF_RLE_COUNT_TOTAL - 1 {
sym.decode_vlc(7) + SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH
} else {
run_sym + SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH
};
if cur_selector_rle_count > total_blocks {
return None;
}
selector_sym = n_sel;
cur_selector_rle_count -= 1;
}
}
if selector_sym >= n_sel {
let hbi = (selector_sym - n_sel) as usize;
if hbi >= selector_history_buf.size() {
return None;
}
let si = selector_history_buf.get(hbi) as u32;
if hbi != 0 {
selector_history_buf.use_index(hbi);
}
si
} else {
if self.selector_history_buf_size != 0 {
selector_history_buf.add(selector_sym as i32);
}
selector_sym
}
};
if endpoint_index >= n_end || selector_index >= n_sel {
return None;
}
if let Some(prev) = video.as_deref_mut() {
prev[(block_x + block_y * num_blocks_x) as usize] =
endpoint_index | (selector_index << 16);
}
indices[(block_x + block_y * num_blocks_x) as usize] =
(endpoint_index as u16, selector_index as u16);
}
}
Some(indices)
}
pub fn transcode_slice_etc1(
&self,
slice_data: &[u8],
num_blocks_x: u32,
num_blocks_y: u32,
video: Option<&mut Vec<u32>>,
out: &mut [u8],
) -> Option<()> {
let indices = self.decode_slice_indices(slice_data, num_blocks_x, num_blocks_y, video)?;
if out.len() != indices.len() * 8 {
return None;
}
out.fill(0);
for (b, &(ei, si)) in indices.iter().enumerate() {
let block =
convert_etc1s_to_etc1(&self.endpoints[ei as usize], &self.selectors[si as usize]);
out[b * 8..b * 8 + 8].copy_from_slice(&block);
}
Some(())
}
pub fn transcode_slice_pvrtc1_4_rgb(
&self,
slice_data: &[u8],
num_blocks_x: u32,
num_blocks_y: u32,
video: Option<&mut Vec<u32>>,
out: &mut [u8],
) -> Option<()> {
let indices = self.decode_slice_indices(slice_data, num_blocks_x, num_blocks_y, video)?;
crate::pvrtc::transcode_etc1s_pvrtc1_4_rgb(
&indices,
&self.endpoints,
&self.selectors,
num_blocks_x,
num_blocks_y,
out,
)
}
pub fn transcode_slice_pvrtc1_4_rgba(
&self,
rgb_slice: &[u8],
alpha_slice: &[u8],
num_blocks_x: u32,
num_blocks_y: u32,
video: Option<(&mut Vec<u32>, &mut Vec<u32>)>,
out: &mut [u8],
) -> Option<()> {
let (vc, va) = match video {
Some((c, a)) => (Some(c), Some(a)),
None => (None, None),
};
let color = self.decode_slice_indices(rgb_slice, num_blocks_x, num_blocks_y, vc)?;
let alpha = self.decode_slice_indices(alpha_slice, num_blocks_x, num_blocks_y, va)?;
crate::pvrtc::transcode_etc1s_pvrtc1_4_rgba(
&color,
&alpha,
&self.endpoints,
&self.selectors,
num_blocks_x,
num_blocks_y,
out,
)
}
#[allow(clippy::too_many_arguments)]
pub fn transcode_slice_rgba32(
&self,
slice_data: &[u8],
num_blocks_x: u32,
num_blocks_y: u32,
width: u32,
height: u32,
video: Option<&mut Vec<u32>>,
out: &mut [u8],
) -> Option<()> {
let indices = self.decode_slice_indices(slice_data, num_blocks_x, num_blocks_y, video)?;
if out.len() != (width * height * 4) as usize {
return None;
}
out.fill(0);
for (b, &(ei, si)) in indices.iter().enumerate() {
let block_x = b as u32 % num_blocks_x;
let block_y = b as u32 / num_blocks_x;
let ep = &self.endpoints[ei as usize];
let sel = &self.selectors[si as usize];
let colors = DecoderEtcBlock::get_block_colors5(ep.color5, ep.inten5 as u32);
let max_x = (width as i32 - block_x as i32 * 4).clamp(0, 4) as u32;
let max_y = (height as i32 - block_y as i32 * 4).clamp(0, 4) as u32;
for y in 0..max_y {
let s = sel.selectors[y as usize] as u32;
for x in 0..max_x {
let c = colors[((s >> (x * 2)) & 3) as usize];
let px = ((block_x * 4 + x) + (block_y * 4 + y) * width) as usize * 4;
out[px] = c.r();
out[px + 1] = c.g();
out[px + 2] = c.b();
out[px + 3] = 255;
}
}
}
Some(())
}
#[allow(clippy::too_many_arguments)]
pub fn transcode_image_rgba32(
&self,
rgb_slice: &[u8],
alpha_slice: &[u8],
num_blocks_x: u32,
num_blocks_y: u32,
width: u32,
height: u32,
video: Option<(&mut Vec<u32>, &mut Vec<u32>)>,
out: &mut [u8],
) -> Option<()> {
let (vc, va) = match video {
Some((c, a)) => (Some(c), Some(a)),
None => (None, None),
};
self.transcode_slice_rgba32(
rgb_slice,
num_blocks_x,
num_blocks_y,
width,
height,
vc,
out,
)?;
let alpha = self.decode_slice_indices(alpha_slice, num_blocks_x, num_blocks_y, va)?;
for (b, &(aei, asi)) in alpha.iter().enumerate() {
let block_x = b as u32 % num_blocks_x;
let block_y = b as u32 / num_blocks_x;
let ep = &self.endpoints[aei as usize];
let sel = &self.selectors[asi as usize];
let acolors = DecoderEtcBlock::get_block_colors5_g(ep.color5, ep.inten5 as u32);
let max_x = (width as i32 - block_x as i32 * 4).clamp(0, 4) as u32;
let max_y = (height as i32 - block_y as i32 * 4).clamp(0, 4) as u32;
for y in 0..max_y {
let s = sel.selectors[y as usize] as u32;
for x in 0..max_x {
let a = acolors[((s >> (x * 2)) & 3) as usize] as u8;
let px = ((block_x * 4 + x) + (block_y * 4 + y) * width) as usize * 4;
out[px + 3] = a;
}
}
}
Some(())
}
#[allow(clippy::too_many_arguments)]
pub fn transcode_slice_565(
&self,
slice_data: &[u8],
num_blocks_x: u32,
num_blocks_y: u32,
width: u32,
height: u32,
bgr: bool,
video: Option<&mut Vec<u32>>,
out: &mut [u8],
) -> Option<()> {
let indices = self.decode_slice_indices(slice_data, num_blocks_x, num_blocks_y, video)?;
if out.len() != (width * height * 2) as usize {
return None;
}
out.fill(0);
for (b, &(ei, si)) in indices.iter().enumerate() {
let block_x = b as u32 % num_blocks_x;
let block_y = b as u32 / num_blocks_x;
let ep = &self.endpoints[ei as usize];
let sel = &self.selectors[si as usize];
let colors = DecoderEtcBlock::get_block_colors5(ep.color5, ep.inten5 as u32);
let mut packed = [0u16; 4];
for (i, c) in colors.iter().enumerate() {
packed[i] = if bgr {
((mul_8(c.b() as u32, 31) << 11)
| (mul_8(c.g() as u32, 63) << 5)
| mul_8(c.r() as u32, 31)) as u16
} else {
((mul_8(c.r() as u32, 31) << 11)
| (mul_8(c.g() as u32, 63) << 5)
| mul_8(c.b() as u32, 31)) as u16
};
}
let max_x = (width as i32 - block_x as i32 * 4).clamp(0, 4) as u32;
let max_y = (height as i32 - block_y as i32 * 4).clamp(0, 4) as u32;
for y in 0..max_y {
let s = sel.selectors[y as usize] as u32;
for x in 0..max_x {
let v = packed[((s >> (x * 2)) & 3) as usize];
let px = ((block_x * 4 + x) + (block_y * 4 + y) * width) as usize * 2;
out[px..px + 2].copy_from_slice(&v.to_le_bytes());
}
}
}
Some(())
}
#[allow(clippy::too_many_arguments)]
pub fn transcode_slice_rgba4444_opaque(
&self,
slice_data: &[u8],
num_blocks_x: u32,
num_blocks_y: u32,
width: u32,
height: u32,
video: Option<&mut Vec<u32>>,
out: &mut [u8],
) -> Option<()> {
let indices = self.decode_slice_indices(slice_data, num_blocks_x, num_blocks_y, video)?;
if out.len() != (width * height * 2) as usize {
return None;
}
out.fill(0);
for (b, &(ei, si)) in indices.iter().enumerate() {
let block_x = b as u32 % num_blocks_x;
let block_y = b as u32 / num_blocks_x;
let ep = &self.endpoints[ei as usize];
let sel = &self.selectors[si as usize];
let colors = DecoderEtcBlock::get_block_colors5(ep.color5, ep.inten5 as u32);
let mut packed = [0u16; 4];
for (i, c) in colors.iter().enumerate() {
packed[i] = ((mul_8(c.r() as u32, 15) << 12)
| (mul_8(c.g() as u32, 15) << 8)
| (mul_8(c.b() as u32, 15) << 4)
| 0xF) as u16;
}
let max_x = (width as i32 - block_x as i32 * 4).clamp(0, 4) as u32;
let max_y = (height as i32 - block_y as i32 * 4).clamp(0, 4) as u32;
for y in 0..max_y {
let s = sel.selectors[y as usize] as u32;
for x in 0..max_x {
let v = packed[((s >> (x * 2)) & 3) as usize];
let px = ((block_x * 4 + x) + (block_y * 4 + y) * width) as usize * 2;
out[px..px + 2].copy_from_slice(&v.to_le_bytes());
}
}
}
Some(())
}
#[allow(clippy::too_many_arguments)]
pub fn transcode_image_rgba4444(
&self,
rgb_slice: &[u8],
alpha_slice: &[u8],
num_blocks_x: u32,
num_blocks_y: u32,
width: u32,
height: u32,
video: Option<(&mut Vec<u32>, &mut Vec<u32>)>,
out: &mut [u8],
) -> Option<()> {
let (vc, va) = match video {
Some((c, a)) => (Some(c), Some(a)),
None => (None, None),
};
if out.len() != (width * height * 2) as usize {
return None;
}
out.fill(0);
let alpha = self.decode_slice_indices(alpha_slice, num_blocks_x, num_blocks_y, va)?;
for (b, &(aei, asi)) in alpha.iter().enumerate() {
let block_x = b as u32 % num_blocks_x;
let block_y = b as u32 / num_blocks_x;
let ep = &self.endpoints[aei as usize];
let sel = &self.selectors[asi as usize];
let acolors = DecoderEtcBlock::get_block_colors5_g(ep.color5, ep.inten5 as u32);
let mut packed = [0u16; 4];
for (i, &c) in acolors.iter().enumerate() {
packed[i] = mul_8(c as u32, 15) as u16;
}
let max_x = (width as i32 - block_x as i32 * 4).clamp(0, 4) as u32;
let max_y = (height as i32 - block_y as i32 * 4).clamp(0, 4) as u32;
for y in 0..max_y {
let s = sel.selectors[y as usize] as u32;
for x in 0..max_x {
let px = ((block_x * 4 + x) + (block_y * 4 + y) * width) as usize * 2;
out[px..px + 2]
.copy_from_slice(&packed[((s >> (x * 2)) & 3) as usize].to_le_bytes());
}
}
}
let indices = self.decode_slice_indices(rgb_slice, num_blocks_x, num_blocks_y, vc)?;
for (b, &(ei, si)) in indices.iter().enumerate() {
let block_x = b as u32 % num_blocks_x;
let block_y = b as u32 / num_blocks_x;
let ep = &self.endpoints[ei as usize];
let sel = &self.selectors[si as usize];
let colors = DecoderEtcBlock::get_block_colors5(ep.color5, ep.inten5 as u32);
let mut packed = [0u16; 4];
for (i, c) in colors.iter().enumerate() {
packed[i] = ((mul_8(c.r() as u32, 15) << 12)
| (mul_8(c.g() as u32, 15) << 8)
| (mul_8(c.b() as u32, 15) << 4)) as u16;
}
let max_x = (width as i32 - block_x as i32 * 4).clamp(0, 4) as u32;
let max_y = (height as i32 - block_y as i32 * 4).clamp(0, 4) as u32;
for y in 0..max_y {
let s = sel.selectors[y as usize] as u32;
for x in 0..max_x {
let px = ((block_x * 4 + x) + (block_y * 4 + y) * width) as usize * 2;
let cur = u16::from_le_bytes([out[px], out[px + 1]]);
let v = (cur & 0xF) | packed[((s >> (x * 2)) & 3) as usize];
out[px..px + 2].copy_from_slice(&v.to_le_bytes());
}
}
}
Some(())
}
pub fn decode_tables(&mut self, table_data: &[u8]) -> bool {
let mut sym = BitwiseDecoder::new(table_data);
if !sym.read_huffman_table(&mut self.endpoint_pred_model)
|| self.endpoint_pred_model.code_sizes.is_empty()
{
return false;
}
if !sym.read_huffman_table(&mut self.delta_endpoint_model)
|| self.delta_endpoint_model.code_sizes.is_empty()
{
return false;
}
if !sym.read_huffman_table(&mut self.selector_model)
|| self.selector_model.code_sizes.is_empty()
{
return false;
}
if !sym.read_huffman_table(&mut self.selector_history_buf_rle_model)
|| self.selector_history_buf_rle_model.code_sizes.is_empty()
{
return false;
}
self.selector_history_buf_size = sym.get_bits(13);
self.selector_history_buf_size != 0
}
}