1use flashraw_core::{Error, Result};
8
9pub fn inflate_zlib(data: &[u8], max_out: usize) -> Result<Vec<u8>> {
11 let hint = max_out.min(data.len().saturating_mul(1032).saturating_add(64));
14 let opts = zune_inflate::DeflateOptions::default().set_limit(max_out).set_size_hint(hint);
15 let mut d = zune_inflate::DeflateDecoder::new_with_options(data, opts);
16 d.decode_zlib().map_err(|e| Error::corrupt(format!("deflate: {e:?}")))
17}
18
19pub fn inflate_zlib_into(data: &[u8], out: &mut [u8]) -> Result<usize> {
23 let (res, rc) = zlib_rs::decompress_slice(out, data, zlib_rs::InflateConfig::default());
24 match rc {
25 zlib_rs::ReturnCode::Ok => Ok(res.len()),
26 rc => Err(Error::corrupt(format!("deflate: {rc:?}"))),
27 }
28}
29
30pub fn undo_horizontal_u16(row: &mut [u16], cpp: usize, factor: usize) {
34 let step = cpp * factor;
35 for i in step..row.len() {
36 row[i] = row[i].wrapping_add(row[i - step]);
37 }
38}
39
40pub fn undo_float_predictor(row: &mut [u8], tmp: &mut Vec<u8>, width_samples: usize, bps_bytes: usize, factor: usize) {
45 let n = width_samples * bps_bytes;
46 if row.len() < n {
47 return;
48 }
49 let row = &mut row[..n];
50 for i in factor..n {
51 row[i] = row[i].wrapping_add(row[i - factor]);
52 }
53 tmp.clear();
54 tmp.resize(n, 0);
55 for s in 0..width_samples {
56 for b in 0..bps_bytes {
57 tmp[s * bps_bytes + b] = row[b * width_samples + s];
58 }
59 }
60 row.copy_from_slice(tmp);
61}
62
63pub fn decode_float_row(
71 row: &mut [u8],
72 samples: usize,
73 bps_bytes: usize,
74 factor: usize,
75 little_endian: bool,
76 out: &mut [f32],
77) {
78 let n = samples * bps_bytes;
79 if row.len() < n || out.len() < samples || !(2..=4).contains(&bps_bytes) {
80 return;
81 }
82 let row = &mut row[..n];
83 let out = &mut out[..samples];
84 if factor == 0 {
85 match (bps_bytes, little_endian) {
86 (4, true) => out
87 .iter_mut()
88 .zip(row.chunks_exact(4))
89 .for_each(|(o, c)| *o = f32::from_le_bytes([c[0], c[1], c[2], c[3]])),
90 (4, false) => out
91 .iter_mut()
92 .zip(row.chunks_exact(4))
93 .for_each(|(o, c)| *o = f32::from_be_bytes([c[0], c[1], c[2], c[3]])),
94 (2, le) => out.iter_mut().zip(row.chunks_exact(2)).for_each(|(o, c)| {
95 *o = f16_to_f32(if le { u16::from_le_bytes([c[0], c[1]]) } else { u16::from_be_bytes([c[0], c[1]]) })
96 }),
97 (_, le) => out.iter_mut().zip(row.chunks_exact(3)).for_each(|(o, c)| {
98 let (a, b, d) = if le { (c[2], c[1], c[0]) } else { (c[0], c[1], c[2]) };
99 *o = f24_to_f32((a as u32) << 16 | (b as u32) << 8 | d as u32)
100 }),
101 }
102 return;
103 }
104 if factor == 1 {
106 let mut acc = row[0];
107 for b in row[1..].iter_mut() {
108 acc = acc.wrapping_add(*b);
109 *b = acc;
110 }
111 } else {
112 for i in factor..n {
113 row[i] = row[i].wrapping_add(row[i - factor]);
114 }
115 }
116 match bps_bytes {
118 4 => {
119 let (p0, rest) = row.split_at(samples);
120 let (p1, rest) = rest.split_at(samples);
121 let (p2, p3) = rest.split_at(samples);
122 for ((((o, &a), &b), &c), &d) in out.iter_mut().zip(p0).zip(p1).zip(p2).zip(p3) {
123 *o = f32::from_bits(u32::from_be_bytes([a, b, c, d]));
124 }
125 }
126 3 => {
127 let (p0, rest) = row.split_at(samples);
128 let (p1, p2) = rest.split_at(samples);
129 for (((o, &a), &b), &c) in out.iter_mut().zip(p0).zip(p1).zip(p2) {
130 *o = f24_to_f32((a as u32) << 16 | (b as u32) << 8 | c as u32);
131 }
132 }
133 _ => {
134 let (p0, p1) = row.split_at(samples);
135 for ((o, &a), &b) in out.iter_mut().zip(p0).zip(p1) {
136 *o = f16_to_f32(u16::from_be_bytes([a, b]));
137 }
138 }
139 }
140}
141
142pub fn f16_to_f32(h: u16) -> f32 {
144 let sign = ((h >> 15) as u32) << 31;
145 let exp = ((h >> 10) & 0x1F) as u32;
146 let mant = (h & 0x3FF) as u32;
147 let bits = if exp == 0 {
148 if mant == 0 {
149 sign
150 } else {
151 let mut e = 127 - 15 + 1;
153 let mut m = mant;
154 while m & 0x400 == 0 {
155 m <<= 1;
156 e -= 1;
157 }
158 sign | ((e as u32) << 23) | ((m & 0x3FF) << 13)
159 }
160 } else if exp == 31 {
161 sign | 0x7F80_0000 | (mant << 13)
162 } else {
163 sign | ((exp + 127 - 15) << 23) | (mant << 13)
164 };
165 f32::from_bits(bits)
166}
167
168pub fn f24_to_f32(v: u32) -> f32 {
170 let sign = (v >> 23) & 1;
171 let exp = (v >> 16) & 0x7F;
172 let mant = v & 0xFFFF;
173 let bits = if exp == 0 && mant == 0 {
174 sign << 31
175 } else if exp == 0x7F {
176 (sign << 31) | 0x7F80_0000 | (mant << 7)
177 } else {
178 (sign << 31) | ((exp + 127 - 63) << 23) | (mant << 7)
179 };
180 f32::from_bits(bits)
181}
182
183pub fn float_bytes_to_f32(src: &[u8], bps_bytes: usize, out: &mut [f32]) {
185 match bps_bytes {
186 2 => {
187 src.chunks_exact(2).zip(out.iter_mut()).for_each(|(c, o)| *o = f16_to_f32(u16::from_be_bytes([c[0], c[1]])))
188 }
189 3 => src
190 .chunks_exact(3)
191 .zip(out.iter_mut())
192 .for_each(|(c, o)| *o = f24_to_f32((c[0] as u32) << 16 | (c[1] as u32) << 8 | c[2] as u32)),
193 _ => src
194 .chunks_exact(4)
195 .zip(out.iter_mut())
196 .for_each(|(c, o)| *o = f32::from_bits(u32::from_be_bytes([c[0], c[1], c[2], c[3]]))),
197 }
198}
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203
204 #[test]
205 fn half_floats() {
206 assert_eq!(f16_to_f32(0x3C00), 1.0);
207 assert_eq!(f16_to_f32(0xC000), -2.0);
208 assert_eq!(f16_to_f32(0x0001), 5.960_464_5e-8);
209 assert!(f16_to_f32(0x7C00).is_infinite());
210 }
211
212 #[test]
213 fn f24() {
214 assert_eq!(f24_to_f32(63 << 16), 1.0);
216 assert_eq!(f24_to_f32((1 << 23) | (64 << 16)), -2.0);
217 }
218
219 #[test]
220 fn horizontal() {
221 let mut r = vec![10u16, 1, 1, 1, 65535];
222 undo_horizontal_u16(&mut r, 1, 1);
223 assert_eq!(r, vec![10, 11, 12, 13, 12]);
224 }
225
226 #[test]
227 fn float_predictor_roundtrip() {
228 let vals = [1.5f32, -2.25, 1000.0, 0.0];
229 let be: Vec<u8> = vals.iter().flat_map(|v| v.to_be_bytes()).collect();
231 let mut planes = vec![0u8; 16];
232 for s in 0..4 {
233 for b in 0..4 {
234 planes[b * 4 + s] = be[s * 4 + b];
235 }
236 }
237 let mut enc = planes.clone();
238 for i in (1..16).rev() {
239 enc[i] = enc[i].wrapping_sub(enc[i - 1]);
240 }
241 let mut tmp = vec![];
242 undo_float_predictor(&mut enc, &mut tmp, 4, 4, 1);
243 let mut out = [0f32; 4];
244 float_bytes_to_f32(&enc, 4, &mut out);
245 assert_eq!(out, vals);
246 }
247
248 #[test]
249 fn fused_float_row_matches_reference() {
250 let mut x: u32 = 12345;
251 for bps in [2usize, 3, 4] {
252 for factor in [0usize, 1, 2, 4] {
253 for le in [false, true] {
254 let samples = 37;
255 let bytes: Vec<u8> = (0..samples * bps)
256 .map(|_| {
257 x = x.wrapping_mul(1664525).wrapping_add(1013904223);
258 (x >> 24) as u8
259 })
260 .collect();
261 let mut r = bytes.clone();
263 let mut tmp = vec![];
264 if factor > 0 {
265 undo_float_predictor(&mut r, &mut tmp, samples, bps, factor);
266 } else if le {
267 for c in r.chunks_exact_mut(bps) {
268 c.reverse();
269 }
270 }
271 let mut want = vec![0f32; samples];
272 float_bytes_to_f32(&r, bps, &mut want);
273 let mut got = vec![0f32; samples];
274 let mut b = bytes.clone();
275 decode_float_row(&mut b, samples, bps, factor, le, &mut got);
276 for (g, w) in got.iter().zip(&want) {
277 assert_eq!(g.to_bits(), w.to_bits(), "bps {bps} factor {factor} le {le}");
278 }
279 }
280 }
281 }
282 }
283
284 #[test]
285 fn inflate_limits() {
286 assert!(inflate_zlib(&[0x78, 0x9c, 0xff], 100).is_err());
287 assert!(inflate_zlib_into(&[0x78, 0x9c, 0xff], &mut [0u8; 100]).is_err());
288 let z = [0x78, 0x9c, 0xcb, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00, 0x06, 0x2c, 0x02, 0x15];
290 let mut out = [0u8; 16];
291 assert_eq!(inflate_zlib_into(&z, &mut out).unwrap(), 5);
292 assert_eq!(&out[..5], b"hello");
293 assert_eq!(inflate_zlib(&z, 16).unwrap(), b"hello");
294 assert!(inflate_zlib_into(&z, &mut [0u8; 3]).is_err());
295 }
296}