87 unsigned char bits, code;
97 int actabsel, dctabsel;
99 unsigned char *pixels;
105 const unsigned char *pos;
109 int mbwidth, mbheight;
110 int mbsizex, mbsizey;
114 unsigned char qtab[4][64];
115 VlcCode vlctab[4][65536];
126 void(*FreeMem)(
void*);
129 inline unsigned char _Clip(
const int x) {
130 return (x < 0) ? 0 : ((
x > 0xFF) ? 0xFF : (unsigned char)
x);
142 inline void _RowIDCT(
int* blk) {
143 int x0, x1, x2, x3, x4, x5, x6, x7, x8;
144 if (!((x1 = blk[4] << 11)
152 blk[0] = blk[1] = blk[2] = blk[3] = blk[4] = blk[5] = blk[6] = blk[7] = blk[0] << 3;
155 x0 = (blk[0] << 11) + 128;
157 x4 = x8 + (W1 - W7) * x4;
158 x5 = x8 - (W1 + W7) * x5;
160 x6 = x8 - (W3 - W5) * x6;
161 x7 = x8 - (W3 + W5) * x7;
165 x2 = x1 - (W2 + W6) * x2;
166 x3 = x1 + (W2 - W6) * x3;
175 x2 = (181 * (x4 + x5) + 128) >> 8;
176 x4 = (181 * (x4 - x5) + 128) >> 8;
177 blk[0] = (x7 + x1) >> 8;
178 blk[1] = (x3 + x2) >> 8;
179 blk[2] = (x0 + x4) >> 8;
180 blk[3] = (x8 + x6) >> 8;
181 blk[4] = (x8 - x6) >> 8;
182 blk[5] = (x0 - x4) >> 8;
183 blk[6] = (x3 - x2) >> 8;
184 blk[7] = (x7 - x1) >> 8;
187 inline void _ColIDCT(
const int* blk,
unsigned char *out,
int stride) {
188 int x0, x1, x2, x3, x4, x5, x6, x7, x8;
189 if (!((x1 = blk[8 * 4] << 8)
195 | (x7 = blk[8 * 3])))
197 x1 = _Clip(((blk[0] + 32) >> 6) + 128);
198 for (x0 = 8; x0; --x0) {
199 *out = (
unsigned char)x1;
204 x0 = (blk[0] << 8) + 8192;
205 x8 = W7 * (x4 + x5) + 4;
206 x4 = (x8 + (W1 - W7) * x4) >> 3;
207 x5 = (x8 - (W1 + W7) * x5) >> 3;
208 x8 = W3 * (x6 + x7) + 4;
209 x6 = (x8 - (W3 - W5) * x6) >> 3;
210 x7 = (x8 - (W3 + W5) * x7) >> 3;
213 x1 = W6 * (x3 + x2) + 4;
214 x2 = (x1 - (W2 + W6) * x2) >> 3;
215 x3 = (x1 + (W2 - W6) * x3) >> 3;
224 x2 = (181 * (x4 + x5) + 128) >> 8;
225 x4 = (181 * (x4 - x5) + 128) >> 8;
226 *out = _Clip(((x7 + x1) >> 14) + 128); out += stride;
227 *out = _Clip(((x3 + x2) >> 14) + 128); out += stride;
228 *out = _Clip(((x0 + x4) >> 14) + 128); out += stride;
229 *out = _Clip(((x8 + x6) >> 14) + 128); out += stride;
230 *out = _Clip(((x8 - x6) >> 14) + 128); out += stride;
231 *out = _Clip(((x0 - x4) >> 14) + 128); out += stride;
232 *out = _Clip(((x3 - x2) >> 14) + 128); out += stride;
233 *out = _Clip(((x7 - x1) >> 14) + 128);
236#define JPEG_DECODER_THROW(e) do { ctx.error = e; return; } while (0)
238 inline int _ShowBits(
int bits) {
239 unsigned char newbyte;
241 while (ctx.bufbits < bits) {
243 ctx.buf = (ctx.buf << 8) | 0xFF;
247 newbyte = *ctx.pos++;
250 ctx.buf = (ctx.buf << 8) | newbyte;
251 if (newbyte == 0xFF) {
253 unsigned char marker = *ctx.pos++;
257 case 0xD9: ctx.size = 0;
break;
259 if ((marker & 0xF8) != 0xD0)
262 ctx.buf = (ctx.buf << 8) | marker;
271 return (ctx.buf >> (ctx.bufbits - bits)) & ((1 << bits) - 1);
274 inline void _SkipBits(
int bits) {
275 if (ctx.bufbits < bits)
276 (void)_ShowBits(bits);
280 inline int _GetBits(
int bits) {
281 int res = _ShowBits(bits);
286 inline void _ByteAlign(
void) {
290 inline void _Skip(
int count) {
297 inline unsigned short _Decode16(
const unsigned char *pos) {
298 return (pos[0] << 8) | pos[1];
301 inline void _DecodeLength(
void) {
303 ctx.length = _Decode16(ctx.pos);
308 inline void _SkipMarker(
void) {
313 inline void _DecodeSOF(
void) {
314 int i, ssxmax = 0, ssymax = 0;
319 ctx.height = _Decode16(ctx.pos + 1);
320 ctx.width = _Decode16(ctx.pos + 3);
321 ctx.ncomp = ctx.pos[5];
331 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c) {
339 ctx.qtused |= 1 << c->qtsel;
340 if (c->ssx > ssxmax) ssxmax = c->ssx;
341 if (c->ssy > ssymax) ssymax = c->ssy;
343 ctx.mbsizex = ssxmax << 3;
344 ctx.mbsizey = ssymax << 3;
345 ctx.mbwidth = (ctx.width + ctx.mbsizex - 1) / ctx.mbsizex;
346 ctx.mbheight = (ctx.height + ctx.mbsizey - 1) / ctx.mbsizey;
347 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c) {
348 c->width = (ctx.width * c->ssx + ssxmax - 1) / ssxmax;
349 c->stride = (c->width + 7) & 0x7FFFFFF8;
350 c->height = (ctx.height * c->ssy + ssymax - 1) / ssymax;
351 c->stride = ctx.mbwidth * ctx.mbsizex * c->ssx / ssxmax;
355 if (ctx.ncomp == 3) {
356 ctx.rgb = (
unsigned char*)AllocMem(ctx.width * ctx.height * ctx.ncomp);
362 inline void _DecodeDHT(
void) {
363 int codelen, currcnt, remain, spread, i, j;
365 unsigned char counts[16];
367 while (ctx.length >= 17) {
371 i = (i | (i >> 3)) & 3;
372 for (codelen = 1; codelen <= 16; ++codelen)
373 counts[codelen - 1] = ctx.pos[codelen];
375 vlc = &ctx.vlctab[i][0];
376 remain = spread = 65536;
377 for (codelen = 1; codelen <= 16; ++codelen) {
379 currcnt = counts[codelen - 1];
380 if (!currcnt)
continue;
382 remain -= currcnt << (16 - codelen);
384 for (i = 0; i < currcnt; ++i) {
385 register unsigned char code = ctx.pos[i];
386 for (j = spread; j; --j) {
387 vlc->bits = (
unsigned char)codelen;
402 inline void _DecodeDQT(
void) {
406 while (ctx.length >= 65) {
409 ctx.qtavail |= 1 << i;
411 for (i = 0; i < 64; ++i)
412 t[i] = ctx.pos[i + 1];
418 inline void _DecodeDRI(
void) {
421 ctx.rstinterval = _Decode16(ctx.pos);
425 inline int _GetVLC(VlcCode* vlc,
unsigned char* code) {
426 int value = _ShowBits(16);
427 int bits = vlc[value].bits;
430 value = vlc[value].code;
431 if (code) *code = (
unsigned char)value;
434 value = _GetBits(bits);
435 if (value < (1 << (bits - 1)))
436 value += ((-1) << bits) + 1;
440 inline void _DecodeBlock(Component* c,
unsigned char* out) {
443 memset(ctx.block, 0,
sizeof(ctx.block));
444 c->dcpred += _GetVLC(&ctx.vlctab[c->dctabsel][0],
NULL);
445 ctx.block[0] = (c->dcpred) * ctx.qtab[c->qtsel][0];
447 value = _GetVLC(&ctx.vlctab[c->actabsel][0], &code);
450 coef += (code >> 4) + 1;
452 ctx.block[(int)ZZ[coef]] = value * ctx.qtab[c->qtsel][coef];
454 for (coef = 0; coef < 64; coef += 8)
455 _RowIDCT(&ctx.block[coef]);
456 for (coef = 0; coef < 8; ++coef)
457 _ColIDCT(&ctx.block[coef], &out[coef], c->stride);
460 inline void _DecodeScan(
void) {
461 int i, mbx, mby, sbx, sby;
462 int rstcount = ctx.rstinterval, nextrst = 0;
468 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c) {
471 c->dctabsel = ctx.pos[1] >> 4;
472 c->actabsel = (ctx.pos[1] & 1) | 2;
477 for (mby = 0; mby < ctx.mbheight; ++mby)
478 for (mbx = 0; mbx < ctx.mbwidth; ++mbx) {
479 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c)
480 for (sby = 0; sby < c->ssy; ++sby)
481 for (sbx = 0; sbx < c->ssx; ++sbx) {
482 _DecodeBlock(c, &c->pixels[((mby * c->ssy + sby) * c->stride + mbx * c->ssx + sbx) << 3]);
486 if (ctx.rstinterval && !(--rstcount)) {
490 nextrst = (nextrst + 1) & 7;
491 rstcount = ctx.rstinterval;
492 for (i = 0; i < 3; ++i)
493 ctx.comp[i].dcpred = 0;
514 inline unsigned char CF(
const int x) {
515 return _Clip((x + 64) >> 7);
518 inline void _UpsampleH(Component* c) {
519 const int xmax = c->width - 3;
520 unsigned char *out, *lin, *lout;
522 out = (
unsigned char*)AllocMem((c->width * c->height) << 1);
526 for (y = c->height; y; --y) {
527 lout[0] = CF(CF2A * lin[0] + CF2B * lin[1]);
528 lout[1] = CF(CF3X * lin[0] + CF3Y * lin[1] + CF3Z * lin[2]);
529 lout[2] = CF(CF3A * lin[0] + CF3B * lin[1] + CF3C * lin[2]);
530 for (x = 0;
x < xmax; ++
x) {
531 lout[(
x << 1) + 3] = CF(CF4A * lin[x] + CF4B * lin[x + 1] + CF4C * lin[x + 2] + CF4D * lin[x + 3]);
532 lout[(
x << 1) + 4] = CF(CF4D * lin[x] + CF4C * lin[x + 1] + CF4B * lin[x + 2] + CF4A * lin[x + 3]);
535 lout += c->width << 1;
536 lout[-3] = CF(CF3A * lin[-1] + CF3B * lin[-2] + CF3C * lin[-3]);
537 lout[-2] = CF(CF3X * lin[-1] + CF3Y * lin[-2] + CF3Z * lin[-3]);
538 lout[-1] = CF(CF2A * lin[-1] + CF2B * lin[-2]);
541 c->stride = c->width;
546 inline void _UpsampleV(Component* c) {
547 const int w = c->width, s1 = c->stride, s2 = s1 + s1;
548 unsigned char *out, *
cin, *
cout;
550 out = (
unsigned char*)AllocMem((c->width * c->height) << 1);
552 for (x = 0;
x < w; ++
x) {
555 *
cout = CF(CF2A * cin[0] + CF2B * cin[s1]);
cout += w;
556 *
cout = CF(CF3X * cin[0] + CF3Y * cin[s1] + CF3Z * cin[s2]);
cout += w;
557 *
cout = CF(CF3A * cin[0] + CF3B * cin[s1] + CF3C * cin[s2]);
cout += w;
559 for (y = c->height - 3; y; --y) {
560 *
cout = CF(CF4A * cin[-s1] + CF4B * cin[0] + CF4C * cin[s1] + CF4D * cin[s2]);
cout += w;
561 *
cout = CF(CF4D * cin[-s1] + CF4C * cin[0] + CF4B * cin[s1] + CF4A * cin[s2]);
cout += w;
565 *
cout = CF(CF3A * cin[0] + CF3B * cin[-s1] + CF3C * cin[-s2]);
cout += w;
566 *
cout = CF(CF3X * cin[0] + CF3Y * cin[-s1] + CF3Z * cin[-s2]);
cout += w;
567 *
cout = CF(CF2A * cin[0] + CF2B * cin[-s1]);
570 c->stride = c->width;
575 inline void _Convert() {
578 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c) {
579 while ((c->width < ctx.width) || (c->height < ctx.height)) {
580 if (c->width < ctx.width) _UpsampleH(c);
581 if (ctx.error)
return;
582 if (c->height < ctx.height) _UpsampleV(c);
583 if (ctx.error)
return;
588 if (ctx.ncomp == 3) {
591 unsigned char *prgb = ctx.rgb;
592 const unsigned char *py = ctx.comp[0].pixels;
593 const unsigned char *pcb = ctx.comp[1].pixels;
594 const unsigned char *pcr = ctx.comp[2].pixels;
595 for (yy = ctx.height; yy; --yy) {
596 for (x = 0;
x < ctx.width; ++
x) {
597 register int y = py[
x] << 8;
598 register int cb = pcb[
x] - 128;
599 register int cr = pcr[
x] - 128;
600 *prgb++ = _Clip((y + 359 * cr + 128) >> 8);
601 *prgb++ = _Clip((y - 88 * cb - 183 * cr + 128) >> 8);
602 *prgb++ = _Clip((y + 454 * cb + 128) >> 8);
604 py += ctx.comp[0].stride;
605 pcb += ctx.comp[1].stride;
606 pcr += ctx.comp[2].stride;
609 else if (ctx.comp[0].width != ctx.comp[0].stride) {
611 unsigned char *pin = &ctx.comp[0].pixels[ctx.comp[0].stride];
612 unsigned char *pout = &ctx.comp[0].pixels[ctx.comp[0].width];
614 for (y = ctx.comp[0].height - 1; y; --y) {
615 memcpy(pout, pin, ctx.comp[0].width);
616 pin += ctx.comp[0].stride;
617 pout += ctx.comp[0].width;
619 ctx.comp[0].stride = ctx.comp[0].width;
623 DecodeResult _Decode(
const unsigned char* jpeg,
const int size) {
624 ctx.pos = (
const unsigned char*)jpeg;
625 ctx.size = size & 0x7FFFFFFF;
627 if ((ctx.pos[0] ^ 0xFF) | (ctx.pos[1] ^ 0xD8))
return NotAJpeg;
630 if ((ctx.size < 2) || (ctx.pos[0] != 0xFF))
return SyntaxError;
632 switch (ctx.pos[-1]) {
633 case 0xC0: _DecodeSOF();
break;
634 case 0xC4: _DecodeDHT();
break;
635 case 0xDB: _DecodeDQT();
break;
636 case 0xDD: _DecodeDRI();
break;
637 case 0xDA: _DecodeScan();
break;
638 case 0xFE: _SkipMarker();
break;
640 if ((ctx.pos[-1] & 0xF0) == 0xE0){