X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fjpeg.c;h=a96a9d7fd5c3e9245b5e87ffc2d5db3a4db9fd34;hb=refs%2Fheads%2Fcoreboot;hp=711f8101bdca17a27717c6b2d46238928f6d7791;hpb=afbed1bde45edc7829ac02644815796efc7dd4ac;p=seabios.git diff --git a/src/jpeg.c b/src/jpeg.c index 711f810..a96a9d7 100644 --- a/src/jpeg.c +++ b/src/jpeg.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2001, Novell Inc. + * Copyright (C) 2010 Kevin O'Connor * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -97,11 +98,9 @@ struct dec_hufftbl { unsigned int llvals[1 << DECBITS]; }; -static void decode_mcus -__P((struct in *, int *, int, struct scan *, int *)); +static void decode_mcus __P((struct in *, int *, int, struct scan *, int *)); static int dec_readmarker __P((struct in *)); -static void dec_makehuff -__P((struct dec_hufftbl *, int *, unsigned char *)); +static void dec_makehuff __P((struct dec_hufftbl *, int *, unsigned char *)); static void setinput __P((struct in *, unsigned char *)); /*********************************/ @@ -123,6 +122,24 @@ static void col221111_32 __P((int *, unsigned char *, int)); /*********************************/ +#define ERR_NO_SOI 1 +#define ERR_NOT_8BIT 2 +#define ERR_HEIGHT_MISMATCH 3 +#define ERR_WIDTH_MISMATCH 4 +#define ERR_BAD_WIDTH_OR_HEIGHT 5 +#define ERR_TOO_MANY_COMPPS 6 +#define ERR_ILLEGAL_HV 7 +#define ERR_QUANT_TABLE_SELECTOR 8 +#define ERR_NOT_YCBCR_221111 9 +#define ERR_UNKNOWN_CID_IN_SCAN 10 +#define ERR_NOT_SEQUENTIAL_DCT 11 +#define ERR_WRONG_MARKER 12 +#define ERR_NO_EOI 13 +#define ERR_BAD_TABLES 14 +#define ERR_DEPTH_MISMATCH 15 + +/*********************************/ + #define M_SOI 0xd8 #define M_APP0 0xe0 #define M_DQT 0xdb @@ -134,21 +151,6 @@ static void col221111_32 __P((int *, unsigned char *, int)); #define M_EOI 0xd9 #define M_COM 0xfe -static unsigned char *datap; - -static int getbyte(void) -{ - return *datap++; -} - -static int getword(void) -{ - int c1, c2; - c1 = *datap++; - c2 = *datap++; - return c1 << 8 | c2; -} - struct comp { int cid; int hv; @@ -164,29 +166,44 @@ struct jpginfo { int rm; /* next restart marker */ }; -static struct jpginfo info; -static struct comp comps[MAXCOMP]; +struct jpeg_decdata { + int dcts[6 * 64 + 16]; + int out[64 * 6]; + int dquant[3][64]; -static struct scan dscans[MAXCOMP]; + unsigned char *datap; + struct jpginfo info; + struct comp comps[MAXCOMP]; + struct scan dscans[MAXCOMP]; + unsigned char quant[4][64]; + struct dec_hufftbl dhuff[4]; + struct in in; -static unsigned char quant[4][64]; - -static struct dec_hufftbl dhuff[4]; + int height, width; +}; -#define dec_huffdc (dhuff + 0) -#define dec_huffac (dhuff + 2) +static int getbyte(struct jpeg_decdata *jpeg) +{ + return *jpeg->datap++; +} -static struct in in; +static int getword(struct jpeg_decdata *jpeg) +{ + int c1, c2; + c1 = *jpeg->datap++; + c2 = *jpeg->datap++; + return c1 << 8 | c2; +} -static int readtables(int till) +static int readtables(struct jpeg_decdata *jpeg, int till) { int m, l, i, j, lq, pq, tq; int tc, th, tt; for (;;) { - if (getbyte() != 0xff) + if (getbyte(jpeg) != 0xff) return -1; - if ((m = getbyte()) == till) + if ((m = getbyte(jpeg)) == till) break; switch (m) { @@ -194,9 +211,9 @@ static int readtables(int till) return 0; case M_DQT: - lq = getword(); + lq = getword(jpeg); while (lq > 2) { - pq = getbyte(); + pq = getbyte(jpeg); tq = pq & 15; if (tq > 3) return -1; @@ -204,176 +221,160 @@ static int readtables(int till) if (pq != 0) return -1; for (i = 0; i < 64; i++) - quant[tq][i] = getbyte(); + jpeg->quant[tq][i] = getbyte(jpeg); lq -= 64 + 1; } break; case M_DHT: - l = getword(); + l = getword(jpeg); while (l > 2) { int hufflen[16], k; unsigned char huffvals[256]; - tc = getbyte(); + tc = getbyte(jpeg); th = tc & 15; tc >>= 4; tt = tc * 2 + th; if (tc > 1 || th > 1) return -1; for (i = 0; i < 16; i++) - hufflen[i] = getbyte(); + hufflen[i] = getbyte(jpeg); l -= 1 + 16; k = 0; for (i = 0; i < 16; i++) { for (j = 0; j < hufflen[i]; j++) - huffvals[k++] = getbyte(); + huffvals[k++] = getbyte(jpeg); l -= hufflen[i]; } - dec_makehuff(dhuff + tt, hufflen, huffvals); + dec_makehuff(jpeg->dhuff + tt, hufflen, huffvals); } break; case M_DRI: - l = getword(); - info.dri = getword(); + l = getword(jpeg); + jpeg->info.dri = getword(jpeg); break; default: - l = getword(); + l = getword(jpeg); while (l-- > 2) - getbyte(); + getbyte(jpeg); break; } } return 0; } -static void dec_initscans(void) +static void dec_initscans(struct jpeg_decdata *jpeg) { int i; - info.nm = info.dri + 1; - info.rm = M_RST0; - for (i = 0; i < info.ns; i++) - dscans[i].dc = 0; + jpeg->info.nm = jpeg->info.dri + 1; + jpeg->info.rm = M_RST0; + for (i = 0; i < jpeg->info.ns; i++) + jpeg->dscans[i].dc = 0; } -static int dec_checkmarker(void) +static int dec_checkmarker(struct jpeg_decdata *jpeg) { int i; - if (dec_readmarker(&in) != info.rm) + if (dec_readmarker(&jpeg->in) != jpeg->info.rm) return -1; - info.nm = info.dri; - info.rm = (info.rm + 1) & ~0x08; - for (i = 0; i < info.ns; i++) - dscans[i].dc = 0; + jpeg->info.nm = jpeg->info.dri; + jpeg->info.rm = (jpeg->info.rm + 1) & ~0x08; + for (i = 0; i < jpeg->info.ns; i++) + jpeg->dscans[i].dc = 0; return 0; } -int jpeg_check_size(unsigned char *buf, int width, int height) +struct jpeg_decdata *jpeg_alloc(void) { - datap = buf; - getbyte(); - getbyte(); - readtables(M_SOF0); - getword(); - getbyte(); - if (height != getword() || width != getword()) - return 0; - return 1; + struct jpeg_decdata *jpeg = malloc_tmphigh(sizeof(*jpeg)); + return jpeg; } -int jpeg_decode(unsigned char *buf, unsigned char *pic, - int width, int height, int depth, - struct jpeg_decdata *decdata) +int jpeg_decode(struct jpeg_decdata *jpeg, unsigned char *buf) { int i, j, m, tac, tdc; - int mcusx, mcusy, mx, my; - int max[6]; - if (!decdata || !buf || !pic) + if (!jpeg || !buf) return -1; - datap = buf; - if (getbyte() != 0xff) + jpeg->datap = buf; + if (getbyte(jpeg) != 0xff) return ERR_NO_SOI; - if (getbyte() != M_SOI) + if (getbyte(jpeg) != M_SOI) return ERR_NO_SOI; - if (readtables(M_SOF0)) + if (readtables(jpeg, M_SOF0)) return ERR_BAD_TABLES; - getword(); - i = getbyte(); + getword(jpeg); + i = getbyte(jpeg); if (i != 8) return ERR_NOT_8BIT; - if (((getword() + 15) & ~15) != height) - return ERR_HEIGHT_MISMATCH; - if (((getword() + 15) & ~15) != width) - return ERR_WIDTH_MISMATCH; - if ((height & 15) || (width & 15)) + jpeg->height = getword(jpeg); + jpeg->width = getword(jpeg); + if ((jpeg->height & 15) || (jpeg->width & 15)) return ERR_BAD_WIDTH_OR_HEIGHT; - info.nc = getbyte(); - if (info.nc > MAXCOMP) + jpeg->info.nc = getbyte(jpeg); + if (jpeg->info.nc > MAXCOMP) return ERR_TOO_MANY_COMPPS; - for (i = 0; i < info.nc; i++) { + for (i = 0; i < jpeg->info.nc; i++) { int h, v; - comps[i].cid = getbyte(); - comps[i].hv = getbyte(); - v = comps[i].hv & 15; - h = comps[i].hv >> 4; - comps[i].tq = getbyte(); + jpeg->comps[i].cid = getbyte(jpeg); + jpeg->comps[i].hv = getbyte(jpeg); + v = jpeg->comps[i].hv & 15; + h = jpeg->comps[i].hv >> 4; + jpeg->comps[i].tq = getbyte(jpeg); if (h > 3 || v > 3) return ERR_ILLEGAL_HV; - if (comps[i].tq > 3) + if (jpeg->comps[i].tq > 3) return ERR_QUANT_TABLE_SELECTOR; } - if (readtables(M_SOS)) + if (readtables(jpeg, M_SOS)) return ERR_BAD_TABLES; - getword(); - info.ns = getbyte(); - if (info.ns != 3) + getword(jpeg); + jpeg->info.ns = getbyte(jpeg); + if (jpeg->info.ns != 3) return ERR_NOT_YCBCR_221111; for (i = 0; i < 3; i++) { - dscans[i].cid = getbyte(); - tdc = getbyte(); + jpeg->dscans[i].cid = getbyte(jpeg); + tdc = getbyte(jpeg); tac = tdc & 15; tdc >>= 4; if (tdc > 1 || tac > 1) return ERR_QUANT_TABLE_SELECTOR; - for (j = 0; j < info.nc; j++) - if (comps[j].cid == dscans[i].cid) + for (j = 0; j < jpeg->info.nc; j++) + if (jpeg->comps[j].cid == jpeg->dscans[i].cid) break; - if (j == info.nc) + if (j == jpeg->info.nc) return ERR_UNKNOWN_CID_IN_SCAN; - dscans[i].hv = comps[j].hv; - dscans[i].tq = comps[j].tq; - dscans[i].hudc.dhuff = dec_huffdc + tdc; - dscans[i].huac.dhuff = dec_huffac + tac; + jpeg->dscans[i].hv = jpeg->comps[j].hv; + jpeg->dscans[i].tq = jpeg->comps[j].tq; + jpeg->dscans[i].hudc.dhuff = &jpeg->dhuff[tdc]; + jpeg->dscans[i].huac.dhuff = &jpeg->dhuff[2 + tac]; } - i = getbyte(); - j = getbyte(); - m = getbyte(); + i = getbyte(jpeg); + j = getbyte(jpeg); + m = getbyte(jpeg); if (i != 0 || j != 63 || m != 0) return ERR_NOT_SEQUENTIAL_DCT; - if (dscans[0].cid != 1 || dscans[1].cid != 2 || dscans[2].cid != 3) + if (jpeg->dscans[0].cid != 1 || jpeg->dscans[1].cid != 2 + || jpeg->dscans[2].cid != 3) return ERR_NOT_YCBCR_221111; - if (dscans[0].hv != 0x22 || dscans[1].hv != 0x11 - || dscans[2].hv != 0x11) + if (jpeg->dscans[0].hv != 0x22 || jpeg->dscans[1].hv != 0x11 + || jpeg->dscans[2].hv != 0x11) return ERR_NOT_YCBCR_221111; - mcusx = width >> 4; - mcusy = height >> 4; - - - idctqtab(quant[dscans[0].tq], decdata->dquant[0]); - idctqtab(quant[dscans[1].tq], decdata->dquant[1]); - idctqtab(quant[dscans[2].tq], decdata->dquant[2]); - initcol(decdata->dquant); - setinput(&in, datap); + idctqtab(jpeg->quant[jpeg->dscans[0].tq], jpeg->dquant[0]); + idctqtab(jpeg->quant[jpeg->dscans[1].tq], jpeg->dquant[1]); + idctqtab(jpeg->quant[jpeg->dscans[2].tq], jpeg->dquant[2]); + initcol(jpeg->dquant); + setinput(&jpeg->in, jpeg->datap); #if 0 /* landing zone */ @@ -382,46 +383,72 @@ int jpeg_decode(unsigned char *buf, unsigned char *pic, img[len + 2] = M_EOF; #endif - dec_initscans(); + dec_initscans(jpeg); + + return 0; +} + +void jpeg_get_size(struct jpeg_decdata *jpeg, int *width, int *height) +{ + *width = jpeg->width; + *height = jpeg->height; +} + +int jpeg_show(struct jpeg_decdata *jpeg, unsigned char *pic, int width + , int height, int depth, int bytes_per_line_dest) +{ + int m, mcusx, mcusy, mx, my, mloffset, jpgbpl; + int max[6]; + + if (jpeg->height != height) + return ERR_HEIGHT_MISMATCH; + if (jpeg->width != width) + return ERR_WIDTH_MISMATCH; + + jpgbpl = width * depth / 8; + mloffset = bytes_per_line_dest > jpgbpl ? bytes_per_line_dest : jpgbpl; - dscans[0].next = 6 - 4; - dscans[1].next = 6 - 4 - 1; - dscans[2].next = 6 - 4 - 1 - 1; /* 411 encoding */ + mcusx = jpeg->width >> 4; + mcusy = jpeg->height >> 4; + + jpeg->dscans[0].next = 6 - 4; + jpeg->dscans[1].next = 6 - 4 - 1; + jpeg->dscans[2].next = 6 - 4 - 1 - 1; /* 411 encoding */ for (my = 0; my < mcusy; my++) { for (mx = 0; mx < mcusx; mx++) { - if (info.dri && !--info.nm) - if (dec_checkmarker()) + if (jpeg->info.dri && !--jpeg->info.nm) + if (dec_checkmarker(jpeg)) return ERR_WRONG_MARKER; - decode_mcus(&in, decdata->dcts, 6, dscans, max); - idct(decdata->dcts, decdata->out, decdata->dquant[0], + decode_mcus(&jpeg->in, jpeg->dcts, 6, jpeg->dscans, max); + idct(jpeg->dcts, jpeg->out, jpeg->dquant[0], IFIX(128.5), max[0]); - idct(decdata->dcts + 64, decdata->out + 64, decdata->dquant[0], + idct(jpeg->dcts + 64, jpeg->out + 64, jpeg->dquant[0], IFIX(128.5), max[1]); - idct(decdata->dcts + 128, decdata->out + 128, - decdata->dquant[0], IFIX(128.5), max[2]); - idct(decdata->dcts + 192, decdata->out + 192, - decdata->dquant[0], IFIX(128.5), max[3]); - idct(decdata->dcts + 256, decdata->out + 256, - decdata->dquant[1], IFIX(0.5), max[4]); - idct(decdata->dcts + 320, decdata->out + 320, - decdata->dquant[2], IFIX(0.5), max[5]); + idct(jpeg->dcts + 128, jpeg->out + 128, jpeg->dquant[0], + IFIX(128.5), max[2]); + idct(jpeg->dcts + 192, jpeg->out + 192, jpeg->dquant[0], + IFIX(128.5), max[3]); + idct(jpeg->dcts + 256, jpeg->out + 256, jpeg->dquant[1], + IFIX(0.5), max[4]); + idct(jpeg->dcts + 320, jpeg->out + 320, jpeg->dquant[2], + IFIX(0.5), max[5]); switch (depth) { case 32: - col221111_32(decdata->out, - pic + (my * 16 * mcusx + mx) * 16 * 4, - mcusx * 16 * 4); + col221111_32(jpeg->out, + pic + (my * 16 * mloffset + mx * 16 * 4), + mloffset); break; case 24: - col221111(decdata->out, - pic + (my * 16 * mcusx + mx) * 16 * 3, - mcusx * 16 * 3); + col221111(jpeg->out, + pic + (my * 16 * mloffset + mx * 16 * 3), + mloffset); break; case 16: - col221111_16(decdata->out, - pic + (my * 16 * mcusx + mx) * (16 * 2), - mcusx * (16 * 2)); + col221111_16(jpeg->out, + pic + (my * 16 * mloffset + mx * 16 * 2), + mloffset); break; default: return ERR_DEPTH_MISMATCH; @@ -430,7 +457,7 @@ int jpeg_decode(unsigned char *buf, unsigned char *pic, } } - m = dec_readmarker(&in); + m = dec_readmarker(&jpeg->in); if (m != M_EOI) return ERR_NO_EOI; @@ -442,8 +469,7 @@ int jpeg_decode(unsigned char *buf, unsigned char *pic, /****************************************************************/ static int fillbits __P((struct in *, int, unsigned int)); -static int dec_rec2 -__P((struct in *, struct dec_hufftbl *, int *, int, int)); +static int dec_rec2 __P((struct in *, struct dec_hufftbl *, int *, int, int)); static void setinput(struct in *in, unsigned char *p) { @@ -696,7 +722,7 @@ static unsigned char zig2[64] = { 6, 13, 17, 24, 32, 38, 47, 49 }; -void idct(int *in, int *out, PREC * quant, PREC off, int max) +static void idct(int *in, int *out, PREC * quant, PREC off, int max) { PREC t0, t1, t2, t3, t4, t5, t6, t7, t; PREC tmp[64], *tmpp; @@ -864,6 +890,15 @@ static void initcol(PREC q[][64]) #endif +#ifdef __LITTLE_ENDIAN +#define PIC(yin, xin, p, xout) \ +( \ + y = outy[(yin) * 8 + xin], \ + STORECLAMP(p[(xout) * 3 + 2], y + cr), \ + STORECLAMP(p[(xout) * 3 + 1], y - cg), \ + STORECLAMP(p[(xout) * 3 + 0], y + cb) \ +) +#else #define PIC(yin, xin, p, xout) \ ( \ y = outy[(yin) * 8 + xin], \ @@ -871,6 +906,7 @@ static void initcol(PREC q[][64]) STORECLAMP(p[(xout) * 3 + 1], y - cg), \ STORECLAMP(p[(xout) * 3 + 2], y + cb) \ ) +#endif #ifdef __LITTLE_ENDIAN #define PIC_16(yin, xin, p, xout, add) \