1use flashraw_core::bits::{BitPumpMsb, BitRead};
15use flashraw_core::{Error, Result};
16
17pub const BLOCK_65000: usize = 256;
19
20pub fn block_len_65000(data: &[u8], pos: usize, len: usize) -> Option<(usize, bool)> {
23 let bsize = (len + 3) & !3;
24 let hdr = data.get(pos..pos + bsize / 2)?;
25 if hdr.iter().any(|&c| c & 15 > 12 || c >> 4 > 12) {
26 return Some((bsize.div_ceil(8) * 12, true));
27 }
28 let mut consumed = bsize / 2;
29 let mut bits = 0u32;
30 if bsize & 7 == 4 {
31 consumed += 2;
32 bits = 16;
33 }
34 for &c in hdr {
35 for l in [(c & 15) as u32, (c >> 4) as u32] {
36 if bits < l {
37 consumed += 4;
38 bits += 32;
39 }
40 bits -= l;
41 }
42 }
43 Some((consumed, false))
44}
45
46pub fn decode_block_65000(data: &[u8], pos: usize, len: usize, out: &mut [i16]) -> Result<bool> {
50 decode_block_65000_at(data, pos, len, out).map(|(raw, _)| raw)
51}
52
53pub fn decode_block_65000_at(data: &[u8], pos: usize, len: usize, out: &mut [i16]) -> Result<(bool, usize)> {
56 let bsize = (len + 3) & !3;
57 let need = bsize.div_ceil(8) * 8;
58 if out.len() < need {
59 return Err(Error::InvalidArgument("Kodak 65000: output block too small".into()));
60 }
61 let hdr = data.get(pos..pos + bsize / 2).ok_or_else(|| Error::corrupt("Kodak 65000: truncated block header"))?;
62 let byte = |p: usize| -> u64 { data.get(p).copied().unwrap_or(0) as u64 };
63 if hdr.iter().any(|&c| c & 15 > 12 || c >> 4 > 12) {
64 let mut p = pos;
66 for i in (0..bsize).step_by(8) {
67 let mut raw = [0u16; 6];
68 for r in raw.iter_mut() {
69 *r = ((byte(p) as u16) << 8) | byte(p + 1) as u16;
70 p += 2;
71 }
72 out[i] = (raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12) as i16;
73 out[i + 1] = (raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12) as i16;
74 for j in 0..6 {
75 out[i + 2 + j] = (raw[j] & 0xfff) as i16;
76 }
77 }
78 return Ok((true, p));
79 }
80 let mut p = pos + bsize / 2;
81 let mut bitbuf: u64 = 0;
82 let mut bits = 0u32;
83 if bsize & 7 == 4 {
84 bitbuf = (byte(p) << 8) | byte(p + 1);
85 p += 2;
86 bits = 16;
87 }
88 for i in 0..bsize {
89 let c = hdr[i / 2];
90 let l = if i & 1 == 0 { c & 15 } else { c >> 4 } as u32;
91 if bits < l {
92 bitbuf |= ((byte(p) << 8 | byte(p + 1)) | (byte(p + 2) << 8 | byte(p + 3)) << 16) << bits;
94 p += 4;
95 bits += 32;
96 }
97 let mut d = (bitbuf & (0xffff >> (16 - l))) as i32;
98 bitbuf >>= l;
99 bits -= l;
100 if l > 0 && d & (1 << (l - 1)) == 0 {
101 d -= (1 << l) - 1;
102 }
103 out[i] = d as i16;
104 }
105 if p > data.len() + 4 {
106 return Err(Error::corrupt("Kodak 65000: truncated block data"));
107 }
108 Ok((false, p))
109}
110
111pub fn scan_65000_rows(data: &[u8], start: usize, width: usize, height: usize) -> Result<Vec<usize>> {
114 let mut rows = Vec::with_capacity(height);
115 let mut pos = start;
116 for _ in 0..height {
117 rows.push(pos);
118 let mut col = 0;
119 while col < width {
120 let len = BLOCK_65000.min(width - col);
121 let (n, _) =
122 block_len_65000(data, pos, len).ok_or_else(|| Error::corrupt("Kodak 65000: truncated data"))?;
123 pos += n;
124 col += BLOCK_65000;
125 }
126 }
127 Ok(rows)
128}
129
130pub fn decode_65000_row(data: &[u8], mut pos: usize, out: &mut [u16], curve: &[u16]) -> Result<usize> {
134 let width = out.len();
135 let mut buf = [0i16; 272];
136 let mut col = 0;
137 while col < width {
138 let len = BLOCK_65000.min(width - col);
139 if data.get(pos..pos + ((len + 3) & !3) / 2).is_none() {
140 return Err(Error::corrupt("Kodak 65000: truncated data"));
141 }
142 let (raw, end) = decode_block_65000_at(data, pos, len, &mut buf)?;
143 pos = end;
144 let mut pred = [0i32; 2];
145 for (i, o) in out[col..col + len].iter_mut().enumerate() {
146 let idx = if raw {
147 buf[i] as i32
148 } else {
149 pred[i & 1] += buf[i] as i32;
150 pred[i & 1]
151 };
152 if (0..0xffff).contains(&idx) {
153 *o = curve.get(idx as usize).copied().unwrap_or(*curve.last().unwrap_or(&0));
154 }
155 }
156 col += BLOCK_65000;
157 }
158 Ok(pos)
159}
160
161pub fn dc120_row(src: &[u8], row: usize, out: &mut [u16]) {
163 const MUL: [usize; 4] = [162, 192, 187, 92];
164 const ADD: [usize; 4] = [0, 636, 424, 212];
165 let shift = row * MUL[row & 3] + ADD[row & 3];
166 let n = src.len();
167 if n == 0 {
168 return;
169 }
170 for (col, o) in out.iter_mut().enumerate() {
171 *o = src[(col + shift) % n] as u16;
172 }
173}
174
175#[inline(always)]
177fn ycc_rgb(y: i32, cb: i32, cr: i32, curve: &[u16], out: &mut [u16]) {
178 let g = y - ((cb + cr + 2) >> 2);
179 let rgb = [g + cr, g, g + cb];
180 for (o, v) in out.iter_mut().zip(rgb) {
181 *o = curve[v.clamp(0, 255) as usize];
182 }
183}
184
185pub fn c330_row(pixel: &[u8], width: usize, curve: &[u16], out: &mut [u16]) {
187 for col in 0..width {
188 let at = |i: usize| pixel.get(i).copied().unwrap_or(0) as i32;
189 let y = at(col * 2);
190 let cb = at(((col * 2) & !3) | 1) - 128;
191 let cr = at(((col * 2) & !3) | 3) - 128;
192 ycc_rgb(y, cb, cr, curve, &mut out[col * 3..col * 3 + 3]);
193 }
194}
195
196pub fn c603_row(pixel: &[u8], width: usize, odd: bool, curve: &[u16], out: &mut [u16]) {
199 let at = |i: usize| pixel.get(i).copied().unwrap_or(0) as i32;
200 for col in 0..width {
201 let y = at(width * 2 * odd as usize + col);
202 let cb = at(width + (col & !1)) - 128;
203 let cr = at(width + (col & !1) + 1) - 128;
204 ycc_rgb(y, cb, cr, curve, &mut out[col * 3..col * 3 + 3]);
205 }
206}
207
208pub fn gamma_curve(pwr: f64, ts: f64, imax: u32) -> Vec<u16> {
211 let mut g = [pwr, ts, 0.0, 0.0, 0.0, 0.0];
212 let mut bnd = [0.0f64, 0.0];
213 bnd[(g[1] >= 1.0) as usize] = 1.0;
214 if g[1] != 0.0 && (g[1] - 1.0) * (g[0] - 1.0) <= 0.0 {
215 for _ in 0..48 {
216 g[2] = (bnd[0] + bnd[1]) / 2.0;
217 if g[0] != 0.0 {
218 let k = ((g[2] / g[1]).powf(-g[0]) - 1.0) / g[0] - 1.0 / g[2] > -1.0;
219 bnd[k as usize] = g[2];
220 } else {
221 let k = g[2] / (1.0 - 1.0 / g[2]).exp() < g[1];
222 bnd[k as usize] = g[2];
223 }
224 }
225 g[3] = g[2] / g[1];
226 if g[0] != 0.0 {
227 g[4] = g[2] * (1.0 / g[0] - 1.0);
228 }
229 }
230 let mut curve = vec![0xffffu16; 0x10000];
231 for (i, c) in curve.iter_mut().enumerate() {
232 let r = i as f64 / imax as f64;
233 if r < 1.0 {
234 let v = if r < g[2] {
235 r / g[1]
236 } else if g[0] != 0.0 {
237 ((r + g[4]) / (1.0 + g[4])).powf(1.0 / g[0])
238 } else {
239 ((r - 1.0) / g[2]).exp()
240 };
241 *c = (0x10000 as f64 * v) as u16;
242 }
243 }
244 curve
245}
246
247pub fn decode_radc(data: &[u8], width: usize, height: usize, cbpp: u32, out: &mut [u16]) -> Result<()> {
251 const SRC: &[i8] = &[
252 1, 1, 2, 3, 3, 4, 4, 2, 5, 7, 6, 5, 7, 6, 7, 8, 1, 0, 2, 1, 3, 3, 4, 4, 5, 2, 6, 7, 7, 6, 8, 5, 8, 8, 2, 1, 2,
253 3, 3, 0, 3, 2, 3, 4, 4, 6, 5, 5, 6, 7, 6, 8, 2, 0, 2, 1, 2, 3, 3, 2, 4, 4, 5, 6, 6, 7, 7, 5, 7, 8, 2, 1, 2, 4,
254 3, 0, 3, 2, 3, 3, 4, 7, 5, 5, 6, 6, 6, 8, 2, 3, 3, 1, 3, 2, 3, 4, 3, 5, 3, 6, 4, 7, 5, 0, 5, 8, 2, 3, 2, 6, 3,
255 0, 3, 1, 4, 4, 4, 5, 4, 7, 5, 2, 5, 8, 2, 4, 2, 7, 3, 3, 3, 6, 4, 1, 4, 2, 4, 5, 5, 0, 5, 8, 2, 6, 3, 1, 3, 3,
256 3, 5, 3, 7, 3, 8, 4, 0, 5, 2, 5, 4, 2, 0, 2, 1, 3, 2, 3, 3, 4, 4, 4, 5, 5, 6, 5, 7, 4, 8, 1, 0, 2, 2, 2, -2, 1,
257 -3, 1, 3, 2, -17, 2, -5, 2, 5, 2, 17, 2, -7, 2, 2, 2, 9, 2, 18, 2, -18, 2, -9, 2, -2, 2, 7, 2, -28, 2, 28, 3,
258 -49, 3, -9, 3, 9, 4, 49, 5, -79, 5, 79, 2, -1, 2, 13, 2, 26, 3, 39, 4, -16, 5, 55, 6, -37, 6, 76, 2, -26, 2,
259 -13, 2, 1, 3, -39, 4, 16, 5, -55, 6, -76, 6, 37,
260 ];
261 const PT: [i32; 12] = [0, 0, 1280, 1344, 2320, 3616, 3328, 8000, 4095, 16383, 65535, 16383];
262 const COLS: usize = 386;
263 if width > 768 || height > 512 || width < 4 || height % 4 != 0 || out.len() < width * height {
264 return Err(Error::corrupt(format!("RADC: unsupported geometry {width}x{height}")));
265 }
266 let mut curve = vec![0u16; 0x10000];
268 for i in (2..12).step_by(2) {
269 for c in PT[i - 2]..=PT[i] {
270 let v = (c - PT[i - 2]) as f32 / (PT[i] - PT[i - 2]) as f32 * (PT[i + 1] - PT[i - 1]) as f32
271 + PT[i - 1] as f32
272 + 0.5f32;
273 curve[c as usize] = v as u16;
274 }
275 }
276 let mut huff = vec![0u16; 19 * 256];
278 let mut s = 0usize;
279 for pair in SRC.chunks_exact(2) {
280 let n = 256usize >> pair[0];
281 for _ in 0..n {
282 if let Some(h) = huff.get_mut(s) {
283 *h = ((pair[0] as u16) << 8) | (pair[1] as u8 as u16);
284 }
285 s += 1;
286 }
287 }
288 let q = if cbpp == 243 { 2 } else { 3 };
289 for c in 0..256usize {
290 huff[18 * 256 + c] = (((8 - q) as u16) << 8) | ((c >> q << q) | 1 << (q - 1)) as u16;
291 }
292 let mut bits = BitPumpMsb::new(data);
293 let token = |bits: &mut BitPumpMsb, tree: usize| -> i32 {
294 let e = huff[tree * 256 + bits.peek(8) as usize];
295 bits.skip((e >> 8) as u32);
296 (e & 0xff) as u8 as i8 as i32
297 };
298 let mut buf = vec![2048i16; 3 * 3 * COLS];
299 let at = |c: usize, y: usize, x: usize| (c * 3 + y) * COLS + x;
300 let mut last = [16i32; 3];
301 let half = width / 2;
302 let raw = |out: &mut [u16], r: usize, x: usize, v: i32| {
303 if let Some(o) = out.get_mut(r * width + x) {
304 *o = v as u16;
305 }
306 };
307 for row in (0..height).step_by(4) {
308 let mut mul = [0i32; 3];
309 for m in mul.iter_mut() {
310 *m = bits.get(6) as i32;
311 }
312 if mul.contains(&0) {
313 return Err(Error::corrupt("RADC: zero multiplier"));
314 }
315 for c in 0..3 {
316 let mut val = ((0x100_0000 / last[c] + 0x7ff) >> 12) * mul[c];
317 let s = if val > 65564 { 10 } else { 12 };
318 let x = (1i64 << (s - 1)) - 1;
319 val <<= 12 - s;
320 for e in buf[c * 3 * COLS..(c + 1) * 3 * COLS].iter_mut() {
321 *e = ((((*e as i64) * val as i64 + x).min(0x7FFF_FFFF) >> s) & 0xffff) as u16 as i16;
322 }
323 last[c] = mul[c];
324 let pred = |buf: &[i16], y: usize, x: usize| -> i32 {
325 if c != 0 {
326 (buf[at(c, y - 1, x)] as i32 + buf[at(c, y, x + 1)] as i32) / 2
327 } else {
328 (buf[at(c, y - 1, x + 1)] as i32 + 2 * buf[at(c, y - 1, x)] as i32 + buf[at(c, y, x + 1)] as i32)
329 / 4
330 }
331 };
332 for r in 0..=(c == 0) as usize {
333 let v = (mul[c] << 7) as i16;
334 buf[at(c, 1, half)] = v;
335 buf[at(c, 2, half)] = v;
336 let mut tree = 1usize;
337 let mut col = half as i32;
338 let mut guard = 0usize;
339 while col > 0 {
340 guard += 1;
341 if guard > 4 * width || bits.exhausted() {
342 return Err(Error::corrupt("RADC: truncated data"));
343 }
344 let t = token(&mut bits, tree);
345 if !(0..=8).contains(&t) {
346 return Err(Error::corrupt("RADC: invalid tree token"));
347 }
348 tree = t as usize;
349 if tree != 0 {
350 col -= 2;
351 if col >= 0 {
352 for y in 1..3 {
353 for x in [col as usize + 1, col as usize] {
354 let nv = if tree == 8 {
355 (token(&mut bits, 18) as u8 as i32) * mul[c]
356 } else {
357 token(&mut bits, tree + 10) * 16 + pred(&buf, y, x)
358 };
359 buf[at(c, y, x)] = nv as i16;
360 }
361 }
362 }
363 } else {
364 loop {
365 let nreps = if col > 2 { token(&mut bits, 9) + 1 } else { 1 };
366 let mut rep = 0;
367 while rep < 8 && rep < nreps && col > 0 {
368 col -= 2;
369 if col >= 0 {
370 for y in 1..3 {
371 for x in [col as usize + 1, col as usize] {
372 buf[at(c, y, x)] = pred(&buf, y, x) as i16;
373 }
374 }
375 }
376 if rep & 1 != 0 {
377 let step = token(&mut bits, 10) << 4;
378 for y in 1..3 {
379 for x in [col.max(0) as usize + 1, col.max(0) as usize] {
380 if col >= 0 {
381 let e = &mut buf[at(c, y, x)];
382 *e = e.wrapping_add(step as i16);
383 }
384 }
385 }
386 }
387 rep += 1;
388 }
389 if nreps != 9 {
390 break;
391 }
392 }
393 }
394 }
395 for y in 0..2 {
396 for x in 0..half {
397 let v = ((buf[at(c, y + 1, x)] as i32) << 4) / mul[c];
398 let v = v.max(0);
399 if c != 0 {
400 raw(out, row + y * 2 + c - 1, x * 2 + 2 - c, v);
401 } else {
402 raw(out, row + r * 2 + y, x * 2 + y, v);
403 }
404 }
405 }
406 let skip = (c == 0) as usize;
408 let (dst, src) = (at(c, 0, 0), at(c, 2, 0));
409 let tmp: Vec<i16> = buf[src..src + COLS - skip].to_vec();
410 buf[dst + skip..dst + COLS].copy_from_slice(&tmp);
411 }
412 }
413 for y in row..row + 4 {
414 for x in 0..width {
415 if (x + y) & 1 == 1 {
416 let r = if x > 0 { x - 1 } else { x + 1 };
417 let s = if x + 1 < width { x + 1 } else { x - 1 };
418 let g = |xx: usize| out[y * width + xx] as i32;
419 let v = ((g(x) - 2048) * 2 + (g(r) + g(s)) / 2).max(0);
420 out[y * width + x] = v as u16;
421 }
422 }
423 }
424 }
425 for v in out[..width * height].iter_mut() {
426 *v = curve[*v as usize];
427 }
428 Ok(())
429}
430
431#[cfg(test)]
432mod tests {
433 use super::*;
434
435 fn encode_block(diffs: &[i32]) -> Vec<u8> {
437 let bsize = (diffs.len() + 3) & !3;
438 let mut d = diffs.to_vec();
439 d.resize(bsize, 0);
440 let lens: Vec<u32> =
441 d.iter().map(|&v| if v == 0 { 0 } else { 32 - v.unsigned_abs().leading_zeros() }).collect();
442 let mut out: Vec<u8> = lens.chunks(2).map(|p| (p[0] | p[1] << 4) as u8).collect();
443 let mut bits: Vec<u8> = Vec::new();
446 for (i, &v) in d.iter().enumerate() {
447 let l = lens[i];
448 let code = if v >= 0 { v as u32 } else { (v + (1 << l) - 1) as u32 };
449 for b in 0..l {
450 bits.push(((code >> b) & 1) as u8);
451 }
452 }
453 let mut words: Vec<u16> = Vec::new();
454 for chunk in bits.chunks(16) {
455 let mut w = 0u16;
456 for (k, &b) in chunk.iter().enumerate() {
457 w |= (b as u16) << k;
458 }
459 words.push(w);
460 }
461 words.resize(words.len() + 4, 0);
463 for w in words {
464 out.extend(w.to_be_bytes());
465 }
466 out
467 }
468
469 #[test]
470 fn block_65000_round_trip() {
471 for n in [256usize, 100, 8, 4, 3] {
472 let diffs: Vec<i32> = (0..n).map(|i| ((i as i32 * 37) % 201) - 100).collect();
473 let data = encode_block(&diffs);
474 let mut out = [0i16; 272];
475 let raw = decode_block_65000(&data, 0, n, &mut out).unwrap();
476 assert!(!raw);
477 assert_eq!(&out[..n].iter().map(|&v| v as i32).collect::<Vec<_>>(), &diffs);
478 }
479 }
480
481 #[test]
482 fn raw_block_and_lengths() {
483 let mut data = vec![0xFFu8; 12];
485 data[0] = 0x1A;
486 data[1] = 0xBC;
487 let mut out = [0i16; 16];
488 assert!(decode_block_65000(&data, 0, 8, &mut out).unwrap());
489 assert_eq!(out[2], 0xABC);
490 assert_eq!(block_len_65000(&data, 0, 8), Some((12, true)));
491 }
492
493 #[test]
494 fn dc120_rotation() {
495 let src: Vec<u8> = (0..848u32).map(|i| (i % 251) as u8).collect();
496 let mut out = vec![0u16; 848];
497 dc120_row(&src, 1, &mut out);
498 assert_eq!(out[0], src[192 + 636] as u16);
499 }
500
501 #[test]
502 fn gamma_curve_monotonic() {
503 let c = gamma_curve(0.0, 3.875, 255);
504 assert_eq!(c[0], 0);
505 assert!(c.windows(2).take(255).all(|w| w[0] <= w[1]));
506 assert_eq!(c[255], 0xffff);
507 }
508
509 #[test]
510 fn radc_garbage_no_panic() {
511 let mut seed = 1u32;
512 let data: Vec<u8> = (0..5000)
513 .map(|_| {
514 seed = seed.wrapping_mul(1664525).wrapping_add(1013904223);
515 (seed >> 24) as u8 | 1
516 })
517 .collect();
518 let mut out = vec![0u16; 768 * 512];
519 let _ = decode_radc(&data, 768, 512, 152, &mut out);
520 assert!(decode_radc(&data, 1000, 512, 152, &mut out).is_err());
521 }
522}