blob: a96a9d7fd5c3e9245b5e87ffc2d5db3a4db9fd34 [file] [log] [blame]
Kevin O'Connorafbed1b2010-06-28 07:34:53 -04001/*
2 * Copyright (C) 2001, Novell Inc.
Kevin O'Connorbbc47222010-07-30 13:07:08 -04003 * Copyright (C) 2010 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connorafbed1b2010-06-28 07:34:53 -04004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of Novell nor the names of the contributors may
18 * be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35/*
36 * a tiny jpeg decoder.
37 *
38 * written in August 2001 by Michael Schroeder <mls@suse.de>
39 *
40 */
41
42#define __LITTLE_ENDIAN
43#include "util.h"
44#include "jpeg.h"
45#define ISHIFT 11
46
47#define IFIX(a) ((int)((a) * (1 << ISHIFT) + .5))
48#define IMULT(a, b) (((a) * (b)) >> ISHIFT)
49#define ITOINT(a) ((a) >> ISHIFT)
50
51#ifndef __P
52# define __P(x) x
53#endif
54
55/* special markers */
56#define M_BADHUFF -1
57#define M_EOF 0x80
58
59struct in {
60 unsigned char *p;
61 unsigned int bits;
62 int left;
63 int marker;
64
65 int (*func) __P((void *));
66 void *data;
67};
68
69/*********************************/
70struct dec_hufftbl;
71struct enc_hufftbl;
72
73union hufftblp {
74 struct dec_hufftbl *dhuff;
75 struct enc_hufftbl *ehuff;
76};
77
78struct scan {
79 int dc; /* old dc value */
80
81 union hufftblp hudc;
82 union hufftblp huac;
83 int next; /* when to switch to next scan */
84
85 int cid; /* component id */
86 int hv; /* horiz/vert, copied from comp */
87 int tq; /* quant tbl, copied from comp */
88};
89
90/*********************************/
91
92#define DECBITS 10 /* seems to be the optimum */
93
94struct dec_hufftbl {
95 int maxcode[17];
96 int valptr[16];
97 unsigned char vals[256];
98 unsigned int llvals[1 << DECBITS];
99};
100
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400101static void decode_mcus __P((struct in *, int *, int, struct scan *, int *));
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400102static int dec_readmarker __P((struct in *));
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400103static void dec_makehuff __P((struct dec_hufftbl *, int *, unsigned char *));
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400104
105static void setinput __P((struct in *, unsigned char *));
106/*********************************/
107
108#undef PREC
109#define PREC int
110
111static void idctqtab __P((unsigned char *, PREC *));
112static void idct __P((int *, int *, PREC *, PREC, int));
113static void scaleidctqtab __P((PREC *, PREC));
114
115/*********************************/
116
117static void initcol __P((PREC[][64]));
118
119static void col221111 __P((int *, unsigned char *, int));
120static void col221111_16 __P((int *, unsigned char *, int));
121static void col221111_32 __P((int *, unsigned char *, int));
122
123/*********************************/
124
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400125#define ERR_NO_SOI 1
126#define ERR_NOT_8BIT 2
127#define ERR_HEIGHT_MISMATCH 3
128#define ERR_WIDTH_MISMATCH 4
129#define ERR_BAD_WIDTH_OR_HEIGHT 5
130#define ERR_TOO_MANY_COMPPS 6
131#define ERR_ILLEGAL_HV 7
132#define ERR_QUANT_TABLE_SELECTOR 8
133#define ERR_NOT_YCBCR_221111 9
134#define ERR_UNKNOWN_CID_IN_SCAN 10
135#define ERR_NOT_SEQUENTIAL_DCT 11
136#define ERR_WRONG_MARKER 12
137#define ERR_NO_EOI 13
138#define ERR_BAD_TABLES 14
139#define ERR_DEPTH_MISMATCH 15
140
141/*********************************/
142
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400143#define M_SOI 0xd8
144#define M_APP0 0xe0
145#define M_DQT 0xdb
146#define M_SOF0 0xc0
147#define M_DHT 0xc4
148#define M_DRI 0xdd
149#define M_SOS 0xda
150#define M_RST0 0xd0
151#define M_EOI 0xd9
152#define M_COM 0xfe
153
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400154struct comp {
155 int cid;
156 int hv;
157 int tq;
158};
159
160#define MAXCOMP 4
161struct jpginfo {
162 int nc; /* number of components */
163 int ns; /* number of scans */
164 int dri; /* restart interval */
165 int nm; /* mcus til next marker */
166 int rm; /* next restart marker */
167};
168
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400169struct jpeg_decdata {
170 int dcts[6 * 64 + 16];
171 int out[64 * 6];
172 int dquant[3][64];
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400173
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400174 unsigned char *datap;
175 struct jpginfo info;
176 struct comp comps[MAXCOMP];
177 struct scan dscans[MAXCOMP];
178 unsigned char quant[4][64];
179 struct dec_hufftbl dhuff[4];
180 struct in in;
Kevin O'Connorbbc47222010-07-30 13:07:08 -0400181
182 int height, width;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400183};
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400184
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400185static int getbyte(struct jpeg_decdata *jpeg)
186{
187 return *jpeg->datap++;
188}
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400189
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400190static int getword(struct jpeg_decdata *jpeg)
191{
192 int c1, c2;
193 c1 = *jpeg->datap++;
194 c2 = *jpeg->datap++;
195 return c1 << 8 | c2;
196}
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400197
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400198static int readtables(struct jpeg_decdata *jpeg, int till)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400199{
200 int m, l, i, j, lq, pq, tq;
201 int tc, th, tt;
202
203 for (;;) {
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400204 if (getbyte(jpeg) != 0xff)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400205 return -1;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400206 if ((m = getbyte(jpeg)) == till)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400207 break;
208
209 switch (m) {
210 case 0xc2:
211 return 0;
212
213 case M_DQT:
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400214 lq = getword(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400215 while (lq > 2) {
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400216 pq = getbyte(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400217 tq = pq & 15;
218 if (tq > 3)
219 return -1;
220 pq >>= 4;
221 if (pq != 0)
222 return -1;
223 for (i = 0; i < 64; i++)
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400224 jpeg->quant[tq][i] = getbyte(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400225 lq -= 64 + 1;
226 }
227 break;
228
229 case M_DHT:
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400230 l = getword(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400231 while (l > 2) {
232 int hufflen[16], k;
233 unsigned char huffvals[256];
234
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400235 tc = getbyte(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400236 th = tc & 15;
237 tc >>= 4;
238 tt = tc * 2 + th;
239 if (tc > 1 || th > 1)
240 return -1;
241 for (i = 0; i < 16; i++)
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400242 hufflen[i] = getbyte(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400243 l -= 1 + 16;
244 k = 0;
245 for (i = 0; i < 16; i++) {
246 for (j = 0; j < hufflen[i]; j++)
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400247 huffvals[k++] = getbyte(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400248 l -= hufflen[i];
249 }
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400250 dec_makehuff(jpeg->dhuff + tt, hufflen, huffvals);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400251 }
252 break;
253
254 case M_DRI:
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400255 l = getword(jpeg);
256 jpeg->info.dri = getword(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400257 break;
258
259 default:
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400260 l = getword(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400261 while (l-- > 2)
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400262 getbyte(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400263 break;
264 }
265 }
266 return 0;
267}
268
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400269static void dec_initscans(struct jpeg_decdata *jpeg)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400270{
271 int i;
272
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400273 jpeg->info.nm = jpeg->info.dri + 1;
274 jpeg->info.rm = M_RST0;
275 for (i = 0; i < jpeg->info.ns; i++)
276 jpeg->dscans[i].dc = 0;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400277}
278
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400279static int dec_checkmarker(struct jpeg_decdata *jpeg)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400280{
281 int i;
282
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400283 if (dec_readmarker(&jpeg->in) != jpeg->info.rm)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400284 return -1;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400285 jpeg->info.nm = jpeg->info.dri;
286 jpeg->info.rm = (jpeg->info.rm + 1) & ~0x08;
287 for (i = 0; i < jpeg->info.ns; i++)
288 jpeg->dscans[i].dc = 0;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400289 return 0;
290}
291
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400292struct jpeg_decdata *jpeg_alloc(void)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400293{
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400294 struct jpeg_decdata *jpeg = malloc_tmphigh(sizeof(*jpeg));
295 return jpeg;
296}
297
Kevin O'Connorbbc47222010-07-30 13:07:08 -0400298int jpeg_decode(struct jpeg_decdata *jpeg, unsigned char *buf)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400299{
300 int i, j, m, tac, tdc;
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400301
Kevin O'Connorbbc47222010-07-30 13:07:08 -0400302 if (!jpeg || !buf)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400303 return -1;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400304 jpeg->datap = buf;
305 if (getbyte(jpeg) != 0xff)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400306 return ERR_NO_SOI;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400307 if (getbyte(jpeg) != M_SOI)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400308 return ERR_NO_SOI;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400309 if (readtables(jpeg, M_SOF0))
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400310 return ERR_BAD_TABLES;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400311 getword(jpeg);
312 i = getbyte(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400313 if (i != 8)
314 return ERR_NOT_8BIT;
Kevin O'Connorbbc47222010-07-30 13:07:08 -0400315 jpeg->height = getword(jpeg);
316 jpeg->width = getword(jpeg);
317 if ((jpeg->height & 15) || (jpeg->width & 15))
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400318 return ERR_BAD_WIDTH_OR_HEIGHT;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400319 jpeg->info.nc = getbyte(jpeg);
320 if (jpeg->info.nc > MAXCOMP)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400321 return ERR_TOO_MANY_COMPPS;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400322 for (i = 0; i < jpeg->info.nc; i++) {
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400323 int h, v;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400324 jpeg->comps[i].cid = getbyte(jpeg);
325 jpeg->comps[i].hv = getbyte(jpeg);
326 v = jpeg->comps[i].hv & 15;
327 h = jpeg->comps[i].hv >> 4;
328 jpeg->comps[i].tq = getbyte(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400329 if (h > 3 || v > 3)
330 return ERR_ILLEGAL_HV;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400331 if (jpeg->comps[i].tq > 3)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400332 return ERR_QUANT_TABLE_SELECTOR;
333 }
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400334 if (readtables(jpeg, M_SOS))
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400335 return ERR_BAD_TABLES;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400336 getword(jpeg);
337 jpeg->info.ns = getbyte(jpeg);
338 if (jpeg->info.ns != 3)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400339 return ERR_NOT_YCBCR_221111;
340 for (i = 0; i < 3; i++) {
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400341 jpeg->dscans[i].cid = getbyte(jpeg);
342 tdc = getbyte(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400343 tac = tdc & 15;
344 tdc >>= 4;
345 if (tdc > 1 || tac > 1)
346 return ERR_QUANT_TABLE_SELECTOR;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400347 for (j = 0; j < jpeg->info.nc; j++)
348 if (jpeg->comps[j].cid == jpeg->dscans[i].cid)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400349 break;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400350 if (j == jpeg->info.nc)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400351 return ERR_UNKNOWN_CID_IN_SCAN;
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400352 jpeg->dscans[i].hv = jpeg->comps[j].hv;
353 jpeg->dscans[i].tq = jpeg->comps[j].tq;
354 jpeg->dscans[i].hudc.dhuff = &jpeg->dhuff[tdc];
355 jpeg->dscans[i].huac.dhuff = &jpeg->dhuff[2 + tac];
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400356 }
357
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400358 i = getbyte(jpeg);
359 j = getbyte(jpeg);
360 m = getbyte(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400361
362 if (i != 0 || j != 63 || m != 0)
363 return ERR_NOT_SEQUENTIAL_DCT;
364
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400365 if (jpeg->dscans[0].cid != 1 || jpeg->dscans[1].cid != 2
366 || jpeg->dscans[2].cid != 3)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400367 return ERR_NOT_YCBCR_221111;
368
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400369 if (jpeg->dscans[0].hv != 0x22 || jpeg->dscans[1].hv != 0x11
370 || jpeg->dscans[2].hv != 0x11)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400371 return ERR_NOT_YCBCR_221111;
372
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400373 idctqtab(jpeg->quant[jpeg->dscans[0].tq], jpeg->dquant[0]);
374 idctqtab(jpeg->quant[jpeg->dscans[1].tq], jpeg->dquant[1]);
375 idctqtab(jpeg->quant[jpeg->dscans[2].tq], jpeg->dquant[2]);
376 initcol(jpeg->dquant);
377 setinput(&jpeg->in, jpeg->datap);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400378
379#if 0
380 /* landing zone */
381 img[len] = 0;
382 img[len + 1] = 0xff;
383 img[len + 2] = M_EOF;
384#endif
385
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400386 dec_initscans(jpeg);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400387
Kevin O'Connorbbc47222010-07-30 13:07:08 -0400388 return 0;
389}
390
391void jpeg_get_size(struct jpeg_decdata *jpeg, int *width, int *height)
392{
393 *width = jpeg->width;
394 *height = jpeg->height;
395}
396
Wayne Xia8031efa2011-07-08 11:03:16 +0800397int jpeg_show(struct jpeg_decdata *jpeg, unsigned char *pic, int width
398 , int height, int depth, int bytes_per_line_dest)
Kevin O'Connorbbc47222010-07-30 13:07:08 -0400399{
Wayne Xia8031efa2011-07-08 11:03:16 +0800400 int m, mcusx, mcusy, mx, my, mloffset, jpgbpl;
Kevin O'Connorbbc47222010-07-30 13:07:08 -0400401 int max[6];
402
403 if (jpeg->height != height)
404 return ERR_HEIGHT_MISMATCH;
405 if (jpeg->width != width)
406 return ERR_WIDTH_MISMATCH;
407
Wayne Xia8031efa2011-07-08 11:03:16 +0800408 jpgbpl = width * depth / 8;
409 mloffset = bytes_per_line_dest > jpgbpl ? bytes_per_line_dest : jpgbpl;
410
Kevin O'Connorbbc47222010-07-30 13:07:08 -0400411 mcusx = jpeg->width >> 4;
412 mcusy = jpeg->height >> 4;
413
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400414 jpeg->dscans[0].next = 6 - 4;
415 jpeg->dscans[1].next = 6 - 4 - 1;
416 jpeg->dscans[2].next = 6 - 4 - 1 - 1; /* 411 encoding */
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400417 for (my = 0; my < mcusy; my++) {
418 for (mx = 0; mx < mcusx; mx++) {
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400419 if (jpeg->info.dri && !--jpeg->info.nm)
420 if (dec_checkmarker(jpeg))
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400421 return ERR_WRONG_MARKER;
422
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400423 decode_mcus(&jpeg->in, jpeg->dcts, 6, jpeg->dscans, max);
424 idct(jpeg->dcts, jpeg->out, jpeg->dquant[0],
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400425 IFIX(128.5), max[0]);
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400426 idct(jpeg->dcts + 64, jpeg->out + 64, jpeg->dquant[0],
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400427 IFIX(128.5), max[1]);
Kevin O'Connor06644f42010-08-28 14:58:15 -0400428 idct(jpeg->dcts + 128, jpeg->out + 128, jpeg->dquant[0],
429 IFIX(128.5), max[2]);
430 idct(jpeg->dcts + 192, jpeg->out + 192, jpeg->dquant[0],
431 IFIX(128.5), max[3]);
432 idct(jpeg->dcts + 256, jpeg->out + 256, jpeg->dquant[1],
433 IFIX(0.5), max[4]);
434 idct(jpeg->dcts + 320, jpeg->out + 320, jpeg->dquant[2],
435 IFIX(0.5), max[5]);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400436
437 switch (depth) {
438 case 32:
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400439 col221111_32(jpeg->out,
Wayne Xia8031efa2011-07-08 11:03:16 +0800440 pic + (my * 16 * mloffset + mx * 16 * 4),
441 mloffset);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400442 break;
443 case 24:
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400444 col221111(jpeg->out,
Wayne Xia8031efa2011-07-08 11:03:16 +0800445 pic + (my * 16 * mloffset + mx * 16 * 3),
446 mloffset);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400447 break;
448 case 16:
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400449 col221111_16(jpeg->out,
Wayne Xia8031efa2011-07-08 11:03:16 +0800450 pic + (my * 16 * mloffset + mx * 16 * 2),
451 mloffset);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400452 break;
453 default:
454 return ERR_DEPTH_MISMATCH;
455 break;
456 }
457 }
458 }
459
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400460 m = dec_readmarker(&jpeg->in);
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400461 if (m != M_EOI)
462 return ERR_NO_EOI;
463
464 return 0;
465}
466
467/****************************************************************/
468/************** huffman decoder ***************/
469/****************************************************************/
470
471static int fillbits __P((struct in *, int, unsigned int));
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400472static int dec_rec2 __P((struct in *, struct dec_hufftbl *, int *, int, int));
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400473
474static void setinput(struct in *in, unsigned char *p)
475{
476 in->p = p;
477 in->left = 0;
478 in->bits = 0;
479 in->marker = 0;
480}
481
482static int fillbits(struct in *in, int le, unsigned int bi)
483{
484 int b, m;
485
486 if (in->marker) {
487 if (le <= 16)
488 in->bits = bi << 16, le += 16;
489 return le;
490 }
491 while (le <= 24) {
492 b = *in->p++;
493 if (b == 0xff && (m = *in->p++) != 0) {
494 if (m == M_EOF) {
495 if (in->func && (m = in->func(in->data)) == 0)
496 continue;
497 }
498 in->marker = m;
499 if (le <= 16)
500 bi = bi << 16, le += 16;
501 break;
502 }
503 bi = bi << 8 | b;
504 le += 8;
505 }
506 in->bits = bi; /* tmp... 2 return values needed */
507 return le;
508}
509
510static int dec_readmarker(struct in *in)
511{
512 int m;
513
514 in->left = fillbits(in, in->left, in->bits);
515 if ((m = in->marker) == 0)
516 return 0;
517 in->left = 0;
518 in->marker = 0;
519 return m;
520}
521
522#define LEBI_DCL int le, bi
523#define LEBI_GET(in) (le = in->left, bi = in->bits)
524#define LEBI_PUT(in) (in->left = le, in->bits = bi)
525
526#define GETBITS(in, n) ( \
527 (le < (n) ? le = fillbits(in, le, bi), bi = in->bits : 0), \
528 (le -= (n)), \
529 bi >> le & ((1 << (n)) - 1) \
530)
531
532#define UNGETBITS(in, n) ( \
533 le += (n) \
534)
535
536
537static int dec_rec2(struct in *in, struct dec_hufftbl *hu, int *runp,
538 int c, int i)
539{
540 LEBI_DCL;
541
542 LEBI_GET(in);
543 if (i) {
544 UNGETBITS(in, i & 127);
545 *runp = i >> 8 & 15;
546 i >>= 16;
547 } else {
548 for (i = DECBITS;
549 (c = ((c << 1) | GETBITS(in, 1))) >= (hu->maxcode[i]); i++);
550 if (i >= 16) {
551 in->marker = M_BADHUFF;
552 return 0;
553 }
554 i = hu->vals[hu->valptr[i] + c - hu->maxcode[i - 1] * 2];
555 *runp = i >> 4;
556 i &= 15;
557 }
558 if (i == 0) { /* sigh, 0xf0 is 11 bit */
559 LEBI_PUT(in);
560 return 0;
561 }
562 /* receive part */
563 c = GETBITS(in, i);
564 if (c < (1 << (i - 1)))
565 c += (-1 << i) + 1;
566 LEBI_PUT(in);
567 return c;
568}
569
570#define DEC_REC(in, hu, r, i) ( \
571 r = GETBITS(in, DECBITS), \
572 i = hu->llvals[r], \
573 i & 128 ? \
574 ( \
575 UNGETBITS(in, i & 127), \
576 r = i >> 8 & 15, \
577 i >> 16 \
578 ) \
579 : \
580 ( \
581 LEBI_PUT(in), \
582 i = dec_rec2(in, hu, &r, r, i), \
583 LEBI_GET(in), \
584 i \
585 ) \
586)
587
588static void decode_mcus(struct in *in, int *dct, int n, struct scan *sc,
589 int *maxp)
590{
591 struct dec_hufftbl *hu;
592 int i, r, t;
593 LEBI_DCL;
594
595 memset(dct, 0, n * 64 * sizeof(*dct));
596 LEBI_GET(in);
597 while (n-- > 0) {
598 hu = sc->hudc.dhuff;
599 *dct++ = (sc->dc += DEC_REC(in, hu, r, t));
600
601 hu = sc->huac.dhuff;
602 i = 63;
603 while (i > 0) {
604 t = DEC_REC(in, hu, r, t);
605 if (t == 0 && r == 0) {
606 dct += i;
607 break;
608 }
609 dct += r;
610 *dct++ = t;
611 i -= r + 1;
612 }
613 *maxp++ = 64 - i;
614 if (n == sc->next)
615 sc++;
616 }
617 LEBI_PUT(in);
618}
619
620static void dec_makehuff(struct dec_hufftbl *hu, int *hufflen,
621 unsigned char *huffvals)
622{
623 int code, k, i, j, d, x, c, v;
624 for (i = 0; i < (1 << DECBITS); i++)
625 hu->llvals[i] = 0;
626
627 /*
628 * llvals layout:
629 *
630 * value v already known, run r, backup u bits:
631 * vvvvvvvvvvvvvvvv 0000 rrrr 1 uuuuuuu
632 * value unknown, size b bits, run r, backup u bits:
633 * 000000000000bbbb 0000 rrrr 0 uuuuuuu
634 * value and size unknown:
635 * 0000000000000000 0000 0000 0 0000000
636 */
637
638 code = 0;
639 k = 0;
640 for (i = 0; i < 16; i++, code <<= 1) { /* sizes */
641 hu->valptr[i] = k;
642 for (j = 0; j < hufflen[i]; j++) {
643 hu->vals[k] = *huffvals++;
644 if (i < DECBITS) {
645 c = code << (DECBITS - 1 - i);
646 v = hu->vals[k] & 0x0f; /* size */
647 for (d = 1 << (DECBITS - 1 - i); --d >= 0;) {
648 if (v + i < DECBITS) { /* both fit in table */
649 x = d >> (DECBITS - 1 - v - i);
650 if (v && x < (1 << (v - 1)))
651 x += (-1 << v) + 1;
652 x = x << 16 | (hu->vals[k] & 0xf0) << 4 |
653 (DECBITS - (i + 1 + v)) | 128;
654 } else
655 x = v << 16 | (hu->vals[k] & 0xf0) << 4 |
656 (DECBITS - (i + 1));
657 hu->llvals[c | d] = x;
658 }
659 }
660 code++;
661 k++;
662 }
663 hu->maxcode[i] = code;
664 }
665 hu->maxcode[16] = 0x20000; /* always terminate decode */
666}
667
668/****************************************************************/
669/************** idct ***************/
670/****************************************************************/
671
672#define ONE ((PREC)IFIX(1.))
673#define S2 ((PREC)IFIX(0.382683432))
674#define C2 ((PREC)IFIX(0.923879532))
675#define C4 ((PREC)IFIX(0.707106781))
676
677#define S22 ((PREC)IFIX(2 * 0.382683432))
678#define C22 ((PREC)IFIX(2 * 0.923879532))
679#define IC4 ((PREC)IFIX(1 / 0.707106781))
680
681#define C3IC1 ((PREC)IFIX(0.847759065)) /* c3/c1 */
682#define C5IC1 ((PREC)IFIX(0.566454497)) /* c5/c1 */
683#define C7IC1 ((PREC)IFIX(0.198912367)) /* c7/c1 */
684
685#define XPP(a,b) (t = a + b, b = a - b, a = t)
686#define XMP(a,b) (t = a - b, b = a + b, a = t)
687#define XPM(a,b) (t = a + b, b = b - a, a = t)
688
689#define ROT(a,b,s,c) ( t = IMULT(a + b, s), \
690 a = IMULT(a, c - s) + t, \
691 b = IMULT(b, c + s) - t)
692
693#define IDCT \
694( \
695 XPP(t0, t1), \
696 XMP(t2, t3), \
697 t2 = IMULT(t2, IC4) - t3, \
698 XPP(t0, t3), \
699 XPP(t1, t2), \
700 XMP(t4, t7), \
701 XPP(t5, t6), \
702 XMP(t5, t7), \
703 t5 = IMULT(t5, IC4), \
704 ROT(t4, t6, S22, C22), \
705 t6 -= t7, \
706 t5 -= t6, \
707 t4 -= t5, \
708 XPP(t0, t7), \
709 XPP(t1, t6), \
710 XPP(t2, t5), \
711 XPP(t3, t4) \
712)
713
714static unsigned char zig2[64] = {
715 0, 2, 3, 9, 10, 20, 21, 35,
716 14, 16, 25, 31, 39, 46, 50, 57,
717 5, 7, 12, 18, 23, 33, 37, 48,
718 27, 29, 41, 44, 52, 55, 59, 62,
719 15, 26, 30, 40, 45, 51, 56, 58,
720 1, 4, 8, 11, 19, 22, 34, 36,
721 28, 42, 43, 53, 54, 60, 61, 63,
722 6, 13, 17, 24, 32, 38, 47, 49
723};
724
Kevin O'Connor2976dd42010-07-30 12:27:14 -0400725static void idct(int *in, int *out, PREC * quant, PREC off, int max)
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400726{
727 PREC t0, t1, t2, t3, t4, t5, t6, t7, t;
728 PREC tmp[64], *tmpp;
729 int i, j;
730 unsigned char *zig2p;
731
732 t0 = off;
733 if (max == 1) {
734 t0 += in[0] * quant[0];
735 for (i = 0; i < 64; i++)
736 out[i] = ITOINT(t0);
737 return;
738 }
739 zig2p = zig2;
740 tmpp = tmp;
741 for (i = 0; i < 8; i++) {
742 j = *zig2p++;
743 t0 += in[j] * quant[j];
744 j = *zig2p++;
745 t5 = in[j] * quant[j];
746 j = *zig2p++;
747 t2 = in[j] * quant[j];
748 j = *zig2p++;
749 t7 = in[j] * quant[j];
750 j = *zig2p++;
751 t1 = in[j] * quant[j];
752 j = *zig2p++;
753 t4 = in[j] * quant[j];
754 j = *zig2p++;
755 t3 = in[j] * quant[j];
756 j = *zig2p++;
757 t6 = in[j] * quant[j];
758 IDCT;
759 tmpp[0 * 8] = t0;
760 tmpp[1 * 8] = t1;
761 tmpp[2 * 8] = t2;
762 tmpp[3 * 8] = t3;
763 tmpp[4 * 8] = t4;
764 tmpp[5 * 8] = t5;
765 tmpp[6 * 8] = t6;
766 tmpp[7 * 8] = t7;
767 tmpp++;
768 t0 = 0;
769 }
770 for (i = 0; i < 8; i++) {
771 t0 = tmp[8 * i + 0];
772 t1 = tmp[8 * i + 1];
773 t2 = tmp[8 * i + 2];
774 t3 = tmp[8 * i + 3];
775 t4 = tmp[8 * i + 4];
776 t5 = tmp[8 * i + 5];
777 t6 = tmp[8 * i + 6];
778 t7 = tmp[8 * i + 7];
779 IDCT;
780 out[8 * i + 0] = ITOINT(t0);
781 out[8 * i + 1] = ITOINT(t1);
782 out[8 * i + 2] = ITOINT(t2);
783 out[8 * i + 3] = ITOINT(t3);
784 out[8 * i + 4] = ITOINT(t4);
785 out[8 * i + 5] = ITOINT(t5);
786 out[8 * i + 6] = ITOINT(t6);
787 out[8 * i + 7] = ITOINT(t7);
788 }
789}
790
791static unsigned char zig[64] = {
792 0, 1, 5, 6, 14, 15, 27, 28,
793 2, 4, 7, 13, 16, 26, 29, 42,
794 3, 8, 12, 17, 25, 30, 41, 43,
795 9, 11, 18, 24, 31, 40, 44, 53,
796 10, 19, 23, 32, 39, 45, 52, 54,
797 20, 22, 33, 38, 46, 51, 55, 60,
798 21, 34, 37, 47, 50, 56, 59, 61,
799 35, 36, 48, 49, 57, 58, 62, 63
800};
801
802static PREC aaidct[8] = {
803 IFIX(0.3535533906), IFIX(0.4903926402),
804 IFIX(0.4619397663), IFIX(0.4157348062),
805 IFIX(0.3535533906), IFIX(0.2777851165),
806 IFIX(0.1913417162), IFIX(0.0975451610)
807};
808
809
810static void idctqtab(unsigned char *qin, PREC * qout)
811{
812 int i, j;
813
814 for (i = 0; i < 8; i++)
815 for (j = 0; j < 8; j++)
816 qout[zig[i * 8 + j]] = qin[zig[i * 8 + j]] *
817 IMULT(aaidct[i], aaidct[j]);
818}
819
820static void scaleidctqtab(PREC * q, PREC sc)
821{
822 int i;
823
824 for (i = 0; i < 64; i++)
825 q[i] = IMULT(q[i], sc);
826}
827
828/****************************************************************/
829/************** color decoder ***************/
830/****************************************************************/
831
832#define ROUND
833
834/*
835 * YCbCr Color transformation:
836 *
837 * y:0..255 Cb:-128..127 Cr:-128..127
838 *
839 * R = Y + 1.40200 * Cr
840 * G = Y - 0.34414 * Cb - 0.71414 * Cr
841 * B = Y + 1.77200 * Cb
842 *
843 * =>
844 * Cr *= 1.40200;
845 * Cb *= 1.77200;
846 * Cg = 0.19421 * Cb + .50937 * Cr;
847 * R = Y + Cr;
848 * G = Y - Cg;
849 * B = Y + Cb;
850 *
851 * =>
852 * Cg = (50 * Cb + 130 * Cr + 128) >> 8;
853 */
854
855static void initcol(PREC q[][64])
856{
857 scaleidctqtab(q[1], IFIX(1.77200));
858 scaleidctqtab(q[2], IFIX(1.40200));
859}
860
861/* This is optimized for the stupid sun SUNWspro compiler. */
862#define STORECLAMP(a,x) \
863( \
864 (a) = (x), \
865 (unsigned int)(x) >= 256 ? \
866 ((a) = (x) < 0 ? 0 : 255) \
867 : \
868 0 \
869)
870
871#define CLAMP(x) ((unsigned int)(x) >= 256 ? ((x) < 0 ? 0 : 255) : (x))
872
873#ifdef ROUND
874
875#define CBCRCG(yin, xin) \
876( \
877 cb = outc[0 +yin*8+xin], \
878 cr = outc[64+yin*8+xin], \
879 cg = (50 * cb + 130 * cr + 128) >> 8 \
880)
881
882#else
883
884#define CBCRCG(yin, xin) \
885( \
886 cb = outc[0 +yin*8+xin], \
887 cr = outc[64+yin*8+xin], \
888 cg = (3 * cb + 8 * cr) >> 4 \
889)
890
891#endif
892
Wayne Xia8031efa2011-07-08 11:03:16 +0800893#ifdef __LITTLE_ENDIAN
894#define PIC(yin, xin, p, xout) \
895( \
896 y = outy[(yin) * 8 + xin], \
897 STORECLAMP(p[(xout) * 3 + 2], y + cr), \
898 STORECLAMP(p[(xout) * 3 + 1], y - cg), \
899 STORECLAMP(p[(xout) * 3 + 0], y + cb) \
900)
901#else
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400902#define PIC(yin, xin, p, xout) \
903( \
904 y = outy[(yin) * 8 + xin], \
905 STORECLAMP(p[(xout) * 3 + 0], y + cr), \
906 STORECLAMP(p[(xout) * 3 + 1], y - cg), \
907 STORECLAMP(p[(xout) * 3 + 2], y + cb) \
908)
Wayne Xia8031efa2011-07-08 11:03:16 +0800909#endif
Kevin O'Connorafbed1b2010-06-28 07:34:53 -0400910
911#ifdef __LITTLE_ENDIAN
912#define PIC_16(yin, xin, p, xout, add) \
913( \
914 y = outy[(yin) * 8 + xin], \
915 y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 8) | \
916 ((CLAMP(y - cg + add ) & 0xfc) << 3) | \
917 ((CLAMP(y + cb + add*2+1) ) >> 3), \
918 p[(xout) * 2 + 0] = y & 0xff, \
919 p[(xout) * 2 + 1] = y >> 8 \
920)
921#else
922#ifdef CONFIG_PPC
923#define PIC_16(yin, xin, p, xout, add) \
924( \
925 y = outy[(yin) * 8 + xin], \
926 y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 7) | \
927 ((CLAMP(y - cg + add*2+1) & 0xf8) << 2) | \
928 ((CLAMP(y + cb + add*2+1) ) >> 3), \
929 p[(xout) * 2 + 0] = y >> 8, \
930 p[(xout) * 2 + 1] = y & 0xff \
931)
932#else
933#define PIC_16(yin, xin, p, xout, add) \
934( \
935 y = outy[(yin) * 8 + xin], \
936 y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 8) | \
937 ((CLAMP(y - cg + add ) & 0xfc) << 3) | \
938 ((CLAMP(y + cb + add*2+1) ) >> 3), \
939 p[(xout) * 2 + 0] = y >> 8, \
940 p[(xout) * 2 + 1] = y & 0xff \
941)
942#endif
943#endif
944
945#define PIC_32(yin, xin, p, xout) \
946( \
947 y = outy[(yin) * 8 + xin], \
948 STORECLAMP(p[(xout) * 4 + 0], y + cr), \
949 STORECLAMP(p[(xout) * 4 + 1], y - cg), \
950 STORECLAMP(p[(xout) * 4 + 2], y + cb), \
951 p[(xout) * 4 + 3] = 0 \
952)
953
954#define PIC221111(xin) \
955( \
956 CBCRCG(0, xin), \
957 PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0), \
958 PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1), \
959 PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0), \
960 PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1) \
961)
962
963#define PIC221111_16(xin) \
964( \
965 CBCRCG(0, xin), \
966 PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0, 3), \
967 PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1, 0), \
968 PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0, 1), \
969 PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1, 2) \
970)
971
972#define PIC221111_32(xin) \
973( \
974 CBCRCG(0, xin), \
975 PIC_32(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0), \
976 PIC_32(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1), \
977 PIC_32(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0), \
978 PIC_32(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1) \
979)
980
981static void col221111(int *out, unsigned char *pic, int width)
982{
983 int i, j, k;
984 unsigned char *pic0, *pic1;
985 int *outy, *outc;
986 int cr, cg, cb, y;
987
988 pic0 = pic;
989 pic1 = pic + width;
990 outy = out;
991 outc = out + 64 * 4;
992 for (i = 2; i > 0; i--) {
993 for (j = 4; j > 0; j--) {
994 for (k = 0; k < 8; k++) {
995 PIC221111(k);
996 }
997 outc += 8;
998 outy += 16;
999 pic0 += 2 * width;
1000 pic1 += 2 * width;
1001 }
1002 outy += 64 * 2 - 16 * 4;
1003 }
1004}
1005
1006static void col221111_16(int *out, unsigned char *pic, int width)
1007{
1008 int i, j, k;
1009 unsigned char *pic0, *pic1;
1010 int *outy, *outc;
1011 int cr, cg, cb, y;
1012
1013 pic0 = pic;
1014 pic1 = pic + width;
1015 outy = out;
1016 outc = out + 64 * 4;
1017 for (i = 2; i > 0; i--) {
1018 for (j = 4; j > 0; j--) {
1019 for (k = 0; k < 8; k++) {
1020 PIC221111_16(k);
1021 }
1022 outc += 8;
1023 outy += 16;
1024 pic0 += 2 * width;
1025 pic1 += 2 * width;
1026 }
1027 outy += 64 * 2 - 16 * 4;
1028 }
1029}
1030
1031static void col221111_32(int *out, unsigned char *pic, int width)
1032{
1033 int i, j, k;
1034 unsigned char *pic0, *pic1;
1035 int *outy, *outc;
1036 int cr, cg, cb, y;
1037
1038 pic0 = pic;
1039 pic1 = pic + width;
1040 outy = out;
1041 outc = out + 64 * 4;
1042 for (i = 2; i > 0; i--) {
1043 for (j = 4; j > 0; j--) {
1044 for (k = 0; k < 8; k++) {
1045 PIC221111_32(k);
1046 }
1047 outc += 8;
1048 outy += 16;
1049 pic0 += 2 * width;
1050 pic1 += 2 * width;
1051 }
1052 outy += 64 * 2 - 16 * 4;
1053 }
1054}