texture2ddecoder/etc/
etc1.rs1use crate::color::color;
2use crate::etc::consts::{ETC1_MODIFIER_TABLE, ETC1_SUBBLOCK_TABLE, WRITE_ORDER_TABLE};
3
4#[inline]
5pub(crate) const fn clamp(n: i32) -> u8 {
6 (if n < 0 {
7 0
8 } else if n > 255 {
9 255
10 } else {
11 n
12 }) as u8
13}
14
15#[inline]
16pub(crate) const fn applicate_color(c: [u8; 3], m: i16) -> u32 {
17 color(
18 clamp(c[0] as i32 + m as i32),
19 clamp(c[1] as i32 + m as i32),
20 clamp(c[2] as i32 + m as i32),
21 255,
22 )
23}
24
25#[inline]
26pub(crate) const fn applicate_color_alpha(c: [u8; 3], m: i16, transparent: bool) -> u32 {
27 color(
28 clamp(c[0] as i32 + m as i32),
29 clamp(c[1] as i32 + m as i32),
30 clamp(c[2] as i32 + m as i32),
31 if transparent { 0 } else { 255 },
32 )
33}
34
35#[inline]
36pub(crate) const fn applicate_color_raw(c: [u8; 3]) -> u32 {
37 color(c[0], c[1], c[2], 255)
38}
39
40#[inline]
41pub fn decode_etc1_block(data: &[u8], outbuf: &mut [u32]) {
42 let code: [u8; 2] = [(data[3] >> 5), (data[3] >> 2 & 7)]; let table: [usize; 16] = ETC1_SUBBLOCK_TABLE[(data[3] & 1) as usize];
44 let mut c: [[u8; 3]; 2] = [[0; 3]; 2];
45 if (data[3] & 2) > 0 {
46 c[0][0] = data[0] & 0xf8;
48 c[0][1] = data[1] & 0xf8;
49 c[0][2] = data[2] & 0xf8;
50 c[1][0] = c[0][0]
51 .overflowing_add(data[0] << 3 & 0x18)
52 .0
53 .overflowing_sub(data[0] << 3 & 0x20)
54 .0;
55 c[1][1] = c[0][1]
56 .overflowing_add(data[1] << 3 & 0x18)
57 .0
58 .overflowing_sub(data[1] << 3 & 0x20)
59 .0;
60 c[1][2] = c[0][2]
61 .overflowing_add(data[2] << 3 & 0x18)
62 .0
63 .overflowing_sub(data[2] << 3 & 0x20)
64 .0;
65 c[0][0] |= c[0][0] >> 5;
66 c[0][1] |= c[0][1] >> 5;
67 c[0][2] |= c[0][2] >> 5;
68 c[1][0] |= c[1][0] >> 5;
69 c[1][1] |= c[1][1] >> 5;
70 c[1][2] |= c[1][2] >> 5;
71 } else {
72 c[0][0] = (data[0] & 0xf0) | data[0] >> 4;
74 c[1][0] = (data[0] & 0x0f) | data[0] << 4;
75 c[0][1] = (data[1] & 0xf0) | data[1] >> 4;
76 c[1][1] = (data[1] & 0x0f) | data[1] << 4;
77 c[0][2] = (data[2] & 0xf0) | data[2] >> 4;
78 c[1][2] = (data[2] & 0x0f) | data[2] << 4;
79 }
80
81 let mut j: usize = u16::from_be_bytes([data[6], data[7]]) as usize; let mut k: usize = u16::from_be_bytes([data[4], data[5]]) as usize; for i in 0..16 {
85 let s: usize = table[i];
86 let m: i16 = ETC1_MODIFIER_TABLE[code[s] as usize][j & 1];
87 outbuf[WRITE_ORDER_TABLE[i]] = applicate_color(c[s], if k & 1 > 0 { -m } else { m });
88 j >>= 1;
89 k >>= 1
90 }
91}