Skip to main content

mlv/
decode.rs

1use crate::lj92::{Lj92, Lj92Error};
2use core::array::from_fn as arr;
3
4#[inline]
5pub fn decode_lj92(data: &[u8], out: &mut [u16]) -> Result<(),Lj92Error> {
6    match Lj92::open(data) {
7        Ok(mut lj92) => lj92.decode(out, 0, None),
8        Err(err) => Err(err)
9    }
10}
11
12#[inline]
13pub fn decode_packed14(data: &[u8], out: &mut [u16]) {
14    let (in_chunk, out_chunk) = (14, 8);
15    for (i,o) in data.chunks_exact(in_chunk).zip(out.chunks_exact_mut(out_chunk)) {
16        [o[0],o[1],o[2],o[3],o[4],o[5],o[6],o[7]] = decode14(arr(|n| i[n]));
17    }
18}
19
20#[inline]
21pub fn decode_packed12(data: &[u8], out: &mut [u16]) {
22    let (in_chunk, out_chunk) = (6, 4);
23    for (i,o) in data.chunks_exact(in_chunk).zip(out.chunks_exact_mut(out_chunk)) {
24        [o[0],o[1],o[2],o[3]] = decode12(arr(|n| i[n]))
25    }
26}
27
28#[inline]
29pub fn decode_packed10(data: &[u8], out: &mut [u16]) {
30    let (in_chunk, out_chunk) = (10, 8);
31    for (i,o) in data.chunks_exact(in_chunk).zip(out.chunks_exact_mut(out_chunk)) {
32        [o[0],o[1],o[2],o[3],o[4],o[5],o[6],o[7]] = decode10(arr(|n| i[n]));
33    }
34}
35
36/* TODO: encoding functions and provide direct bitdepth to bitdepth for re-encoding */
37
38/* Internal implementations */
39
40#[inline]
41const fn ones(n: u8) -> u16 { !(0xFFFF << n) }
42
43/* Decodes 8 pixels from 14 bytes of 14-bit packed data */
44#[inline(always)]
45const fn decode14([a,b,c,d,e,f,g,h,i,j,k,l,m,n]: [u8; 14]) -> [u16; 8] {
46    let mask = ones(14);
47    let word_a: u16 = u16::from_le_bytes([a,b]);
48    let word_b: u16 = u16::from_le_bytes([c,d]);
49    let word_c: u16 = u16::from_le_bytes([e,f]);
50    let word_d: u16 = u16::from_le_bytes([g,h]);
51    let word_e: u16 = u16::from_le_bytes([i,j]);
52    let word_f: u16 = u16::from_le_bytes([k,l]);
53    let word_g: u16 = u16::from_le_bytes([m,n]);
54    return [
55        word_a >> 2,
56        ((word_a << 12) | (word_b >>  4)) & mask,
57        ((word_b << 10) | (word_c >>  6)) & mask,
58        ((word_c <<  8) | (word_d >>  8)) & mask,
59        ((word_d <<  6) | (word_e >> 10)) & mask,
60        ((word_e <<  4) | (word_f >> 12)) & mask,
61        ((word_f <<  2) | (word_g >> 14)) & mask,
62        word_g & mask,
63    ]
64}
65
66/* Decodes 4 pixels from 6 bytes of 12-bit packed data */
67#[inline(always)]
68const fn decode12([a,b,c,d,e,f]: [u8; 6]) -> [u16; 4] {
69    let mask = ones(12);
70    let word_a: u16 = u16::from_le_bytes([a,b]);
71    let word_b: u16 = u16::from_le_bytes([c,d]);
72    let word_c: u16 = u16::from_le_bytes([e,f]);
73    return [
74        word_a >> 4,
75        ((word_a << 8) | (word_b >> 8)) & mask,
76        ((word_b << 4) | (word_c >> 12)) & mask,
77        word_c & mask,
78    ]
79}
80
81/* Decodes 8 pixels from 10 bytes of 10-bit packed data */
82#[inline(always)]
83const fn decode10([a,b,c,d,e,f,g,h,i,j]: [u8; 10]) -> [u16; 8] {
84    let mask = ones(10);
85    let word_a: u16 = u16::from_le_bytes([a,b]);
86    let word_b: u16 = u16::from_le_bytes([c,d]);
87    let word_c: u16 = u16::from_le_bytes([e,f]);
88    let word_d: u16 = u16::from_le_bytes([g,h]);
89    let word_e: u16 = u16::from_le_bytes([i,j]);
90    return [
91        word_a >> 6,
92        ((word_a << 4) | (word_b >> 12)) & mask,
93        (word_b >> 2) & mask,
94        ((word_b << 8) | (word_c >> 8)) & mask,
95        (word_c << 2) & mask,
96        ((word_c << 12) | (word_d >> 4)) & mask,
97        ((word_d << 6) | (word_e >> 10)) & mask,
98        word_e & mask,
99    ]
100}