1use crate::ImageBuffer;
5
6const TYPE_Y: u16 = 0x000C;
7const TYPE_YUV420: u16 = 0x3900;
8const TYPE_YUV422: u16 = 0x0390;
9const TYPE_YUV440: u16 = 0x1390;
10const TYPE_YUV444: u16 = 0x00E4;
11const TYPE_RGB444: u16 = 0x01E4;
12
13const FOLDING: [u8; 64] = [56u8, 57, 8, 40, 9, 58, 59, 10, 41, 0, 48, 1, 42, 11, 60, 61, 12, 43, 2, 49, 16, 32, 17, 50, 3, 44, 13, 62, 63, 14, 45, 4, 51, 18, 33, 24, 25, 34, 19, 52, 5, 46, 15, 47, 6, 53, 20, 35, 26, 27, 36, 21, 54, 7, 55, 22, 37, 28, 29, 38, 23, 39, 30, 31,];
14const FC0: f32 = 1.0;
15const FC1: f32 = 0.98078528;
16const FC2: f32 = 0.92387953;
17const FC3: f32 = 0.83146961;
18const FC4: f32 = 0.70710678;
19const FC5: f32 = 0.55557023;
20const FC6: f32 = 0.38268343;
21const FC7: f32 = 0.19509032;
22
23const FIX: u8 = 8;
24const ONE: f32 = (1 << FIX) as f32;
25const C0: i32 = (FC0 * ONE) as i32;
26const C1: i32 = (FC1 * ONE) as i32;
27const C2: i32 = (FC2 * ONE) as i32;
28const C3: i32 = (FC3 * ONE) as i32;
29const C4: i32 = (FC4 * ONE) as i32;
30const C5: i32 = (FC5 * ONE) as i32;
31const C6: i32 = (FC6 * ONE) as i32;
32const C7: i32 = (FC7 * ONE) as i32;
33
34const C7PC1: i32 = C7 + C1;
35const C5PC3: i32 = C5 + C3;
36const C7MC1: i32 = C7 - C1;
37const C5MC3: i32 = C5 - C3;
38const C0S: i32 = C0 >> 1;
39const C6PC2: i32 = C6 + C2;
40const C6MC2: i32 = C6 - C2;
41
42fn from_le16(src: &[u8]) -> u16 {
43 ((src[1] as u16) << 8) | (src[0] as u16)
44}
45
46fn from_le32(src: &[u8]) -> u32 {
47 ((src[3] as u32) << 24) | ((src[2] as u32) << 16) | ((src[1] as u32) << 8) | (src[0] as u32)
48}
49
50fn from_be16(src: &[u8]) -> u16 {
51 ((src[0] as u16) << 8) | (src[1] as u16)
52}
53
54fn from_be32(src: &[u8]) -> u32 {
55 ((src[0] as u32) << 24) | ((src[1] as u32) << 16) | ((src[2] as u32) << 8) | (src[3] as u32)
56}
57
58fn make_coeff(cat: u8, code: isize) -> i32 {
59 let mcat = cat - 1;
60 let hmcat = 1 << mcat;
61 let base = code & (hmcat - 1);
62 if (code & hmcat) != 0 {
63 (base + hmcat) as i32
64 }
65 else {
66 (base + 1 - (1 << cat)) as i32
67 }
68}
69
70#[derive(Copy, Clone)]
71struct Table {
72 prefix: [u16; 65536],
73}
74
75impl Table {
76 pub fn new_empty() -> Table {
77 Table {
78 prefix: [0u16; 65536],
79 }
80 }
81
82 pub fn new(bits: [u8; 16], huffval: [u8; 256]) -> Table {
83 let mut prefix = [0u16; 65536];
84 let mut dp = 0;
85 let mut count = 0;
86 for i in 1..17 {
87 for _k in 0..bits[i - 1] {
89 let runcat = huffval[count] as u16;
91 for _l in 0..(65536 >> i) {
92 prefix[dp] = (runcat << 8) | (i as u16);
93 dp += 1;
94 }
95 count += 1;
96 }
97 }
98 Table {
99 prefix: prefix,
100 }
101 }
102}
103
104fn jpeg_get8(block: &[u8], rp: &mut usize) -> u8 {
105 let mut b = block[*rp];
106 *rp += 1;
108 if b == 0xFF {
109 b = block[*rp];
110 *rp += 1;
112 if b == 0 {
113 return 0xFF;
114 }
115 }
116 b
117}
118
119struct Reader<'a> {
120 block: &'a [u8],
121 rp: usize,
122 bit: u32,
123 cache: u32,
124}
125
126impl<'a> Reader<'a> {
127 pub fn new(block: &'a [u8]) -> Reader<'a> {
128 let mut rp = 0usize;
129 let mut bit = 0u32;
130 let mut cache = 0u32;
131 while bit <= 24 {
132 let b = jpeg_get8(block, &mut rp);
133 cache |= (b as u32) << (24 - bit);
134 bit += 8;
135 }
136 Reader {
137 block: block,
138 rp: rp,
139 bit: bit,
140 cache: cache,
141 }
142 }
143
144 fn restock(&mut self) {
145 while self.bit <= 24 {
146 let b = if self.rp >= self.block.len() {0} else {jpeg_get8(self.block, &mut self.rp)}; self.cache |= (b as u32) << (24 - self.bit);
148 self.bit += 8;
149 }
150 }
151
152 pub fn peek(&self, n: usize) -> u32 {
153 self.cache >> (32 - n)
154 }
155
156 pub fn skip(&mut self, n: usize) {
157 self.cache <<= n;
158 self.bit -= n as u32;
159 self.restock();
160 }
161
162 pub fn get1(&mut self) -> bool {
163 let result = self.peek(1) == 1;
164 self.skip(1);
166 result
167 }
168
169 pub fn getn(&mut self, n: usize) -> u32 {
170 let result = self.peek(n);
171 self.skip(n);
173 result
174 }
175
176 pub fn get_code(&mut self, table: &Table) -> u8 {
177 let index = self.cache >> 16;
178 let d = table.prefix[index as usize];
179 let symbol = (d >> 8) & 255;
180 let n = d & 255;
181 self.skip(n as usize);
183 symbol as u8
184 }
185
186 pub fn enter(&mut self, rp: usize) {
187 self.rp = rp;
188 self.cache = 0;
189 self.bit = 0;
190 self.restock();
191 }
192
193 pub fn leave(&mut self) -> usize {
194 if (self.bit == 32) && (self.rp == 4) {
197 return 0;
198 }
199 for _i in 0..((self.bit + 7) / 8) - 2 {
217 if (self.block[self.rp - 1] == 0x00) && (self.block[self.rp - 2] == 0xFF) {
218 self.rp -= 1;
219 }
220 self.rp -= 1;
221 }
222 self.rp
224 }
225}
226
227fn unpack_sequential(reader: &mut Reader, coeffs: &mut [i32], dcht: &Table, acht: &Table, dc: &mut i32) {
228 let cat = reader.get_code(dcht);
229 if cat > 0 {
230 let code = reader.getn(cat as usize);
231 *dc += make_coeff(cat, code as isize) as i32;
232 }
233 coeffs[FOLDING[0] as usize] = *dc;
234 let mut i = 1;
236 while i < 64 {
237 let runcat = reader.get_code(acht);
238 let run = runcat >> 4;
239 let cat = runcat & 15;
240 if cat > 0 {
241 let code = reader.getn(cat as usize);
242 let coeff = make_coeff(cat, code as isize) as i32;
243 i += run;
244 coeffs[FOLDING[i as usize] as usize] = coeff;
245 }
247 else {
248 if run == 15 { i += 15;
250 }
252 else { break;
255 }
256 }
257 i += 1;
258 }
259}
260
261fn unpack_progressive_start_dc(reader: &mut Reader, coeffs: &mut[i32], dcht: &Table, dc: &mut i32, shift: u8) {
262 let cat = reader.get_code(dcht);
263 if cat > 0 {
264 let code = reader.getn(cat as usize);
265 *dc += make_coeff(cat, code as isize) as i32;
266 }
267 coeffs[FOLDING[0] as usize] = *dc << shift;
269}
270
271fn unpack_progressive_start_ac(reader: &mut Reader, coeffs: &mut[i32], acht: &Table, start: u8, end: u8, shift: u8, eobrun: &mut usize) {
272 if *eobrun != 0 {
273 *eobrun -= 1;
274 }
275 else {
276 let mut i = start;
277 while i <= end {
278 let runcat = reader.get_code(acht);
279 let run = runcat >> 4;
280 let cat = runcat & 15;
281 if cat != 0 {
282 let code = reader.getn(cat as usize);
283 let coeff = make_coeff(cat, code as isize);
284 i += run;
285 coeffs[FOLDING[i as usize] as usize] = (coeff << shift) as i32;
286 }
287 else {
288 if run == 15 {
289 i += 15;
290 }
291 else {
292 *eobrun = 1 << run;
293 if run != 0 {
294 *eobrun += reader.getn(run as usize) as usize;
295 }
296 *eobrun -= 1;
297 break;
298 }
299 }
300 i += 1;
301 }
302 }
303}
304
305fn unpack_progressive_refine_dc(reader: &mut Reader, coeffs: &mut[i32], shift: u8) {
306 if reader.get1() {
307 coeffs[FOLDING[0] as usize] |= 1 << shift;
308 }
309}
310
311fn update_nonzeros(reader: &mut Reader, coeffs: &mut[i32], start: u8, end: u8, shift: u8, count: u8) -> u8 {
312 let mut i = start;
313 let mut k = count;
314 while i <= end {
315 if coeffs[FOLDING[i as usize] as usize] != 0 {
316 if reader.get1() {
317 if coeffs[FOLDING[i as usize] as usize] > 0 {
318 coeffs[FOLDING[i as usize] as usize] += 1 << shift;
319 }
320 else {
321 coeffs[FOLDING[i as usize] as usize] -= 1 << shift;
322 }
323 }
324 }
325 else {
326 if k == 0 {
327 return i;
328 }
329 k -= 1;
330 }
331 i += 1;
332 }
333 i
334}
335
336fn unpack_progressive_refine_ac(reader: &mut Reader, coeffs: &mut[i32], acht: &Table, start: u8, end: u8, shift: u8, eobrun: &mut usize) {
337 if *eobrun != 0 {
338 update_nonzeros(reader, &mut coeffs[0..64], start, end, shift, 64);
339 *eobrun -= 1;
340 }
341 else {
342 let mut i = start;
343 while i <= end {
344 let runcat = reader.get_code(acht);
345 let run = runcat >> 4;
346 let cat = runcat & 15;
347 if cat != 0 {
348 let sb = reader.get1();
349 i = update_nonzeros(reader, &mut coeffs[0..64], i, end, shift, run);
350 if sb {
351 coeffs[FOLDING[i as usize] as usize] = 1 << shift;
352 }
353 else {
354 coeffs[FOLDING[i as usize] as usize] = 11 << shift;
355 }
356 }
357 else {
358 if run == 15 {
359 i = update_nonzeros(reader, &mut coeffs[0..64], i, end, shift, 15);
360 }
361 else {
362 *eobrun = 1 << run;
363 if run != 0 {
364 *eobrun += reader.getn(run as usize) as usize;
365 }
366 *eobrun -= 1;
367 update_nonzeros(reader, &mut coeffs[0..64], i, end, shift, 64);
368 break;
369 }
370 }
371 }
372 }
373}
374
375fn unpack_block(reader: &mut Reader, coeffs: &mut [i32], dcht: &Table, acht: &Table, dc: &mut i32, start: u8, end: u8, shift: u8, refine: bool, eobrun: &mut usize) {
376 if refine {
377 if start == 0 {
378 unpack_progressive_refine_dc(reader, &mut coeffs[0..64], shift);
379 }
380 else {
381 unpack_progressive_refine_ac(reader, &mut coeffs[0..64], &acht, start, end, shift, eobrun);
382 }
383 }
384 else {
385 if start == 0 {
386 if (end == 63) && (shift == 0) {
387 unpack_sequential(reader, &mut coeffs[0..64], &dcht, &acht, dc);
388 }
389 else {
390 unpack_progressive_start_dc(reader, &mut coeffs[0..64], &dcht, dc, shift);
391 }
392 }
393 else {
394 unpack_progressive_start_ac(reader, &mut coeffs[0..64], &acht, start, end, shift, eobrun);
395 }
396 }
397}
398
399fn unpack_macroblock(
400 reader: &mut Reader,
401 coeffs: &mut [i32],
402 dcht: &[Table],
403 acht: &[Table],
404 dt: &[usize],
405 at: &[usize],
406 dc: &mut [i32],
407 start: u8,
408 end: u8,
409 shift: u8,
410 refine: bool,
411 eobrun: &mut usize,
412 itype: u16,
413 rescnt: &mut usize,
414 resint: usize,
415 mask: u8
416) {
417 match itype {
418 TYPE_Y => {
419 if (mask & 1) != 0 {
420 unpack_block(reader, &mut coeffs[0..64], &dcht[dt[0]], &acht[at[0]], &mut dc[0], start, end, shift, refine, eobrun);
421 }
422 },
423 TYPE_YUV420 => {
424 if (mask & 1) != 0 {
425 unpack_block(reader, &mut coeffs[0..64], &dcht[dt[0]], &acht[at[0]], &mut dc[0], start, end, shift, refine, eobrun);
426 unpack_block(reader, &mut coeffs[64..128], &dcht[dt[0]], &acht[at[0]], &mut dc[0], start, end, shift, refine, eobrun);
427 unpack_block(reader, &mut coeffs[128..192], &dcht[dt[0]], &acht[at[0]], &mut dc[0], start, end, shift, refine, eobrun);
428 unpack_block(reader, &mut coeffs[192..256], &dcht[dt[0]], &acht[at[0]], &mut dc[0], start, end, shift, refine, eobrun);
429 }
430 if (mask & 2) != 0 {
431 unpack_block(reader, &mut coeffs[256..320], &dcht[dt[1]], &acht[at[1]], &mut dc[1], start, end, shift, refine, eobrun);
432 }
433 if (mask & 4) != 0 {
434 unpack_block(reader, &mut coeffs[320..384], &dcht[dt[2]], &acht[at[2]], &mut dc[2], start, end, shift, refine, eobrun);
435 }
436 },
437 TYPE_YUV422 | TYPE_YUV440 => {
438 if (mask & 1) != 0 {
439 unpack_block(reader, &mut coeffs[0..64], &dcht[dt[0]], &acht[at[0]], &mut dc[0], start, end, shift, refine, eobrun);
440 unpack_block(reader, &mut coeffs[64..128], &dcht[dt[0]], &acht[at[0]], &mut dc[0], start, end, shift, refine, eobrun);
441 }
442 if (mask & 2) != 0 {
443 unpack_block(reader, &mut coeffs[128..192], &dcht[dt[1]], &acht[at[1]], &mut dc[1], start, end, shift, refine, eobrun);
444 }
445 if (mask & 4) != 0 {
446 unpack_block(reader, &mut coeffs[192..256], &dcht[dt[2]], &acht[at[2]], &mut dc[2], start, end, shift, refine, eobrun);
447 }
448 },
449 TYPE_YUV444 | TYPE_RGB444 => {
450 if (mask & 1) != 0 {
451 unpack_block(reader, &mut coeffs[0..64], &dcht[dt[0]], &acht[at[0]], &mut dc[0], start, end, shift, refine, eobrun);
452 }
453 if (mask & 2) != 0 {
454 unpack_block(reader, &mut coeffs[64..128], &dcht[dt[1]], &acht[at[1]], &mut dc[1], start, end, shift, refine, eobrun);
455 }
456 if (mask & 4) != 0 {
457 unpack_block(reader, &mut coeffs[128..192], &dcht[dt[2]], &acht[at[2]], &mut dc[2], start, end, shift, refine, eobrun);
458 }
459 },
460 _ => {},
461 }
462 if resint != 0 {
463 *rescnt -= 1;
464 if *rescnt == 0 {
465 let mut tsp = reader.leave();
466 if (reader.block[tsp] == 0xFF) && ((reader.block[tsp + 1] >= 0xD0) && (reader.block[tsp + 1] < 0xD8)) {
467 tsp += 2;
468 *rescnt = resint;
469 dc[0] = 0;
470 dc[1] = 0;
471 dc[2] = 0;
472 }
473 reader.enter(tsp);
474 }
475 }
476}
477
478fn partial_idct(out: &mut [i32], inp: &[i32]) {
479
480 for i in 0..8 {
481 let x3 = inp[i];
482 let x1 = inp[i + 8];
483 let x5 = inp[i + 16];
484 let x7 = inp[i + 24];
485 let x6 = inp[i + 32];
486 let x2 = inp[i + 40];
487 let x4 = inp[i + 48];
488 let x0 = inp[i + 56];
489
490 let q17 = C1 * (x1 + x7);
491 let q35 = C3 * (x3 + x5);
492 let r3 = C7PC1 * x1 - q17;
493 let d3 = C5PC3 * x3 - q35;
494 let r0 = C7MC1 * x7 + q17;
495 let d0 = C5MC3 * x5 + q35;
496 let b0 = r0 + d0;
497 let d2 = r3 + d3;
498 let d1 = r0 - d0;
499 let b3 = r3 - d3;
500 let b1 = C4 * ((d1 + d2) >> FIX);
501 let b2 = C4 * ((d1 - d2) >> FIX);
502 let q26 = C2 * (x2 + x6);
503 let p04 = C4 * (x0 + x4) + C0S;
504 let n04 = C4 * (x0 - x4) + C0S;
505 let p26 = C6MC2 * x6 + q26;
506 let n62 = C6PC2 * x2 - q26;
507 let a0 = p04 + p26;
508 let a1 = n04 + n62;
509 let a3 = p04 - p26;
510 let a2 = n04 - n62;
511 let y0 = (a0 + b0) >> (FIX + 1);
512 let y1 = (a1 + b1) >> (FIX + 1);
513 let y3 = (a3 + b3) >> (FIX + 1);
514 let y2 = (a2 + b2) >> (FIX + 1);
515 let y7 = (a0 - b0) >> (FIX + 1);
516 let y6 = (a1 - b1) >> (FIX + 1);
517 let y4 = (a3 - b3) >> (FIX + 1);
518 let y5 = (a2 - b2) >> (FIX + 1);
519
520 out[i] = y0;
521 out[i + 8] = y1;
522 out[i + 16] = y3;
523 out[i + 24] = y2;
524 out[i + 32] = y7;
525 out[i + 40] = y6;
526 out[i + 48] = y4;
527 out[i + 56] = y5;
528 }
529}
530
531
532fn unswizzle_transpose_swizzle(out: &mut [i32], inp: &[i32]) {
595 out[0] = inp[3];
596 out[1] = inp[11];
597 out[2] = inp[27];
598 out[3] = inp[19];
599 out[4] = inp[51];
600 out[5] = inp[59];
601 out[6] = inp[43];
602 out[7] = inp[35];
603 out[8] = inp[1];
604 out[9] = inp[9];
605 out[10] = inp[25];
606 out[11] = inp[17];
607 out[12] = inp[49];
608 out[13] = inp[57];
609 out[14] = inp[41];
610 out[15] = inp[33];
611
612 out[16] = inp[5];
613 out[17] = inp[13];
614 out[18] = inp[29];
615 out[19] = inp[21];
616 out[20] = inp[53];
617 out[21] = inp[61];
618 out[22] = inp[45];
619 out[23] = inp[37];
620 out[24] = inp[7];
621 out[25] = inp[15];
622 out[26] = inp[31];
623 out[27] = inp[23];
624 out[28] = inp[55];
625 out[29] = inp[63];
626 out[30] = inp[47];
627 out[31] = inp[39];
628
629 out[32] = inp[6];
630 out[33] = inp[14];
631 out[34] = inp[30];
632 out[35] = inp[22];
633 out[36] = inp[54];
634 out[37] = inp[62];
635 out[38] = inp[46];
636 out[39] = inp[38];
637 out[40] = inp[2];
638 out[41] = inp[10];
639 out[42] = inp[26];
640 out[43] = inp[18];
641 out[44] = inp[50];
642 out[45] = inp[58];
643 out[46] = inp[42];
644 out[47] = inp[34];
645
646 out[48] = inp[4];
647 out[49] = inp[12];
648 out[50] = inp[28];
649 out[51] = inp[20];
650 out[52] = inp[52];
651 out[53] = inp[60];
652 out[54] = inp[44];
653 out[55] = inp[36];
654 out[56] = inp[0];
655 out[57] = inp[8];
656 out[58] = inp[24];
657 out[59] = inp[16];
658 out[60] = inp[48];
659 out[61] = inp[56];
660 out[62] = inp[40];
661 out[63] = inp[32];
662}
663
664fn unswizzle_transpose(out: &mut [i32], inp: &[i32]) {
665 out[0] = inp[0];
666 out[1] = inp[8];
667 out[2] = inp[24];
668 out[3] = inp[16];
669 out[4] = inp[48];
670 out[5] = inp[56];
671 out[6] = inp[40];
672 out[7] = inp[32];
673 out[8] = inp[1];
674 out[9] = inp[9];
675 out[10] = inp[25];
676 out[11] = inp[17];
677 out[12] = inp[49];
678 out[13] = inp[57];
679 out[14] = inp[41];
680 out[15] = inp[33];
681
682 out[16] = inp[2];
683 out[17] = inp[10];
684 out[18] = inp[26];
685 out[19] = inp[18];
686 out[20] = inp[50];
687 out[21] = inp[58];
688 out[22] = inp[42];
689 out[23] = inp[34];
690 out[24] = inp[3];
691 out[25] = inp[11];
692 out[26] = inp[27];
693 out[27] = inp[19];
694 out[28] = inp[51];
695 out[29] = inp[59];
696 out[30] = inp[43];
697 out[31] = inp[35];
698
699 out[32] = inp[4];
700 out[33] = inp[12];
701 out[34] = inp[28];
702 out[35] = inp[20];
703 out[36] = inp[52];
704 out[37] = inp[60];
705 out[38] = inp[44];
706 out[39] = inp[36];
707 out[40] = inp[5];
708 out[41] = inp[13];
709 out[42] = inp[29];
710 out[43] = inp[21];
711 out[44] = inp[53];
712 out[45] = inp[61];
713 out[46] = inp[45];
714 out[47] = inp[37];
715
716 out[48] = inp[6];
717 out[49] = inp[14];
718 out[50] = inp[30];
719 out[51] = inp[22];
720 out[52] = inp[54];
721 out[53] = inp[62];
722 out[54] = inp[46];
723 out[55] = inp[38];
724 out[56] = inp[7];
725 out[57] = inp[15];
726 out[58] = inp[31];
727 out[59] = inp[23];
728 out[60] = inp[55];
729 out[61] = inp[63];
730 out[62] = inp[47];
731 out[63] = inp[39];
732}
733
734fn convert_block(block: &mut [i32], qtable: &[i32]) {
735 let mut temp0 = [0i32; 64];
736 for i in 0..64 {
737 temp0[i] = block[i] * qtable[i];
738 }
739 let mut temp1 = [0i32; 64];
740 partial_idct(&mut temp1, &temp0);
741 let mut temp2 = [0i32; 64];
742 unswizzle_transpose_swizzle(&mut temp2, &temp1);
743 let mut temp3 = [0i32; 64];
744 partial_idct(&mut temp3, &temp2);
745 unswizzle_transpose(block, &temp3);
746}
747
748fn convert_blocks(coeffs: &mut [i32], count: usize, pattern: u16, qtable: &[[i32; 64]], qt: &[usize; 3]) {
749 let mut curp = pattern;
750 for i in 0..count {
751 if (curp & 3) == 3 {
752 curp = pattern;
753 }
754 convert_block(&mut coeffs[i * 64..i * 64 + 64], &qtable[qt[(curp & 3) as usize]]);
755 curp >>= 2;
756 }
757}
758
759fn clamp<T: std::cmp::PartialOrd>(v: T, min: T, max: T) -> T {
760 if v < min {
761 return min;
762 }
763 else if v > max {
764 return max;
765 }
766 v
767}
768
769fn draw_rgb(image: &mut ImageBuffer, px: usize, py: usize, r: i32, g: i32, b: i32) {
770 image.data[py * image.width + px] = 0xFF000000 | ((clamp(r, 0, 255) as u32) << 16) | ((clamp(g, 0, 255) as u32) << 8) | (clamp(b, 0, 255) as u32);
771}
772
773fn draw_yuv(image: &mut ImageBuffer, px: usize, py: usize, y: i32, u: i32, v: i32) {
774 let r = ((y << 8) + 359 * v) >> 8;
775 let g = ((y << 8) - 88 * u - 183 * v) >> 8;
776 let b = ((y << 8) + 454 * u) >> 8;
777 draw_rgb(image, px, py, r, g, b);
778}
779
780fn draw_macroblock_y(image: &mut ImageBuffer, x0: usize, y0: usize, width: usize, height: usize, coeffs: &[i32]) {
781 for i in 0..height {
782 for k in 0..width {
783 draw_yuv(image, x0 + k, y0 + i, (coeffs[i * 8 + k] + 128) as i32, 0, 0);
784 }
785 }
786}
787
788fn draw_macroblock_yuv420(image: &mut ImageBuffer, x0: usize, y0: usize, width: usize, height: usize, coeffs: &[i32]) {
789 for i in 0..height {
790 for k in 0..width {
791 let by = (i >> 3) * 2 + (k >> 3);
792 let si = i & 7;
793 let sk = k & 7;
794 let y = coeffs[by * 64 + si * 8 + sk] + 128;
795 let hi = i >> 1;
796 let hk = k >> 1;
797 let u = coeffs[256 + hi * 8 + hk];
798 let v = coeffs[320 + hi * 8 + hk];
799 draw_yuv(image, x0 + k, y0 + i, y as i32, u as i32, v as i32);
800 }
801 }
802}
803
804fn draw_macroblock_yuv422_normal(image: &mut ImageBuffer, x0: usize, y0: usize, width: usize, height: usize, coeffs: &[i32]) {
805 for i in 0..height {
806 for k in 0..width {
807 let by = k >> 3;
808 let sk = k & 7;
809 let hk = k >> 1;
810 let y = coeffs[by * 64 + i * 8 + sk] + 128;
811 let u = coeffs[128 + i * 8 + hk];
812 let v = coeffs[192 + i * 8 + hk];
813 draw_yuv(image, x0 + k, y0 + i, y as i32, u as i32, v as i32);
814 }
815 }
816}
817
818#[cfg(feature="nightly")]
819fn draw_macroblock_yuv422(image: &mut ImageBuffer, x0: usize, y0: usize, width: usize, height: usize, coeffs: &[i32]) {
820 if width & 3 != 0 {
821 return draw_macroblock_yuv422_normal(image, x0, y0, width, height, coeffs);
822 }
823 return draw_macroblock_yuv422_simd(image, x0, y0, width, height, coeffs);
824}
825
826#[cfg(not(feature="nightly"))]
827fn draw_macroblock_yuv422(image: &mut ImageBuffer, x0: usize, y0: usize, width: usize, height: usize, coeffs: &[i32]) {
828 return draw_macroblock_yuv422_normal(image, x0, y0, width, height, coeffs);
829}
830
831#[cfg(feature="nightly")]
832fn draw_macroblock_yuv422_simd(image: &mut ImageBuffer, x0: usize, y0: usize, width: usize, height: usize, coeffs: &[i32]) {
833 use std::simd::*;
834
835 fn draw_rgb_simd(image: &mut ImageBuffer, px: usize, py: usize, r: i32x4, g: i32x4, b: i32x4) {
836 for i in 0..4 {
837 image.data[py * image.width + px + i] = 0xFF000000 | ((r[i] as u32) << 16) | ((g[i] as u32) << 8) | (b[i] as u32);
838 }
839 }
840
841 fn i32x4v(a: i32, b: i32, c: i32, d: i32) -> i32x4 {i32x4::from_array([a, b, c, d])}
842 fn i32x4s(a: i32) -> i32x4 {i32x4::from_array([a; 4])}
843
844 fn draw_yuv_simd(image: &mut ImageBuffer, px: usize, py: usize, y: i32x4, u: i32x4, v: i32x4) {
845 let r = ((y << i32x4s(8)) + i32x4s(359) * v) >> i32x4s(8);
847 let g = ((y << i32x4s(8)) - i32x4s(88) * u - i32x4s(183) * v) >> i32x4s(8);
848 let b = ((y << i32x4s(8)) + i32x4s(454) * u) >> i32x4s(8);
849 draw_rgb_simd(image, px, py, r.clamp(i32x4s(0), i32x4s(255)), g.clamp(i32x4s(0), i32x4s(255)), b.clamp(i32x4s(0), i32x4s(255)));
850 }
851
852 for i in 0..height {
853 for k in (0..width).step_by(4) {
854 let k0 = k;
855 let hk0 = k0 >> 1;
856 let by0 = k0 >> 3;
857 let sk0 = k0 & 7;
858 let k1 = k + 1;
859 let hk1 = k1 >> 1;
860 let by1 = k1 >> 3;
861 let sk1 = k1 & 7;
862 let k2 = k + 2;
863 let hk2 = k2 >> 1;
864 let by2 = k2 >> 3;
865 let sk2 = k2 & 7;
866 let k3 = k + 3;
867 let hk3 = k3 >> 1;
868 let by3 = k3 >> 3;
869 let sk3 = k3 & 7;
870 let y = i32x4v(coeffs[by0 * 64 + i * 8 + sk0], coeffs[by1 * 64 + i * 8 + sk1], coeffs[by2 * 64 + i * 8 + sk2], coeffs[by3 * 64 + i * 8 + sk3]) + i32x4s(128);
871 let u = i32x4v(coeffs[128 + i * 8 + hk0], coeffs[128 + i * 8 + hk1], coeffs[128 + i * 8 + hk2], coeffs[128 + i * 8 + hk3]);
872 let v = i32x4v(coeffs[192 + i * 8 + hk0], coeffs[192 + i * 8 + hk1], coeffs[192 + i * 8 + hk2], coeffs[192 + i * 8 + hk3]);
873 draw_yuv_simd(image, x0 + k, y0 + i, y, u, v);
874 }
875 }
876}
877
878fn draw_macroblock_yuv440(image: &mut ImageBuffer, x0: usize, y0: usize, width: usize, height: usize, coeffs: &[i32]) {
879 for i in 0..height {
880 for k in 0..width {
881 let by = i >> 3;
882 let si = k & 7;
883 let y = coeffs[by * 64 + si * 8 + k] + 128;
884 let hi = i >> 1;
885 let u = coeffs[128 + hi * 8 + k];
886 let v = coeffs[192 + hi * 8 + k];
887 draw_yuv(image, x0 + k, y0 + i, y as i32, u as i32, v as i32);
888 }
889 }
890}
891
892fn draw_macroblock_yuv444(image: &mut ImageBuffer, x0: usize, y0: usize, width: usize, height: usize, coeffs: &[i32]) {
893 for i in 0..height {
894 for k in 0..width {
895 let y = coeffs[i * 8 + k] + 128;
896 let u = coeffs[64 + i * 8 + k];
897 let v = coeffs[128 + i * 8 + k];
898 draw_yuv(image, x0 + k, y0 + i, y as i32, u as i32, v as i32);
899 }
900 }
901}
902
903fn draw_macroblock_rgb444(image: &mut ImageBuffer, x0: usize, y0: usize, width: usize, height: usize, coeffs: &[i32]) {
904 for i in 0..height {
905 for k in 0..width {
906 let r = coeffs[i * 8 + k] + 128;
907 let g = coeffs[64 + i * 8 + k] + 128;
908 let b = coeffs[128 + i * 8 + k] + 128;
909 draw_rgb(image, x0 + k, y0 + i, r as i32, g as i32, b as i32);
910 }
911 }
912}
913
914pub fn test(src: &[u8]) -> Option<(usize, usize)> {
915 let mut sp = 0;
916 if from_be16(&src[sp..sp + 2]) != 0xFFD8 {
917 return None;
918 }
919 sp += 2;
920 while sp < src.len() {
921 let marker = from_be16(&src[sp..sp + 2]);
922 let length = from_be16(&src[sp + 2..sp + 4]) as usize;
923 match marker {
924 0xFFC0 | 0xFFC1 | 0xFFC2 => {
925 let width = from_be16(&src[sp + 5..sp + 7]) as usize;
926 let height = from_be16(&src[sp + 7..sp + 9]) as usize;
927 let components = src[sp + 9];
928 if (components == 1) || (components == 3) { return Some((width, height));
930 }
931 return None;
932 },
933 _ => {},
934 }
935 sp += length + 2;
936 }
937 None
938}
939
940pub fn decode(src: &[u8]) -> Result<ImageBuffer, String> {
941 if from_be16(&src[0..2]) != 0xFFD8 {
942 return Err("Invalid JPEG 1".to_string());
943 }
944 let mut qtable = [[0i32; 64]; 4];
945 let mut dcht = [Table::new_empty(); 4];
946 let mut acht = [Table::new_empty(); 4];
947 let mut qt = [0usize; 3];
948 let mut dt = [0usize; 3];
949 let mut at = [0usize; 3];
950 #[allow(unused_assignments)]
951 let mut width = 1;
952 #[allow(unused_assignments)]
953 let mut height = 1;
954 #[allow(unused_assignments)]
955 let mut itype = 0; #[allow(unused_assignments)]
957 let mut mbtotal = 0; #[allow(unused_assignments)]
959 let mut mbwidth = 0;
960 #[allow(unused_assignments)]
961 let mut mbheight = 0;
962 #[allow(unused_assignments)]
963 let mut cpmb = 0;
964 let mut coeffs: Vec<i32> = Vec::new(); #[allow(unused_assignments)]
966 let mut resint = 0;
967 #[allow(unused_assignments)]
968 let mut sp = 2;
969 while sp < src.len() {
970 let marker = from_be16(&src[sp..sp + 2]);
971 let length = if marker != 0xFFD9 {from_be16(&src[sp + 2..sp + 4]) as usize} else {0};
972 match marker {
974 0xFFC0 | 0xFFC1 | 0xFFC2 => { if src[sp + 4] != 8 {
977 return Err("Invalid JPEG 2".to_string());
978 }
979 height = from_be16(&src[sp + 5..sp + 7]) as usize;
980 width = from_be16(&src[sp + 7..sp + 9]) as usize;
981 let components = src[sp + 9];
982 if (components != 1) && (components != 3) {
984 return Err("Invalid JPEG 3".to_string());
985 }
986 let mut samp = [0u8; 3];
987 let mut tsp = sp + 10;
988 for i in 0..components {
989 if src[tsp] != i + 1 {
990 return Err("Invalid JPEG 4".to_string());
991 }
992 samp[i as usize] = src[tsp + 1];
993 qt[i as usize] = src[tsp + 2] as usize;
994 tsp += 3;
995 }
997 if components == 3 {
998 if (samp[1] != 0x11) || (samp[2] != 0x11) {
999 return Err("Invalid JPEG 5".to_string());
1000 }
1001 let sw = ((samp[0] >> 4) * 8) as usize;
1002 let sh = ((samp[0] & 15) * 8) as usize;
1003 mbwidth = (width + sw - 1) / sw;
1005 mbheight = (height + sh - 1) / sh;
1006 cpmb = 128 + 64 * ((samp[0] >> 4) as usize) * ((samp[0] & 15) as usize);
1008 itype = match samp[0] {
1009 0x11 => TYPE_YUV444,
1010 0x12 => TYPE_YUV440,
1011 0x21 => TYPE_YUV422,
1012 0x22 => TYPE_YUV420,
1013 _ => {
1014 return Err("Invalid JPEG 6".to_string());
1015 },
1016 };
1017 }
1018 else {
1019 mbwidth = (width + 7) / 8;
1020 mbheight = (height + 7) / 8;
1021 cpmb = 64;
1022 itype = TYPE_Y;
1023 }
1024 mbtotal = mbwidth * mbheight;
1025 coeffs.resize(mbtotal * cpmb as usize, 0);
1026 },
1029 0xFFC4 => { let mut tsp = sp + 4;
1031 while tsp < sp + length + 2 {
1032 let d = src[tsp];
1033 tsp += 1;
1034 let tc = d >> 4;
1035 let n = d & 15;
1036 let mut bits = [0u8; 16];
1038 let mut total = 0usize;
1039 for i in 0..16 {
1040 bits[i] = src[tsp];
1041 tsp += 1;
1042 total += bits[i] as usize;
1043 }
1044 if total >= 256 {
1045 return Err("Invalid JPEG 7".to_string());
1046 }
1047 let mut huffval = [0u8; 256];
1049 for i in 0..total {
1050 huffval[i] = src[tsp];
1051 tsp += 1;
1053 }
1054 let table = Table::new(bits, huffval);
1055 if tc != 0 {
1056 acht[n as usize] = table;
1057 }
1058 else {
1059 dcht[n as usize] = table;
1060 }
1061 }
1062 },
1063 0xFFD8 => { },
1065 0xFFDA => { let mut tsp = sp + 4;
1068 let count = src[tsp];
1069 tsp += 1;
1070 let mut mask = 0;
1072 for _i in 0..count {
1073 let index = src[tsp] - 1;
1074 tsp += 1;
1075 mask |= 1 << index;
1076 let n = src[tsp];
1077 tsp += 1;
1078 dt[index as usize] = (n >> 4) as usize;
1079 at[index as usize] = (n & 15) as usize;
1080 }
1082 let start = src[tsp];
1083 tsp += 1;
1084 let end = src[tsp];
1085 tsp += 1;
1086 let d = src[tsp];
1087 tsp += 1;
1088 let refine = (d & 0xF0) != 0;
1089 let shift = d & 15;
1090 let mut reader = Reader::new(&src[tsp..]);
1092 let mut rescnt = resint;
1093 let mut eobrun = 0;
1094 let mut dc = [0i32; 3];
1095 for i in 0..mbtotal {
1096 unpack_macroblock(&mut reader, &mut coeffs[i * cpmb..(i + 1) * cpmb], &dcht, &acht, &dt, &at, &mut dc, start, end, shift, refine, &mut eobrun, itype, &mut rescnt, resint, mask);
1098 }
1099 sp = (tsp + reader.leave()) - length - 2;
1100 },
1102 0xFFDB => { let mut tsp = sp + 4;
1104 while tsp < sp + length + 2 {
1105 let d = src[tsp];
1106 tsp += 1;
1107 let n = d & 15;
1108 if (d >> 4) != 0 {
1110 for k in 0..64 {
1111 qtable[n as usize][FOLDING[k as usize] as usize] = from_be16(&src[tsp..tsp + 2]) as i32;
1112 tsp += 2;
1113 }
1114 }
1115 else {
1116 for k in 0..64 {
1117 qtable[n as usize][FOLDING[k as usize] as usize] = src[tsp] as i32;
1118 tsp += 1;
1119 }
1120 }
1121 }
1122 },
1123 0xFFDD => { resint = from_be16(&src[sp + 4..sp + 6]) as usize;
1125 },
1126 0xFFE1 => { let header = from_be32(&src[sp + 4..sp + 8]);
1128 if header == 0x45786966 { let start = sp + 10;
1130 let mut tsp = start;
1131 let le = from_be16(&src[tsp..tsp + 2]) == 0x4949; tsp += 4; tsp += (if le {from_le32(&src[tsp..tsp + 4])} else {from_be32(&src[tsp..tsp + 4])} -8) as usize; let entries = if le {from_le16(&src[tsp..tsp + 2])} else {from_be16(&src[tsp..tsp + 2])}; tsp += 2;
1136 for _i in 0..entries {
1137 let tag = if le {from_le16(&src[tsp..tsp + 2])} else {from_be16(&src[tsp..tsp + 2])};
1138 tsp += 2;
1139 let format = if le {from_le16(&src[tsp..tsp + 2])} else {from_be16(&src[tsp..tsp + 2])};
1140 tsp += 2;
1141 if format > 12 {
1142 return Err("Invalid JPEG 8".to_string());
1143 }
1144 let components = if le {from_le32(&src[tsp..tsp + 4])} else {from_be32(&src[tsp..tsp + 4])};
1145 tsp += 4;
1146 let data = if le {from_le32(&src[tsp..tsp + 4])} else {from_be32(&src[tsp..tsp + 4])};
1147 tsp += 4;
1148 let elsize = [0usize, 1, 1, 2, 4, 8, 1, 0, 2, 4, 8, 4, 8];
1149 let total = elsize[format as usize] * (components as usize);
1150 let mut dsp = start + data as usize;
1151 if total <= 4 {
1152 dsp = tsp - 4;
1153 }
1154 match tag {
1156 0x0106 => { let pe = if le {from_le16(&src[dsp..dsp + 2])} else {from_be16(&src[dsp..dsp + 2])};
1158 if (pe != 2) || (itype != TYPE_YUV444) {
1159 return Err("Invalid JPEG 9".to_string());
1160 }
1161 itype = TYPE_RGB444;
1162 },
1163 0xA001 => { },
1165 _ => {
1166 }
1167 }
1168 }
1169 }
1170 },
1171 0xFFC8 | 0xFFDC | 0xFFE0 | 0xFFE2..=0xFFEF | 0xFFF0..=0xFFFF => { },
1173 _ => { let mut image = ImageBuffer::new(width, height);
1176 match itype {
1177 TYPE_Y => {convert_blocks(&mut coeffs, mbtotal, TYPE_Y, &qtable, &qt);},
1178 TYPE_YUV420 => {convert_blocks(&mut coeffs, mbtotal * 6, TYPE_YUV420, &qtable, &qt);},
1179 TYPE_YUV422 => {convert_blocks(&mut coeffs, mbtotal * 4, TYPE_YUV422, &qtable, &qt);},
1180 TYPE_YUV440 => {convert_blocks(&mut coeffs, mbtotal * 4, TYPE_YUV440, &qtable, &qt);},
1181 TYPE_YUV444 => {convert_blocks(&mut coeffs, mbtotal * 3, TYPE_YUV444, &qtable, &qt);},
1182 TYPE_RGB444 => {convert_blocks(&mut coeffs, mbtotal * 3, TYPE_RGB444, &qtable, &qt);},
1183 _ => {},
1184 }
1185 #[allow(unused_assignments)]
1186 let mut mb = 0;
1187 for i in 0..mbheight - 1 {
1188 for k in 0..mbwidth - 1 {
1189 match itype {
1190 TYPE_Y => {draw_macroblock_y(&mut image, k * 8, i * 8, 8, 8, &coeffs[mb..mb + 64]); mb += 64;},
1191 TYPE_YUV420 => {draw_macroblock_yuv420(&mut image, k * 16, i * 16, 16, 16, &coeffs[mb..mb + 384]); mb += 384;},
1192 TYPE_YUV422 => {draw_macroblock_yuv422(&mut image, k * 16, i * 8, 16, 8, &coeffs[mb..mb + 256]); mb += 256;},
1193 TYPE_YUV440 => {draw_macroblock_yuv440(&mut image, k * 8, i * 16, 8, 16, &coeffs[mb..mb + 256]); mb += 256;},
1194 TYPE_YUV444 => {draw_macroblock_yuv444(&mut image, k * 8, i * 8, 8, 8, &coeffs[mb..mb + 192]); mb += 192;},
1195 TYPE_RGB444 => {draw_macroblock_rgb444(&mut image, k * 8, i * 8, 8, 8, &coeffs[mb..mb + 192]); mb += 192;},
1196 _ => {},
1197 }
1198 }
1199 match itype {
1200 TYPE_Y => {draw_macroblock_y(&mut image, mbwidth * 8 - 8, i * 8, width - (mbwidth - 1) * 8, 8, &coeffs[mb..mb + 64]); mb += 64;},
1201 TYPE_YUV420 => {draw_macroblock_yuv420(&mut image, mbwidth * 16 - 16, i * 16, width - (mbwidth - 1) * 16, 16, &coeffs[mb..mb + 384]); mb += 384;},
1202 TYPE_YUV422 => {draw_macroblock_yuv422(&mut image, mbwidth * 16 - 16, i * 8, width - (mbwidth - 1) * 16, 8, &coeffs[mb..mb + 256]); mb += 256;},
1203 TYPE_YUV440 => {draw_macroblock_yuv440(&mut image, mbwidth * 8 - 8, i * 16, width - (mbwidth - 1) * 8, 16, &coeffs[mb..mb + 256]); mb += 256;},
1204 TYPE_YUV444 => {draw_macroblock_yuv444(&mut image, mbwidth * 8 - 8, i * 8, width - (mbwidth - 1) * 8, 8, &coeffs[mb..mb + 192]); mb += 192;},
1205 TYPE_RGB444 => {draw_macroblock_rgb444(&mut image, mbwidth * 8 - 8, i * 8, width - (mbwidth - 1) * 8, 8, &coeffs[mb..mb + 192]); mb += 192;},
1206 _ => {},
1207 }
1208 }
1209 for k in 0..mbwidth - 1 {
1210 match itype {
1211 TYPE_Y => {draw_macroblock_y(&mut image, k * 8, mbheight * 8 - 8, 8, mbheight * 8 - height, &coeffs[mb..mb + 64]); mb += 64;},
1212 TYPE_YUV420 => {draw_macroblock_yuv420(&mut image, k * 16, mbheight * 16 - 16, 16, height - (mbheight - 1) * 16, &coeffs[mb..mb + 384]); mb += 384;},
1213 TYPE_YUV422 => {draw_macroblock_yuv422(&mut image, k * 16, mbheight * 8 - 8, 16, height - (mbheight - 1) * 8, &coeffs[mb..mb + 256]); mb += 256;},
1214 TYPE_YUV440 => {draw_macroblock_yuv440(&mut image, k * 8, mbheight * 16 - 16, 8, height - (mbheight - 1) * 16, &coeffs[mb..mb + 256]); mb += 256;},
1215 TYPE_YUV444 => {draw_macroblock_yuv444(&mut image, k * 8, mbheight * 8 - 8, 8, height - (mbheight - 1) * 8, &coeffs[mb..mb + 192]); mb += 192;},
1216 TYPE_RGB444 => {draw_macroblock_rgb444(&mut image, k * 8, mbheight * 8 - 8, 8, height - (mbheight - 1) * 8, &coeffs[mb..mb + 192]); mb += 192;},
1217 _ => {},
1218 }
1219 }
1220 match itype {
1221 TYPE_Y => {draw_macroblock_y(&mut image, mbwidth * 8 - 8, mbheight * 8 - 8, width - (mbwidth - 1) * 8, height - (mbheight - 1) * 8, &coeffs[mb..mb + 64]);},
1222 TYPE_YUV420 => {draw_macroblock_yuv420(&mut image, mbwidth * 16 - 16, mbheight * 16 - 16, width - (mbwidth - 1) * 16, height - (mbheight - 1) * 16, &coeffs[mb..mb + 384]);},
1223 TYPE_YUV422 => {draw_macroblock_yuv422(&mut image, mbwidth * 16 - 16, mbheight * 8 - 8, width - (mbwidth - 1) * 16, height - (mbheight - 1) * 8, &coeffs[mb..mb + 256]);},
1224 TYPE_YUV440 => {draw_macroblock_yuv440(&mut image, mbwidth * 8 - 8, mbheight * 16 - 16, width - (mbwidth - 1) * 8, height - (mbheight - 1) * 16, &coeffs[mb..mb + 256]);},
1225 TYPE_YUV444 => {draw_macroblock_yuv444(&mut image, mbwidth * 8 - 8, mbheight * 8 - 8, width - (mbwidth - 1) * 8, height - (mbheight - 1) * 8, &coeffs[mb..mb + 192]);},
1226 TYPE_RGB444 => {draw_macroblock_rgb444(&mut image, mbwidth * 8 - 8, mbheight * 8 - 8, width - (mbwidth - 1) * 8, height - (mbheight - 1) * 8, &coeffs[mb..mb + 192]);},
1227 _ => {},
1228 }
1229 return Ok(image);
1230 },
1231
1232 }
1236 sp += length + 2;
1237 }
1238 Err("Invalid JPEG 11".to_string())
1239}
1240
1241pub fn encode(_image: &ImageBuffer) -> Result<Vec<u8>, String> {
1242 Err("not implemented yet".to_string())
1243}