pub mod bc6h;
pub mod bc6h_tables;
use crate::astc::{decode, unpack};
pub fn transcode_astc_hdr_4x4(img: &[u8], bx: u32, by: u32, out: &mut [u8]) -> Option<()> {
let total = (bx as usize).checked_mul(by as usize)?.checked_mul(16)?;
if img.len() < total {
return None;
}
if out.len() != total {
return None;
}
out.copy_from_slice(&img[..total]);
Some(())
}
pub fn transcode_bc6h(img: &[u8], bx: u32, by: u32, out: &mut [u8]) -> Option<()> {
let total = (bx as usize).checked_mul(by as usize)?.checked_mul(16)?;
if img.len() < total {
return None;
}
if out.len() != total {
return None;
}
out.fill(0);
for (dst, src) in out.chunks_exact_mut(16).zip(img.chunks_exact(16)) {
let src: &[u8; 16] = src.try_into().ok()?;
let log = unpack::unpack_block(src, 4, 4)?;
*<&mut [u8; 16]>::try_from(dst).ok()? = bc6h::transcode_block_bc6h(&log)?;
}
Some(())
}
fn transcode_half(
img: &[u8],
bx: u32,
by: u32,
lw: u32,
lh: u32,
ncomp: usize,
out: &mut [u8],
) -> Option<()> {
let total = (bx as usize).checked_mul(by as usize)?.checked_mul(16)?;
if img.len() < total {
return None;
}
if out.len() != (lw as usize) * (lh as usize) * 2 * ncomp {
return None;
}
out.fill(0);
for block_y in 0..by {
for block_x in 0..bx {
let b = ((block_x + block_y * bx) as usize) * 16;
let src: &[u8; 16] = img[b..b + 16].try_into().ok()?;
let log = unpack::unpack_block(src, 4, 4)?;
let mut texels = [[0u16; 4]; 16];
decode::decode_block_hdr16(&log, 4, 4, &mut texels)?;
let max_x = 4.min(lw - block_x * 4);
let max_y = 4.min(lh - block_y * 4);
for y in 0..max_y {
for x in 0..max_x {
let t = &texels[(x + y * 4) as usize];
let o = ((block_x * 4 + x) + (block_y * 4 + y) * lw) as usize * 2 * ncomp;
for c in 0..ncomp {
out[o + 2 * c..o + 2 * c + 2].copy_from_slice(&t[c].to_le_bytes());
}
}
}
}
}
Some(())
}
pub fn transcode_rgb_half(
img: &[u8],
bx: u32,
by: u32,
lw: u32,
lh: u32,
out: &mut [u8],
) -> Option<()> {
transcode_half(img, bx, by, lw, lh, 3, out)
}
pub fn transcode_rgba_half(
img: &[u8],
bx: u32,
by: u32,
lw: u32,
lh: u32,
out: &mut [u8],
) -> Option<()> {
transcode_half(img, bx, by, lw, lh, 4, out)
}
pub fn transcode_rgb_9e5(
img: &[u8],
bx: u32,
by: u32,
lw: u32,
lh: u32,
out: &mut [u8],
) -> Option<()> {
let total = (bx as usize).checked_mul(by as usize)?.checked_mul(16)?;
if img.len() < total {
return None;
}
if out.len() != (lw as usize) * (lh as usize) * 4 {
return None;
}
out.fill(0);
for block_y in 0..by {
for block_x in 0..bx {
let b = ((block_x + block_y * bx) as usize) * 16;
let src: &[u8; 16] = img[b..b + 16].try_into().ok()?;
let log = unpack::unpack_block(src, 4, 4)?;
let mut texels = [0u32; 16];
decode::decode_block_9e5(&log, 4, 4, &mut texels)?;
let max_x = 4.min(lw - block_x * 4);
let max_y = 4.min(lh - block_y * 4);
for y in 0..max_y {
for x in 0..max_x {
let o = ((block_x * 4 + x) + (block_y * 4 + y) * lw) as usize * 4;
out[o..o + 4].copy_from_slice(&texels[(x + y * 4) as usize].to_le_bytes());
}
}
}
}
Some(())
}