1use crate::sony_arw6_curve::LLVC3_CURVE;
20use flashraw_core::{Error, Result, par};
21
22const STREAM_OFFSET: usize = 0x200;
23const BIAS: i32 = 2048;
24const MAX_PLANE_SAMPLES: usize = 128 * 1024 * 1024;
25
26fn corrupt(what: &str) -> Error {
27 Error::corrupt(format!("ARW6: {what}"))
28}
29
30fn require(cond: bool, what: &str) -> Result<()> {
31 if cond { Ok(()) } else { Err(corrupt(what)) }
32}
33
34fn be16(d: &[u8], p: usize) -> Result<u32> {
35 d.get(p..p + 2).map(|b| u16::from_be_bytes([b[0], b[1]]) as u32).ok_or_else(|| corrupt("truncated header"))
36}
37
38fn be32(d: &[u8], p: usize) -> Result<u32> {
39 d.get(p..p + 4).map(|b| u32::from_be_bytes([b[0], b[1], b[2], b[3]])).ok_or_else(|| corrupt("truncated header"))
40}
41
42fn le32(d: &[u8], p: usize) -> Result<u32> {
43 d.get(p..p + 4).map(|b| u32::from_le_bytes([b[0], b[1], b[2], b[3]])).ok_or_else(|| corrupt("truncated header"))
44}
45
46#[derive(Clone, Default)]
48struct Plane {
49 rows: usize,
50 cols: usize,
51 data: Vec<i32>,
52}
53
54impl Plane {
55 fn new(rows: usize, cols: usize) -> Result<Self> {
56 let n = rows.checked_mul(cols).filter(|&n| n <= MAX_PLANE_SAMPLES).ok_or_else(|| corrupt("plane too large"))?;
57 Ok(Plane { rows, cols, data: vec![0; n] })
58 }
59 #[inline(always)]
60 fn at(&self, r: usize, c: usize) -> i32 {
61 self.data[r * self.cols + c]
62 }
63 #[inline(always)]
64 fn set(&mut self, r: usize, c: usize, v: i32) {
65 self.data[r * self.cols + c] = v;
66 }
67 fn row(&self, r: usize) -> &[i32] {
68 &self.data[r * self.cols..(r + 1) * self.cols]
69 }
70 fn row_mut(&mut self, r: usize) -> &mut [i32] {
71 &mut self.data[r * self.cols..(r + 1) * self.cols]
72 }
73 fn head(&self, rows: usize) -> Result<Plane> {
75 require(rows <= self.rows, "plane row count")?;
76 Ok(Plane { rows, cols: self.cols, data: self.data[..rows * self.cols].to_vec() })
77 }
78}
79
80#[inline(always)]
82fn fshr(x: i32, bits: u32) -> i32 {
83 x >> bits
84}
85
86#[inline(always)]
88fn sign16(x: i32) -> i32 {
89 x as u16 as i16 as i32
90}
91
92#[inline(always)]
94fn edge_detail(x: i32, odd_mode: bool) -> i32 {
95 let half = x.signum();
96 let odd = x % 2 != 0;
97 let use_half = if odd_mode { odd } else { x != 0 && !odd };
98 x.wrapping_mul(2).wrapping_add(if use_half { half } else { 0 })
99}
100
101struct HeaderBits<'a> {
106 data: &'a [u8],
107 pos: usize,
108}
109
110impl HeaderBits<'_> {
111 fn read(&mut self, n: u32) -> Result<u32> {
112 require(self.pos + n as usize <= self.data.len() * 8, "packet header beyond data")?;
113 let mut out = 0u32;
114 for _ in 0..n {
115 let b = (self.data[self.pos >> 3] >> (7 - (self.pos & 7))) & 1;
116 out = (out << 1) | b as u32;
117 self.pos += 1;
118 }
119 Ok(out)
120 }
121}
122
123struct CoeffBits<'a> {
128 data: &'a [u8],
129 next: usize,
131 cache: u64,
133 nbits: u32,
134 remaining: u64,
136 status: u8,
137}
138
139impl<'a> CoeffBits<'a> {
140 fn new(packet: &'a [u8], payload_offset: usize, byte_length: usize) -> Self {
141 let words = ((byte_length.div_ceil(8)) + 1) & !1;
142 CoeffBits { data: packet, next: payload_offset, cache: 0, nbits: 0, remaining: words as u64 * 64, status: 0 }
143 }
144
145 #[inline(always)]
147 fn refill(&mut self) {
148 if self.nbits > 55 {
149 return;
150 }
151 let take = (63 - self.nbits) >> 3;
152 let w = match self.data.get(self.next..self.next + 8) {
153 Some(b) => u64::from_be_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]),
154 None => {
155 let mut b = [0u8; 8];
156 if let Some(t) = self.data.get(self.next..) {
157 let k = t.len().min(8);
158 b[..k].copy_from_slice(&t[..k]);
159 }
160 u64::from_be_bytes(b)
161 }
162 };
163 let bits = take * 8;
165 self.cache |= (w >> (64 - bits)) << (64 - bits - self.nbits);
166 self.next += take as usize;
167 self.nbits += bits;
168 }
169
170 #[inline(always)]
171 fn consume(&mut self, n: u32) {
172 self.cache <<= n;
173 self.nbits -= n;
174 self.remaining -= n as u64;
175 }
176
177 #[inline(always)]
179 fn read(&mut self, n: u32) -> u32 {
180 if n == 0 {
181 return 0;
182 }
183 if n as u64 > self.remaining {
184 return self.read_past_limit(n);
185 }
186 if self.nbits < n {
187 self.refill();
188 }
189 let v = (self.cache >> (64 - n)) as u32;
190 self.consume(n);
191 v
192 }
193
194 #[cold]
195 fn read_past_limit(&mut self, n: u32) -> u32 {
196 let avail = self.remaining as u32;
198 let head = if avail > 0 { self.read(avail) } else { 0 };
199 self.status = 2;
200 self.remaining = 0;
201 head.checked_shl(n - avail).unwrap_or(0)
203 }
204
205 #[inline(always)]
206 fn bit(&mut self) -> u32 {
207 self.read(1)
208 }
209
210 fn unary_plus_one(&mut self) -> i32 {
212 let mut zeros = 0i32;
213 loop {
214 if self.status != 0 {
215 return zeros + 1;
216 }
217 if self.remaining == 0 {
218 self.status = 2;
220 return zeros + 1;
221 }
222 self.refill();
223 let avail = (self.nbits as u64).min(self.remaining) as u32;
224 let lz = self.cache.leading_zeros();
225 if lz < avail {
226 self.consume(lz + 1);
227 return zeros + lz as i32 + 1;
228 }
229 self.consume(avail);
230 zeros += avail as i32;
231 }
232 }
233
234 #[inline(always)]
237 fn leading_one_within(&mut self, k: u32) -> Option<u32> {
238 if k as u64 <= self.remaining && k <= 32 {
239 self.refill();
240 let lz = self.cache.leading_zeros();
241 if lz < k {
242 self.consume(lz + 1);
243 return Some(lz);
244 }
245 self.consume(k);
246 return None;
247 }
248 (0..k).find(|_| self.bit() != 0)
249 }
250}
251
252#[inline(always)]
255fn update_width(br: &mut CoeffBits, w: i32) -> i32 {
256 if br.bit() == 0 || br.status != 0 {
257 return w;
258 }
259 if br.bit() == 0 || br.status != 0 {
260 return w + br.unary_plus_one();
261 }
262 match br.leading_one_within((w - 1).max(0) as u32) {
263 Some(z) => w - (z as i32 + 1),
264 None => 0,
265 }
266}
267
268fn zero_run(br: &mut CoeffBits, remaining: i32) -> i32 {
270 if remaining <= 1 {
271 return remaining;
272 }
273 let max_prefix = 32 - ((remaining - 1) as u32).leading_zeros() as i32;
274 let mut zeros = 0;
275 while zeros < max_prefix {
276 if br.bit() != 0 {
277 break;
278 }
279 if br.status != 0 {
280 return remaining;
281 }
282 zeros += 1;
283 }
284 if zeros >= max_prefix {
285 return remaining;
286 }
287 let base = 1 << zeros;
288 if base >= remaining {
289 return remaining;
290 }
291 let extra = if zeros > 0 { br.read(zeros as u32) as i32 } else { 0 };
292 (base + extra).min(remaining)
293}
294
295fn decode_component(br: &mut CoeffBits, groups: usize, shift: u32, dst: &mut [i32]) {
297 let row_width = dst.len();
298 let mut width = update_width(br, 0);
299 let mut gi = 0usize;
300 let mut out = 0usize;
301 while gi < groups {
302 if br.status != 0 || width > 0x13 {
303 if br.status == 0 {
304 br.status = 1;
305 }
306 dst[out..].fill(0);
307 return;
308 }
309 if width == 0 {
310 let run = zero_run(br, (groups - gi) as i32) as usize;
311 let n = (run * 4).min(row_width - out);
312 dst[out..out + n].fill(0);
313 out += n;
314 gi += run;
315 if gi >= groups {
316 break;
317 }
318 width = br.unary_plus_one();
319 continue;
320 }
321 let mut vals = [0i32; 4];
322 for v in vals.iter_mut() {
323 let x = br.read(width as u32);
324 *v = if shift > 0 && x > 0 {
325 (((2 * x as u64 + 1) << (shift - 1)) - (x as u64 & 1)) as i32
326 } else {
327 x as i32
328 };
329 }
330 let next = if gi + 1 < groups { update_width(br, width) } else { width };
331 for v in vals.iter_mut() {
332 if *v > 0 {
333 let s = br.bit() as i32;
334 *v = v.wrapping_sub(2i32.wrapping_mul(*v).wrapping_mul(s));
335 }
336 }
337 for v in vals {
338 if out < row_width {
339 dst[out] = v;
340 out += 1;
341 }
342 }
343 width = next;
344 gi += 1;
345 }
346 dst[out..].fill(0);
347}
348
349#[derive(Debug, Clone, Copy)]
353struct DirEntry {
354 group: usize,
355 index: usize,
356 start: usize,
357 length: usize,
358}
359
360#[derive(Debug, Clone, Copy)]
362pub struct TileStream {
363 pub offset: usize,
364 pub length: usize,
365 pub x: usize,
366 pub y: usize,
367 pub width: usize,
368 pub height: usize,
369}
370
371fn parse_stream_header(stream: &[u8]) -> Option<(usize, usize)> {
373 if stream.len() < 0x80 || !(stream.starts_with(b"A000") || stream.starts_with(b"0000")) {
374 return None;
375 }
376 let wc = be16(stream, 0x0c).ok()?;
377 let we = be16(stream, 0x0e).ok()?;
378 if (wc >> 4) & 0x3f != 16 || we >> 13 != 3 || (we >> 10) & 3 != 3 {
379 return None;
380 }
381 let w = be16(stream, 8).ok()? as usize;
382 let hh = be16(stream, 0x0a).ok()? as usize;
383 if w == 0 || hh == 0 || w % 16 != 0 {
384 return None;
385 }
386 Some((w, hh))
387}
388
389fn group_sizes(stream: &[u8], p: usize) -> Result<[usize; 5]> {
391 let mut g = [0usize; 5];
392 for (i, v) in g.iter_mut().enumerate() {
393 *v = ((be32(stream, p + 3 * i)? >> 4) & 0x0fff_fff0) as usize;
394 }
395 Ok(g)
396}
397
398fn stream_length(stream: &[u8]) -> Result<usize> {
399 require(stream.len() >= 0x80, "stream too short")?;
400 let payload: usize = group_sizes(stream, 0x10)?.iter().sum();
401 require(payload <= stream.len() - 0x80, "stream payload beyond strip")?;
402 Ok(0x80 + payload)
403}
404
405pub fn find_streams(strip: &[u8], full_w: usize, full_h: usize) -> Vec<TileStream> {
407 let mut streams = Vec::new();
408 if full_w == 0 || full_h == 0 || strip.len() < STREAM_OFFSET + 0x80 {
409 return streams;
410 }
411 let count = le32(strip, 0).unwrap_or(0) as usize;
412 if (1..=16).contains(&count) {
413 'tiles: for index in 0..count {
414 let entry = 0x08 + index * 0x18;
415 let fields: Option<Vec<u32>> = (0..6).map(|k| le32(strip, entry + 4 * k).ok()).collect();
416 let Some(f) = fields else {
417 streams.clear();
418 break;
419 };
420 let (table_offset, tx, ty, tw, th) = (f[0] as usize, f[2] as usize, f[3] as usize, f[4], f[5]);
421 let start = if table_offset != 0 { table_offset } else { STREAM_OFFSET };
422 if start > strip.len() - 0x80 {
423 streams.clear();
424 break;
425 }
426 let end = (strip.len() - 0x80).min(start.saturating_add(0x1000));
427 let mut cand = start;
428 while cand <= end {
429 if let Some((w, hh)) = parse_stream_header(&strip[cand..]) {
430 if let Ok(len) = stream_length(&strip[cand..]) {
431 let tile_w = if tw != 0 { tw as usize } else { w };
432 let tile_h = if th != 0 { th as usize } else { hh * 2 };
433 if len > 0x80
434 && cand + len <= strip.len()
435 && tile_w == w
436 && tile_h == hh * 2
437 && tx + tile_w <= full_w
438 && ty + tile_h <= full_h
439 {
440 streams.push(TileStream {
441 offset: cand,
442 length: len,
443 x: tx,
444 y: ty,
445 width: w,
446 height: hh * 2,
447 });
448 continue 'tiles;
449 }
450 }
451 }
452 cand += 0x10;
453 }
454 streams.clear();
455 break;
456 }
457 if streams.len() == count {
458 return streams;
459 }
460 streams.clear();
461 }
462 if let Some((w, hh)) = parse_stream_header(&strip[STREAM_OFFSET..]) {
463 if let Ok(len) = stream_length(&strip[STREAM_OFFSET..]) {
464 if w == full_w && hh * 2 == full_h {
465 streams.push(TileStream { offset: STREAM_OFFSET, length: len, x: 0, y: 0, width: w, height: hh * 2 });
466 }
467 }
468 }
469 streams
470}
471
472fn parse_directory(stream: &[u8]) -> Result<Vec<DirEntry>> {
473 let groups = group_sizes(stream, 0x10)?;
474 let mut entries = Vec::new();
475 let mut pos = 0x30usize;
476 let mut base = 0usize;
477 for (group, &group_len) in groups.iter().enumerate() {
478 require(pos + 0x10 <= stream.len(), "directory beyond stream")?;
479 let n = (stream[pos] & 0x0f) as usize;
480 require(n <= 9, "directory entry count")?;
481 let mut values = [0usize; 9];
482 for (i, v) in values.iter_mut().take(5).enumerate() {
483 *v = ((be32(stream, pos + 3 * i)? & 0x00ff_ffff) << 4) as usize;
484 }
485 let mut consumed = 0x10;
486 if n >= 5 {
487 require(pos + 0x20 <= stream.len(), "directory beyond stream")?;
488 for i in 0..4 {
489 values[5 + i] = ((be32(stream, pos + 0x10 + 3 * i)? & 0x00ff_ffff) << 4) as usize;
490 }
491 consumed = 0x20;
492 }
493 let mut local = 0usize;
494 for (index, &length) in values.iter().take(n).enumerate() {
495 let start = 0x80 + base + local;
496 require(start <= stream.len() && length <= stream.len() - start, "packet beyond stream")?;
497 entries.push(DirEntry { group, index, start, length });
498 local += length;
499 }
500 require(local <= group_len, "group size mismatch")?;
501 base += group_len;
502 pos += consumed;
503 }
504 Ok(entries)
505}
506
507struct Record {
508 byte_length: usize,
509 selectors: [u8; 3],
510 payload_offset: usize,
511}
512
513struct Packet<'a> {
514 kind: usize,
515 data: &'a [u8],
516 records: Vec<Record>,
517}
518
519fn parse_packet(data: &[u8]) -> Result<Packet<'_>> {
520 require(data.len() >= 16, "packet too short")?;
521 let mut br = HeaderBits { data, pos: 0 };
522 let control_count = br.read(16)? as usize;
523 let extra_count = br.read(24)? as usize;
524 let tag4 = br.read(4)?;
525 let reserved4 = br.read(4)?;
526 let kind = br.read(2)? as usize;
527 let control_words = br.read(6)?;
528 let block_count = br.read(16)? as usize;
529 let width_marker = br.read(8)?;
530 let reserved8 = br.read(8)?;
531 for _ in 0..5 {
532 require(br.read(8)? == 0, "packet header padding")?;
533 }
534 require(tag4 == 4 && reserved4 == 0 && control_words == 0, "packet header tag")?;
535 require(kind == 1 || kind == 3, "packet type")?;
536 require(block_count > 0 && block_count <= 30000, "packet block count")?;
537 require(width_marker == 0x10 && reserved8 == 0, "packet width marker")?;
538 let control_bytes = (control_count + 1) << 4;
539 let total = (control_count + 1 + extra_count) << 4;
540 require(total == data.len() && control_bytes <= data.len(), "packet size")?;
541 let mut cursor = control_bytes;
542 let mut records = Vec::with_capacity(block_count);
543 for _ in 0..block_count {
544 let byte_length = br.read(16)? as usize;
545 let mut selectors = [0u8; 3];
546 for s in selectors.iter_mut().take(kind) {
547 *s = br.read(4)? as u8;
548 }
549 require(byte_length <= data.len() && cursor <= data.len() - byte_length, "packet record beyond packet")?;
550 records.push(Record { byte_length, selectors, payload_offset: cursor });
551 cursor += byte_length;
552 }
553 Ok(Packet { kind, data, records })
554}
555
556fn row_multiplier(group: usize) -> usize {
557 match group {
558 4 => 8,
559 0 => 1,
560 g => 1 << (g - 1),
561 }
562}
563
564fn packet_planes(
566 stream: &[u8],
567 dir: &[DirEntry],
568 mosaic_w: usize,
569 coded_h: usize,
570 group: usize,
571 index: usize,
572 parallel: bool,
573) -> Result<Vec<Plane>> {
574 let e = dir.iter().find(|e| e.group == group && e.index == index).ok_or_else(|| corrupt("missing packet"))?;
575 let p = parse_packet(&stream[e.start..e.start + e.length])?;
576 let comps = if p.kind == 1 { 1 } else { 3 };
577 let row_width = match (p.kind, group) {
578 (1, 4) => mosaic_w / 2,
579 (1, _) => mosaic_w / 16,
580 (3, 1..=3) => mosaic_w >> (5 - group),
581 _ => return Err(corrupt("invalid packet type or group")),
582 };
583 let rm = row_multiplier(group);
584 let rows = p.records.len() * rm;
585 require(coded_h > 0 && coded_h <= 0x7fff, "coded height")?;
586 let expected = (coded_h.div_ceil(16) + 1) * rm;
587 let groups_per_row = row_width.div_ceil(4);
588 require(row_width > 0 && groups_per_row > 0 && rows > 0, "packet geometry")?;
589 if rows != expected {
590 require(coded_h % 16 != 0 && expected.checked_sub(rows) == Some(rm), "packet row count")?;
591 }
592 require(p.records.len() <= stream.len() / 16 + 1, "packet record count")?;
593 let mut planes: Vec<Plane> = (0..comps).map(|_| Plane::new(expected, row_width)).collect::<Result<_>>()?;
594 let record_rows = rm * row_width;
597 let mut bufs: Vec<Vec<i32>> = Vec::new();
598 let decode_record = |ri: usize| -> Vec<i32> {
599 let rec = &p.records[ri];
600 let mut buf = vec![0i32; comps * record_rows];
601 if rec.byte_length > 0 {
602 let mut bits = CoeffBits::new(p.data, rec.payload_offset, rec.byte_length);
603 for ci in 0..comps {
604 let shift = if ci < p.kind { rec.selectors[ci] as u32 } else { 0 };
605 for r in 0..rm {
606 let off = ci * record_rows + r * row_width;
607 decode_component(&mut bits, groups_per_row, shift, &mut buf[off..off + row_width]);
608 }
609 }
610 }
611 buf
612 };
613 bufs.extend(par::map((0..p.records.len()).collect(), parallel, decode_record));
614 for (ri, buf) in bufs.iter().enumerate() {
615 for (ci, plane) in planes.iter_mut().enumerate() {
616 let dst = &mut plane.data[ri * record_rows..(ri + 1) * record_rows];
617 dst.copy_from_slice(&buf[ci * record_rows..(ci + 1) * record_rows]);
618 }
619 }
620 Ok(planes)
621}
622
623fn integrate(coeffs: &Plane, rows: usize, start: usize) -> Result<Plane> {
628 require(rows <= coeffs.rows && start <= rows, "band-0 rows")?;
629 let mut out = Plane::new(rows - start, coeffs.cols)?;
630 for y in start..rows {
631 let src = coeffs.row(y);
632 let dst = out.row_mut(y - start);
633 let mut acc = 0i32;
634 for (d, &s) in dst.iter_mut().zip(src) {
635 acc = acc.wrapping_add(sign16(s).wrapping_mul(2));
636 *d = acc / 2;
637 }
638 }
639 Ok(out)
640}
641
642const LIFT_ROWS: usize = 16;
644
645fn inv53_vertical(low: &Plane, high: &Plane, parallel: bool) -> Result<Plane> {
647 require(low.rows == high.rows && low.cols == high.cols, "vertical lifting shapes")?;
648 let (h, w) = (low.rows, low.cols);
649 let mut lo2 = Plane::new(h, w)?;
650 par::for_each_row_chunk(&mut lo2.data, w, LIFT_ROWS, parallel, |first, chunk| {
651 for (i, d) in chunk.chunks_mut(w).enumerate() {
652 let y = first + i;
653 let hp = high.row(y.saturating_sub(1));
654 let hc = high.row(y);
655 let l = low.row(y);
656 for (x, d) in d.iter_mut().enumerate() {
657 *d = l[x].wrapping_sub(fshr(hp[x].wrapping_add(hc[x]).wrapping_add(2), 2));
658 }
659 }
660 });
661 let mut out = Plane::new(h * 2, w)?;
662 let lo2 = &lo2;
663 par::for_each_row_chunk(&mut out.data, 2 * w, LIFT_ROWS, parallel, |first, chunk| {
664 for (i, pair) in chunk.chunks_mut(2 * w).enumerate() {
665 let y = first + i;
666 let ln = lo2.row(if y + 1 < h { y + 1 } else { y });
667 let lc = lo2.row(y);
668 let hc = high.row(y);
669 let (r0, r1) = pair.split_at_mut(w);
670 r0.copy_from_slice(lc);
671 for (x, d) in r1.iter_mut().enumerate() {
672 *d = hc[x].wrapping_add(fshr(lc[x].wrapping_add(ln[x]), 1));
673 }
674 }
675 });
676 Ok(out)
677}
678
679fn inv53_horizontal(low: &Plane, high: &Plane, parallel: bool) -> Result<Plane> {
681 require(low.rows == high.rows && low.cols == high.cols, "horizontal lifting shapes")?;
682 let (h, w) = (low.rows, low.cols);
683 let mut out = Plane::new(h, w * 2)?;
684 if w == 0 {
685 return Ok(out);
686 }
687 par::for_each_row_chunk(&mut out.data, 2 * w, LIFT_ROWS, parallel, |first, chunk| {
688 let mut lo2 = vec![0i32; w];
689 for (i, o) in chunk.chunks_mut(2 * w).enumerate() {
690 let y = first + i;
691 let l = low.row(y);
692 let hi = high.row(y);
693 lo2[0] = l[0].wrapping_sub(fshr(hi[0].wrapping_add(hi[0]).wrapping_add(2), 2));
694 for x in 1..w {
695 lo2[x] = l[x].wrapping_sub(fshr(hi[x - 1].wrapping_add(hi[x]).wrapping_add(2), 2));
696 }
697 for x in 0..w {
698 let ln = lo2[if x + 1 < w { x + 1 } else { x }];
699 o[2 * x] = lo2[x];
700 o[2 * x + 1] = hi[x].wrapping_add(fshr(lo2[x].wrapping_add(ln), 1));
701 }
702 }
703 });
704 Ok(out)
705}
706
707fn inv53_vertical_high_leading(low: &Plane, high: &Plane) -> Result<Plane> {
709 require(low.cols == high.cols, "lifting shapes")?;
710 require(high.rows == low.rows || high.rows == low.rows + 1, "lifting row counts")?;
711 require(low.rows > 0, "empty lifting band")?;
712 let (lh, hh, w) = (low.rows, high.rows, low.cols);
713 let mut lo2 = Plane::new(lh, w)?;
714 let mut hi2 = Plane::new(hh, w)?;
715 for y in 0..lh {
716 let next = if hh == lh + 1 || y + 1 < hh { y + 1 } else { y };
717 let next = next.min(hh - 1);
718 for x in 0..w {
719 let v = high.at(y, x).wrapping_add(high.at(next, x)).wrapping_add(2);
720 lo2.set(y, x, low.at(y, x).wrapping_sub(fshr(v, 2)));
721 }
722 }
723 if hh == lh + 1 {
724 for x in 0..w {
725 hi2.set(0, x, high.at(0, x).wrapping_add(lo2.at(0, x)));
726 hi2.set(hh - 1, x, high.at(hh - 1, x).wrapping_add(lo2.at(lh - 1, x)));
727 }
728 for y in 1..hh - 1 {
729 for x in 0..w {
730 let v = fshr(lo2.at(y - 1, x).wrapping_add(lo2.at(y, x)), 1);
731 hi2.set(y, x, high.at(y, x).wrapping_add(v));
732 }
733 }
734 let mut out = Plane::new(lh * 2 + 1, w)?;
735 for y in 0..lh {
736 out.row_mut(2 * y).copy_from_slice(hi2.row(y));
737 out.row_mut(2 * y + 1).copy_from_slice(lo2.row(y));
738 }
739 let last = out.rows - 1;
740 out.row_mut(last).copy_from_slice(hi2.row(hh - 1));
741 return Ok(out);
742 }
743 for x in 0..w {
744 hi2.set(0, x, high.at(0, x).wrapping_add(lo2.at(0, x)));
745 }
746 for y in 1..hh {
747 for x in 0..w {
748 let v = fshr(lo2.at(y - 1, x).wrapping_add(lo2.at(y, x)), 1);
749 hi2.set(y, x, high.at(y, x).wrapping_add(v));
750 }
751 }
752 let mut out = Plane::new(lh * 2, w)?;
753 for y in 0..lh {
754 out.row_mut(2 * y).copy_from_slice(hi2.row(y));
755 out.row_mut(2 * y + 1).copy_from_slice(lo2.row(y));
756 }
757 Ok(out)
758}
759
760fn synth_level(ll: &Plane, s0: &Plane, s1: &Plane, s2: &Plane, parallel: bool) -> Result<Plane> {
762 let (h, w) = (ll.rows, ll.cols);
763 require(s0.cols == w && s1.cols == w && s2.cols == w, "subband widths")?;
764 require(s0.rows > h && s1.rows > h && s2.rows > h && h > 0, "subband rows")?;
765 let mut lh = Plane::new(h, w)?;
766 let mut hh = Plane::new(h, w)?;
767 for y in 0..h - 1 {
768 lh.row_mut(y).copy_from_slice(s1.row(y + 1));
769 hh.row_mut(y).copy_from_slice(s2.row(y + 1));
770 }
771 lh.row_mut(h - 1).copy_from_slice(s0.row(h));
772 hh.row_mut(h - 1).copy_from_slice(s1.row(h));
773 let lo = inv53_vertical(ll, &lh, parallel)?;
774 let hi = inv53_vertical(&s0.head(h)?, &hh, parallel)?;
775 inv53_horizontal(&lo, &hi, parallel)
776}
777
778fn synth_level_stride(
780 ll: &Plane,
781 s0: &Plane,
782 s1: &Plane,
783 s2: &Plane,
784 edge: usize,
785 odd: bool,
786 parallel: bool,
787) -> Result<Plane> {
788 if edge == 0 {
789 return synth_level(ll, s0, s1, s2, parallel);
790 }
791 let (h, w) = (ll.rows, ll.cols);
792 require(s0.cols == w && s1.cols == w && s2.cols == w, "subband widths")?;
793 require(h >= 2 * edge && s0.rows >= h + 2 * edge && s1.rows >= h + edge && s2.rows >= h, "subband rows")?;
794 let mut hl = Plane::new(h, w)?;
795 let mut lh = Plane::new(h, w)?;
796 let mut hh = Plane::new(h, w)?;
797 for y in 0..edge {
798 hl.row_mut(y).copy_from_slice(s0.row(y));
799 lh.row_mut(y).copy_from_slice(s0.row(y + edge));
800 for x in 0..w {
801 hh.set(y, x, edge_detail(s1.at(y, x), odd));
802 }
803 }
804 for y in edge..h - edge {
805 hl.row_mut(y).copy_from_slice(s0.row(y + edge));
806 lh.row_mut(y).copy_from_slice(s1.row(y + edge));
807 hh.row_mut(y).copy_from_slice(s2.row(y + edge));
808 }
809 for y in h - edge..h {
810 let k = y - (h - edge);
811 hl.row_mut(y).copy_from_slice(s0.row(h + k));
812 lh.row_mut(y).copy_from_slice(s0.row(h + edge + k));
813 for x in 0..w {
814 hh.set(y, x, edge_detail(s1.at(h + k, x), odd));
815 }
816 }
817 let lo = inv53_vertical(ll, &lh, parallel)?;
818 let hi = inv53_vertical(&hl, &hh, parallel)?;
819 inv53_horizontal(&lo, &hi, parallel)
820}
821
822fn synth_guard1(ll: &Plane, s0: &Plane, s1: &Plane, s2: &Plane, parallel: bool) -> Result<Plane> {
824 let (h, w) = (ll.rows, ll.cols);
825 require(s0.cols == w && s1.cols == w && s2.cols == w, "subband widths")?;
826 require(s0.rows >= h + 2 && s1.rows >= h + 2 && s2.rows >= h + 2, "subband rows")?;
827 let mut lh = Plane::new(h + 1, w)?;
828 let mut hh = Plane::new(h + 1, w)?;
829 let mut hl = Plane::new(h, w)?;
830 for y in 0..h {
831 hl.row_mut(y).copy_from_slice(s0.row(y + 1));
832 lh.row_mut(y).copy_from_slice(s1.row(y + 1));
833 hh.row_mut(y).copy_from_slice(s2.row(y + 1));
834 }
835 lh.row_mut(h).copy_from_slice(s0.row(h + 1));
836 hh.row_mut(h).copy_from_slice(s1.row(h + 1));
837 let lo = inv53_vertical_high_leading(ll, &lh)?;
838 let hi = inv53_vertical_high_leading(&hl, &hh)?;
839 inv53_horizontal(&lo, &hi, parallel)
840}
841
842fn synth_guard2(ll: &Plane, s0: &Plane, s1: &Plane, s2: &Plane, odd: bool, parallel: bool) -> Result<Plane> {
844 let (h, w) = (ll.rows, ll.cols);
845 require(s0.cols == w && s1.cols == w && s2.cols == w, "subband widths")?;
846 require(h > 0 && s0.rows >= h + 3 && s1.rows > h && s2.rows > h, "subband rows")?;
847 let mut hl = Plane::new(h, w)?;
848 let mut lh = Plane::new(h, w)?;
849 let mut hh = Plane::new(h, w)?;
850 lh.row_mut(0).copy_from_slice(s0.row(0));
851 for x in 0..w {
852 hh.set(0, x, edge_detail(s0.at(1, x), odd));
853 }
854 for y in 0..h {
855 hl.row_mut(y).copy_from_slice(s0.row(y + 2));
856 }
857 for y in 1..h {
858 lh.row_mut(y).copy_from_slice(s1.row(y + 1));
859 hh.row_mut(y).copy_from_slice(s2.row(y + 1));
860 }
861 let lo = inv53_vertical_high_leading(ll, &lh)?;
862 let hi = inv53_vertical_high_leading(&hl, &hh)?;
863 inv53_horizontal(&lo, &hi, parallel)
864}
865
866fn synth_guard3(ll: &Plane, s0: &Plane, s1: &Plane, s2: &Plane, odd: bool, parallel: bool) -> Result<Plane> {
868 let (h, w) = (ll.rows, ll.cols);
869 require(s0.cols == w && s1.cols == w && s2.cols == w, "subband widths")?;
870 require(h >= 2 && s0.rows >= h + 5 && s1.rows >= h + 2 && s2.rows >= h + 2, "subband rows")?;
871 let mut hl = Plane::new(h, w)?;
872 let mut lh = Plane::new(h, w)?;
873 let mut hh = Plane::new(h, w)?;
874 hl.row_mut(0).copy_from_slice(s0.row(0));
875 lh.row_mut(0).copy_from_slice(s0.row(1));
876 lh.row_mut(h - 1).copy_from_slice(s0.row(h + 3));
877 for x in 0..w {
878 hh.set(0, x, edge_detail(s0.at(2, x), odd));
879 hh.set(h - 1, x, edge_detail(s0.at(h + 4, x), odd));
880 }
881 for y in 1..h {
882 hl.row_mut(y).copy_from_slice(s0.row(y + 3));
883 }
884 for y in 1..h - 1 {
885 lh.row_mut(y).copy_from_slice(s1.row(y + 3));
886 hh.row_mut(y).copy_from_slice(s2.row(y + 3));
887 }
888 let lo = inv53_vertical(ll, &lh, parallel)?;
889 let hi = inv53_vertical(&hl, &hh, parallel)?;
890 inv53_horizontal(&lo, &hi, parallel)
891}
892
893fn final_green(ll: &Plane, detail: &Plane, top_rows: usize, parallel: bool) -> Result<Plane> {
896 let (h, w) = (ll.rows, ll.cols);
897 require(top_rows <= 8 && detail.cols == w && detail.rows >= 8 + h.saturating_sub(top_rows), "green detail")?;
898 if h == 0 || w == 0 {
899 return Plane::new(h, w * 2);
900 }
901 let sel = |y: usize| detail.row(if y < top_rows { y } else { y + 8 - top_rows });
903 let mut odd = Plane::new(h, w)?;
904 par::for_each_row_chunk(&mut odd.data, w, LIFT_ROWS, parallel, |first, chunk| {
905 for (i, o) in chunk.chunks_mut(w).enumerate() {
906 let y = first + i;
907 let (cur, prev, l) = (sel(y), sel(y.saturating_sub(1)), ll.row(y));
908 for x in 0..w {
909 let pred = if x + 1 < w {
910 fshr(cur[x + 1].wrapping_add(prev[x]).wrapping_add(cur[x]).wrapping_add(prev[x + 1]), 2)
911 } else {
912 fshr(prev[x].wrapping_add(cur[x]).wrapping_mul(2), 2)
913 };
914 o[x] = ((2 * l[x] as i64 - pred as i64) >> 1) as i32;
915 }
916 }
917 });
918 let mut out = Plane::new(h, w * 2)?;
919 let odd = &odd;
920 par::for_each_row_chunk(&mut out.data, 2 * w, LIFT_ROWS, parallel, |first, chunk| {
921 for (i, o) in chunk.chunks_mut(2 * w).enumerate() {
922 let y = first + i;
923 let (od, on, sl) = (odd.row(y), odd.row(if y + 1 < h { y + 1 } else { y }), sel(y));
924 let v = (od[0].wrapping_add(on[0]) as i64 * 2) >> 2;
925 o[0] = sl[0].wrapping_add(v as i32);
926 o[1] = od[0];
927 for x in 1..w {
928 let s = od[x - 1].wrapping_add(on[x - 1]).wrapping_add(on[x]).wrapping_add(od[x]);
929 o[2 * x] = sl[x].wrapping_add(fshr(s, 2));
930 o[2 * x + 1] = od[x];
931 }
932 }
933 });
934 Ok(out)
935}
936
937struct DecodedTile {
939 full_green: Plane,
940 red: Plane,
941 blue: Plane,
942}
943
944fn decode_stream(stream: &[u8], parallel: bool) -> Result<DecodedTile> {
946 let (width, half_h) = parse_stream_header(stream).ok_or_else(|| corrupt("invalid stream header"))?;
947 let dir = parse_directory(stream)?;
948 let coded_h = half_h * 2;
949 let padded = coded_h.div_ceil(16) * 16;
950 let guarded = coded_h != padded;
951 let low_rows = padded / 16;
952 let low_start = guarded as usize;
953
954 let plane = |index: usize| -> Result<Plane> {
957 let b0 = packet_planes(stream, &dir, width, coded_h, 0, index, parallel)?;
958 let mut p = integrate(&b0[0], low_rows, low_start)?;
959 for group in 1..=3 {
960 let edge = [0, 0, 1, 2][group];
961 let odd = group == 3 && index != 0;
962 let s = packet_planes(stream, &dir, width, coded_h, group, index, parallel)?;
963 require(s.len() == 3, "detail packet with one component")?;
964 p = if guarded {
965 match group {
966 1 => synth_guard1(&p, &s[0], &s[1], &s[2], parallel)?,
967 2 => synth_guard2(&p, &s[0], &s[1], &s[2], false, parallel)?,
968 _ => synth_guard3(&p, &s[0], &s[1], &s[2], odd, parallel)?,
969 }
970 } else {
971 synth_level_stride(&p, &s[0], &s[1], &s[2], edge, odd, parallel)?
972 };
973 }
974 Ok(p)
975 };
976 let mut planes = par::map(vec![0usize, 1, 2], parallel, plane).into_iter();
977 let (Some(green), Some(red), Some(blue)) = (planes.next(), planes.next(), planes.next()) else {
978 return Err(corrupt("missing colour plane"));
979 };
980 let (green, red, blue) = (green?, red?, blue?);
981 let g4 = packet_planes(stream, &dir, width, coded_h, 4, 0, parallel)?;
982 let full_green = final_green(&green, &g4[0], if guarded { 2 } else { 4 }, parallel)?;
983 Ok(DecodedTile { full_green, red, blue })
984}
985
986#[inline(always)]
987fn clamp_code(x: i32) -> i32 {
988 x.saturating_add(BIAS).clamp(0, 4095) - BIAS
989}
990
991#[inline(always)]
992fn sample(x: i32) -> u16 {
993 LLVC3_CURVE[x.saturating_add(BIAS).clamp(0, 4095) as usize]
994}
995
996pub fn decode(strip: &[u8], out: &mut [u16], raw_w: usize, raw_h: usize, parallel: bool) -> Result<()> {
998 require(raw_w > 0 && raw_h > 0 && raw_w % 16 == 0 && raw_h % 2 == 0, "frame size")?;
999 require(out.len() >= raw_w * raw_h, "output buffer")?;
1000 require(strip.len() >= STREAM_OFFSET + 0x80, "strip too short")?;
1001 let streams = find_streams(strip, raw_w, raw_h);
1002 require(!streams.is_empty(), "no tile streams")?;
1003 let tiles: Vec<Result<DecodedTile>> =
1004 par::map(streams.clone(), parallel, |s| decode_stream(&strip[s.offset..s.offset + s.length], parallel));
1005 for (s, tile) in streams.iter().zip(tiles) {
1006 let t = tile?;
1007 let (half_h, half_w) = (s.height / 2, s.width / 2);
1008 require(
1009 t.full_green.rows >= half_h
1010 && t.full_green.cols == s.width
1011 && t.red.rows >= half_h
1012 && t.red.cols == half_w
1013 && t.blue.rows >= half_h
1014 && t.blue.cols == half_w,
1015 "tile plane sizes",
1016 )?;
1017 let band = &mut out[s.y * raw_w..(s.y + s.height) * raw_w];
1019 par::for_each_row_chunk(band, 2 * raw_w, 8, parallel, |first, chunk| {
1020 for (i, pair) in chunk.chunks_mut(2 * raw_w).enumerate() {
1021 let y = first + i;
1022 let (r0, r1) = pair.split_at_mut(raw_w);
1023 let (r0, r1) = (&mut r0[s.x..s.x + s.width], &mut r1[s.x..s.x + s.width]);
1024 let (fg, red, blue) = (t.full_green.row(y), t.red.row(y), t.blue.row(y));
1025 for x in 0..half_w {
1026 let g0 = clamp_code(fg[2 * x]);
1027 let g1 = clamp_code(fg[2 * x + 1]);
1028 let gavg = ((g0 as i64 + g1 as i64) >> 1) as i32;
1029 r0[2 * x] = sample(gavg.wrapping_add(red[x].wrapping_mul(2)));
1030 r0[2 * x + 1] = sample(fg[2 * x + 1]);
1031 r1[2 * x] = sample(fg[2 * x]);
1032 r1[2 * x + 1] = sample(gavg.wrapping_add(blue[x].wrapping_mul(2)));
1033 }
1034 }
1035 });
1036 }
1037 Ok(())
1038}
1039
1040#[cfg(test)]
1041mod tests {
1042 use super::*;
1043
1044 #[test]
1045 fn helpers_match_definitions() {
1046 for x in -9..=9 {
1047 assert_eq!(fshr(x, 1), (x as f64 / 2.0).floor() as i32);
1048 assert_eq!(fshr(x, 2), (x as f64 / 4.0).floor() as i32);
1049 }
1050 assert_eq!(edge_detail(3, true), 7);
1051 assert_eq!(edge_detail(3, false), 6);
1052 assert_eq!(edge_detail(-4, false), -9);
1053 assert_eq!(edge_detail(-4, true), -8);
1054 assert_eq!(edge_detail(0, false), 0);
1055 assert_eq!(sign16(0xffff), -1);
1056 assert_eq!(sample(-5000), LLVC3_CURVE[0]);
1057 assert_eq!(sample(5000), 39002);
1058 }
1059
1060 #[test]
1061 fn coefficient_bits_and_limits() {
1062 let data = [0b1010_0000u8, 0xff, 0, 0, 0, 0, 0, 0, 0x80];
1063 let mut b = CoeffBits::new(&data, 0, 1);
1064 assert_eq!(b.read(3), 0b101);
1065 assert_eq!(b.read(8), 0b0000_0111);
1066 let mut b = CoeffBits::new(&data, 0, 1);
1068 b.read(32);
1069 b.read(32);
1070 b.read(32);
1071 b.read(24);
1072 assert_eq!(b.read(16), 0);
1073 assert_eq!(b.status, 2);
1074 }
1075
1076 #[test]
1077 fn inverse_lifting_reconstructs_forward_53() {
1078 let sig: Vec<i32> = vec![10, 13, 7, 2, 8, 30, 31, 29, 5, 6];
1080 let n = sig.len() / 2;
1081 let mut high = vec![0; n];
1082 let mut low = vec![0; n];
1083 for i in 0..n {
1084 let r = if 2 * i + 2 < sig.len() { sig[2 * i + 2] } else { sig[2 * i] };
1085 high[i] = sig[2 * i + 1] - fshr(sig[2 * i] + r, 1);
1086 }
1087 for i in 0..n {
1088 let hp = high[i.saturating_sub(1)];
1089 low[i] = sig[2 * i] + fshr(hp + high[i] + 2, 2);
1090 }
1091 let lo = Plane { rows: 1, cols: n, data: low };
1092 let hi = Plane { rows: 1, cols: n, data: high };
1093 assert_eq!(inv53_horizontal(&lo, &hi, false).unwrap().data, sig);
1094 }
1095
1096 struct RefBits<'a> {
1098 data: &'a [u8],
1099 start: usize,
1100 pos: usize,
1101 limit: usize,
1102 status: u8,
1103 }
1104
1105 impl RefBits<'_> {
1106 fn bit(&mut self) -> u32 {
1107 if self.pos >= self.limit {
1108 self.status = 2;
1109 return 0;
1110 }
1111 let byte = self.start + self.pos / 8;
1112 let b = self.data.get(byte).map(|&b| (b >> (7 - self.pos % 8)) & 1).unwrap_or(0) as u32;
1113 self.pos += 1;
1114 b
1115 }
1116 fn read(&mut self, n: u32) -> u32 {
1117 (0..n).fold(0, |a, _| a << 1 | self.bit())
1118 }
1119 fn unary_plus_one(&mut self) -> i32 {
1120 let mut zeros = 0;
1121 while self.status == 0 {
1122 let b = self.bit();
1123 if self.status != 0 {
1124 break;
1125 }
1126 if b != 0 {
1127 return zeros + 1;
1128 }
1129 zeros += 1;
1130 }
1131 zeros + 1
1132 }
1133 fn leading_one_within(&mut self, k: u32) -> Option<u32> {
1134 (0..k).find(|_| self.bit() != 0)
1135 }
1136 }
1137
1138 #[test]
1139 fn coefficient_reader_matches_bit_reference() {
1140 let mut x = 99u32;
1141 let data: Vec<u8> = (0..300)
1142 .map(|i| {
1143 x = x.wrapping_mul(1664525).wrapping_add(1013904223);
1144 let b = (x >> 24) as u8;
1145 if i % 5 == 0 { 0 } else { b & (b >> 1) }
1146 })
1147 .collect();
1148 for (off, len) in [(0usize, 40usize), (3, 100), (17, 7), (250, 60)] {
1149 let mut a = CoeffBits::new(&data, off, len);
1150 let words = ((len.div_ceil(8)) + 1) & !1;
1151 let mut b = RefBits { data: &data, start: off, pos: 0, limit: words * 64, status: 0 };
1152 let mut y = off as u32 + 7;
1153 for step in 0..400 {
1154 y = y.wrapping_mul(1103515245).wrapping_add(12345);
1155 match (y >> 16) % 3 {
1156 0 => {
1157 let n = (y >> 8) % 33;
1158 assert_eq!(a.read(n), b.read(n), "read {n} step {step}");
1159 }
1160 1 => assert_eq!(a.unary_plus_one(), b.unary_plus_one(), "unary step {step}"),
1161 _ => {
1162 let k = (y >> 8) % 20;
1163 assert_eq!(a.leading_one_within(k), b.leading_one_within(k), "lead {k} step {step}");
1164 }
1165 }
1166 assert_eq!(a.status != 0, b.status != 0, "status step {step}");
1167 }
1168 }
1169 }
1170
1171 #[test]
1172 fn garbage_strips_are_rejected() {
1173 let mut out = vec![0u16; 64 * 32];
1174 assert!(decode(&[0u8; 100], &mut out, 64, 32, false).is_err());
1175 let mut strip = vec![0u8; 0x400];
1176 strip[0x200..0x204].copy_from_slice(b"A000");
1177 assert!(decode(&strip, &mut out, 64, 32, false).is_err());
1178 }
1179}