blob: ed4377f41ae0a962920c0c0d6ed7bdd1cc816c51 [file] [log] [blame]
Angel Pons118a9c72020-04-02 23:48:34 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauerd650e992010-02-22 04:33:13 +00002
3/*
4 * a tiny jpeg decoder.
5 *
6 * written in August 2001 by Michael Schroeder <mls@suse.de>
7 *
8 */
9
10#define __LITTLE_ENDIAN
11#include <string.h>
12#include "jpeg.h"
13#define ISHIFT 11
14
15#define IFIX(a) ((int)((a) * (1 << ISHIFT) + .5))
16#define IMULT(a, b) (((a) * (b)) >> ISHIFT)
17#define ITOINT(a) ((a) >> ISHIFT)
18
19#ifndef __P
20# define __P(x) x
21#endif
22
23/* special markers */
24#define M_BADHUFF -1
25#define M_EOF 0x80
26
27struct in {
28 unsigned char *p;
29 unsigned int bits;
30 int left;
31 int marker;
32
33 int (*func) __P((void *));
34 void *data;
35};
36
37/*********************************/
38struct dec_hufftbl;
39struct enc_hufftbl;
40
41union hufftblp {
42 struct dec_hufftbl *dhuff;
43 struct enc_hufftbl *ehuff;
44};
45
46struct scan {
47 int dc; /* old dc value */
48
49 union hufftblp hudc;
50 union hufftblp huac;
51 int next; /* when to switch to next scan */
52
53 int cid; /* component id */
54 int hv; /* horiz/vert, copied from comp */
55 int tq; /* quant tbl, copied from comp */
56};
57
58/*********************************/
59
60#define DECBITS 10 /* seems to be the optimum */
61
62struct dec_hufftbl {
63 int maxcode[17];
64 int valptr[16];
65 unsigned char vals[256];
66 unsigned int llvals[1 << DECBITS];
67};
68
69static void decode_mcus __P((struct in *, int *, int, struct scan *, int *));
70static int dec_readmarker __P((struct in *));
71static void dec_makehuff __P((struct dec_hufftbl *, int *, unsigned char *));
72
73static void setinput __P((struct in *, unsigned char *));
74/*********************************/
75
76#undef PREC
77#define PREC int
78
79static void idctqtab __P((unsigned char *, PREC *));
80static void idct __P((int *, int *, PREC *, PREC, int));
81static void scaleidctqtab __P((PREC *, PREC));
82
83/*********************************/
84
85static void initcol __P((PREC[][64]));
86
87static void col221111 __P((int *, unsigned char *, int));
88static void col221111_16 __P((int *, unsigned char *, int));
89static void col221111_32 __P((int *, unsigned char *, int));
90
91/*********************************/
92
93#define M_SOI 0xd8
94#define M_APP0 0xe0
95#define M_DQT 0xdb
96#define M_SOF0 0xc0
97#define M_DHT 0xc4
98#define M_DRI 0xdd
99#define M_SOS 0xda
100#define M_RST0 0xd0
101#define M_EOI 0xd9
102#define M_COM 0xfe
103
104static unsigned char *datap;
105
106static int getbyte(void)
107{
108 return *datap++;
109}
110
111static int getword(void)
112{
113 int c1, c2;
114 c1 = *datap++;
115 c2 = *datap++;
116 return c1 << 8 | c2;
117}
118
119struct comp {
120 int cid;
121 int hv;
122 int tq;
123};
124
125#define MAXCOMP 4
126struct jpginfo {
127 int nc; /* number of components */
128 int ns; /* number of scans */
129 int dri; /* restart interval */
130 int nm; /* mcus til next marker */
131 int rm; /* next restart marker */
132};
133
134static struct jpginfo info;
135static struct comp comps[MAXCOMP];
136
137static struct scan dscans[MAXCOMP];
138
139static unsigned char quant[4][64];
140
141static struct dec_hufftbl dhuff[4];
142
143#define dec_huffdc (dhuff + 0)
144#define dec_huffac (dhuff + 2)
145
Stefan Reinauer87489e12010-03-17 04:03:22 +0000146static struct in glob_in;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000147
148static int readtables(int till)
149{
150 int m, l, i, j, lq, pq, tq;
151 int tc, th, tt;
152
153 for (;;) {
154 if (getbyte() != 0xff)
155 return -1;
Lee Leahy491c5b62017-03-10 15:51:04 -0800156 m = getbyte();
157 if (m == till)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000158 break;
159
160 switch (m) {
161 case 0xc2:
162 return 0;
163
164 case M_DQT:
165 lq = getword();
166 while (lq > 2) {
167 pq = getbyte();
168 tq = pq & 15;
169 if (tq > 3)
170 return -1;
171 pq >>= 4;
172 if (pq != 0)
173 return -1;
174 for (i = 0; i < 64; i++)
175 quant[tq][i] = getbyte();
176 lq -= 64 + 1;
177 }
178 break;
179
180 case M_DHT:
181 l = getword();
182 while (l > 2) {
183 int hufflen[16], k;
184 unsigned char huffvals[256];
185
186 tc = getbyte();
187 th = tc & 15;
188 tc >>= 4;
189 tt = tc * 2 + th;
190 if (tc > 1 || th > 1)
191 return -1;
192 for (i = 0; i < 16; i++)
193 hufflen[i] = getbyte();
194 l -= 1 + 16;
195 k = 0;
196 for (i = 0; i < 16; i++) {
197 for (j = 0; j < hufflen[i]; j++)
198 huffvals[k++] = getbyte();
199 l -= hufflen[i];
200 }
201 dec_makehuff(dhuff + tt, hufflen,
202 huffvals);
203 }
204 break;
205
206 case M_DRI:
207 l = getword();
208 info.dri = getword();
209 break;
210
211 default:
212 l = getword();
213 while (l-- > 2)
214 getbyte();
215 break;
216 }
217 }
218 return 0;
219}
220
221static void dec_initscans(void)
222{
223 int i;
224
225 info.nm = info.dri + 1;
226 info.rm = M_RST0;
227 for (i = 0; i < info.ns; i++)
228 dscans[i].dc = 0;
229}
230
231static int dec_checkmarker(void)
232{
233 int i;
234
Stefan Reinauer87489e12010-03-17 04:03:22 +0000235 if (dec_readmarker(&glob_in) != info.rm)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000236 return -1;
237 info.nm = info.dri;
238 info.rm = (info.rm + 1) & ~0x08;
239 for (i = 0; i < info.ns; i++)
240 dscans[i].dc = 0;
241 return 0;
242}
243
Patrick Georgi246179a2015-08-09 18:23:10 +0200244void jpeg_fetch_size(unsigned char *buf, int *width, int *height)
245{
246 datap = buf;
247 getbyte();
248 getbyte();
249 readtables(M_SOF0);
250 getword();
251 getbyte();
252 *height = getword();
253 *width = getword();
254}
255
Stefan Reinauerd650e992010-02-22 04:33:13 +0000256int jpeg_check_size(unsigned char *buf, int width, int height)
257{
Lee Leahye20a3192017-03-09 16:21:34 -0800258 datap = buf;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000259 getbyte();
260 getbyte();
261 readtables(M_SOF0);
262 getword();
263 getbyte();
Lee Leahye20a3192017-03-09 16:21:34 -0800264 if (height != getword() || width != getword())
Stefan Reinauerd650e992010-02-22 04:33:13 +0000265 return 0;
Lee Leahye20a3192017-03-09 16:21:34 -0800266 return 1;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000267}
268
Stefan Reinauer14e22772010-04-27 06:56:47 +0000269int jpeg_decode(unsigned char *buf, unsigned char *pic,
Nico Huber99eee162023-07-14 00:09:00 +0200270 int width, int height, int bytes_per_line, int depth,
271 struct jpeg_decdata *decdata)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000272{
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
Stefan Reinauerd650e992010-02-22 04:33:13 +0000359 dec_initscans();
360
361 dscans[0].next = 6 - 4;
362 dscans[1].next = 6 - 4 - 1;
363 dscans[2].next = 6 - 4 - 1 - 1; /* 411 encoding */
364 for (my = 0; my < mcusy; my++) {
365 for (mx = 0; mx < mcusx; mx++) {
366 if (info.dri && !--info.nm)
367 if (dec_checkmarker())
368 return ERR_WRONG_MARKER;
369
Stefan Reinauer87489e12010-03-17 04:03:22 +0000370 decode_mcus(&glob_in, decdata->dcts, 6, dscans, max);
Lee Leahy73402172017-03-10 15:23:24 -0800371 idct(decdata->dcts, decdata->out, decdata->dquant[0],
372 IFIX(128.5), max[0]);
373 idct(decdata->dcts + 64, decdata->out + 64,
374 decdata->dquant[0], IFIX(128.5), max[1]);
375 idct(decdata->dcts + 128, decdata->out + 128,
376 decdata->dquant[0], IFIX(128.5), max[2]);
377 idct(decdata->dcts + 192, decdata->out + 192,
378 decdata->dquant[0], IFIX(128.5), max[3]);
379 idct(decdata->dcts + 256, decdata->out + 256,
380 decdata->dquant[1], IFIX(0.5), max[4]);
381 idct(decdata->dcts + 320, decdata->out + 320,
382 decdata->dquant[2], IFIX(0.5), max[5]);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000383
384 switch (depth) {
385 case 32:
Nico Huber99eee162023-07-14 00:09:00 +0200386 col221111_32(decdata->out,
387 pic + my * 16 * bytes_per_line + mx * 16 * 4,
388 bytes_per_line);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000389 break;
390 case 24:
Nico Huber99eee162023-07-14 00:09:00 +0200391 col221111(decdata->out,
392 pic + my * 16 * bytes_per_line + mx * 16 * 3,
393 bytes_per_line);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000394 break;
395 case 16:
Nico Huber99eee162023-07-14 00:09:00 +0200396 col221111_16(decdata->out,
397 pic + my * 16 * bytes_per_line + mx * 16 * 2,
398 bytes_per_line);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000399 break;
400 default:
401 return ERR_DEPTH_MISMATCH;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000402 }
403 }
404 }
405
Stefan Reinauer87489e12010-03-17 04:03:22 +0000406 m = dec_readmarker(&glob_in);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000407 if (m != M_EOI)
408 return ERR_NO_EOI;
409
410 return 0;
411}
412
413/****************************************************************/
414/************** huffman decoder ***************/
415/****************************************************************/
416
417static int fillbits __P((struct in *, int, unsigned int));
418static int dec_rec2
419__P((struct in *, struct dec_hufftbl *, int *, int, int));
420
421static void setinput(struct in *in, unsigned char *p)
422{
423 in->p = p;
424 in->left = 0;
425 in->bits = 0;
426 in->marker = 0;
427}
428
429static int fillbits(struct in *in, int le, unsigned int bi)
430{
431 int b, m;
432
433 if (in->marker) {
434 if (le <= 16)
435 in->bits = bi << 16, le += 16;
436 return le;
437 }
438 while (le <= 24) {
439 b = *in->p++;
Lee Leahy491c5b62017-03-10 15:51:04 -0800440 if (b == 0xff) {
441 m = *in->p++;
442 if (m != 0) {
443 if (m == M_EOF) {
444 if (in->func) {
445 m = in->func(in->data);
446 if (m == 0)
447 continue;
Martin Roth1d5e2402017-07-23 20:04:41 -0600448 }
Lee Leahy491c5b62017-03-10 15:51:04 -0800449 }
450 in->marker = m;
451 if (le <= 16)
452 bi = bi << 16, le += 16;
453 break;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000454 }
Stefan Reinauerd650e992010-02-22 04:33:13 +0000455 }
456 bi = bi << 8 | b;
457 le += 8;
458 }
459 in->bits = bi; /* tmp... 2 return values needed */
460 return le;
461}
462
463static int dec_readmarker(struct in *in)
464{
465 int m;
466
467 in->left = fillbits(in, in->left, in->bits);
Lee Leahy491c5b62017-03-10 15:51:04 -0800468 m = in->marker;
469 if (m == 0)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000470 return 0;
471 in->left = 0;
472 in->marker = 0;
473 return m;
474}
475
476#define LEBI_DCL int le, bi
477#define LEBI_GET(in) (le = in->left, bi = in->bits)
478#define LEBI_PUT(in) (in->left = le, in->bits = bi)
479
Lee Leahye20a3192017-03-09 16:21:34 -0800480#define GETBITS(in, n) ( \
481 (le < (n) ? le = fillbits(in, le, bi), bi = in->bits : 0), \
482 (le -= (n)), \
483 bi >> le & ((1 << (n)) - 1) \
484 )
Stefan Reinauerd650e992010-02-22 04:33:13 +0000485
486#define UNGETBITS(in, n) ( \
Lee Leahye20a3192017-03-09 16:21:34 -0800487 le += (n) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000488)
489
490
491static int dec_rec2(struct in *in, struct dec_hufftbl *hu, int *runp, int c,
492 int i)
493{
494 LEBI_DCL;
495
496 LEBI_GET(in);
497 if (i) {
498 UNGETBITS(in, i & 127);
499 *runp = i >> 8 & 15;
500 i >>= 16;
501 } else {
Lee Leahy73402172017-03-10 15:23:24 -0800502 for (i = DECBITS; (c = ((c << 1) | GETBITS(in, 1)))
503 >= (hu->maxcode[i]); i++)
Lee Leahyb6ee0f92017-03-09 13:35:26 -0800504 ;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000505 if (i >= 16) {
506 in->marker = M_BADHUFF;
507 return 0;
508 }
509 i = hu->vals[hu->valptr[i] + c - hu->maxcode[i - 1] * 2];
510 *runp = i >> 4;
511 i &= 15;
512 }
513 if (i == 0) { /* sigh, 0xf0 is 11 bit */
514 LEBI_PUT(in);
515 return 0;
516 }
517 /* receive part */
518 c = GETBITS(in, i);
519 if (c < (1 << (i - 1)))
520 c += (-1 << i) + 1;
521 LEBI_PUT(in);
522 return c;
523}
524
Lee Leahye20a3192017-03-09 16:21:34 -0800525#define DEC_REC(in, hu, r, i) ( \
526 r = GETBITS(in, DECBITS), \
527 i = hu->llvals[r], \
528 i & 128 ? \
529 ( \
530 UNGETBITS(in, i & 127), \
531 r = i >> 8 & 15, \
532 i >> 16 \
533 ) \
534 : \
535 ( \
536 LEBI_PUT(in), \
537 i = dec_rec2(in, hu, &r, r, i), \
538 LEBI_GET(in), \
539 i \
540 ) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000541)
542
Lee Leahy73402172017-03-10 15:23:24 -0800543static void decode_mcus(struct in *in, int *dct, int n, struct scan *sc,
544 int *maxp)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000545{
546 struct dec_hufftbl *hu;
547 int i, r, t;
548 LEBI_DCL;
549
550 memset(dct, 0, n * 64 * sizeof(*dct));
551 LEBI_GET(in);
552 while (n-- > 0) {
553 hu = sc->hudc.dhuff;
554 *dct++ = (sc->dc += DEC_REC(in, hu, r, t));
555
556 hu = sc->huac.dhuff;
557 i = 63;
558 while (i > 0) {
559 t = DEC_REC(in, hu, r, t);
560 if (t == 0 && r == 0) {
561 dct += i;
562 break;
563 }
564 dct += r;
565 *dct++ = t;
566 i -= r + 1;
567 }
568 *maxp++ = 64 - i;
569 if (n == sc->next)
570 sc++;
571 }
572 LEBI_PUT(in);
573}
574
Lee Leahy73402172017-03-10 15:23:24 -0800575static void dec_makehuff(struct dec_hufftbl *hu, int *hufflen,
576 unsigned char *huffvals)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000577{
578 int code, k, i, j, d, x, c, v;
579 for (i = 0; i < (1 << DECBITS); i++)
580 hu->llvals[i] = 0;
581
582/*
583 * llvals layout:
584 *
585 * value v already known, run r, backup u bits:
586 * vvvvvvvvvvvvvvvv 0000 rrrr 1 uuuuuuu
587 * value unknown, size b bits, run r, backup u bits:
588 * 000000000000bbbb 0000 rrrr 0 uuuuuuu
589 * value and size unknown:
590 * 0000000000000000 0000 0000 0 0000000
591 */
592 code = 0;
593 k = 0;
594 for (i = 0; i < 16; i++, code <<= 1) { /* sizes */
595 hu->valptr[i] = k;
596 for (j = 0; j < hufflen[i]; j++) {
597 hu->vals[k] = *huffvals++;
598 if (i < DECBITS) {
599 c = code << (DECBITS - 1 - i);
600 v = hu->vals[k] & 0x0f; /* size */
601 for (d = 1 << (DECBITS - 1 - i); --d >= 0;) {
Lee Leahy73402172017-03-10 15:23:24 -0800602 /* both fit in table */
603 if (v + i < DECBITS) {
Stefan Reinauerd650e992010-02-22 04:33:13 +0000604 x = d >> (DECBITS - 1 - v -
605 i);
606 if (v && x < (1 << (v - 1)))
607 x += (-1 << v) + 1;
Lee Leahy73402172017-03-10 15:23:24 -0800608 x = x << 16 | (hu->vals[k]
609 & 0xf0) << 4 |
610 (DECBITS - (i + 1 + v))
611 | 128;
Stefan Reinauerd650e992010-02-22 04:33:13 +0000612 } else
Lee Leahy73402172017-03-10 15:23:24 -0800613 x = v << 16 | (hu->vals[k]
614 & 0xf0) << 4 |
Lee Leahye20a3192017-03-09 16:21:34 -0800615 (DECBITS - (i + 1));
Stefan Reinauerd650e992010-02-22 04:33:13 +0000616 hu->llvals[c | d] = x;
617 }
618 }
619 code++;
620 k++;
621 }
622 hu->maxcode[i] = code;
623 }
624 hu->maxcode[16] = 0x20000; /* always terminate decode */
625}
626
627/****************************************************************/
628/************** idct ***************/
629/****************************************************************/
630
631#define ONE ((PREC)IFIX(1.))
632#define S2 ((PREC)IFIX(0.382683432))
633#define C2 ((PREC)IFIX(0.923879532))
634#define C4 ((PREC)IFIX(0.707106781))
635
636#define S22 ((PREC)IFIX(2 * 0.382683432))
637#define C22 ((PREC)IFIX(2 * 0.923879532))
638#define IC4 ((PREC)IFIX(1 / 0.707106781))
639
640#define C3IC1 ((PREC)IFIX(0.847759065)) /* c3/c1 */
641#define C5IC1 ((PREC)IFIX(0.566454497)) /* c5/c1 */
642#define C7IC1 ((PREC)IFIX(0.198912367)) /* c7/c1 */
643
Lee Leahy35af5c42017-03-09 17:35:28 -0800644#define XPP(a, b) (t = a + b, b = a - b, a = t)
645#define XMP(a, b) (t = a - b, b = a + b, a = t)
646#define XPM(a, b) (t = a + b, b = b - a, a = t)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000647
Lee Leahy35af5c42017-03-09 17:35:28 -0800648#define ROT(a, b, s, c) (t = IMULT(a + b, s), \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000649 a = IMULT(a, c - s) + t, \
650 b = IMULT(b, c + s) - t)
651
Lee Leahye20a3192017-03-09 16:21:34 -0800652#define IDCT \
653( \
654 XPP(t0, t1), \
655 XMP(t2, t3), \
656 t2 = IMULT(t2, IC4) - t3, \
657 XPP(t0, t3), \
658 XPP(t1, t2), \
659 XMP(t4, t7), \
660 XPP(t5, t6), \
661 XMP(t5, t7), \
662 t5 = IMULT(t5, IC4), \
663 ROT(t4, t6, S22, C22), \
664 t6 -= t7, \
665 t5 -= t6, \
666 t4 -= t5, \
667 XPP(t0, t7), \
668 XPP(t1, t6), \
669 XPP(t2, t5), \
670 XPP(t3, t4) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000671)
672
673static unsigned char zig2[64] = {
674 0, 2, 3, 9, 10, 20, 21, 35,
675 14, 16, 25, 31, 39, 46, 50, 57,
676 5, 7, 12, 18, 23, 33, 37, 48,
677 27, 29, 41, 44, 52, 55, 59, 62,
678 15, 26, 30, 40, 45, 51, 56, 58,
679 1, 4, 8, 11, 19, 22, 34, 36,
680 28, 42, 43, 53, 54, 60, 61, 63,
681 6, 13, 17, 24, 32, 38, 47, 49
682};
683
Stefan Reinauer87489e12010-03-17 04:03:22 +0000684void idct(int *in, int *out, PREC *lquant, PREC off, int max)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000685{
686 PREC t0, t1, t2, t3, t4, t5, t6, t7, t;
687 PREC tmp[64], *tmpp;
688 int i, j;
689 unsigned char *zig2p;
690
691 t0 = off;
692 if (max == 1) {
Stefan Reinauer87489e12010-03-17 04:03:22 +0000693 t0 += in[0] * lquant[0];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000694 for (i = 0; i < 64; i++)
695 out[i] = ITOINT(t0);
696 return;
697 }
698 zig2p = zig2;
699 tmpp = tmp;
700 for (i = 0; i < 8; i++) {
701 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000702 t0 += in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000703 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000704 t5 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000705 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000706 t2 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000707 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000708 t7 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000709 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000710 t1 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000711 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000712 t4 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000713 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000714 t3 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000715 j = *zig2p++;
Stefan Reinauer87489e12010-03-17 04:03:22 +0000716 t6 = in[j] * lquant[j];
Stefan Reinauerd650e992010-02-22 04:33:13 +0000717 IDCT;
718 tmpp[0 * 8] = t0;
719 tmpp[1 * 8] = t1;
720 tmpp[2 * 8] = t2;
721 tmpp[3 * 8] = t3;
722 tmpp[4 * 8] = t4;
723 tmpp[5 * 8] = t5;
724 tmpp[6 * 8] = t6;
725 tmpp[7 * 8] = t7;
726 tmpp++;
727 t0 = 0;
728 }
729 for (i = 0; i < 8; i++) {
730 t0 = tmp[8 * i + 0];
731 t1 = tmp[8 * i + 1];
732 t2 = tmp[8 * i + 2];
733 t3 = tmp[8 * i + 3];
734 t4 = tmp[8 * i + 4];
735 t5 = tmp[8 * i + 5];
736 t6 = tmp[8 * i + 6];
737 t7 = tmp[8 * i + 7];
738 IDCT;
739 out[8 * i + 0] = ITOINT(t0);
740 out[8 * i + 1] = ITOINT(t1);
741 out[8 * i + 2] = ITOINT(t2);
742 out[8 * i + 3] = ITOINT(t3);
743 out[8 * i + 4] = ITOINT(t4);
744 out[8 * i + 5] = ITOINT(t5);
745 out[8 * i + 6] = ITOINT(t6);
746 out[8 * i + 7] = ITOINT(t7);
747 }
748}
749
750static unsigned char zig[64] = {
751 0, 1, 5, 6, 14, 15, 27, 28,
752 2, 4, 7, 13, 16, 26, 29, 42,
753 3, 8, 12, 17, 25, 30, 41, 43,
754 9, 11, 18, 24, 31, 40, 44, 53,
755 10, 19, 23, 32, 39, 45, 52, 54,
756 20, 22, 33, 38, 46, 51, 55, 60,
757 21, 34, 37, 47, 50, 56, 59, 61,
758 35, 36, 48, 49, 57, 58, 62, 63
759};
760
761static PREC aaidct[8] = {
762 IFIX(0.3535533906), IFIX(0.4903926402),
763 IFIX(0.4619397663), IFIX(0.4157348062),
764 IFIX(0.3535533906), IFIX(0.2777851165),
765 IFIX(0.1913417162), IFIX(0.0975451610)
766};
767
768
769static void idctqtab(unsigned char *qin, PREC *qout)
770{
771 int i, j;
772
773 for (i = 0; i < 8; i++)
774 for (j = 0; j < 8; j++)
775 qout[zig[i * 8 + j]] = qin[zig[i * 8 + j]] *
Lee Leahye20a3192017-03-09 16:21:34 -0800776 IMULT(aaidct[i], aaidct[j]);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000777}
778
779static void scaleidctqtab(PREC *q, PREC sc)
780{
781 int i;
782
783 for (i = 0; i < 64; i++)
784 q[i] = IMULT(q[i], sc);
785}
786
787/****************************************************************/
788/************** color decoder ***************/
789/****************************************************************/
790
791#define ROUND
792
793/*
794 * YCbCr Color transformation:
795 *
796 * y:0..255 Cb:-128..127 Cr:-128..127
797 *
798 * R = Y + 1.40200 * Cr
799 * G = Y - 0.34414 * Cb - 0.71414 * Cr
800 * B = Y + 1.77200 * Cb
801 *
802 * =>
803 * Cr *= 1.40200;
804 * Cb *= 1.77200;
805 * Cg = 0.19421 * Cb + .50937 * Cr;
806 * R = Y + Cr;
807 * G = Y - Cg;
808 * B = Y + Cb;
809 *
810 * =>
811 * Cg = (50 * Cb + 130 * Cr + 128) >> 8;
812 */
813
814static void initcol(PREC q[][64])
815{
816 scaleidctqtab(q[1], IFIX(1.77200));
817 scaleidctqtab(q[2], IFIX(1.40200));
818}
819
820/* This is optimized for the stupid sun SUNWspro compiler. */
Lee Leahy35af5c42017-03-09 17:35:28 -0800821#define STORECLAMP(a, x) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000822( \
Lee Leahye20a3192017-03-09 16:21:34 -0800823 (a) = (x), \
824 (unsigned int)(x) >= 256 ? \
825 ((a) = (x) < 0 ? 0 : 255) \
826 : \
827 0 \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000828)
829
830#define CLAMP(x) ((unsigned int)(x) >= 256 ? ((x) < 0 ? 0 : 255) : (x))
831
832#ifdef ROUND
833
834#define CBCRCG(yin, xin) \
835( \
Lee Leahy35af5c42017-03-09 17:35:28 -0800836 cb = outc[0 + yin * 8 + xin], \
837 cr = outc[64 + yin * 8 + xin], \
Lee Leahye20a3192017-03-09 16:21:34 -0800838 cg = (50 * cb + 130 * cr + 128) >> 8 \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000839)
840
841#else
842
843#define CBCRCG(yin, xin) \
844( \
Lee Leahy35af5c42017-03-09 17:35:28 -0800845 cb = outc[0 + yin*8 + xin], \
846 cr = outc[64 + yin*8 + xin], \
Lee Leahye20a3192017-03-09 16:21:34 -0800847 cg = (3 * cb + 8 * cr) >> 4 \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000848)
849
850#endif
851
852#define PIC(yin, xin, p, xout) \
853( \
Lee Leahye20a3192017-03-09 16:21:34 -0800854 y = outy[(yin) * 8 + xin], \
855 STORECLAMP(p[(xout) * 3 + 0], y + cr), \
856 STORECLAMP(p[(xout) * 3 + 1], y - cg), \
857 STORECLAMP(p[(xout) * 3 + 2], y + cb) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000858)
859
860#ifdef __LITTLE_ENDIAN
Lee Leahye20a3192017-03-09 16:21:34 -0800861#define PIC_16(yin, xin, p, xout, add) \
862( \
863 y = outy[(yin) * 8 + xin], \
864 y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 8) | \
865 ((CLAMP(y - cg + add) & 0xfc) << 3) | \
866 ((CLAMP(y + cb + add*2+1)) >> 3), \
867 p[(xout) * 2 + 0] = y & 0xff, \
868 p[(xout) * 2 + 1] = y >> 8 \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000869)
870#else
871#ifdef CONFIG_PPC
Lee Leahye20a3192017-03-09 16:21:34 -0800872#define PIC_16(yin, xin, p, xout, add) \
873( \
874 y = outy[(yin) * 8 + xin], \
875 y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 7) | \
876 ((CLAMP(y - cg + add*2+1) & 0xf8) << 2) | \
877 ((CLAMP(y + cb + add*2+1)) >> 3), \
878 p[(xout) * 2 + 0] = y >> 8, \
879 p[(xout) * 2 + 1] = y & 0xff \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000880)
881#else
Lee Leahye20a3192017-03-09 16:21:34 -0800882#define PIC_16(yin, xin, p, xout, add) \
883( \
884 y = outy[(yin) * 8 + xin], \
885 y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 8) | \
886 ((CLAMP(y - cg + add) & 0xfc) << 3) | \
887 ((CLAMP(y + cb + add*2+1)) >> 3), \
888 p[(xout) * 2 + 0] = y >> 8, \
889 p[(xout) * 2 + 1] = y & 0xff \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000890)
891#endif
892#endif
893
894#define PIC_32(yin, xin, p, xout) \
895( \
Lee Leahye20a3192017-03-09 16:21:34 -0800896 y = outy[(yin) * 8 + xin], \
897 STORECLAMP(p[(xout) * 4 + 0], y + cr), \
898 STORECLAMP(p[(xout) * 4 + 1], y - cg), \
899 STORECLAMP(p[(xout) * 4 + 2], y + cb), \
900 p[(xout) * 4 + 3] = 0 \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000901)
902
Lee Leahye20a3192017-03-09 16:21:34 -0800903#define PIC221111(xin) \
904( \
905 CBCRCG(0, xin), \
906 PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0), \
907 PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1), \
908 PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0), \
909 PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000910)
911
Lee Leahye20a3192017-03-09 16:21:34 -0800912#define PIC221111_16(xin) \
913( \
914 CBCRCG(0, xin), \
915 PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0, 3), \
916 PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1, 0), \
917 PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0, 1), \
918 PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1, 2) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000919)
920
Lee Leahye20a3192017-03-09 16:21:34 -0800921#define PIC221111_32(xin) \
922( \
923 CBCRCG(0, xin), \
924 PIC_32(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0), \
925 PIC_32(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1), \
926 PIC_32(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0), \
927 PIC_32(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1) \
Stefan Reinauerd650e992010-02-22 04:33:13 +0000928)
929
930static void col221111(int *out, unsigned char *pic, int width)
931{
932 int i, j, k;
933 unsigned char *pic0, *pic1;
934 int *outy, *outc;
935 int cr, cg, cb, y;
936
937 pic0 = pic;
938 pic1 = pic + width;
939 outy = out;
940 outc = out + 64 * 4;
941 for (i = 2; i > 0; i--) {
942 for (j = 4; j > 0; j--) {
Lee Leahy2f919ec2017-03-08 17:37:06 -0800943 for (k = 0; k < 8; k++)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000944 PIC221111(k);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000945 outc += 8;
946 outy += 16;
947 pic0 += 2 * width;
948 pic1 += 2 * width;
949 }
950 outy += 64 * 2 - 16 * 4;
951 }
952}
953
954static void col221111_16(int *out, unsigned char *pic, int width)
955{
956 int i, j, k;
957 unsigned char *pic0, *pic1;
958 int *outy, *outc;
959 int cr, cg, cb, y;
960
961 pic0 = pic;
962 pic1 = pic + width;
963 outy = out;
964 outc = out + 64 * 4;
965 for (i = 2; i > 0; i--) {
966 for (j = 4; j > 0; j--) {
Lee Leahy2f919ec2017-03-08 17:37:06 -0800967 for (k = 0; k < 8; k++)
Lee Leahye20a3192017-03-09 16:21:34 -0800968 PIC221111_16(k);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000969 outc += 8;
970 outy += 16;
971 pic0 += 2 * width;
972 pic1 += 2 * width;
973 }
974 outy += 64 * 2 - 16 * 4;
975 }
976}
977
978static void col221111_32(int *out, unsigned char *pic, int width)
979{
980 int i, j, k;
981 unsigned char *pic0, *pic1;
982 int *outy, *outc;
983 int cr, cg, cb, y;
984
985 pic0 = pic;
986 pic1 = pic + width;
987 outy = out;
988 outc = out + 64 * 4;
989 for (i = 2; i > 0; i--) {
990 for (j = 4; j > 0; j--) {
Lee Leahy2f919ec2017-03-08 17:37:06 -0800991 for (k = 0; k < 8; k++)
Stefan Reinauerd650e992010-02-22 04:33:13 +0000992 PIC221111_32(k);
Stefan Reinauerd650e992010-02-22 04:33:13 +0000993 outc += 8;
994 outy += 16;
995 pic0 += 2 * width;
996 pic1 += 2 * width;
997 }
998 outy += 64 * 2 - 16 * 4;
999 }
1000}