blob: 23532024e38ebbe97fd1a0956fe6e6df6cdc12e1 [file] [log] [blame]
Angel Pons118a9c72020-04-02 23:48:34 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Stefan Reinauerd650e992010-02-22 04:33:13 +00003
4/*
5 * a tiny jpeg decoder.
6 *
7 * written in August 2001 by Michael Schroeder <mls@suse.de>
8 *
9 */
10
11#define __LITTLE_ENDIAN
12#include <string.h>
13#include "jpeg.h"
14#define ISHIFT 11
15
16#define IFIX(a) ((int)((a) * (1 << ISHIFT) + .5))
17#define IMULT(a, b) (((a) * (b)) >> ISHIFT)
18#define ITOINT(a) ((a) >> ISHIFT)
19
20#ifndef __P
21# define __P(x) x
22#endif
23
24/* special markers */
25#define M_BADHUFF -1
26#define M_EOF 0x80
27
28struct in {
29 unsigned char *p;
30 unsigned int bits;
31 int left;
32 int marker;
33
34 int (*func) __P((void *));
35 void *data;
36};
37
38/*********************************/
39struct dec_hufftbl;
40struct enc_hufftbl;
41
42union hufftblp {
43 struct dec_hufftbl *dhuff;
44 struct enc_hufftbl *ehuff;
45};
46
47struct scan {
48 int dc; /* old dc value */
49
50 union hufftblp hudc;
51 union hufftblp huac;
52 int next; /* when to switch to next scan */
53
54 int cid; /* component id */
55 int hv; /* horiz/vert, copied from comp */
56 int tq; /* quant tbl, copied from comp */
57};
58
59/*********************************/
60
61#define DECBITS 10 /* seems to be the optimum */
62
63struct dec_hufftbl {
64 int maxcode[17];
65 int valptr[16];
66 unsigned char vals[256];
67 unsigned int llvals[1 << DECBITS];
68};
69
70static void decode_mcus __P((struct in *, int *, int, struct scan *, int *));
71static int dec_readmarker __P((struct in *));
72static void dec_makehuff __P((struct dec_hufftbl *, int *, unsigned char *));
73
74static void setinput __P((struct in *, unsigned char *));
75/*********************************/
76
77#undef PREC
78#define PREC int
79
80static void idctqtab __P((unsigned char *, PREC *));
81static void idct __P((int *, int *, PREC *, PREC, int));
82static void scaleidctqtab __P((PREC *, PREC));
83
84/*********************************/
85
86static void initcol __P((PREC[][64]));
87
88static void col221111 __P((int *, unsigned char *, int));
89static void col221111_16 __P((int *, unsigned char *, int));
90static void col221111_32 __P((int *, unsigned char *, int));
91
92/*********************************/
93
94#define M_SOI 0xd8
95#define M_APP0 0xe0
96#define M_DQT 0xdb
97#define M_SOF0 0xc0
98#define M_DHT 0xc4
99#define M_DRI 0xdd
100#define M_SOS 0xda
101#define M_RST0 0xd0
102#define M_EOI 0xd9
103#define M_COM 0xfe
104
105static unsigned char *datap;
106
107static int getbyte(void)
108{
109 return *datap++;
110}
111
112static int getword(void)
113{
114 int c1, c2;
115 c1 = *datap++;
116 c2 = *datap++;
117 return c1 << 8 | c2;
118}
119
120struct comp {
121 int cid;
122 int hv;
123 int tq;
124};
125
126#define MAXCOMP 4
127struct jpginfo {
128 int nc; /* number of components */
129 int ns; /* number of scans */
130 int dri; /* restart interval */
131 int nm; /* mcus til next marker */
132 int rm; /* next restart marker */
133};
134
135static struct jpginfo info;
136static struct comp comps[MAXCOMP];
137
138static struct scan dscans[MAXCOMP];
139
140static unsigned char quant[4][64];
141
142static struct dec_hufftbl dhuff[4];
143
144#define dec_huffdc (dhuff + 0)
145#define dec_huffac (dhuff + 2)
146
Stefan Reinauer87489e12010-03-17 04:03:22 +0000147static struct in glob_in;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000148
149static int readtables(int till)
150{
151 int m, l, i, j, lq, pq, tq;
152 int tc, th, tt;
153
154 for (;;) {
155 if (getbyte() != 0xff)
156 return -1;
Lee Leahy491c5b62017-03-10 15:51:04 -0800157 m = getbyte();
158 if (m == till)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000159 break;
160
161 switch (m) {
162 case 0xc2:
163 return 0;
164
165 case M_DQT:
166 lq = getword();
167 while (lq > 2) {
168 pq = getbyte();
169 tq = pq & 15;
170 if (tq > 3)
171 return -1;
172 pq >>= 4;
173 if (pq != 0)
174 return -1;
175 for (i = 0; i < 64; i++)
176 quant[tq][i] = getbyte();
177 lq -= 64 + 1;
178 }
179 break;
180
181 case M_DHT:
182 l = getword();
183 while (l > 2) {
184 int hufflen[16], k;
185 unsigned char huffvals[256];
186
187 tc = getbyte();
188 th = tc & 15;
189 tc >>= 4;
190 tt = tc * 2 + th;
191 if (tc > 1 || th > 1)
192 return -1;
193 for (i = 0; i < 16; i++)
194 hufflen[i] = getbyte();
195 l -= 1 + 16;
196 k = 0;
197 for (i = 0; i < 16; i++) {
198 for (j = 0; j < hufflen[i]; j++)
199 huffvals[k++] = getbyte();
200 l -= hufflen[i];
201 }
202 dec_makehuff(dhuff + tt, hufflen,
203 huffvals);
204 }
205 break;
206
207 case M_DRI:
208 l = getword();
209 info.dri = getword();
210 break;
211
212 default:
213 l = getword();
214 while (l-- > 2)
215 getbyte();
216 break;
217 }
218 }
219 return 0;
220}
221
222static void dec_initscans(void)
223{
224 int i;
225
226 info.nm = info.dri + 1;
227 info.rm = M_RST0;
228 for (i = 0; i < info.ns; i++)
229 dscans[i].dc = 0;
230}
231
232static int dec_checkmarker(void)
233{
234 int i;
235
Stefan Reinauer87489e12010-03-17 04:03:22 +0000236 if (dec_readmarker(&glob_in) != info.rm)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000237 return -1;
238 info.nm = info.dri;
239 info.rm = (info.rm + 1) & ~0x08;
240 for (i = 0; i < info.ns; i++)
241 dscans[i].dc = 0;
242 return 0;
243}
244
Patrick Georgi246179a2015-08-09 18:23:10 +0200245void jpeg_fetch_size(unsigned char *buf, int *width, int *height)
246{
247 datap = buf;
248 getbyte();
249 getbyte();
250 readtables(M_SOF0);
251 getword();
252 getbyte();
253 *height = getword();
254 *width = getword();
255}
256
Stefan Reinauerd650e992010-02-22 04:33:13 +0000257int jpeg_check_size(unsigned char *buf, int width, int height)
258{
Lee Leahye20a3192017-03-09 16:21:34 -0800259 datap = buf;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000260 getbyte();
261 getbyte();
262 readtables(M_SOF0);
263 getword();
264 getbyte();
Lee Leahye20a3192017-03-09 16:21:34 -0800265 if (height != getword() || width != getword())
Stefan Reinauerd650e992010-02-22 04:33:13 +0000266 return 0;
Lee Leahye20a3192017-03-09 16:21:34 -0800267 return 1;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000268}
269
Stefan Reinauer14e22772010-04-27 06:56:47 +0000270int jpeg_decode(unsigned char *buf, unsigned char *pic,
Stefan Reinauerd650e992010-02-22 04:33:13 +0000271 int width, int height, int depth, struct jpeg_decdata *decdata)
272{
273 int i, j, m, tac, tdc;
274 int mcusx, mcusy, mx, my;
275 int max[6];
276
277 if (!decdata || !buf || !pic)
278 return -1;
279 datap = buf;
280 if (getbyte() != 0xff)
281 return ERR_NO_SOI;
282 if (getbyte() != M_SOI)
283 return ERR_NO_SOI;
284 if (readtables(M_SOF0))
285 return ERR_BAD_TABLES;
286 getword();
287 i = getbyte();
288 if (i != 8)
289 return ERR_NOT_8BIT;
290 if (((getword() + 15) & ~15) != height)
291 return ERR_HEIGHT_MISMATCH;
292 if (((getword() + 15) & ~15) != width)
293 return ERR_WIDTH_MISMATCH;
294 if ((height & 15) || (width & 15))
295 return ERR_BAD_WIDTH_OR_HEIGHT;
296 info.nc = getbyte();
297 if (info.nc > MAXCOMP)
298 return ERR_TOO_MANY_COMPPS;
299 for (i = 0; i < info.nc; i++) {
300 int h, v;
301 comps[i].cid = getbyte();
302 comps[i].hv = getbyte();
303 v = comps[i].hv & 15;
304 h = comps[i].hv >> 4;
305 comps[i].tq = getbyte();
306 if (h > 3 || v > 3)
307 return ERR_ILLEGAL_HV;
308 if (comps[i].tq > 3)
309 return ERR_QUANT_TABLE_SELECTOR;
310 }
311 if (readtables(M_SOS))
312 return ERR_BAD_TABLES;
313 getword();
314 info.ns = getbyte();
315 if (info.ns != 3)
316 return ERR_NOT_YCBCR_221111;
317 for (i = 0; i < 3; i++) {
318 dscans[i].cid = getbyte();
319 tdc = getbyte();
320 tac = tdc & 15;
321 tdc >>= 4;
322 if (tdc > 1 || tac > 1)
323 return ERR_QUANT_TABLE_SELECTOR;
324 for (j = 0; j < info.nc; j++)
325 if (comps[j].cid == dscans[i].cid)
326 break;
327 if (j == info.nc)
328 return ERR_UNKNOWN_CID_IN_SCAN;
329 dscans[i].hv = comps[j].hv;
330 dscans[i].tq = comps[j].tq;
331 dscans[i].hudc.dhuff = dec_huffdc + tdc;
332 dscans[i].huac.dhuff = dec_huffac + tac;
333 }
334
335 i = getbyte();
336 j = getbyte();
337 m = getbyte();
338
339 if (i != 0 || j != 63 || m != 0)
340 return ERR_NOT_SEQUENTIAL_DCT;
341
342 if (dscans[0].cid != 1 || dscans[1].cid != 2 || dscans[2].cid != 3)
343 return ERR_NOT_YCBCR_221111;
344
Lee Leahy73402172017-03-10 15:23:24 -0800345 if (dscans[0].hv != 0x22 || dscans[1].hv != 0x11
346 || dscans[2].hv != 0x11)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000347 return ERR_NOT_YCBCR_221111;
348
349 mcusx = width >> 4;
350 mcusy = height >> 4;
351
352
353 idctqtab(quant[dscans[0].tq], decdata->dquant[0]);
354 idctqtab(quant[dscans[1].tq], decdata->dquant[1]);
355 idctqtab(quant[dscans[2].tq], decdata->dquant[2]);
356 initcol(decdata->dquant);
Stefan Reinauer87489e12010-03-17 04:03:22 +0000357 setinput(&glob_in, datap);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000358
359#if 0
360 /* landing zone */
361 img[len] = 0;
362 img[len + 1] = 0xff;
363 img[len + 2] = M_EOF;
364#endif
365
366 dec_initscans();
367
368 dscans[0].next = 6 - 4;
369 dscans[1].next = 6 - 4 - 1;
370 dscans[2].next = 6 - 4 - 1 - 1; /* 411 encoding */
371 for (my = 0; my < mcusy; my++) {
372 for (mx = 0; mx < mcusx; mx++) {
373 if (info.dri && !--info.nm)
374 if (dec_checkmarker())
375 return ERR_WRONG_MARKER;
376
Stefan Reinauer87489e12010-03-17 04:03:22 +0000377 decode_mcus(&glob_in, decdata->dcts, 6, dscans, max);
Lee Leahy73402172017-03-10 15:23:24 -0800378 idct(decdata->dcts, decdata->out, decdata->dquant[0],
379 IFIX(128.5), max[0]);
380 idct(decdata->dcts + 64, decdata->out + 64,
381 decdata->dquant[0], IFIX(128.5), max[1]);
382 idct(decdata->dcts + 128, decdata->out + 128,
383 decdata->dquant[0], IFIX(128.5), max[2]);
384 idct(decdata->dcts + 192, decdata->out + 192,
385 decdata->dquant[0], IFIX(128.5), max[3]);
386 idct(decdata->dcts + 256, decdata->out + 256,
387 decdata->dquant[1], IFIX(0.5), max[4]);
388 idct(decdata->dcts + 320, decdata->out + 320,
389 decdata->dquant[2], IFIX(0.5), max[5]);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000390
391 switch (depth) {
392 case 32:
Lee Leahy73402172017-03-10 15:23:24 -0800393 col221111_32(decdata->out, pic
394 + (my * 16 * mcusx + mx) * 16 * 4,
395 mcusx * 16 * 4);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000396 break;
397 case 24:
Lee Leahy73402172017-03-10 15:23:24 -0800398 col221111(decdata->out, pic
399 + (my * 16 * mcusx + mx) * 16 * 3,
400 mcusx * 16 * 3);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000401 break;
402 case 16:
Lee Leahy73402172017-03-10 15:23:24 -0800403 col221111_16(decdata->out, pic
404 + (my * 16 * mcusx + mx) * (16 * 2),
405 mcusx * (16 * 2));
Stefan Reinauerd650e992010-02-22 04:33:13 +0000406 break;
407 default:
408 return ERR_DEPTH_MISMATCH;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000409 }
410 }
411 }
412
Stefan Reinauer87489e12010-03-17 04:03:22 +0000413 m = dec_readmarker(&glob_in);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000414 if (m != M_EOI)
415 return ERR_NO_EOI;
416
417 return 0;
418}
419
420/****************************************************************/
421/************** huffman decoder ***************/
422/****************************************************************/
423
424static int fillbits __P((struct in *, int, unsigned int));
425static int dec_rec2
426__P((struct in *, struct dec_hufftbl *, int *, int, int));
427
428static void setinput(struct in *in, unsigned char *p)
429{
430 in->p = p;
431 in->left = 0;
432 in->bits = 0;
433 in->marker = 0;
434}
435
436static int fillbits(struct in *in, int le, unsigned int bi)
437{
438 int b, m;
439
440 if (in->marker) {
441 if (le <= 16)
442 in->bits = bi << 16, le += 16;
443 return le;
444 }
445 while (le <= 24) {
446 b = *in->p++;
Lee Leahy491c5b62017-03-10 15:51:04 -0800447 if (b == 0xff) {
448 m = *in->p++;
449 if (m != 0) {
450 if (m == M_EOF) {
451 if (in->func) {
452 m = in->func(in->data);
453 if (m == 0)
454 continue;
Martin Roth1d5e2402017-07-23 20:04:41 -0600455 }
Lee Leahy491c5b62017-03-10 15:51:04 -0800456 }
457 in->marker = m;
458 if (le <= 16)
459 bi = bi << 16, le += 16;
460 break;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000461 }
Stefan Reinauerd650e992010-02-22 04:33:13 +0000462 }
463 bi = bi << 8 | b;
464 le += 8;
465 }
466 in->bits = bi; /* tmp... 2 return values needed */
467 return le;
468}
469
470static int dec_readmarker(struct in *in)
471{
472 int m;
473
474 in->left = fillbits(in, in->left, in->bits);
Lee Leahy491c5b62017-03-10 15:51:04 -0800475 m = in->marker;
476 if (m == 0)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000477 return 0;
478 in->left = 0;
479 in->marker = 0;
480 return m;
481}
482
483#define LEBI_DCL int le, bi
484#define LEBI_GET(in) (le = in->left, bi = in->bits)
485#define LEBI_PUT(in) (in->left = le, in->bits = bi)
486
Lee Leahye20a3192017-03-09 16:21:34 -0800487#define GETBITS(in, n) ( \
488 (le < (n) ? le = fillbits(in, le, bi), bi = in->bits : 0), \
489 (le -= (n)), \
490 bi >> le & ((1 << (n)) - 1) \
491 )
Stefan Reinauerd650e992010-02-22 04:33:13 +0000492
493#define UNGETBITS(in, n) ( \
Lee Leahye20a3192017-03-09 16:21:34 -0800494 le += (n) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000495)
496
497
498static int dec_rec2(struct in *in, struct dec_hufftbl *hu, int *runp, int c,
499 int i)
500{
501 LEBI_DCL;
502
503 LEBI_GET(in);
504 if (i) {
505 UNGETBITS(in, i & 127);
506 *runp = i >> 8 & 15;
507 i >>= 16;
508 } else {
Lee Leahy73402172017-03-10 15:23:24 -0800509 for (i = DECBITS; (c = ((c << 1) | GETBITS(in, 1)))
510 >= (hu->maxcode[i]); i++)
Lee Leahyb6ee0f92017-03-09 13:35:26 -0800511 ;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000512 if (i >= 16) {
513 in->marker = M_BADHUFF;
514 return 0;
515 }
516 i = hu->vals[hu->valptr[i] + c - hu->maxcode[i - 1] * 2];
517 *runp = i >> 4;
518 i &= 15;
519 }
520 if (i == 0) { /* sigh, 0xf0 is 11 bit */
521 LEBI_PUT(in);
522 return 0;
523 }
524 /* receive part */
525 c = GETBITS(in, i);
526 if (c < (1 << (i - 1)))
527 c += (-1 << i) + 1;
528 LEBI_PUT(in);
529 return c;
530}
531
Lee Leahye20a3192017-03-09 16:21:34 -0800532#define DEC_REC(in, hu, r, i) ( \
533 r = GETBITS(in, DECBITS), \
534 i = hu->llvals[r], \
535 i & 128 ? \
536 ( \
537 UNGETBITS(in, i & 127), \
538 r = i >> 8 & 15, \
539 i >> 16 \
540 ) \
541 : \
542 ( \
543 LEBI_PUT(in), \
544 i = dec_rec2(in, hu, &r, r, i), \
545 LEBI_GET(in), \
546 i \
547 ) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000548)
549
Lee Leahy73402172017-03-10 15:23:24 -0800550static void decode_mcus(struct in *in, int *dct, int n, struct scan *sc,
551 int *maxp)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000552{
553 struct dec_hufftbl *hu;
554 int i, r, t;
555 LEBI_DCL;
556
557 memset(dct, 0, n * 64 * sizeof(*dct));
558 LEBI_GET(in);
559 while (n-- > 0) {
560 hu = sc->hudc.dhuff;
561 *dct++ = (sc->dc += DEC_REC(in, hu, r, t));
562
563 hu = sc->huac.dhuff;
564 i = 63;
565 while (i > 0) {
566 t = DEC_REC(in, hu, r, t);
567 if (t == 0 && r == 0) {
568 dct += i;
569 break;
570 }
571 dct += r;
572 *dct++ = t;
573 i -= r + 1;
574 }
575 *maxp++ = 64 - i;
576 if (n == sc->next)
577 sc++;
578 }
579 LEBI_PUT(in);
580}
581
Lee Leahy73402172017-03-10 15:23:24 -0800582static void dec_makehuff(struct dec_hufftbl *hu, int *hufflen,
583 unsigned char *huffvals)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000584{
585 int code, k, i, j, d, x, c, v;
586 for (i = 0; i < (1 << DECBITS); i++)
587 hu->llvals[i] = 0;
588
589/*
590 * llvals layout:
591 *
592 * value v already known, run r, backup u bits:
593 * vvvvvvvvvvvvvvvv 0000 rrrr 1 uuuuuuu
594 * value unknown, size b bits, run r, backup u bits:
595 * 000000000000bbbb 0000 rrrr 0 uuuuuuu
596 * value and size unknown:
597 * 0000000000000000 0000 0000 0 0000000
598 */
599 code = 0;
600 k = 0;
601 for (i = 0; i < 16; i++, code <<= 1) { /* sizes */
602 hu->valptr[i] = k;
603 for (j = 0; j < hufflen[i]; j++) {
604 hu->vals[k] = *huffvals++;
605 if (i < DECBITS) {
606 c = code << (DECBITS - 1 - i);
607 v = hu->vals[k] & 0x0f; /* size */
608 for (d = 1 << (DECBITS - 1 - i); --d >= 0;) {
Lee Leahy73402172017-03-10 15:23:24 -0800609 /* both fit in table */
610 if (v + i < DECBITS) {
Stefan Reinauerd650e992010-02-22 04:33:13 +0000611 x = d >> (DECBITS - 1 - v -
612 i);
613 if (v && x < (1 << (v - 1)))
614 x += (-1 << v) + 1;
Lee Leahy73402172017-03-10 15:23:24 -0800615 x = x << 16 | (hu->vals[k]
616 & 0xf0) << 4 |
617 (DECBITS - (i + 1 + v))
618 | 128;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000619 } else
Lee Leahy73402172017-03-10 15:23:24 -0800620 x = v << 16 | (hu->vals[k]
621 & 0xf0) << 4 |
Lee Leahye20a3192017-03-09 16:21:34 -0800622 (DECBITS - (i + 1));
Stefan Reinauerd650e992010-02-22 04:33:13 +0000623 hu->llvals[c | d] = x;
624 }
625 }
626 code++;
627 k++;
628 }
629 hu->maxcode[i] = code;
630 }
631 hu->maxcode[16] = 0x20000; /* always terminate decode */
632}
633
634/****************************************************************/
635/************** idct ***************/
636/****************************************************************/
637
638#define ONE ((PREC)IFIX(1.))
639#define S2 ((PREC)IFIX(0.382683432))
640#define C2 ((PREC)IFIX(0.923879532))
641#define C4 ((PREC)IFIX(0.707106781))
642
643#define S22 ((PREC)IFIX(2 * 0.382683432))
644#define C22 ((PREC)IFIX(2 * 0.923879532))
645#define IC4 ((PREC)IFIX(1 / 0.707106781))
646
647#define C3IC1 ((PREC)IFIX(0.847759065)) /* c3/c1 */
648#define C5IC1 ((PREC)IFIX(0.566454497)) /* c5/c1 */
649#define C7IC1 ((PREC)IFIX(0.198912367)) /* c7/c1 */
650
Lee Leahy35af5c42017-03-09 17:35:28 -0800651#define XPP(a, b) (t = a + b, b = a - b, a = t)
652#define XMP(a, b) (t = a - b, b = a + b, a = t)
653#define XPM(a, b) (t = a + b, b = b - a, a = t)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000654
Lee Leahy35af5c42017-03-09 17:35:28 -0800655#define ROT(a, b, s, c) (t = IMULT(a + b, s), \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000656 a = IMULT(a, c - s) + t, \
657 b = IMULT(b, c + s) - t)
658
Lee Leahye20a3192017-03-09 16:21:34 -0800659#define IDCT \
660( \
661 XPP(t0, t1), \
662 XMP(t2, t3), \
663 t2 = IMULT(t2, IC4) - t3, \
664 XPP(t0, t3), \
665 XPP(t1, t2), \
666 XMP(t4, t7), \
667 XPP(t5, t6), \
668 XMP(t5, t7), \
669 t5 = IMULT(t5, IC4), \
670 ROT(t4, t6, S22, C22), \
671 t6 -= t7, \
672 t5 -= t6, \
673 t4 -= t5, \
674 XPP(t0, t7), \
675 XPP(t1, t6), \
676 XPP(t2, t5), \
677 XPP(t3, t4) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000678)
679
680static unsigned char zig2[64] = {
681 0, 2, 3, 9, 10, 20, 21, 35,
682 14, 16, 25, 31, 39, 46, 50, 57,
683 5, 7, 12, 18, 23, 33, 37, 48,
684 27, 29, 41, 44, 52, 55, 59, 62,
685 15, 26, 30, 40, 45, 51, 56, 58,
686 1, 4, 8, 11, 19, 22, 34, 36,
687 28, 42, 43, 53, 54, 60, 61, 63,
688 6, 13, 17, 24, 32, 38, 47, 49
689};
690
Stefan Reinauer87489e12010-03-17 04:03:22 +0000691void idct(int *in, int *out, PREC *lquant, PREC off, int max)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000692{
693 PREC t0, t1, t2, t3, t4, t5, t6, t7, t;
694 PREC tmp[64], *tmpp;
695 int i, j;
696 unsigned char *zig2p;
697
698 t0 = off;
699 if (max == 1) {
Stefan Reinauer87489e12010-03-17 04:03:22 +0000700 t0 += in[0] * lquant[0];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000701 for (i = 0; i < 64; i++)
702 out[i] = ITOINT(t0);
703 return;
704 }
705 zig2p = zig2;
706 tmpp = tmp;
707 for (i = 0; i < 8; i++) {
708 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000709 t0 += in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000710 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000711 t5 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000712 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000713 t2 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000714 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000715 t7 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000716 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000717 t1 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000718 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000719 t4 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000720 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000721 t3 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000722 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000723 t6 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000724 IDCT;
725 tmpp[0 * 8] = t0;
726 tmpp[1 * 8] = t1;
727 tmpp[2 * 8] = t2;
728 tmpp[3 * 8] = t3;
729 tmpp[4 * 8] = t4;
730 tmpp[5 * 8] = t5;
731 tmpp[6 * 8] = t6;
732 tmpp[7 * 8] = t7;
733 tmpp++;
734 t0 = 0;
735 }
736 for (i = 0; i < 8; i++) {
737 t0 = tmp[8 * i + 0];
738 t1 = tmp[8 * i + 1];
739 t2 = tmp[8 * i + 2];
740 t3 = tmp[8 * i + 3];
741 t4 = tmp[8 * i + 4];
742 t5 = tmp[8 * i + 5];
743 t6 = tmp[8 * i + 6];
744 t7 = tmp[8 * i + 7];
745 IDCT;
746 out[8 * i + 0] = ITOINT(t0);
747 out[8 * i + 1] = ITOINT(t1);
748 out[8 * i + 2] = ITOINT(t2);
749 out[8 * i + 3] = ITOINT(t3);
750 out[8 * i + 4] = ITOINT(t4);
751 out[8 * i + 5] = ITOINT(t5);
752 out[8 * i + 6] = ITOINT(t6);
753 out[8 * i + 7] = ITOINT(t7);
754 }
755}
756
757static unsigned char zig[64] = {
758 0, 1, 5, 6, 14, 15, 27, 28,
759 2, 4, 7, 13, 16, 26, 29, 42,
760 3, 8, 12, 17, 25, 30, 41, 43,
761 9, 11, 18, 24, 31, 40, 44, 53,
762 10, 19, 23, 32, 39, 45, 52, 54,
763 20, 22, 33, 38, 46, 51, 55, 60,
764 21, 34, 37, 47, 50, 56, 59, 61,
765 35, 36, 48, 49, 57, 58, 62, 63
766};
767
768static PREC aaidct[8] = {
769 IFIX(0.3535533906), IFIX(0.4903926402),
770 IFIX(0.4619397663), IFIX(0.4157348062),
771 IFIX(0.3535533906), IFIX(0.2777851165),
772 IFIX(0.1913417162), IFIX(0.0975451610)
773};
774
775
776static void idctqtab(unsigned char *qin, PREC *qout)
777{
778 int i, j;
779
780 for (i = 0; i < 8; i++)
781 for (j = 0; j < 8; j++)
782 qout[zig[i * 8 + j]] = qin[zig[i * 8 + j]] *
Lee Leahye20a3192017-03-09 16:21:34 -0800783 IMULT(aaidct[i], aaidct[j]);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000784}
785
786static void scaleidctqtab(PREC *q, PREC sc)
787{
788 int i;
789
790 for (i = 0; i < 64; i++)
791 q[i] = IMULT(q[i], sc);
792}
793
794/****************************************************************/
795/************** color decoder ***************/
796/****************************************************************/
797
798#define ROUND
799
800/*
801 * YCbCr Color transformation:
802 *
803 * y:0..255 Cb:-128..127 Cr:-128..127
804 *
805 * R = Y + 1.40200 * Cr
806 * G = Y - 0.34414 * Cb - 0.71414 * Cr
807 * B = Y + 1.77200 * Cb
808 *
809 * =>
810 * Cr *= 1.40200;
811 * Cb *= 1.77200;
812 * Cg = 0.19421 * Cb + .50937 * Cr;
813 * R = Y + Cr;
814 * G = Y - Cg;
815 * B = Y + Cb;
816 *
817 * =>
818 * Cg = (50 * Cb + 130 * Cr + 128) >> 8;
819 */
820
821static void initcol(PREC q[][64])
822{
823 scaleidctqtab(q[1], IFIX(1.77200));
824 scaleidctqtab(q[2], IFIX(1.40200));
825}
826
827/* This is optimized for the stupid sun SUNWspro compiler. */
Lee Leahy35af5c42017-03-09 17:35:28 -0800828#define STORECLAMP(a, x) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000829( \
Lee Leahye20a3192017-03-09 16:21:34 -0800830 (a) = (x), \
831 (unsigned int)(x) >= 256 ? \
832 ((a) = (x) < 0 ? 0 : 255) \
833 : \
834 0 \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000835)
836
837#define CLAMP(x) ((unsigned int)(x) >= 256 ? ((x) < 0 ? 0 : 255) : (x))
838
839#ifdef ROUND
840
841#define CBCRCG(yin, xin) \
842( \
Lee Leahy35af5c42017-03-09 17:35:28 -0800843 cb = outc[0 + yin * 8 + xin], \
844 cr = outc[64 + yin * 8 + xin], \
Lee Leahye20a3192017-03-09 16:21:34 -0800845 cg = (50 * cb + 130 * cr + 128) >> 8 \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000846)
847
848#else
849
850#define CBCRCG(yin, xin) \
851( \
Lee Leahy35af5c42017-03-09 17:35:28 -0800852 cb = outc[0 + yin*8 + xin], \
853 cr = outc[64 + yin*8 + xin], \
Lee Leahye20a3192017-03-09 16:21:34 -0800854 cg = (3 * cb + 8 * cr) >> 4 \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000855)
856
857#endif
858
859#define PIC(yin, xin, p, xout) \
860( \
Lee Leahye20a3192017-03-09 16:21:34 -0800861 y = outy[(yin) * 8 + xin], \
862 STORECLAMP(p[(xout) * 3 + 0], y + cr), \
863 STORECLAMP(p[(xout) * 3 + 1], y - cg), \
864 STORECLAMP(p[(xout) * 3 + 2], y + cb) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000865)
866
867#ifdef __LITTLE_ENDIAN
Lee Leahye20a3192017-03-09 16:21:34 -0800868#define PIC_16(yin, xin, p, xout, add) \
869( \
870 y = outy[(yin) * 8 + xin], \
871 y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 8) | \
872 ((CLAMP(y - cg + add) & 0xfc) << 3) | \
873 ((CLAMP(y + cb + add*2+1)) >> 3), \
874 p[(xout) * 2 + 0] = y & 0xff, \
875 p[(xout) * 2 + 1] = y >> 8 \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000876)
877#else
878#ifdef CONFIG_PPC
Lee Leahye20a3192017-03-09 16:21:34 -0800879#define PIC_16(yin, xin, p, xout, add) \
880( \
881 y = outy[(yin) * 8 + xin], \
882 y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 7) | \
883 ((CLAMP(y - cg + add*2+1) & 0xf8) << 2) | \
884 ((CLAMP(y + cb + add*2+1)) >> 3), \
885 p[(xout) * 2 + 0] = y >> 8, \
886 p[(xout) * 2 + 1] = y & 0xff \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000887)
888#else
Lee Leahye20a3192017-03-09 16:21:34 -0800889#define PIC_16(yin, xin, p, xout, add) \
890( \
891 y = outy[(yin) * 8 + xin], \
892 y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 8) | \
893 ((CLAMP(y - cg + add) & 0xfc) << 3) | \
894 ((CLAMP(y + cb + add*2+1)) >> 3), \
895 p[(xout) * 2 + 0] = y >> 8, \
896 p[(xout) * 2 + 1] = y & 0xff \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000897)
898#endif
899#endif
900
901#define PIC_32(yin, xin, p, xout) \
902( \
Lee Leahye20a3192017-03-09 16:21:34 -0800903 y = outy[(yin) * 8 + xin], \
904 STORECLAMP(p[(xout) * 4 + 0], y + cr), \
905 STORECLAMP(p[(xout) * 4 + 1], y - cg), \
906 STORECLAMP(p[(xout) * 4 + 2], y + cb), \
907 p[(xout) * 4 + 3] = 0 \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000908)
909
Lee Leahye20a3192017-03-09 16:21:34 -0800910#define PIC221111(xin) \
911( \
912 CBCRCG(0, xin), \
913 PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0), \
914 PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1), \
915 PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0), \
916 PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000917)
918
Lee Leahye20a3192017-03-09 16:21:34 -0800919#define PIC221111_16(xin) \
920( \
921 CBCRCG(0, xin), \
922 PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0, 3), \
923 PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1, 0), \
924 PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0, 1), \
925 PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1, 2) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000926)
927
Lee Leahye20a3192017-03-09 16:21:34 -0800928#define PIC221111_32(xin) \
929( \
930 CBCRCG(0, xin), \
931 PIC_32(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0), \
932 PIC_32(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1), \
933 PIC_32(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0), \
934 PIC_32(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000935)
936
937static void col221111(int *out, unsigned char *pic, int width)
938{
939 int i, j, k;
940 unsigned char *pic0, *pic1;
941 int *outy, *outc;
942 int cr, cg, cb, y;
943
944 pic0 = pic;
945 pic1 = pic + width;
946 outy = out;
947 outc = out + 64 * 4;
948 for (i = 2; i > 0; i--) {
949 for (j = 4; j > 0; j--) {
Lee Leahy2f919ec2017-03-08 17:37:06 -0800950 for (k = 0; k < 8; k++)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000951 PIC221111(k);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000952 outc += 8;
953 outy += 16;
954 pic0 += 2 * width;
955 pic1 += 2 * width;
956 }
957 outy += 64 * 2 - 16 * 4;
958 }
959}
960
961static void col221111_16(int *out, unsigned char *pic, int width)
962{
963 int i, j, k;
964 unsigned char *pic0, *pic1;
965 int *outy, *outc;
966 int cr, cg, cb, y;
967
968 pic0 = pic;
969 pic1 = pic + width;
970 outy = out;
971 outc = out + 64 * 4;
972 for (i = 2; i > 0; i--) {
973 for (j = 4; j > 0; j--) {
Lee Leahy2f919ec2017-03-08 17:37:06 -0800974 for (k = 0; k < 8; k++)
Lee Leahye20a3192017-03-09 16:21:34 -0800975 PIC221111_16(k);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000976 outc += 8;
977 outy += 16;
978 pic0 += 2 * width;
979 pic1 += 2 * width;
980 }
981 outy += 64 * 2 - 16 * 4;
982 }
983}
984
985static void col221111_32(int *out, unsigned char *pic, int width)
986{
987 int i, j, k;
988 unsigned char *pic0, *pic1;
989 int *outy, *outc;
990 int cr, cg, cb, y;
991
992 pic0 = pic;
993 pic1 = pic + width;
994 outy = out;
995 outc = out + 64 * 4;
996 for (i = 2; i > 0; i--) {
997 for (j = 4; j > 0; j--) {
Lee Leahy2f919ec2017-03-08 17:37:06 -0800998 for (k = 0; k < 8; k++)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000999 PIC221111_32(k);
Stefan Reinauerd650e992010-02-22 04:33:13 +00001000 outc += 8;
1001 outy += 16;
1002 pic0 += 2 * width;
1003 pic1 += 2 * width;
1004 }
1005 outy += 64 * 2 - 16 * 4;
1006 }
1007}