| /*************************************************************************** |
| * __________ __ ___. |
| * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| * \/ \/ \/ \/ \/ |
| * $Id$ |
| * |
| * JPEG image viewer |
| * (This is a real mess if it has to be coded in one single C file) |
| * |
| * Copyright (C) 2009 Andrew Mahone fractional decode, split IDCT - 16-point |
| * IDCT based on IJG jpeg-7 pre-release |
| * File scrolling addition (C) 2005 Alexander Spyridakis |
| * Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon |
| * Heavily borrowed from the IJG implementation (C) Thomas G. Lane |
| * Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| ****************************************************************************/ |
| |
| #include "plugin.h" |
| #include "debug.h" |
| #include "jpeg_load.h" |
| /*#define JPEG_BS_DEBUG*/ |
| //#define ROCKBOX_DEBUG_JPEG |
| /* for portability of below JPEG code */ |
| #define MEMSET(p,v,c) memset(p,v,c) |
| #define MEMCPY(d,s,c) memcpy(d,s,c) |
| #define INLINE static inline |
| #define ENDIAN_SWAP16(n) n /* only for poor little endian machines */ |
| #ifdef ROCKBOX_DEBUG_JPEG |
| #define JDEBUGF DEBUGF |
| #else |
| #define JDEBUGF(...) |
| #endif |
| |
| /**************** begin JPEG code ********************/ |
| |
| #ifdef HAVE_LCD_COLOR |
| typedef struct uint8_rgb jpeg_pix_t; |
| #else |
| typedef uint8_t jpeg_pix_t; |
| #endif |
| #define JPEG_IDCT_TRANSPOSE |
| #define JPEG_PIX_SZ (sizeof(jpeg_pix_t)) |
| #ifdef HAVE_LCD_COLOR |
| #define COLOR_EXTRA_IDCT_WS 64 |
| #else |
| #define COLOR_EXTRA_IDCT_WS 0 |
| #endif |
| #ifdef JPEG_IDCT_TRANSPOSE |
| #define V_OUT(n) ws2[8*n] |
| #define V_IN_ST 1 |
| #define TRANSPOSE_EXTRA_IDCT_WS 64 |
| #else |
| #define V_OUT(n) ws[8*n] |
| #define V_IN_ST 8 |
| #define TRANSPOSE_EXTRA_IDCT_WS 0 |
| #endif |
| #define IDCT_WS_SIZE (64 + TRANSPOSE_EXTRA_IDCT_WS + COLOR_EXTRA_IDCT_WS) |
| |
| /* This can't be in jpeg_load.h because plugin.h includes it, and it conflicts |
| * with the definition in jpeg_decoder.h |
| */ |
| struct jpeg |
| { |
| #ifdef JPEG_FROM_MEM |
| unsigned char *data; |
| #else |
| int fd; |
| int buf_left; |
| int buf_index; |
| #endif |
| unsigned long len; |
| unsigned long int bitbuf; |
| int bitbuf_bits; |
| int marker_ind; |
| int marker_val; |
| unsigned char marker; |
| int x_size, y_size; /* size of image (can be less than block boundary) */ |
| int x_phys, y_phys; /* physical size, block aligned */ |
| int x_mbl; /* x dimension of MBL */ |
| int y_mbl; /* y dimension of MBL */ |
| int blocks; /* blocks per MB */ |
| int restart_interval; /* number of MCUs between RSTm markers */ |
| int restart; /* blocks until next restart marker */ |
| int mcu_row; /* current row relative to first row of this row of MCUs */ |
| unsigned char *out_ptr; /* pointer to current row to output */ |
| int cur_row; /* current row relative to top of image */ |
| int set_rows; |
| int store_pos[4]; /* for Y block ordering */ |
| #ifdef HAVE_LCD_COLOR |
| int last_dc_val[3]; |
| int h_scale[2]; /* horizontal scalefactor = (2**N) / 8 */ |
| int v_scale[2]; /* same as above, for vertical direction */ |
| int k_need[2]; /* per component zig-zag index of last needed coefficient */ |
| int zero_need[2]; /* per compenent number of coefficients to zero */ |
| #else |
| int last_dc_val; |
| int h_scale[1]; /* horizontal scalefactor = (2**N) / 8 */ |
| int v_scale[1]; /* same as above, for vertical direction */ |
| int k_need[1]; /* per component zig-zag index of last needed coefficient */ |
| int zero_need[1]; /* per compenent number of coefficients to zero */ |
| #endif |
| jpeg_pix_t *img_buf; |
| |
| int16_t quanttable[4][QUANT_TABLE_LENGTH];/* raw quantization tables 0-3 */ |
| |
| struct huffman_table hufftable[2]; /* Huffman tables */ |
| struct derived_tbl dc_derived_tbls[2]; /* Huffman-LUTs */ |
| struct derived_tbl ac_derived_tbls[2]; |
| |
| struct frame_component frameheader[3]; /* Component descriptor */ |
| struct scan_component scanheader[3]; /* currently not used */ |
| |
| int mcu_membership[6]; /* info per block */ |
| int tab_membership[6]; |
| int subsample_x[3]; /* info per component */ |
| int subsample_y[3]; |
| bool resize; |
| unsigned char buf[JPEG_READ_BUF_SIZE]; |
| struct img_part part; |
| }; |
| |
| #ifdef JPEG_FROM_MEM |
| static struct jpeg jpeg; |
| #endif |
| |
| INLINE unsigned range_limit(int value) |
| { |
| #if CONFIG_CPU == SH7034 |
| unsigned tmp; |
| asm ( /* Note: Uses knowledge that only low byte of result is used */ |
| "extu.b %[v],%[t] \n" |
| "cmp/eq %[v],%[t] \n" /* low byte == whole number ? */ |
| "bt 1f \n" /* yes: no overflow */ |
| "cmp/pz %[v] \n" /* overflow: positive? */ |
| "subc %[v],%[v] \n" /* %[r] now either 0 or 0xffffffff */ |
| "1: \n" |
| : /* outputs */ |
| [v]"+r"(value), |
| [t]"=&r"(tmp) |
| ); |
| return value; |
| #elif defined(CPU_COLDFIRE) |
| /* Note: Uses knowledge that only the low byte of the result is used */ |
| asm ( |
| "cmp.l #255,%[v] \n" /* overflow? */ |
| "bls.b 1f \n" /* no: return value */ |
| /* yes: set low byte to appropriate boundary */ |
| "spl.b %[v] \n" |
| "1: \n" |
| : /* outputs */ |
| [v]"+d"(value) |
| ); |
| return value; |
| #elif defined(CPU_ARM) |
| /* Note: Uses knowledge that only the low byte of the result is used */ |
| asm ( |
| "cmp %[v], #255 \n" /* out of range 0..255? */ |
| "mvnhi %[v], %[v], asr #31 \n" /* yes: set all bits to ~(sign_bit) */ |
| : /* outputs */ |
| [v]"+r"(value) |
| ); |
| return value; |
| #else |
| if ((unsigned)value <= 255) |
| return value; |
| |
| if (value < 0) |
| return 0; |
| |
| return 255; |
| #endif |
| } |
| |
| INLINE unsigned scale_output(int value) |
| { |
| #if defined(CPU_ARM) && ARM_ARCH >= 6 |
| asm ( |
| "usat %[v], #8, %[v], asr #18\n" |
| : [v] "+r" (value) |
| ); |
| return value; |
| #else |
| return range_limit(value >> 18); |
| #endif |
| } |
| |
| /* IDCT implementation */ |
| |
| |
| #define CONST_BITS 13 |
| #define PASS1_BITS 2 |
| |
| |
| /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus |
| * causing a lot of useless floating-point operations at run time. |
| * To get around this we use the following pre-calculated constants. |
| * If you change CONST_BITS you may want to add appropriate values. |
| * (With a reasonable C compiler, you can just rely on the FIX() macro...) |
| */ |
| #define FIX_0_298631336 2446 /* FIX(0.298631336) */ |
| #define FIX_0_390180644 3196 /* FIX(0.390180644) */ |
| #define FIX_0_541196100 4433 /* FIX(0.541196100) */ |
| #define FIX_0_765366865 6270 /* FIX(0.765366865) */ |
| #define FIX_0_899976223 7373 /* FIX(0.899976223) */ |
| #define FIX_1_175875602 9633 /* FIX(1.175875602) */ |
| #define FIX_1_501321110 12299 /* FIX(1.501321110) */ |
| #define FIX_1_847759065 15137 /* FIX(1.847759065) */ |
| #define FIX_1_961570560 16069 /* FIX(1.961570560) */ |
| #define FIX_2_053119869 16819 /* FIX(2.053119869) */ |
| #define FIX_2_562915447 20995 /* FIX(2.562915447) */ |
| #define FIX_3_072711026 25172 /* FIX(3.072711026) */ |
| |
| |
| |
| /* Multiply an long variable by an long constant to yield an long result. |
| * For 8-bit samples with the recommended scaling, all the variable |
| * and constant values involved are no more than 16 bits wide, so a |
| * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. |
| * For 12-bit samples, a full 32-bit multiplication will be needed. |
| */ |
| #define MULTIPLY(var1, var2) ((var1) * (var2)) |
| |
| #if defined(CPU_SH) || defined(CPU_COLDFIRE) || \ |
| (defined(CPU_ARM) && ARM_ARCH > 4) |
| #define MULTIPLY16(var,const) (((short) (var)) * ((short) (const))) |
| #else |
| #define MULTIPLY16 MULTIPLY |
| #endif |
| |
| /* |
| * Macros for handling fixed-point arithmetic; these are used by many |
| * but not all of the DCT/IDCT modules. |
| * |
| * All values are expected to be of type INT32. |
| * Fractional constants are scaled left by CONST_BITS bits. |
| * CONST_BITS is defined within each module using these macros, |
| * and may differ from one module to the next. |
| */ |
| #define ONE ((long)1) |
| #define CONST_SCALE (ONE << CONST_BITS) |
| |
| /* Convert a positive real constant to an integer scaled by CONST_SCALE. |
| * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, |
| * thus causing a lot of useless floating-point operations at run time. |
| */ |
| #define FIX(x) ((long) ((x) * CONST_SCALE + 0.5)) |
| #define RIGHT_SHIFT(x,shft) ((x) >> (shft)) |
| |
| /* Descale and correctly round an int value that's scaled by N bits. |
| * We assume RIGHT_SHIFT rounds towards minus infinity, so adding |
| * the fudge factor is correct for either sign of X. |
| */ |
| #define DESCALE(x,n) (((x) + (1l << ((n)-1))) >> (n)) |
| |
| #define DS_OUT ((CONST_BITS)+(PASS1_BITS)+3) |
| |
| /* |
| * Conversion of full 0-255 range YCrCb to RGB: |
| * |R| |1.000000 -0.000001 1.402000| |Y'| |
| * |G| = |1.000000 -0.334136 -0.714136| |Pb| |
| * |B| |1.000000 1.772000 0.000000| |Pr| |
| * Scaled (yields s15-bit output): |
| * |R| |128 0 179| |Y | |
| * |G| = |128 -43 -91| |Cb - 128| |
| * |B| |128 227 0| |Cr - 128| |
| */ |
| #define YFAC 128 |
| #define RVFAC 179 |
| #define GUFAC (-43) |
| #define GVFAC (-91) |
| #define BUFAC 227 |
| #define COMPONENT_SHIFT 15 |
| |
| #ifndef CPU_ARM |
| /* horizontal-pass 1-point IDCT */ |
| static void jpeg_idct1h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep) |
| { |
| for (; ws < end; ws += 8) |
| { |
| *out = range_limit(128 + (int) DESCALE(*ws, 3 + PASS1_BITS)); |
| out += rowstep; |
| } |
| } |
| |
| /* vertical-pass 2-point IDCT */ |
| static void jpeg_idct2v(int16_t *ws, int16_t *end) |
| { |
| for (; ws < end; ws++) |
| { |
| int tmp1 = ws[0*8]; |
| int tmp2 = ws[1*8]; |
| ws[0*8] = tmp1 + tmp2; |
| ws[1*8] = tmp1 - tmp2; |
| } |
| } |
| |
| /* horizontal-pass 2-point IDCT */ |
| static void jpeg_idct2h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep) |
| { |
| for (; ws < end; ws += 8, out += rowstep) |
| { |
| int tmp1 = ws[0] + (ONE << (PASS1_BITS + 2)) |
| + (128 << (PASS1_BITS + 3)); |
| int tmp2 = ws[1]; |
| out[JPEG_PIX_SZ*0] = range_limit((int) RIGHT_SHIFT(tmp1 + tmp2, |
| PASS1_BITS + 3)); |
| out[JPEG_PIX_SZ*1] = range_limit((int) RIGHT_SHIFT(tmp1 - tmp2, |
| PASS1_BITS + 3)); |
| } |
| } |
| |
| /* vertical-pass 4-point IDCT */ |
| static void jpeg_idct4v(int16_t *ws, int16_t *end) |
| { |
| for (; ws < end; ws++) |
| { |
| int tmp0, tmp2, tmp10, tmp12; |
| int z1, z2, z3; |
| /* Even part */ |
| |
| tmp0 = ws[8*0]; |
| tmp2 = ws[8*2]; |
| |
| tmp10 = (tmp0 + tmp2) << PASS1_BITS; |
| tmp12 = (tmp0 - tmp2) << PASS1_BITS; |
| |
| /* Odd part */ |
| /* Same rotation as in the even part of the 8x8 LL&M IDCT */ |
| |
| z2 = ws[8*1]; |
| z3 = ws[8*3]; |
| |
| z1 = MULTIPLY16(z2 + z3, FIX_0_541196100) + |
| (ONE << (CONST_BITS - PASS1_BITS - 1)); |
| tmp0 = RIGHT_SHIFT(z1 + MULTIPLY16(z3, - FIX_1_847759065), |
| CONST_BITS-PASS1_BITS); |
| tmp2 = RIGHT_SHIFT(z1 + MULTIPLY16(z2, FIX_0_765366865), |
| CONST_BITS-PASS1_BITS); |
| |
| /* Final output stage */ |
| ws[8*0] = (int) (tmp10 + tmp2); |
| ws[8*3] = (int) (tmp10 - tmp2); |
| ws[8*1] = (int) (tmp12 + tmp0); |
| ws[8*2] = (int) (tmp12 - tmp0); |
| } |
| } |
| |
| /* horizontal-pass 4-point IDCT */ |
| static void jpeg_idct4h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep) |
| { |
| for (; ws < end; out += rowstep, ws += 8) |
| { |
| int tmp0, tmp2, tmp10, tmp12; |
| int z1, z2, z3; |
| /* Even part */ |
| |
| tmp0 = (int) ws[0] + (ONE << (PASS1_BITS + 2)) |
| + (128 << (PASS1_BITS + 3)); |
| tmp2 = (int) ws[2]; |
| |
| tmp10 = (tmp0 + tmp2) << CONST_BITS; |
| tmp12 = (tmp0 - tmp2) << CONST_BITS; |
| |
| /* Odd part */ |
| /* Same rotation as in the even part of the 8x8 LL&M IDCT */ |
| |
| z2 = (int) ws[1]; |
| z3 = (int) ws[3]; |
| |
| z1 = MULTIPLY16(z2 + z3, FIX_0_541196100); |
| tmp0 = z1 - MULTIPLY16(z3, FIX_1_847759065); |
| tmp2 = z1 + MULTIPLY16(z2, FIX_0_765366865); |
| |
| /* Final output stage */ |
| |
| out[JPEG_PIX_SZ*0] = range_limit((int) RIGHT_SHIFT(tmp10 + tmp2, |
| DS_OUT)); |
| out[JPEG_PIX_SZ*3] = range_limit((int) RIGHT_SHIFT(tmp10 - tmp2, |
| DS_OUT)); |
| out[JPEG_PIX_SZ*1] = range_limit((int) RIGHT_SHIFT(tmp12 + tmp0, |
| DS_OUT)); |
| out[JPEG_PIX_SZ*2] = range_limit((int) RIGHT_SHIFT(tmp12 - tmp0, |
| DS_OUT)); |
| } |
| } |
| |
| /* vertical-pass 8-point IDCT */ |
| static void jpeg_idct8v(int16_t *ws, int16_t *end) |
| { |
| long tmp0, tmp1, tmp2, tmp3; |
| long tmp10, tmp11, tmp12, tmp13; |
| long z1, z2, z3, z4, z5; |
| #ifdef JPEG_IDCT_TRANSPOSE |
| int16_t *ws2 = ws + 64; |
| for (; ws < end; ws += 8, ws2++) |
| { |
| #else |
| for (; ws < end; ws++) |
| { |
| #endif |
| /* Due to quantization, we will usually find that many of the input |
| * coefficients are zero, especially the AC terms. We can exploit this |
| * by short-circuiting the IDCT calculation for any column in which all |
| * the AC terms are zero. In that case each output is equal to the |
| * DC coefficient (with scale factor as needed). |
| * With typical images and quantization tables, half or more of the |
| * column DCT calculations can be simplified this way. |
| */ |
| if ((ws[V_IN_ST*1] | ws[V_IN_ST*2] | ws[V_IN_ST*3] |
| | ws[V_IN_ST*4] | ws[V_IN_ST*5] | ws[V_IN_ST*6] | ws[V_IN_ST*7]) == 0) |
| { |
| /* AC terms all zero */ |
| int dcval = ws[V_IN_ST*0] << PASS1_BITS; |
| |
| V_OUT(0) = V_OUT(1) = V_OUT(2) = V_OUT(3) = V_OUT(4) = V_OUT(5) = |
| V_OUT(6) = V_OUT(7) = dcval; |
| continue; |
| } |
| |
| /* Even part: reverse the even part of the forward DCT. */ |
| /* The rotator is sqrt(2)*c(-6). */ |
| |
| z2 = ws[V_IN_ST*2]; |
| z3 = ws[V_IN_ST*6]; |
| |
| z1 = MULTIPLY16(z2 + z3, FIX_0_541196100); |
| tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065); |
| tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865); |
| |
| z2 = ws[V_IN_ST*0] << CONST_BITS; |
| z2 += ONE << (CONST_BITS - PASS1_BITS - 1); |
| z3 = ws[V_IN_ST*4] << CONST_BITS; |
| |
| tmp0 = (z2 + z3); |
| tmp1 = (z2 - z3); |
| |
| tmp10 = tmp0 + tmp3; |
| tmp13 = tmp0 - tmp3; |
| tmp11 = tmp1 + tmp2; |
| tmp12 = tmp1 - tmp2; |
| |
| /* Odd part per figure 8; the matrix is unitary and hence its |
| transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ |
| |
| tmp0 = ws[V_IN_ST*7]; |
| tmp1 = ws[V_IN_ST*5]; |
| tmp2 = ws[V_IN_ST*3]; |
| tmp3 = ws[V_IN_ST*1]; |
| |
| z1 = tmp0 + tmp3; |
| z2 = tmp1 + tmp2; |
| z3 = tmp0 + tmp2; |
| z4 = tmp1 + tmp3; |
| z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ |
| |
| tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ |
| tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ |
| tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ |
| tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ |
| z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ |
| z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ |
| z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ |
| z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ |
| |
| z3 += z5; |
| z4 += z5; |
| |
| tmp0 += z1 + z3; |
| tmp1 += z2 + z4; |
| tmp2 += z2 + z3; |
| tmp3 += z1 + z4; |
| |
| /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ |
| |
| V_OUT(0) = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); |
| V_OUT(7) = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); |
| V_OUT(1) = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); |
| V_OUT(6) = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); |
| V_OUT(2) = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); |
| V_OUT(5) = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); |
| V_OUT(3) = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); |
| V_OUT(4) = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); |
| } |
| } |
| |
| /* horizontal-pass 8-point IDCT */ |
| static void jpeg_idct8h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep) |
| { |
| long tmp0, tmp1, tmp2, tmp3; |
| long tmp10, tmp11, tmp12, tmp13; |
| long z1, z2, z3, z4, z5; |
| for (; ws < end; out += rowstep, ws += 8) |
| { |
| /* Rows of zeroes can be exploited in the same way as we did with |
| * columns. However, the column calculation has created many nonzero AC |
| * terms, so the simplification applies less often (typically 5% to 10% |
| * of the time). On machines with very fast multiplication, it's |
| * possible that the test takes more time than it's worth. In that |
| * case this section may be commented out. |
| */ |
| |
| #ifndef NO_ZERO_ROW_TEST |
| if ((ws[1] | ws[2] | ws[3] |
| | ws[4] | ws[5] | ws[6] | ws[7]) == 0) |
| { |
| /* AC terms all zero */ |
| unsigned char dcval = range_limit(128 + (int) DESCALE((long) ws[0], |
| PASS1_BITS+3)); |
| |
| out[JPEG_PIX_SZ*0] = dcval; |
| out[JPEG_PIX_SZ*1] = dcval; |
| out[JPEG_PIX_SZ*2] = dcval; |
| out[JPEG_PIX_SZ*3] = dcval; |
| out[JPEG_PIX_SZ*4] = dcval; |
| out[JPEG_PIX_SZ*5] = dcval; |
| out[JPEG_PIX_SZ*6] = dcval; |
| out[JPEG_PIX_SZ*7] = dcval; |
| continue; |
| } |
| #endif |
| |
| /* Even part: reverse the even part of the forward DCT. */ |
| /* The rotator is sqrt(2)*c(-6). */ |
| |
| z2 = (long) ws[2]; |
| z3 = (long) ws[6]; |
| |
| z1 = MULTIPLY16(z2 + z3, FIX_0_541196100); |
| tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065); |
| tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865); |
| |
| z4 = (long) ws[0] + (ONE << (PASS1_BITS + 2)) |
| + (128 << (PASS1_BITS + 3)); |
| z4 <<= CONST_BITS; |
| z5 = (long) ws[4] << CONST_BITS; |
| tmp0 = z4 + z5; |
| tmp1 = z4 - z5; |
| |
| tmp10 = tmp0 + tmp3; |
| tmp13 = tmp0 - tmp3; |
| tmp11 = tmp1 + tmp2; |
| tmp12 = tmp1 - tmp2; |
| |
| /* Odd part per figure 8; the matrix is unitary and hence its |
| * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ |
| |
| tmp0 = (long) ws[7]; |
| tmp1 = (long) ws[5]; |
| tmp2 = (long) ws[3]; |
| tmp3 = (long) ws[1]; |
| |
| z1 = tmp0 + tmp3; |
| z2 = tmp1 + tmp2; |
| z3 = tmp0 + tmp2; |
| z4 = tmp1 + tmp3; |
| z5 = MULTIPLY16(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ |
| |
| tmp0 = MULTIPLY16(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ |
| tmp1 = MULTIPLY16(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ |
| tmp2 = MULTIPLY16(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ |
| tmp3 = MULTIPLY16(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ |
| z1 = MULTIPLY16(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ |
| z2 = MULTIPLY16(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ |
| z3 = MULTIPLY16(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ |
| z4 = MULTIPLY16(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ |
| |
| z3 += z5; |
| z4 += z5; |
| |
| tmp0 += z1 + z3; |
| tmp1 += z2 + z4; |
| tmp2 += z2 + z3; |
| tmp3 += z1 + z4; |
| |
| /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ |
| |
| out[JPEG_PIX_SZ*0] = range_limit((int) RIGHT_SHIFT(tmp10 + tmp3, |
| DS_OUT)); |
| out[JPEG_PIX_SZ*7] = range_limit((int) RIGHT_SHIFT(tmp10 - tmp3, |
| DS_OUT)); |
| out[JPEG_PIX_SZ*1] = range_limit((int) RIGHT_SHIFT(tmp11 + tmp2, |
| DS_OUT)); |
| out[JPEG_PIX_SZ*6] = range_limit((int) RIGHT_SHIFT(tmp11 - tmp2, |
| DS_OUT)); |
| out[JPEG_PIX_SZ*2] = range_limit((int) RIGHT_SHIFT(tmp12 + tmp1, |
| DS_OUT)); |
| out[JPEG_PIX_SZ*5] = range_limit((int) RIGHT_SHIFT(tmp12 - tmp1, |
| DS_OUT)); |
| out[JPEG_PIX_SZ*3] = range_limit((int) RIGHT_SHIFT(tmp13 + tmp0, |
| DS_OUT)); |
| out[JPEG_PIX_SZ*4] = range_limit((int) RIGHT_SHIFT(tmp13 - tmp0, |
| DS_OUT)); |
| } |
| } |
| |
| #else |
| extern void jpeg_idct1h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep); |
| extern void jpeg_idct2v(int16_t *ws, int16_t *end); |
| extern void jpeg_idct2h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep); |
| extern void jpeg_idct4v(int16_t *ws, int16_t *end); |
| extern void jpeg_idct4h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep); |
| extern void jpeg_idct8v(int16_t *ws, int16_t *end); |
| extern void jpeg_idct8h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep); |
| #endif |
| |
| #ifdef HAVE_LCD_COLOR |
| /* vertical-pass 16-point IDCT */ |
| static void jpeg_idct16v(int16_t *ws, int16_t *end) |
| { |
| long tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; |
| long tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; |
| long z1, z2, z3, z4; |
| #ifdef JPEG_IDCT_TRANSPOSE |
| int16_t *ws2 = ws + 64; |
| for (; ws < end; ws += 8, ws2++) |
| { |
| #else |
| for (; ws < end; ws++) |
| { |
| #endif |
| /* Even part */ |
| |
| tmp0 = ws[V_IN_ST*0] << CONST_BITS; |
| /* Add fudge factor here for final descale. */ |
| tmp0 += 1 << (CONST_BITS-PASS1_BITS-1); |
| |
| z1 = ws[V_IN_ST*4]; |
| tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ |
| tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ |
| |
| tmp10 = tmp0 + tmp1; |
| tmp11 = tmp0 - tmp1; |
| tmp12 = tmp0 + tmp2; |
| tmp13 = tmp0 - tmp2; |
| |
| z1 = ws[V_IN_ST*2]; |
| z2 = ws[V_IN_ST*6]; |
| z3 = z1 - z2; |
| z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ |
| z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ |
| |
| /* (c6+c2)[16] = (c3+c1)[8] */ |
| tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); |
| /* (c6-c14)[16] = (c3-c7)[8] */ |
| tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); |
| /* (c2-c10)[16] = (c1-c5)[8] */ |
| tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); |
| /* (c10-c14)[16] = (c5-c7)[8] */ |
| tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); |
| |
| tmp20 = tmp10 + tmp0; |
| tmp27 = tmp10 - tmp0; |
| tmp21 = tmp12 + tmp1; |
| tmp26 = tmp12 - tmp1; |
| tmp22 = tmp13 + tmp2; |
| tmp25 = tmp13 - tmp2; |
| tmp23 = tmp11 + tmp3; |
| tmp24 = tmp11 - tmp3; |
| |
| /* Odd part */ |
| |
| z1 = ws[V_IN_ST*1]; |
| z2 = ws[V_IN_ST*3]; |
| z3 = ws[V_IN_ST*5]; |
| z4 = ws[V_IN_ST*7]; |
| |
| tmp11 = z1 + z3; |
| |
| tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ |
| tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ |
| tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ |
| tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ |
| tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ |
| tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ |
| tmp0 = tmp1 + tmp2 + tmp3 - |
| MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ |
| tmp13 = tmp10 + tmp11 + tmp12 - |
| MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ |
| z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ |
| tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ |
| tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ |
| z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ |
| tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ |
| tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ |
| z2 += z4; |
| z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ |
| tmp1 += z1; |
| tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ |
| z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ |
| tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ |
| tmp12 += z2; |
| z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ |
| tmp2 += z2; |
| tmp3 += z2; |
| z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ |
| tmp10 += z2; |
| tmp11 += z2; |
| |
| /* Final output stage */ |
| V_OUT(0) = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS); |
| V_OUT(15) = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS); |
| V_OUT(1) = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS); |
| V_OUT(14) = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS); |
| V_OUT(2) = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS); |
| V_OUT(13) = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS); |
| V_OUT(3) = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS); |
| V_OUT(12) = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS); |
| V_OUT(4) = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS); |
| V_OUT(11) = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS); |
| V_OUT(5) = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS); |
| V_OUT(10) = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS); |
| V_OUT(6) = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS); |
| V_OUT(9) = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS); |
| V_OUT(7) = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS); |
| V_OUT(8) = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS); |
| } |
| } |
| |
| /* horizontal-pass 16-point IDCT */ |
| static void jpeg_idct16h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep) |
| { |
| long tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; |
| long tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; |
| long z1, z2, z3, z4; |
| for (; ws < end; out += rowstep, ws += 8) |
| { |
| /* Even part */ |
| |
| /* Add fudge factor here for final descale. */ |
| tmp0 = (long) ws[0] + (ONE << (PASS1_BITS+2)) |
| + (128 << (PASS1_BITS + 3)); |
| tmp0 <<= CONST_BITS; |
| |
| z1 = (long) ws[4]; |
| tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ |
| tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ |
| |
| tmp10 = tmp0 + tmp1; |
| tmp11 = tmp0 - tmp1; |
| tmp12 = tmp0 + tmp2; |
| tmp13 = tmp0 - tmp2; |
| |
| z1 = (long) ws[2]; |
| z2 = (long) ws[6]; |
| z3 = z1 - z2; |
| z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ |
| z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ |
| |
| /* (c6+c2)[16] = (c3+c1)[8] */ |
| tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); |
| /* (c6-c14)[16] = (c3-c7)[8] */ |
| tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); |
| /* (c2-c10)[16] = (c1-c5)[8] */ |
| tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); |
| /* (c10-c14)[16] = (c5-c7)[8] */ |
| tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); |
| |
| tmp20 = tmp10 + tmp0; |
| tmp27 = tmp10 - tmp0; |
| tmp21 = tmp12 + tmp1; |
| tmp26 = tmp12 - tmp1; |
| tmp22 = tmp13 + tmp2; |
| tmp25 = tmp13 - tmp2; |
| tmp23 = tmp11 + tmp3; |
| tmp24 = tmp11 - tmp3; |
| |
| /* Odd part */ |
| |
| z1 = (long) ws[1]; |
| z2 = (long) ws[3]; |
| z3 = (long) ws[5]; |
| z4 = (long) ws[7]; |
| |
| tmp11 = z1 + z3; |
| |
| tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ |
| tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ |
| tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ |
| tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ |
| tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ |
| tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ |
| tmp0 = tmp1 + tmp2 + tmp3 - |
| MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ |
| tmp13 = tmp10 + tmp11 + tmp12 - |
| MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ |
| z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ |
| tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ |
| tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ |
| z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ |
| tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ |
| tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ |
| z2 += z4; |
| z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ |
| tmp1 += z1; |
| tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ |
| z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ |
| tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ |
| tmp12 += z2; |
| z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ |
| tmp2 += z2; |
| tmp3 += z2; |
| z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ |
| tmp10 += z2; |
| tmp11 += z2; |
| |
| /* Final output stage */ |
| |
| out[JPEG_PIX_SZ*0] = scale_output(tmp20 + tmp0); |
| out[JPEG_PIX_SZ*15] = scale_output(tmp20 - tmp0); |
| out[JPEG_PIX_SZ*1] = scale_output(tmp21 + tmp1); |
| out[JPEG_PIX_SZ*14] = scale_output(tmp21 - tmp1); |
| out[JPEG_PIX_SZ*2] = scale_output(tmp22 + tmp2); |
| out[JPEG_PIX_SZ*13] = scale_output(tmp22 - tmp2); |
| out[JPEG_PIX_SZ*3] = scale_output(tmp23 + tmp3); |
| out[JPEG_PIX_SZ*12] = scale_output(tmp23 - tmp3); |
| out[JPEG_PIX_SZ*4] = scale_output(tmp24 + tmp10); |
| out[JPEG_PIX_SZ*11] = scale_output(tmp24 - tmp10); |
| out[JPEG_PIX_SZ*5] = scale_output(tmp25 + tmp11); |
| out[JPEG_PIX_SZ*10] = scale_output(tmp25 - tmp11); |
| out[JPEG_PIX_SZ*6] = scale_output(tmp26 + tmp12); |
| out[JPEG_PIX_SZ*9] = scale_output(tmp26 - tmp12); |
| out[JPEG_PIX_SZ*7] = scale_output(tmp27 + tmp13); |
| out[JPEG_PIX_SZ*8] = scale_output(tmp27 - tmp13); |
| } |
| } |
| #endif |
| |
| struct idct_entry { |
| int scale; |
| void (*v_idct)(int16_t *ws, int16_t *end); |
| void (*h_idct)(int16_t *ws, unsigned char *out, int16_t *end, int rowstep); |
| }; |
| |
| static const struct idct_entry idct_tbl[] = { |
| { PASS1_BITS, NULL, jpeg_idct1h }, |
| { PASS1_BITS, jpeg_idct2v, jpeg_idct2h }, |
| { 0, jpeg_idct4v, jpeg_idct4h }, |
| { 0, jpeg_idct8v, jpeg_idct8h }, |
| #ifdef HAVE_LCD_COLOR |
| { 0, jpeg_idct16v, jpeg_idct16h }, |
| #endif |
| }; |
| |
| /* JPEG decoder implementation */ |
| |
| #ifdef JPEG_FROM_MEM |
| INLINE unsigned char *jpeg_getc(struct jpeg* p_jpeg) |
| { |
| if (LIKELY(p_jpeg->len)) |
| { |
| p_jpeg->len--; |
| return p_jpeg->data++; |
| } else |
| return NULL; |
| } |
| |
| INLINE bool skip_bytes(struct jpeg* p_jpeg, int count) |
| { |
| if (p_jpeg->len >= (unsigned)count) |
| { |
| p_jpeg->len -= count; |
| p_jpeg->data += count; |
| return true; |
| } else { |
| p_jpeg->data += p_jpeg->len; |
| p_jpeg->len = 0; |
| return false; |
| } |
| } |
| |
| INLINE void jpeg_putc(struct jpeg* p_jpeg) |
| { |
| p_jpeg->len++; |
| p_jpeg->data--; |
| } |
| #else |
| INLINE void fill_buf(struct jpeg* p_jpeg) |
| { |
| p_jpeg->buf_left = read(p_jpeg->fd, p_jpeg->buf, |
| (p_jpeg->len >= JPEG_READ_BUF_SIZE)? |
| JPEG_READ_BUF_SIZE : p_jpeg->len); |
| p_jpeg->buf_index = 0; |
| if (p_jpeg->buf_left > 0) |
| p_jpeg->len -= p_jpeg->buf_left; |
| } |
| |
| static unsigned char *jpeg_getc(struct jpeg* p_jpeg) |
| { |
| if (UNLIKELY(p_jpeg->buf_left < 1)) |
| fill_buf(p_jpeg); |
| if (UNLIKELY(p_jpeg->buf_left < 1)) |
| return NULL; |
| p_jpeg->buf_left--; |
| return (p_jpeg->buf_index++) + p_jpeg->buf; |
| } |
| |
| INLINE bool skip_bytes_seek(struct jpeg* p_jpeg) |
| { |
| if (UNLIKELY(lseek(p_jpeg->fd, -p_jpeg->buf_left, SEEK_CUR) < 0)) |
| return false; |
| p_jpeg->buf_left = 0; |
| return true; |
| } |
| |
| static bool skip_bytes(struct jpeg* p_jpeg, int count) |
| { |
| p_jpeg->buf_left -= count; |
| p_jpeg->buf_index += count; |
| return p_jpeg->buf_left >= 0 || skip_bytes_seek(p_jpeg); |
| } |
| |
| static void jpeg_putc(struct jpeg* p_jpeg) |
| { |
| p_jpeg->buf_left++; |
| p_jpeg->buf_index--; |
| } |
| #endif |
| |
| #define e_skip_bytes(jpeg, count) \ |
| do {\ |
| if (UNLIKELY(!skip_bytes((jpeg),(count)))) \ |
| return -1; \ |
| } while (0) |
| |
| #define e_getc(jpeg, code) \ |
| ({ \ |
| unsigned char *c; \ |
| if (UNLIKELY(!(c = jpeg_getc(jpeg)))) \ |
| return (code); \ |
| *c; \ |
| }) |
| |
| #define d_getc(jpeg, def) \ |
| ({ \ |
| unsigned char *cp = jpeg_getc(jpeg); \ |
| unsigned char c = LIKELY(cp) ? *cp : (def); \ |
| c; \ |
| }) |
| |
| /* Preprocess the JPEG JFIF file */ |
| static int process_markers(struct jpeg* p_jpeg) |
| { |
| unsigned char c; |
| int marker_size; /* variable length of marker segment */ |
| int i, j, n; |
| int ret = 0; /* returned flags */ |
| bool done = false; |
| |
| while (!done && (c = e_getc(p_jpeg, -1))) |
| { |
| if (c != 0xFF) /* no marker? */ |
| { |
| JDEBUGF("Non-marker data\n"); |
| continue; /* discard */ |
| } |
| |
| c = e_getc(p_jpeg, -1); |
| JDEBUGF("marker value %X\n",c); |
| switch (c) |
| { |
| case 0xFF: /* Previous FF was fill byte */ |
| jpeg_putc(p_jpeg); /* This FF could be start of a marker */ |
| continue; |
| case 0x00: /* Zero stuffed byte */ |
| break; /* discard */ |
| |
| case 0xC0: /* SOF Huff - Baseline DCT */ |
| { |
| JDEBUGF("SOF marker "); |
| ret |= SOF0; |
| marker_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */ |
| marker_size |= e_getc(p_jpeg, -1); /* Lowbyte */ |
| JDEBUGF("len: %d\n", marker_size); |
| n = e_getc(p_jpeg, -1); /* sample precision (= 8 or 12) */ |
| if (n != 8) |
| { |
| return(-1); /* Unsupported sample precision */ |
| } |
| p_jpeg->y_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */ |
| p_jpeg->y_size |= e_getc(p_jpeg, -1); /* Lowbyte */ |
| p_jpeg->x_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */ |
| p_jpeg->x_size |= e_getc(p_jpeg, -1); /* Lowbyte */ |
| JDEBUGF(" dimensions: %dx%d\n", p_jpeg->x_size, |
| p_jpeg->y_size); |
| |
| n = (marker_size-2-6)/3; |
| if (e_getc(p_jpeg, -1) != n || (n != 1 && n != 3)) |
| { |
| return(-2); /* Unsupported SOF0 component specification */ |
| } |
| for (i=0; i<n; i++) |
| { |
| /* Component info */ |
| p_jpeg->frameheader[i].ID = e_getc(p_jpeg, -1); |
| p_jpeg->frameheader[i].horizontal_sampling = |
| (c = e_getc(p_jpeg, -1)) >> 4; |
| p_jpeg->frameheader[i].vertical_sampling = c & 0x0F; |
| p_jpeg->frameheader[i].quanttable_select = |
| e_getc(p_jpeg, -1); |
| if (p_jpeg->frameheader[i].horizontal_sampling > 2 |
| || p_jpeg->frameheader[i].vertical_sampling > 2) |
| return -3; /* Unsupported SOF0 subsampling */ |
| } |
| p_jpeg->blocks = n; |
| } |
| break; |
| |
| case 0xC1: /* SOF Huff - Extended sequential DCT*/ |
| case 0xC2: /* SOF Huff - Progressive DCT*/ |
| case 0xC3: /* SOF Huff - Spatial (sequential) lossless*/ |
| case 0xC5: /* SOF Huff - Differential sequential DCT*/ |
| case 0xC6: /* SOF Huff - Differential progressive DCT*/ |
| case 0xC7: /* SOF Huff - Differential spatial*/ |
| case 0xC8: /* SOF Arith - Reserved for JPEG extensions*/ |
| case 0xC9: /* SOF Arith - Extended sequential DCT*/ |
| case 0xCA: /* SOF Arith - Progressive DCT*/ |
| case 0xCB: /* SOF Arith - Spatial (sequential) lossless*/ |
| case 0xCD: /* SOF Arith - Differential sequential DCT*/ |
| case 0xCE: /* SOF Arith - Differential progressive DCT*/ |
| case 0xCF: /* SOF Arith - Differential spatial*/ |
| { |
| return (-4); /* other DCT model than baseline not implemented */ |
| } |
| |
| case 0xC4: /* Define Huffman Table(s) */ |
| { |
| ret |= DHT; |
| marker_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */ |
| marker_size |= e_getc(p_jpeg, -1); /* Lowbyte */ |
| marker_size -= 2; |
| |
| while (marker_size > 17) /* another table */ |
| { |
| c = e_getc(p_jpeg, -1); |
| marker_size--; |
| int sum = 0; |
| i = c & 0x0F; /* table index */ |
| if (i > 1) |
| { |
| return (-5); /* Huffman table index out of range */ |
| } else { |
| if (c & 0xF0) /* AC table */ |
| { |
| for (j=0; j<16; j++) |
| { |
| p_jpeg->hufftable[i].huffmancodes_ac[j] = |
| (c = e_getc(p_jpeg, -1)); |
| sum += c; |
| marker_size -= 1; |
| } |
| if(16 + sum > AC_LEN) |
| return -10; /* longer than allowed */ |
| |
| for (; j < 16 + sum; j++) |
| { |
| p_jpeg->hufftable[i].huffmancodes_ac[j] = |
| e_getc(p_jpeg, -1); |
| marker_size--; |
| } |
| } |
| else /* DC table */ |
| { |
| for (j=0; j<16; j++) |
| { |
| p_jpeg->hufftable[i].huffmancodes_dc[j] = |
| (c = e_getc(p_jpeg, -1)); |
| sum += c; |
| marker_size--; |
| } |
| if(16 + sum > DC_LEN) |
| return -11; /* longer than allowed */ |
| |
| for (; j < 16 + sum; j++) |
| { |
| p_jpeg->hufftable[i].huffmancodes_dc[j] = |
| e_getc(p_jpeg, -1); |
| marker_size--; |
| } |
| } |
| } |
| } /* while */ |
| e_skip_bytes(p_jpeg, marker_size); |
| } |
| break; |
| |
| case 0xCC: /* Define Arithmetic coding conditioning(s) */ |
| return(-6); /* Arithmetic coding not supported */ |
| |
| case 0xD8: /* Start of Image */ |
| JDEBUGF("SOI\n"); |
| break; |
| case 0xD9: /* End of Image */ |
| JDEBUGF("EOI\n"); |
| break; |
| case 0x01: /* for temp private use arith code */ |
| JDEBUGF("private\n"); |
| break; /* skip parameterless marker */ |
| |
| |
| case 0xDA: /* Start of Scan */ |
| { |
| ret |= SOS; |
| marker_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */ |
| marker_size |= e_getc(p_jpeg, -1); /* Lowbyte */ |
| marker_size -= 2; |
| |
| n = (marker_size-1-3)/2; |
| if (e_getc(p_jpeg, -1) != n || (n != 1 && n != 3)) |
| { |
| return (-7); /* Unsupported SOS component specification */ |
| } |
| marker_size--; |
| for (i=0; i<n; i++) |
| { |
| p_jpeg->scanheader[i].ID = e_getc(p_jpeg, -1); |
| p_jpeg->scanheader[i].DC_select = (c = e_getc(p_jpeg, -1)) |
| >> 4; |
| p_jpeg->scanheader[i].AC_select = c & 0x0F; |
| marker_size -= 2; |
| } |
| /* skip spectral information */ |
| e_skip_bytes(p_jpeg, marker_size); |
| done = true; |
| } |
| break; |
| |
| case 0xDB: /* Define quantization Table(s) */ |
| { |
| ret |= DQT; |
| marker_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */ |
| marker_size |= e_getc(p_jpeg, -1); /* Lowbyte */ |
| marker_size -= 2; |
| |
| n = (marker_size)/(QUANT_TABLE_LENGTH+1); /* # of tables */ |
| for (i=0; i<n; i++) |
| { |
| int id = e_getc(p_jpeg, -1); /* ID */ |
| marker_size--; |
| if (id >= 4) |
| { |
| return (-8); /* Unsupported quantization table */ |
| } |
| /* Read Quantisation table: */ |
| for (j=0; j<QUANT_TABLE_LENGTH; j++) |
| { |
| p_jpeg->quanttable[id][j] = e_getc(p_jpeg, -1); |
| marker_size--; |
| } |
| } |
| e_skip_bytes(p_jpeg, marker_size); |
| } |
| break; |
| |
| case 0xDD: /* Define Restart Interval */ |
| { |
| marker_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */ |
| marker_size |= e_getc(p_jpeg, -1); /* Lowbyte */ |
| marker_size -= 4; |
| /* Highbyte */ |
| p_jpeg->restart_interval = e_getc(p_jpeg, -1) << 8; |
| p_jpeg->restart_interval |= e_getc(p_jpeg, -1); /* Lowbyte */ |
| e_skip_bytes(p_jpeg, marker_size); /* skip segment */ |
| } |
| break; |
| |
| case 0xDC: /* Define Number of Lines */ |
| case 0xDE: /* Define Hierarchical progression */ |
| case 0xDF: /* Expand Reference Component(s) */ |
| case 0xE0: /* Application Field 0*/ |
| case 0xE1: /* Application Field 1*/ |
| case 0xE2: /* Application Field 2*/ |
| case 0xE3: /* Application Field 3*/ |
| case 0xE4: /* Application Field 4*/ |
| case 0xE5: /* Application Field 5*/ |
| case 0xE6: /* Application Field 6*/ |
| case 0xE7: /* Application Field 7*/ |
| case 0xE8: /* Application Field 8*/ |
| case 0xE9: /* Application Field 9*/ |
| case 0xEA: /* Application Field 10*/ |
| case 0xEB: /* Application Field 11*/ |
| case 0xEC: /* Application Field 12*/ |
| case 0xED: /* Application Field 13*/ |
| case 0xEE: /* Application Field 14*/ |
| case 0xEF: /* Application Field 15*/ |
| case 0xFE: /* Comment */ |
| { |
| marker_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */ |
| marker_size |= e_getc(p_jpeg, -1); /* Lowbyte */ |
| marker_size -= 2; |
| JDEBUGF("unhandled marker len %d\n", marker_size); |
| e_skip_bytes(p_jpeg, marker_size); /* skip segment */ |
| } |
| break; |
| |
| case 0xF0: /* Reserved for JPEG extensions */ |
| case 0xF1: /* Reserved for JPEG extensions */ |
| case 0xF2: /* Reserved for JPEG extensions */ |
| case 0xF3: /* Reserved for JPEG extensions */ |
| case 0xF4: /* Reserved for JPEG extensions */ |
| case 0xF5: /* Reserved for JPEG extensions */ |
| case 0xF6: /* Reserved for JPEG extensions */ |
| case 0xF7: /* Reserved for JPEG extensions */ |
| case 0xF8: /* Reserved for JPEG extensions */ |
| case 0xF9: /* Reserved for JPEG extensions */ |
| case 0xFA: /* Reserved for JPEG extensions */ |
| case 0xFB: /* Reserved for JPEG extensions */ |
| case 0xFC: /* Reserved for JPEG extensions */ |
| case 0xFD: /* Reserved for JPEG extensions */ |
| case 0x02: /* Reserved */ |
| default: |
| return (-9); /* Unknown marker */ |
| } /* switch */ |
| } /* while */ |
| |
| return (ret); /* return flags with seen markers */ |
| } |
| |
| static const struct huffman_table luma_table = |
| { |
| { |
| 0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00, |
| 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B |
| }, |
| { |
| 0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00, |
| 0x01,0x7D,0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06, |
| 0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42, |
| 0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24,0x33,0x62,0x72,0x82,0x09,0x0A,0x16, |
| 0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,0x2A,0x34,0x35,0x36,0x37, |
| 0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55, |
| 0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73, |
| 0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89, |
| 0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5, |
| 0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA, |
| 0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6, |
| 0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA, |
| 0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA |
| } |
| }; |
| |
| static const struct huffman_table chroma_table = |
| { |
| { |
| 0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00, |
| 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B |
| }, |
| { |
| 0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01, |
| 0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41, |
| 0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1, |
| 0xC1,0x09,0x23,0x33,0x52,0xF0,0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34, |
| 0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,0x27,0x28,0x29,0x2A,0x35,0x36, |
| 0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54, |
| 0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A, |
| 0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87, |
| 0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3, |
| 0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8, |
| 0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4, |
| 0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9, |
| 0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA |
| } |
| }; |
| |
| static void default_huff_tbl(struct jpeg* p_jpeg) |
| { |
| |
| MEMCPY(&p_jpeg->hufftable[0], &luma_table, sizeof(luma_table)); |
| MEMCPY(&p_jpeg->hufftable[1], &chroma_table, sizeof(chroma_table)); |
| |
| return; |
| } |
| |
| /* Compute the derived values for a Huffman table */ |
| static void fix_huff_tbl(int* htbl, struct derived_tbl* dtbl) |
| { |
| int p, i, l, si; |
| int lookbits, ctr; |
| char huffsize[257]; |
| unsigned int huffcode[257]; |
| unsigned int code; |
| |
| dtbl->pub = htbl; /* fill in back link */ |
| |
| /* Figure C.1: make table of Huffman code length for each symbol */ |
| /* Note that this is in code-length order. */ |
| |
| p = 0; |
| for (l = 1; l <= 16; l++) |
| { /* all possible code length */ |
| for (i = 1; i <= (int) htbl[l-1]; i++) /* all codes per length */ |
| huffsize[p++] = (char) l; |
| } |
| huffsize[p] = 0; |
| |
| /* Figure C.2: generate the codes themselves */ |
| /* Note that this is in code-length order. */ |
| |
| code = 0; |
| si = huffsize[0]; |
| p = 0; |
| while (huffsize[p]) |
| { |
| while (((int) huffsize[p]) == si) |
| { |
| huffcode[p++] = code; |
| code++; |
| } |
| code <<= 1; |
| si++; |
| } |
| |
| /* Figure F.15: generate decoding tables for bit-sequential decoding */ |
| |
| p = 0; |
| for (l = 1; l <= 16; l++) |
| { |
| if (htbl[l-1]) |
| { |
| /* huffval[] index of 1st symbol of code length l */ |
| dtbl->valptr[l] = p; |
| dtbl->mincode[l] = huffcode[p]; /* minimum code of length l */ |
| p += htbl[l-1]; |
| dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ |
| } |
| else |
| { |
| dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ |
| } |
| } |
| dtbl->maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */ |
| |
| /* Compute lookahead tables to speed up decoding. |
| * First we set all the table entries to 0, indicating "too long"; |
| * then we iterate through the Huffman codes that are short enough and |
| * fill in all the entries that correspond to bit sequences starting |
| * with that code. |
| */ |
| |
| MEMSET(dtbl->look_nbits, 0, sizeof(dtbl->look_nbits)); |
| |
| p = 0; |
| for (l = 1; l <= HUFF_LOOKAHEAD; l++) |
| { |
| for (i = 1; i <= (int) htbl[l-1]; i++, p++) |
| { |
| /* l = current code's length, p = its index in huffcode[] & |
| * huffval[]. Generate left-justified code followed by all possible |
| * bit sequences |
| */ |
| lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); |
| for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) |
| { |
| dtbl->look_nbits[lookbits] = l; |
| dtbl->look_sym[lookbits] = htbl[16+p]; |
| lookbits++; |
| } |
| } |
| } |
| } |
| |
| |
| /* zag[i] is the natural-order position of the i'th element of zigzag order. */ |
| static const unsigned char zag[] = |
| { |
| #ifdef JPEG_IDCT_TRANSPOSE |
| 0, 8, 1, 2, 9, 16, 24, 17, |
| 10, 3, 4, 11, 18, 25, 32, 40, |
| 33, 26, 19, 12, 5, 6, 13, 20, |
| 27, 34, 41, 48, 56, 49, 42, 35, |
| 28, 21, 14, 7, 15, 22, 29, 36, |
| 43, 50, 57, 58, 51, 44, 37, 30, |
| 23, 31, 38, 45, 52, 59, 60, 53, |
| 46, 39, 47, 54, 61, 62, 55, 63, |
| #endif |
| 0, 1, 8, 16, 9, 2, 3, 10, |
| 17, 24, 32, 25, 18, 11, 4, 5, |
| 12, 19, 26, 33, 40, 48, 41, 34, |
| 27, 20, 13, 6, 7, 14, 21, 28, |
| 35, 42, 49, 56, 57, 50, 43, 36, |
| 29, 22, 15, 23, 30, 37, 44, 51, |
| 58, 59, 52, 45, 38, 31, 39, 46, |
| 53, 60, 61, 54, 47, 55, 62, 63, |
| }; |
| |
| /* zig[i] is the the zig-zag order position of the i'th element of natural |
| * order, reading left-to-right then top-to-bottom. |
| */ |
| static const unsigned char zig[] = |
| { |
| 0, 1, 5, 6, 14, 15, 27, 28, |
| 2, 4, 7, 13, 16, 26, 29, 42, |
| 3, 8, 12, 17, 25, 30, 41, 43, |
| 9, 11, 18, 24, 31, 40, 44, 53, |
| 10, 19, 23, 32, 39, 45, 52, 54, |
| 20, 22, 33, 38, 46, 51, 55, 60, |
| 21, 34, 37, 47, 50, 56, 59, 61, |
| 35, 36, 48, 49, 57, 58, 62, 63 |
| }; |
| |
| /* Reformat some image header data so that the decoder can use it properly. */ |
| INLINE void fix_headers(struct jpeg* p_jpeg) |
| { |
| int i; |
| |
| for (i=0; i<4; i++) |
| p_jpeg->store_pos[i] = i; /* default ordering */ |
| |
| /* assignments for the decoding of blocks */ |
| if (p_jpeg->frameheader[0].horizontal_sampling == 2 |
| && p_jpeg->frameheader[0].vertical_sampling == 1) |
| { /* 4:2:2 */ |
| p_jpeg->blocks = 4; |
| p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16; |
| p_jpeg->x_phys = p_jpeg->x_mbl * 16; |
| p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8; |
| p_jpeg->y_phys = p_jpeg->y_mbl * 8; |
| p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */ |
| p_jpeg->mcu_membership[1] = 0; |
| p_jpeg->mcu_membership[2] = 1; |
| p_jpeg->mcu_membership[3] = 2; |
| p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */ |
| p_jpeg->tab_membership[1] = 0; |
| p_jpeg->tab_membership[2] = 1; |
| p_jpeg->tab_membership[3] = 1; |
| p_jpeg->subsample_x[0] = 1; |
| p_jpeg->subsample_x[1] = 2; |
| p_jpeg->subsample_x[2] = 2; |
| p_jpeg->subsample_y[0] = 1; |
| p_jpeg->subsample_y[1] = 1; |
| p_jpeg->subsample_y[2] = 1; |
| } |
| if (p_jpeg->frameheader[0].horizontal_sampling == 1 |
| && p_jpeg->frameheader[0].vertical_sampling == 2) |
| { /* 4:2:2 vertically subsampled */ |
| p_jpeg->store_pos[1] = 2; /* block positions are mirrored */ |
| p_jpeg->store_pos[2] = 1; |
| p_jpeg->blocks = 4; |
| p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8; |
| p_jpeg->x_phys = p_jpeg->x_mbl * 8; |
| p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16; |
| p_jpeg->y_phys = p_jpeg->y_mbl * 16; |
| p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */ |
| p_jpeg->mcu_membership[1] = 0; |
| p_jpeg->mcu_membership[2] = 1; |
| p_jpeg->mcu_membership[3] = 2; |
| p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */ |
| p_jpeg->tab_membership[1] = 0; |
| p_jpeg->tab_membership[2] = 1; |
| p_jpeg->tab_membership[3] = 1; |
| p_jpeg->subsample_x[0] = 1; |
| p_jpeg->subsample_x[1] = 1; |
| p_jpeg->subsample_x[2] = 1; |
| p_jpeg->subsample_y[0] = 1; |
| p_jpeg->subsample_y[1] = 2; |
| p_jpeg->subsample_y[2] = 2; |
| } |
| else if (p_jpeg->frameheader[0].horizontal_sampling == 2 |
| && p_jpeg->frameheader[0].vertical_sampling == 2) |
| { /* 4:2:0 */ |
| p_jpeg->blocks = 6; |
| p_jpeg->x_mbl = (p_jpeg->x_size+15) / 16; |
| p_jpeg->x_phys = p_jpeg->x_mbl * 16; |
| p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16; |
| p_jpeg->y_phys = p_jpeg->y_mbl * 16; |
| p_jpeg->mcu_membership[0] = 0; |
| p_jpeg->mcu_membership[1] = 0; |
| p_jpeg->mcu_membership[2] = 0; |
| p_jpeg->mcu_membership[3] = 0; |
| p_jpeg->mcu_membership[4] = 1; |
| p_jpeg->mcu_membership[5] = 2; |
| p_jpeg->tab_membership[0] = 0; |
| p_jpeg->tab_membership[1] = 0; |
| p_jpeg->tab_membership[2] = 0; |
| p_jpeg->tab_membership[3] = 0; |
| p_jpeg->tab_membership[4] = 1; |
| p_jpeg->tab_membership[5] = 1; |
| p_jpeg->subsample_x[0] = 1; |
| p_jpeg->subsample_x[1] = 2; |
| p_jpeg->subsample_x[2] = 2; |
| p_jpeg->subsample_y[0] = 1; |
| p_jpeg->subsample_y[1] = 2; |
| p_jpeg->subsample_y[2] = 2; |
| } |
| else if (p_jpeg->frameheader[0].horizontal_sampling == 1 |
| && p_jpeg->frameheader[0].vertical_sampling == 1) |
| { /* 4:4:4 */ |
| /* don't overwrite p_jpeg->blocks */ |
| p_jpeg->x_mbl = (p_jpeg->x_size+7) / 8; |
| p_jpeg->x_phys = p_jpeg->x_mbl * 8; |
| p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8; |
| p_jpeg->y_phys = p_jpeg->y_mbl * 8; |
| p_jpeg->mcu_membership[0] = 0; |
| p_jpeg->mcu_membership[1] = 1; |
| p_jpeg->mcu_membership[2] = 2; |
| p_jpeg->tab_membership[0] = 0; |
| p_jpeg->tab_membership[1] = 1; |
| p_jpeg->tab_membership[2] = 1; |
| p_jpeg->subsample_x[0] = 1; |
| p_jpeg->subsample_x[1] = 1; |
| p_jpeg->subsample_x[2] = 1; |
| p_jpeg->subsample_y[0] = 1; |
| p_jpeg->subsample_y[1] = 1; |
| p_jpeg->subsample_y[2] = 1; |
| } |
| else |
| { |
| /* error */ |
| } |
| |
| } |
| |
| INLINE void fix_huff_tables(struct jpeg *p_jpeg) |
| { |
| fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_dc, |
| &p_jpeg->dc_derived_tbls[0]); |
| fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_ac, |
| &p_jpeg->ac_derived_tbls[0]); |
| fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_dc, |
| &p_jpeg->dc_derived_tbls[1]); |
| fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_ac, |
| &p_jpeg->ac_derived_tbls[1]); |
| } |
| |
| /* Because some of the IDCT routines never multiply by any constants, and |
| * therefore do not produce shifted output, we add the shift into the |
| * quantization table when one of these IDCT routines is used, rather than |
| * have the IDCT shift each value it processes. |
| */ |
| INLINE void fix_quant_tables(struct jpeg *p_jpeg) |
| { |
| int shift, i, j; |
| for (i = 0; i < 2; i++) |
| { |
| shift = idct_tbl[p_jpeg->v_scale[i]].scale; |
| if (shift) |
| { |
| for (j = 0; j < 64; j++) |
| p_jpeg->quanttable[i][j] <<= shift; |
| } |
| } |
| } |
| |
| /* |
| * These functions/macros provide the in-line portion of bit fetching. |
| * Use check_bit_buffer to ensure there are N bits in get_buffer |
| * before using get_bits, peek_bits, or drop_bits. |
| * check_bit_buffer(state,n,action); |
| * Ensure there are N bits in get_buffer; if suspend, take action. |
| * val = get_bits(n); |
| * Fetch next N bits. |
| * val = peek_bits(n); |
| * Fetch next N bits without removing them from the buffer. |
| * drop_bits(n); |
| * Discard next N bits. |
| * The value N should be a simple variable, not an expression, because it |
| * is evaluated multiple times. |
| */ |
| |
| static void fill_bit_buffer(struct jpeg* p_jpeg) |
| { |
| unsigned char byte, marker; |
| |
| if (p_jpeg->marker_val) |
| p_jpeg->marker_ind += 16; |
| byte = d_getc(p_jpeg, 0); |
| if (UNLIKELY(byte == 0xFF)) /* legal marker can be byte stuffing or RSTm */ |
| { /* simplification: just skip the (one-byte) marker code */ |
| marker = d_getc(p_jpeg, 0); |
| if ((marker & ~7) == 0xD0) |
| { |
| p_jpeg->marker_val = marker; |
| p_jpeg->marker_ind = 8; |
| } |
| } |
| p_jpeg->bitbuf = (p_jpeg->bitbuf << 8) | byte; |
| |
| byte = d_getc(p_jpeg, 0); |
| if (UNLIKELY(byte == 0xFF)) /* legal marker can be byte stuffing or RSTm */ |
| { /* simplification: just skip the (one-byte) marker code */ |
| marker = d_getc(p_jpeg, 0); |
| if ((marker & ~7) == 0xD0) |
| { |
| p_jpeg->marker_val = marker; |
| p_jpeg->marker_ind = 0; |
| } |
| } |
| p_jpeg->bitbuf = (p_jpeg->bitbuf << 8) | byte; |
| p_jpeg->bitbuf_bits += 16; |
| #ifdef JPEG_BS_DEBUG |
| DEBUGF("read in: %04X\n", p_jpeg->bitbuf & 0xFFFF); |
| #endif |
| } |
| |
| INLINE void check_bit_buffer(struct jpeg *p_jpeg, int nbits) |
| { |
| if (nbits > p_jpeg->bitbuf_bits) |
| fill_bit_buffer(p_jpeg); |
| } |
| |
| INLINE int get_bits(struct jpeg *p_jpeg, int nbits) |
| { |
| #ifdef JPEG_BS_DEBUG |
| if (nbits > p_jpeg->bitbuf_bits) |
| DEBUGF("bitbuffer underrun\n"); |
| int mask = BIT_N(p_jpeg->bitbuf_bits - 1); |
| int i; |
| DEBUGF("get %d bits: ", nbits); |
| for (i = 0; i < nbits; i++) |
| DEBUGF("%d",!!(p_jpeg->bitbuf & (mask >>= 1))); |
| DEBUGF("\n"); |
| #endif |
| return ((int) (p_jpeg->bitbuf >> (p_jpeg->bitbuf_bits -= nbits))) & |
| (BIT_N(nbits)-1); |
| } |
| |
| INLINE int peek_bits(struct jpeg *p_jpeg, int nbits) |
| { |
| #ifdef JPEG_BS_DEBUG |
| int mask = BIT_N(p_jpeg->bitbuf_bits - 1); |
| int i; |
| DEBUGF("peek %d bits: ", nbits); |
| for (i = 0; i < nbits; i++) |
| DEBUGF("%d",!!(p_jpeg->bitbuf & (mask >>= 1))); |
| DEBUGF("\n"); |
| #endif |
| return ((int) (p_jpeg->bitbuf >> (p_jpeg->bitbuf_bits - nbits))) & |
| (BIT_N(nbits)-1); |
| } |
| |
| INLINE void drop_bits(struct jpeg *p_jpeg, int nbits) |
| { |
| #ifdef JPEG_BS_DEBUG |
| int mask = BIT_N(p_jpeg->bitbuf_bits - 1); |
| int i; |
| DEBUGF("drop %d bits: ", nbits); |
| for (i = 0; i < nbits; i++) |
| DEBUGF("%d",!!(p_jpeg->bitbuf & (mask >>= 1))); |
| DEBUGF("\n"); |
| #endif |
| p_jpeg->bitbuf_bits -= nbits; |
| } |
| |
| /* re-synchronize to entropy data (skip restart marker) */ |
| static void search_restart(struct jpeg *p_jpeg) |
| { |
| if (p_jpeg->marker_val) |
| { |
| p_jpeg->marker_val = 0; |
| p_jpeg->bitbuf_bits = p_jpeg->marker_ind; |
| p_jpeg->marker_ind = 0; |
| return; |
| } |
| unsigned char byte; |
| p_jpeg->bitbuf_bits = 0; |
| while ((byte = d_getc(p_jpeg, 0xFF))) |
| { |
| if (byte == 0xff) |
| { |
| byte = d_getc(p_jpeg, 0xD0); |
| if ((byte & ~7) == 0xD0) |
| { |
| return; |
| } |
| else |
| jpeg_putc(p_jpeg); |
| } |
| } |
| } |
| |
| /* Figure F.12: extend sign bit. */ |
| #if CONFIG_CPU == SH7034 |
| /* SH1 lacks a variable-shift instruction */ |
| #define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) |
| |
| static const int extend_test[16] = /* entry n is 2**(n-1) */ |
| { |
| 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, |
| 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 |
| }; |
| |
| static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ |
| { |
| 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, |
| ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, |
| ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, |
| ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 |
| }; |
| #else |
| /* This saves some code and data size, benchmarks about the same on RAM */ |
| #define HUFF_EXTEND(x,s) \ |
| ({ \ |
| int x__ = x; \ |
| int s__ = s; \ |
| x__ & BIT_N(s__- 1) ? x__ : x__ + (-1 << s__) + 1; \ |
| }) |
| #endif |
| |
| /* Decode a single value */ |
| #define huff_decode_dc(p_jpeg, tbl, s, r) \ |
| { \ |
| int nb, look; \ |
| \ |
| check_bit_buffer((p_jpeg), HUFF_LOOKAHEAD); \ |
| look = peek_bits((p_jpeg), HUFF_LOOKAHEAD); \ |
| if ((nb = (tbl)->look_nbits[look]) != 0) \ |
| { \ |
| drop_bits((p_jpeg), nb); \ |
| s = (tbl)->look_sym[look]; \ |
| check_bit_buffer((p_jpeg), s); \ |
| r = get_bits((p_jpeg), s); \ |
| } else { \ |
| /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */ \ |
| long code; \ |
| nb=HUFF_LOOKAHEAD+1; \ |
| check_bit_buffer((p_jpeg), nb); \ |
| code = get_bits((p_jpeg), nb); \ |
| while (code > (tbl)->maxcode[nb]) \ |
| { \ |
| code <<= 1; \ |
| check_bit_buffer((p_jpeg), 1); \ |
| code |= get_bits((p_jpeg), 1); \ |
| nb++; \ |
| } \ |
| if (nb > 16) /* error in Huffman */ \ |
| { \ |
| r = 0; s = 0; /* fake a zero, this is most safe */ \ |
| } else { \ |
| s = (tbl)->pub[16 + (tbl)->valptr[nb] + \ |
| ((int) (code - (tbl)->mincode[nb]))]; \ |
| check_bit_buffer((p_jpeg), s); \ |
| r = get_bits((p_jpeg), s); \ |
| } \ |
| } /* end slow decode */ \ |
| } |
| |
| #define huff_decode_ac(p_jpeg, tbl, s) \ |
| { \ |
| int nb, look; \ |
| \ |
| check_bit_buffer((p_jpeg), HUFF_LOOKAHEAD); \ |
| look = peek_bits((p_jpeg), HUFF_LOOKAHEAD); \ |
| if ((nb = (tbl)->look_nbits[look]) != 0) \ |
| { \ |
| drop_bits((p_jpeg), nb); \ |
| s = (tbl)->look_sym[look]; \ |
| } else { \ |
| /* slow_DECODE(s, HUFF_LOOKAHEAD+1)) < 0); */ \ |
| long code; \ |
| nb=HUFF_LOOKAHEAD+1; \ |
| check_bit_buffer((p_jpeg), nb); \ |
| code = get_bits((p_jpeg), nb); \ |
| while (code > (tbl)->maxcode[nb]) \ |
| { \ |
| code <<= 1; \ |
| check_bit_buffer((p_jpeg), 1); \ |
| code |= get_bits((p_jpeg), 1); \ |
| nb++; \ |
| } \ |
| if (nb > 16) /* error in Huffman */ \ |
| { \ |
| s = 0; /* fake a zero, this is most safe */ \ |
| } else { \ |
| s = (tbl)->pub[16 + (tbl)->valptr[nb] + \ |
| ((int) (code - (tbl)->mincode[nb]))]; \ |
| } \ |
| } /* end slow decode */ \ |
| } |
| |
| static struct img_part *store_row_jpeg(void *jpeg_args) |
| { |
| struct jpeg *p_jpeg = (struct jpeg*) jpeg_args; |
| #ifdef HAVE_LCD_COLOR |
| int mcu_hscale = p_jpeg->h_scale[1]; |
| int mcu_vscale = p_jpeg->v_scale[1]; |
| #else |
| int mcu_hscale = (p_jpeg->h_scale[0] + |
| p_jpeg->frameheader[0].horizontal_sampling - 1); |
| int mcu_vscale = (p_jpeg->v_scale[0] + |
| p_jpeg->frameheader[0].vertical_sampling - 1); |
| #endif |
| unsigned int width = p_jpeg->x_mbl << mcu_hscale; |
| unsigned int b_width = width * JPEG_PIX_SZ; |
| int height = BIT_N(mcu_vscale); |
| int x; |
| if (!p_jpeg->mcu_row) /* Need to decode a new row of MCUs */ |
| { |
| p_jpeg->out_ptr = (unsigned char *)p_jpeg->img_buf; |
| int store_offs[4]; |
| #ifdef HAVE_LCD_COLOR |
| unsigned mcu_width = BIT_N(mcu_hscale); |
| #endif |
| int mcu_offset = JPEG_PIX_SZ << mcu_hscale; |
| unsigned char *out = p_jpeg->out_ptr; |
| store_offs[p_jpeg->store_pos[0]] = 0; |
| store_offs[p_jpeg->store_pos[1]] = JPEG_PIX_SZ << p_jpeg->h_scale[0]; |
| store_offs[p_jpeg->store_pos[2]] = b_width << p_jpeg->v_scale[0]; |
| store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; |
| /* decoded DCT coefficients */ |
| int16_t block[IDCT_WS_SIZE] __attribute__((aligned(8))); |
| for (x = 0; x < p_jpeg->x_mbl; x++) |
| { |
| int blkn; |
| for (blkn = 0; blkn < p_jpeg->blocks; blkn++) |
| { |
| int ci = p_jpeg->mcu_membership[blkn]; /* component index */ |
| int ti = p_jpeg->tab_membership[blkn]; /* table index */ |
| #ifdef JPEG_IDCT_TRANSPOSE |
| bool transpose = p_jpeg->v_scale[!!ci] > 2; |
| #endif |
| int k = 1; /* coefficient index */ |
| int s, r; /* huffman values */ |
| struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti]; |
| struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti]; |
| |
| /* Section F.2.2.1: decode the DC coefficient difference */ |
| huff_decode_dc(p_jpeg, dctbl, s, r); |
| |
| #ifndef HAVE_LCD_COLOR |
| if (!ci) |
| #endif |
| { |
| s = HUFF_EXTEND(r, s); |
| #ifdef HAVE_LCD_COLOR |
| p_jpeg->last_dc_val[ci] += s; |
| /* output it (assumes zag[0] = 0) */ |
| block[0] = MULTIPLY16(p_jpeg->last_dc_val[ci], |
| p_jpeg->quanttable[!!ci][0]); |
| #else |
| p_jpeg->last_dc_val += s; |
| /* output it (assumes zag[0] = 0) */ |
| block[0] = MULTIPLY16(p_jpeg->last_dc_val, |
| p_jpeg->quanttable[0][0]); |
| #endif |
| /* coefficient buffer must be cleared */ |
| MEMSET(block+1, 0, p_jpeg->zero_need[!!ci] * sizeof(int)); |
| /* Section F.2.2.2: decode the AC coefficients */ |
| while(true) |
| { |
| huff_decode_ac(p_jpeg, actbl, s); |
| r = s >> 4; |
| s &= 15; |
| k += r; |
| if (s) |
| { |
| check_bit_buffer(p_jpeg, s); |
| if (k >= p_jpeg->k_need[!!ci]) |
| goto skip_rest; |
| r = get_bits(p_jpeg, s); |
| r = HUFF_EXTEND(r, s); |
| r = MULTIPLY16(r, p_jpeg->quanttable[!!ci][k]); |
| #ifdef JPEG_IDCT_TRANSPOSE |
| block[zag[transpose ? k : k + 64]] = r ; |
| #else |
| block[zag[k]] = r ; |
| #endif |
| } |
| else |
| { |
| if (r != 15) |
| goto block_end; |
| } |
| if ((++k) & 64) |
| goto block_end; |
| } /* for k */ |
| } |
| for (; k < 64; k++) |
| { |
| huff_decode_ac(p_jpeg, actbl, s); |
| r = s >> 4; |
| s &= 15; |
| |
| if (s) |
| { |
| k += r; |
| check_bit_buffer(p_jpeg, s); |
| skip_rest: |
| drop_bits(p_jpeg, s); |
| } |
| else |
| { |
| if (r != 15) |
| break; |
| k += r; |
| } |
| } /* for k */ |
| block_end: |
| #ifndef HAVE_LCD_COLOR |
| if (!ci) |
| #endif |
| { |
| int idct_cols = BIT_N(MIN(p_jpeg->h_scale[!!ci], 3)); |
| int idct_rows = BIT_N(p_jpeg->v_scale[!!ci]); |
| unsigned char *b_out = out + (ci ? ci : store_offs[blkn]); |
| if (idct_tbl[p_jpeg->v_scale[!!ci]].v_idct) |
| #ifdef JPEG_IDCT_TRANSPOSE |
| idct_tbl[p_jpeg->v_scale[!!ci]].v_idct(block, |
| transpose ? block + 8 * idct_cols |
| : block + idct_cols); |
| uint16_t * h_block = transpose ? block + 64 : block; |
| idct_tbl[p_jpeg->h_scale[!!ci]].h_idct(h_block, b_out, |
| h_block + idct_rows * 8, b_width); |
| #else |
| idct_tbl[p_jpeg->v_scale[!!ci]].v_idct(block, |
| block + idct_cols); |
| idct_tbl[p_jpeg->h_scale[!!ci]].h_idct(block, b_out, |
| block + idct_rows * 8, b_width); |
| #endif |
| } |
| } /* for blkn */ |
| /* don't starve other threads while an MCU row decodes */ |
| yield(); |
| #ifdef HAVE_LCD_COLOR |
| unsigned int xp; |
| int yp; |
| unsigned char *row = out; |
| if (p_jpeg->blocks == 1) |
| { |
| for (yp = 0; yp < height; yp++, row += b_width) |
| { |
| unsigned char *px = row; |
| for (xp = 0; xp < mcu_width; xp++, px += JPEG_PIX_SZ) |
| { |
| px[1] = px[2] = px[0]; |
| } |
| } |
| } |
| #endif |
| out += mcu_offset; |
| if (p_jpeg->restart_interval && --p_jpeg->restart == 0) |
| { /* if a restart marker is due: */ |
| p_jpeg->restart = p_jpeg->restart_interval; /* count again */ |
| search_restart(p_jpeg); /* align the bitstream */ |
| #ifdef HAVE_LCD_COLOR |
| p_jpeg->last_dc_val[0] = p_jpeg->last_dc_val[1] = |
| p_jpeg->last_dc_val[2] = 0; /* reset decoder */ |
| #else |
| p_jpeg->last_dc_val = 0; |
| #endif |
| } |
| } |
| } /* if !p_jpeg->mcu_row */ |
| p_jpeg->mcu_row = (p_jpeg->mcu_row + 1) & (height - 1); |
| p_jpeg->part.len = width; |
| p_jpeg->part.buf = (jpeg_pix_t *)p_jpeg->out_ptr; |
| p_jpeg->out_ptr += b_width; |
| return &(p_jpeg->part); |
| } |
| |
| /****************************************************************************** |
| * read_jpeg_file() |
| * |
| * Reads a JPEG file and puts the data in rockbox format in *bitmap. |
| * |
| *****************************************************************************/ |
| #ifndef JPEG_FROM_MEM |
| int clip_jpeg_file(const char* filename, |
| int offset, |
| unsigned long jpeg_size, |
| struct bitmap *bm, |
| int maxsize, |
| int format, |
| const struct custom_format *cformat) |
| { |
| int fd, ret; |
| fd = open(filename, O_RDONLY); |
| JDEBUGF("read_jpeg_file: filename: %s buffer len: %d cformat: %p\n", |
| filename, maxsize, cformat); |
| /* Exit if file opening failed */ |
| if (fd < 0) { |
| DEBUGF("read_jpeg_file: can't open '%s', rc: %d\n", filename, fd); |
| return fd * 10 - 1; |
| } |
| lseek(fd, offset, SEEK_SET); |
| ret = clip_jpeg_fd(fd, jpeg_size, bm, maxsize, format, cformat); |
| close(fd); |
| return ret; |
| } |
| |
| int read_jpeg_file(const char* filename, |
| struct bitmap *bm, |
| int maxsize, |
| int format, |
| const struct custom_format *cformat) |
| { |
| return clip_jpeg_file(filename, 0, 0, bm, maxsize, format, cformat); |
| } |
| #endif |
| |
| static int calc_scale(int in_size, int out_size) |
| { |
| int scale = 0; |
| out_size <<= 3; |
| for (scale = 0; scale < 3; scale++) |
| { |
| if (out_size <= in_size) |
| break; |
| else |
| in_size <<= 1; |
| } |
| return scale; |
| } |
| |
| #ifdef JPEG_FROM_MEM |
| int get_jpeg_dim_mem(unsigned char *data, unsigned long len, |
| struct dim *size) |
| { |
| struct jpeg *p_jpeg = &jpeg; |
| memset(p_jpeg, 0, sizeof(struct jpeg)); |
| p_jpeg->data = data; |
| p_jpeg->len = len; |
| int status = process_markers(p_jpeg); |
| if (status < 0) |
| return status; |
| if ((status & (DQT | SOF0)) != (DQT | SOF0)) |
| return -(status * 16); |
| size->width = p_jpeg->x_size; |
| size->height = p_jpeg->y_size; |
| return 0; |
| } |
| |
| int decode_jpeg_mem(unsigned char *data, |
| #else |
| int clip_jpeg_fd(int fd, |
| #endif |
| unsigned long len, |
| struct bitmap *bm, |
| int maxsize, |
| int format, |
| const struct custom_format *cformat) |
| { |
| bool resize = false, dither = false; |
| struct rowset rset; |
| struct dim src_dim; |
| int status; |
| int bm_size; |
| #ifdef JPEG_FROM_MEM |
| struct jpeg *p_jpeg = &jpeg; |
| #else |
| struct jpeg *p_jpeg = (struct jpeg*)bm->data; |
| int tmp_size = maxsize; |
| ALIGN_BUFFER(p_jpeg, tmp_size, sizeof(int)); |
| /* not enough memory for our struct jpeg */ |
| if ((size_t)tmp_size < sizeof(struct jpeg)) |
| return -1; |
| #endif |
| memset(p_jpeg, 0, sizeof(struct jpeg)); |
| p_jpeg->len = len; |
| #ifdef JPEG_FROM_MEM |
| p_jpeg->data = data; |
| #else |
| p_jpeg->fd = fd; |
| if (p_jpeg->len == 0) |
| p_jpeg->len = filesize(p_jpeg->fd); |
| #endif |
| status = process_markers(p_jpeg); |
| #ifndef JPEG_FROM_MEM |
| JDEBUGF("position in file: %d buffer fill: %d\n", |
| (int)lseek(p_jpeg->fd, 0, SEEK_CUR), p_jpeg->buf_left); |
| #endif |
| if (status < 0) |
| return status; |
| if ((status & (DQT | SOF0)) != (DQT | SOF0)) |
| return -(status * 16); |
| if (!(status & DHT)) /* if no Huffman table present: */ |
| default_huff_tbl(p_jpeg); /* use default */ |
| fix_headers(p_jpeg); /* derive Huffman and other lookup-tables */ |
| src_dim.width = p_jpeg->x_size; |
| src_dim.height = p_jpeg->y_size; |
| if (format & FORMAT_RESIZE) |
| resize = true; |
| if (format & FORMAT_DITHER) |
| dither = true; |
| #ifdef HAVE_LCD_COLOR |
| bm->alpha_offset = 0; /* no alpha channel */ |
| #endif |
| if (resize) { |
| struct dim resize_dim = { |
| .width = bm->width, |
| .height = bm->height, |
| }; |
| if (format & FORMAT_KEEP_ASPECT) |
| recalc_dimension(&resize_dim, &src_dim); |
| bm->width = resize_dim.width; |
| bm->height = resize_dim.height; |
| } else { |
| bm->width = p_jpeg->x_size; |
| bm->height = p_jpeg->y_size; |
| } |
| p_jpeg->h_scale[0] = calc_scale(p_jpeg->x_size, bm->width); |
| p_jpeg->v_scale[0] = calc_scale(p_jpeg->y_size, bm->height); |
| JDEBUGF("luma IDCT size: %dx%d\n", BIT_N(p_jpeg->h_scale[0]), |
| BIT_N(p_jpeg->v_scale[0])); |
| if ((p_jpeg->x_size << p_jpeg->h_scale[0]) >> 3 == bm->width && |
| (p_jpeg->y_size << p_jpeg->v_scale[0]) >> 3 == bm->height) |
| resize = false; |
| #ifdef HAVE_LCD_COLOR |
| p_jpeg->h_scale[1] = p_jpeg->h_scale[0] + |
| p_jpeg->frameheader[0].horizontal_sampling - 1; |
| p_jpeg->v_scale[1] = p_jpeg->v_scale[0] + |
| p_jpeg->frameheader[0].vertical_sampling - 1; |
| JDEBUGF("chroma IDCT size: %dx%d\n", BIT_N(p_jpeg->h_scale[1]), |
| BIT_N(p_jpeg->v_scale[1])); |
| #endif |
| JDEBUGF("scaling from %dx%d -> %dx%d\n", |
| (p_jpeg->x_size << p_jpeg->h_scale[0]) >> 3, |
| (p_jpeg->y_size << p_jpeg->v_scale[0]) >> 3, |
| bm->width, bm->height); |
| fix_quant_tables(p_jpeg); |
| int decode_w = BIT_N(p_jpeg->h_scale[0]) - 1; |
| int decode_h = BIT_N(p_jpeg->v_scale[0]) - 1; |
| src_dim.width = (p_jpeg->x_size << p_jpeg->h_scale[0]) >> 3; |
| src_dim.height = (p_jpeg->y_size << p_jpeg->v_scale[0]) >> 3; |
| #ifdef JPEG_IDCT_TRANSPOSE |
| if (p_jpeg->v_scale[0] > 2) |
| p_jpeg->zero_need[0] = (decode_w << 3) + decode_h; |
| else |
| #endif |
| p_jpeg->zero_need[0] = (decode_h << 3) + decode_w; |
| p_jpeg->k_need[0] = zig[(decode_h << 3) + decode_w]; |
| JDEBUGF("need luma components to %d\n", p_jpeg->k_need[0]); |
| #ifdef HAVE_LCD_COLOR |
| decode_w = BIT_N(MIN(p_jpeg->h_scale[1],3)) - 1; |
| decode_h = BIT_N(MIN(p_jpeg->v_scale[1],3)) - 1; |
| if (p_jpeg->v_scale[1] > 2) |
| p_jpeg->zero_need[1] = (decode_w << 3) + decode_h; |
| else |
| p_jpeg->zero_need[1] = (decode_h << 3) + decode_w; |
| p_jpeg->k_need[1] = zig[(decode_h << 3) + decode_w]; |
| JDEBUGF("need chroma components to %d\n", p_jpeg->k_need[1]); |
| #endif |
| if (cformat) |
| bm_size = cformat->get_size(bm); |
| else |
| bm_size = BM_SIZE(bm->width,bm->height,FORMAT_NATIVE,false); |
| if (bm_size > maxsize) |
| return -1; |
| char *buf_start = (char *)bm->data + bm_size; |
| char *buf_end = (char *)bm->data + maxsize; |
| maxsize = buf_end - buf_start; |
| #ifndef JPEG_FROM_MEM |
| ALIGN_BUFFER(buf_start, maxsize, sizeof(uint32_t)); |
| if (maxsize < (int)sizeof(struct jpeg)) |
| return -1; |
| memmove(buf_start, p_jpeg, sizeof(struct jpeg)); |
| p_jpeg = (struct jpeg *)buf_start; |
| buf_start += sizeof(struct jpeg); |
| maxsize = buf_end - buf_start; |
| #endif |
| fix_huff_tables(p_jpeg); |
| #ifdef HAVE_LCD_COLOR |
| int decode_buf_size = (p_jpeg->x_mbl << p_jpeg->h_scale[1]) |
| << p_jpeg->v_scale[1]; |
| #else |
| int decode_buf_size = (p_jpeg->x_mbl << p_jpeg->h_scale[0]) |
| << p_jpeg->v_scale[0]; |
| decode_buf_size <<= p_jpeg->frameheader[0].horizontal_sampling + |
| p_jpeg->frameheader[0].vertical_sampling - 2; |
| #endif |
| decode_buf_size *= JPEG_PIX_SZ; |
| JDEBUGF("decode buffer size: %d\n", decode_buf_size); |
| p_jpeg->img_buf = (jpeg_pix_t *)buf_start; |
| if (buf_end - buf_start < decode_buf_size) |
| return -1; |
| buf_start += decode_buf_size; |
| maxsize = buf_end - buf_start; |
| memset(p_jpeg->img_buf, 0, decode_buf_size); |
| p_jpeg->mcu_row = 0; |
| p_jpeg->restart = p_jpeg->restart_interval; |
| rset.rowstart = 0; |
| rset.rowstop = bm->height; |
| rset.rowstep = 1; |
| p_jpeg->resize = resize; |
| if (resize) |
| { |
| if (resize_on_load(bm, dither, &src_dim, &rset, buf_start, maxsize, |
| cformat, IF_PIX_FMT(p_jpeg->blocks == 1 ? 0 : 1,) store_row_jpeg, |
| p_jpeg)) |
| return bm_size; |
| } else { |
| int row; |
| struct scaler_context ctx = { |
| .bm = bm, |
| .dither = dither, |
| }; |
| #if LCD_DEPTH > 1 |
| void (*output_row_8)(uint32_t, void*, struct scaler_context*) = |
| output_row_8_native; |
| #elif defined(PLUGIN) |
| void (*output_row_8)(uint32_t, void*, struct scaler_context*) = NULL; |
| #endif |
| #if LCD_DEPTH > 1 || defined(PLUGIN) |
| if (cformat) |
| output_row_8 = cformat->output_row_8; |
| #endif |
| struct img_part *part; |
| for (row = 0; row < bm->height; row++) |
| { |
| part = store_row_jpeg(p_jpeg); |
| #ifdef HAVE_LCD_COLOR |
| if (p_jpeg->blocks > 1) |
| { |
| struct uint8_rgb *qp = part->buf; |
| struct uint8_rgb *end = qp + bm->width; |
| uint8_t y, u, v; |
| unsigned r, g, b; |
| for (; qp < end; qp++) |
| { |
| y = qp->blue; |
| u = qp->green; |
| v = qp->red; |
| yuv_to_rgb(y, u, v, &r, &g, &b); |
| qp->red = r; |
| qp->blue = b; |
| qp->green = g; |
| } |
| } |
| #endif |
| output_row_8(row, part->buf, &ctx); |
| } |
| return bm_size; |
| } |
| return 0; |
| } |
| |
| #ifndef JPEG_FROM_MEM |
| int read_jpeg_fd(int fd, |
| struct bitmap *bm, |
| int maxsize, |
| int format, |
| const struct custom_format *cformat) |
| { |
| return clip_jpeg_fd(fd, 0, bm, maxsize, format, cformat); |
| } |
| #endif |
| |
| /**************** end JPEG code ********************/ |