2009-05-01 23:24:23 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* 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*/
|
2009-07-22 22:10:25 +00:00
|
|
|
//#define ROCKBOX_DEBUG_JPEG
|
2009-05-01 23:24:23 +00:00
|
|
|
/* 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 */
|
2009-05-08 03:46:48 +00:00
|
|
|
#ifdef ROCKBOX_DEBUG_JPEG
|
|
|
|
#define JDEBUGF DEBUGF
|
|
|
|
#else
|
|
|
|
#define JDEBUGF(...)
|
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
|
|
|
|
/**************** begin JPEG code ********************/
|
|
|
|
|
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
|
|
typedef struct uint8_rgb jpeg_pix_t;
|
|
|
|
#else
|
|
|
|
typedef uint8_t jpeg_pix_t;
|
|
|
|
#endif
|
2009-06-19 02:56:00 +00:00
|
|
|
#define JPEG_IDCT_TRANSPOSE
|
2009-05-01 23:24:23 +00:00
|
|
|
#define JPEG_PIX_SZ (sizeof(jpeg_pix_t))
|
2009-06-19 02:56:00 +00:00
|
|
|
#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)
|
2009-05-01 23:24:23 +00:00
|
|
|
|
|
|
|
/* 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
|
|
|
|
{
|
2009-05-08 03:46:48 +00:00
|
|
|
#ifdef JPEG_FROM_MEM
|
|
|
|
unsigned char *data;
|
|
|
|
unsigned long len;
|
|
|
|
#else
|
2009-05-01 23:24:23 +00:00
|
|
|
int fd;
|
|
|
|
int buf_left;
|
2009-05-11 00:16:48 +00:00
|
|
|
int buf_index;
|
2009-05-08 03:46:48 +00:00
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
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];
|
2009-05-07 08:32:17 +00:00
|
|
|
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 */
|
2009-05-01 23:24:23 +00:00
|
|
|
#else
|
|
|
|
int last_dc_val;
|
2009-05-07 08:32:17 +00:00
|
|
|
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 */
|
2009-05-01 23:24:23 +00:00
|
|
|
#endif
|
|
|
|
jpeg_pix_t *img_buf;
|
|
|
|
|
2009-06-11 23:48:30 +00:00
|
|
|
int16_t quanttable[4][QUANT_TABLE_LENGTH];/* raw quantization tables 0-3 */
|
2009-05-01 23:24:23 +00:00
|
|
|
|
|
|
|
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];
|
2009-05-09 07:31:27 +00:00
|
|
|
bool resize;
|
2009-05-01 23:24:23 +00:00
|
|
|
unsigned char buf[JPEG_READ_BUF_SIZE];
|
|
|
|
struct img_part part;
|
|
|
|
};
|
|
|
|
|
2009-05-08 03:46:48 +00:00
|
|
|
#ifdef JPEG_FROM_MEM
|
|
|
|
static struct jpeg jpeg;
|
|
|
|
#endif
|
|
|
|
|
2009-05-01 23:24:23 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2009-06-27 10:01:24 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2009-05-01 23:24:23 +00:00
|
|
|
/* 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))
|
|
|
|
|
2009-06-11 23:48:30 +00:00
|
|
|
#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
|
|
|
|
|
2009-05-01 23:24:23 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
|
2009-06-19 08:26:05 +00:00
|
|
|
#ifndef CPU_ARM
|
2009-05-01 23:24:23 +00:00
|
|
|
/* horizontal-pass 1-point IDCT */
|
2009-06-19 02:56:00 +00:00
|
|
|
static void jpeg_idct1h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-06-14 02:28:35 +00:00
|
|
|
for (; ws < end; ws += 8)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-06-11 23:48:37 +00:00
|
|
|
*out = range_limit(128 + (int) DESCALE(*ws, 3 + PASS1_BITS));
|
2009-05-01 23:24:23 +00:00
|
|
|
out += rowstep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vertical-pass 2-point IDCT */
|
2009-06-19 02:56:00 +00:00
|
|
|
static void jpeg_idct2v(int16_t *ws, int16_t *end)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-06-14 02:28:35 +00:00
|
|
|
for (; ws < end; ws++)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-06-19 02:56:00 +00:00
|
|
|
int tmp1 = ws[0*8];
|
|
|
|
int tmp2 = ws[1*8];
|
|
|
|
ws[0*8] = tmp1 + tmp2;
|
|
|
|
ws[1*8] = tmp1 - tmp2;
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* horizontal-pass 2-point IDCT */
|
2009-06-19 02:56:00 +00:00
|
|
|
static void jpeg_idct2h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-06-14 02:28:35 +00:00
|
|
|
for (; ws < end; ws += 8, out += rowstep)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-06-11 23:48:37 +00:00
|
|
|
int tmp1 = ws[0] + (ONE << (PASS1_BITS + 2))
|
|
|
|
+ (128 << (PASS1_BITS + 3));
|
2009-05-01 23:24:23 +00:00
|
|
|
int tmp2 = ws[1];
|
|
|
|
out[JPEG_PIX_SZ*0] = range_limit((int) RIGHT_SHIFT(tmp1 + tmp2,
|
2009-06-11 23:48:30 +00:00
|
|
|
PASS1_BITS + 3));
|
2009-05-01 23:24:23 +00:00
|
|
|
out[JPEG_PIX_SZ*1] = range_limit((int) RIGHT_SHIFT(tmp1 - tmp2,
|
2009-06-11 23:48:30 +00:00
|
|
|
PASS1_BITS + 3));
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vertical-pass 4-point IDCT */
|
2009-06-19 02:56:00 +00:00
|
|
|
static void jpeg_idct4v(int16_t *ws, int16_t *end)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-06-14 02:28:35 +00:00
|
|
|
for (; ws < end; ws++)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-06-11 23:48:30 +00:00
|
|
|
int tmp0, tmp2, tmp10, tmp12;
|
|
|
|
int z1, z2, z3;
|
2009-05-01 23:24:23 +00:00
|
|
|
/* 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 */
|
2009-06-19 02:56:00 +00:00
|
|
|
static void jpeg_idct4h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-06-14 02:28:35 +00:00
|
|
|
for (; ws < end; out += rowstep, ws += 8)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-06-11 23:48:45 +00:00
|
|
|
int tmp0, tmp2, tmp10, tmp12;
|
|
|
|
int z1, z2, z3;
|
2009-05-01 23:24:23 +00:00
|
|
|
/* Even part */
|
|
|
|
|
2009-06-12 00:02:18 +00:00
|
|
|
tmp0 = (int) ws[0] + (ONE << (PASS1_BITS + 2))
|
2009-06-11 23:48:37 +00:00
|
|
|
+ (128 << (PASS1_BITS + 3));
|
2009-05-01 23:24:23 +00:00
|
|
|
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);
|
2009-06-11 23:48:45 +00:00
|
|
|
tmp0 = z1 - MULTIPLY16(z3, FIX_1_847759065);
|
2009-05-01 23:24:23 +00:00
|
|
|
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 */
|
2009-06-19 02:56:00 +00:00
|
|
|
static void jpeg_idct8v(int16_t *ws, int16_t *end)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
|
|
|
long tmp0, tmp1, tmp2, tmp3;
|
|
|
|
long tmp10, tmp11, tmp12, tmp13;
|
|
|
|
long z1, z2, z3, z4, z5;
|
2009-06-19 02:56:00 +00:00
|
|
|
#ifdef JPEG_IDCT_TRANSPOSE
|
|
|
|
int16_t *ws2 = ws + 64;
|
|
|
|
for (; ws < end; ws += 8, ws2++)
|
|
|
|
{
|
|
|
|
#else
|
2009-06-14 02:28:35 +00:00
|
|
|
for (; ws < end; ws++)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-06-19 02:56:00 +00:00
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
/* 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.
|
|
|
|
*/
|
2009-06-19 02:56:00 +00:00
|
|
|
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)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
|
|
|
/* AC terms all zero */
|
2009-06-19 02:56:00 +00:00
|
|
|
int dcval = ws[V_IN_ST*0] << PASS1_BITS;
|
2009-05-01 23:24:23 +00:00
|
|
|
|
2009-06-19 02:56:00 +00:00
|
|
|
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;
|
2009-05-01 23:24:23 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Even part: reverse the even part of the forward DCT. */
|
|
|
|
/* The rotator is sqrt(2)*c(-6). */
|
|
|
|
|
2009-06-19 02:56:00 +00:00
|
|
|
z2 = ws[V_IN_ST*2];
|
|
|
|
z3 = ws[V_IN_ST*6];
|
2009-05-01 23:24:23 +00:00
|
|
|
|
|
|
|
z1 = MULTIPLY16(z2 + z3, FIX_0_541196100);
|
|
|
|
tmp2 = z1 + MULTIPLY16(z3, - FIX_1_847759065);
|
|
|
|
tmp3 = z1 + MULTIPLY16(z2, FIX_0_765366865);
|
|
|
|
|
2009-06-19 02:56:00 +00:00
|
|
|
z2 = ws[V_IN_ST*0] << CONST_BITS;
|
2009-05-01 23:24:23 +00:00
|
|
|
z2 += ONE << (CONST_BITS - PASS1_BITS - 1);
|
2009-06-19 02:56:00 +00:00
|
|
|
z3 = ws[V_IN_ST*4] << CONST_BITS;
|
2009-05-01 23:24:23 +00:00
|
|
|
|
|
|
|
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. */
|
|
|
|
|
2009-06-19 02:56:00 +00:00
|
|
|
tmp0 = ws[V_IN_ST*7];
|
|
|
|
tmp1 = ws[V_IN_ST*5];
|
|
|
|
tmp2 = ws[V_IN_ST*3];
|
|
|
|
tmp3 = ws[V_IN_ST*1];
|
2009-05-01 23:24:23 +00:00
|
|
|
|
|
|
|
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 */
|
|
|
|
|
2009-06-19 02:56:00 +00:00
|
|
|
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);
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* horizontal-pass 8-point IDCT */
|
2009-06-19 02:56:00 +00:00
|
|
|
static void jpeg_idct8h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
|
|
|
long tmp0, tmp1, tmp2, tmp3;
|
|
|
|
long tmp10, tmp11, tmp12, tmp13;
|
|
|
|
long z1, z2, z3, z4, z5;
|
2009-06-14 02:28:35 +00:00
|
|
|
for (; ws < end; out += rowstep, ws += 8)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
|
|
|
/* 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 */
|
2009-06-11 23:48:37 +00:00
|
|
|
unsigned char dcval = range_limit(128 + (int) DESCALE((long) ws[0],
|
2009-05-01 23:24:23 +00:00
|
|
|
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);
|
|
|
|
|
2009-06-11 23:48:37 +00:00
|
|
|
z4 = (long) ws[0] + (ONE << (PASS1_BITS + 2))
|
|
|
|
+ (128 << (PASS1_BITS + 3));
|
2009-05-01 23:24:23 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-27 09:21:22 +00:00
|
|
|
#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
|
|
|
|
|
2009-05-09 10:32:13 +00:00
|
|
|
#ifdef HAVE_LCD_COLOR
|
2009-05-01 23:24:23 +00:00
|
|
|
/* vertical-pass 16-point IDCT */
|
2009-06-19 02:56:00 +00:00
|
|
|
static void jpeg_idct16v(int16_t *ws, int16_t *end)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
|
|
|
long tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13;
|
|
|
|
long tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27;
|
|
|
|
long z1, z2, z3, z4;
|
2009-06-19 02:56:00 +00:00
|
|
|
#ifdef JPEG_IDCT_TRANSPOSE
|
|
|
|
int16_t *ws2 = ws + 64;
|
|
|
|
for (; ws < end; ws += 8, ws2++)
|
|
|
|
{
|
|
|
|
#else
|
2009-06-14 02:28:35 +00:00
|
|
|
for (; ws < end; ws++)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-06-19 02:56:00 +00:00
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
/* Even part */
|
|
|
|
|
2009-06-19 02:56:00 +00:00
|
|
|
tmp0 = ws[V_IN_ST*0] << CONST_BITS;
|
2009-05-01 23:24:23 +00:00
|
|
|
/* Add fudge factor here for final descale. */
|
|
|
|
tmp0 += 1 << (CONST_BITS-PASS1_BITS-1);
|
|
|
|
|
2009-06-19 02:56:00 +00:00
|
|
|
z1 = ws[V_IN_ST*4];
|
2009-05-01 23:24:23 +00:00
|
|
|
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;
|
|
|
|
|
2009-06-19 02:56:00 +00:00
|
|
|
z1 = ws[V_IN_ST*2];
|
|
|
|
z2 = ws[V_IN_ST*6];
|
2009-05-01 23:24:23 +00:00
|
|
|
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 */
|
|
|
|
|
2009-06-19 02:56:00 +00:00
|
|
|
z1 = ws[V_IN_ST*1];
|
|
|
|
z2 = ws[V_IN_ST*3];
|
|
|
|
z3 = ws[V_IN_ST*5];
|
|
|
|
z4 = ws[V_IN_ST*7];
|
2009-05-01 23:24:23 +00:00
|
|
|
|
|
|
|
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 */
|
2009-06-19 02:56:00 +00:00
|
|
|
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);
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* horizontal-pass 16-point IDCT */
|
2009-06-19 02:56:00 +00:00
|
|
|
static void jpeg_idct16h(int16_t *ws, unsigned char *out, int16_t *end, int rowstep)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
|
|
|
long tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13;
|
|
|
|
long tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27;
|
|
|
|
long z1, z2, z3, z4;
|
2009-06-14 02:28:35 +00:00
|
|
|
for (; ws < end; out += rowstep, ws += 8)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
|
|
|
/* Even part */
|
|
|
|
|
|
|
|
/* Add fudge factor here for final descale. */
|
2009-06-11 23:48:37 +00:00
|
|
|
tmp0 = (long) ws[0] + (ONE << (PASS1_BITS+2))
|
|
|
|
+ (128 << (PASS1_BITS + 3));
|
2009-05-01 23:24:23 +00:00
|
|
|
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 */
|
|
|
|
|
2009-06-27 10:01:24 +00:00
|
|
|
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);
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
}
|
2009-05-09 10:32:13 +00:00
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
|
|
|
|
struct idct_entry {
|
2009-06-11 23:48:30 +00:00
|
|
|
int scale;
|
2009-06-14 02:28:35 +00:00
|
|
|
void (*v_idct)(int16_t *ws, int16_t *end);
|
|
|
|
void (*h_idct)(int16_t *ws, unsigned char *out, int16_t *end, int rowstep);
|
2009-05-01 23:24:23 +00:00
|
|
|
};
|
|
|
|
|
2010-04-06 19:37:41 +00:00
|
|
|
static const struct idct_entry idct_tbl[] = {
|
2009-06-19 02:56:00 +00:00
|
|
|
{ PASS1_BITS, NULL, jpeg_idct1h },
|
|
|
|
{ PASS1_BITS, jpeg_idct2v, jpeg_idct2h },
|
|
|
|
{ 0, jpeg_idct4v, jpeg_idct4h },
|
|
|
|
{ 0, jpeg_idct8v, jpeg_idct8h },
|
2009-05-09 10:32:13 +00:00
|
|
|
#ifdef HAVE_LCD_COLOR
|
2009-06-19 02:56:00 +00:00
|
|
|
{ 0, jpeg_idct16v, jpeg_idct16h },
|
2009-05-09 10:32:13 +00:00
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* JPEG decoder implementation */
|
|
|
|
|
2009-05-08 03:46:48 +00:00
|
|
|
#ifdef JPEG_FROM_MEM
|
|
|
|
INLINE unsigned char *getc(struct jpeg* p_jpeg)
|
|
|
|
{
|
2009-05-11 00:16:57 +00:00
|
|
|
if (LIKELY(p_jpeg->len))
|
2009-05-08 03:46:48 +00:00
|
|
|
{
|
|
|
|
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 putc(struct jpeg* p_jpeg)
|
|
|
|
{
|
|
|
|
p_jpeg->len++;
|
|
|
|
p_jpeg->data--;
|
|
|
|
}
|
|
|
|
#else
|
2009-05-01 23:24:23 +00:00
|
|
|
INLINE void fill_buf(struct jpeg* p_jpeg)
|
|
|
|
{
|
|
|
|
p_jpeg->buf_left = read(p_jpeg->fd, p_jpeg->buf, JPEG_READ_BUF_SIZE);
|
2009-05-11 00:16:48 +00:00
|
|
|
p_jpeg->buf_index = 0;
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned char *getc(struct jpeg* p_jpeg)
|
|
|
|
{
|
2009-05-11 00:16:57 +00:00
|
|
|
if (UNLIKELY(p_jpeg->buf_left < 1))
|
2009-05-01 23:24:23 +00:00
|
|
|
fill_buf(p_jpeg);
|
2009-05-11 00:16:57 +00:00
|
|
|
if (UNLIKELY(p_jpeg->buf_left < 1))
|
2009-05-01 23:24:23 +00:00
|
|
|
return NULL;
|
|
|
|
p_jpeg->buf_left--;
|
2009-05-11 00:16:48 +00:00
|
|
|
return (p_jpeg->buf_index++) + p_jpeg->buf;
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
INLINE bool skip_bytes_seek(struct jpeg* p_jpeg)
|
|
|
|
{
|
2009-05-11 00:16:57 +00:00
|
|
|
if (UNLIKELY(lseek(p_jpeg->fd, -p_jpeg->buf_left, SEEK_CUR) < 0))
|
2009-05-01 23:24:23 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2009-05-08 03:46:48 +00:00
|
|
|
static void putc(struct jpeg* p_jpeg)
|
|
|
|
{
|
|
|
|
p_jpeg->buf_left++;
|
|
|
|
p_jpeg->buf_index--;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-05-01 23:24:23 +00:00
|
|
|
#define e_skip_bytes(jpeg, count) \
|
|
|
|
do {\
|
2009-05-11 00:16:57 +00:00
|
|
|
if (UNLIKELY(!skip_bytes((jpeg),(count)))) \
|
2009-05-01 23:24:23 +00:00
|
|
|
return -1; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define e_getc(jpeg, code) \
|
|
|
|
({ \
|
|
|
|
unsigned char *c; \
|
2009-05-11 00:16:57 +00:00
|
|
|
if (UNLIKELY(!(c = getc(jpeg)))) \
|
2009-05-01 23:24:23 +00:00
|
|
|
return (code); \
|
|
|
|
*c; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define d_getc(jpeg, def) \
|
|
|
|
({ \
|
|
|
|
unsigned char *cp = getc(jpeg); \
|
2009-05-11 00:16:57 +00:00
|
|
|
unsigned char c = LIKELY(cp) ? *cp : (def); \
|
2009-05-01 23:24:23 +00:00
|
|
|
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 */
|
|
|
|
|
|
|
|
while ((c = e_getc(p_jpeg, -1)))
|
|
|
|
{
|
|
|
|
if (c != 0xFF) /* no marker? */
|
|
|
|
{
|
2009-05-08 03:46:48 +00:00
|
|
|
JDEBUGF("Non-marker data\n");
|
2009-05-01 23:24:23 +00:00
|
|
|
putc(p_jpeg);
|
|
|
|
break; /* exit marker processing */
|
|
|
|
}
|
|
|
|
|
|
|
|
c = e_getc(p_jpeg, -1);
|
2009-05-08 03:46:48 +00:00
|
|
|
JDEBUGF("marker value %X\n",c);
|
2009-05-01 23:24:23 +00:00
|
|
|
switch (c)
|
|
|
|
{
|
|
|
|
case 0xFF: /* Fill byte */
|
|
|
|
ret |= FILL_FF;
|
|
|
|
case 0x00: /* Zero stuffed byte - entropy data */
|
|
|
|
putc(p_jpeg);
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case 0xC0: /* SOF Huff - Baseline DCT */
|
|
|
|
{
|
2009-05-08 03:46:48 +00:00
|
|
|
JDEBUGF("SOF marker ");
|
2009-05-01 23:24:23 +00:00
|
|
|
ret |= SOF0;
|
|
|
|
marker_size = e_getc(p_jpeg, -1) << 8; /* Highbyte */
|
|
|
|
marker_size |= e_getc(p_jpeg, -1); /* Lowbyte */
|
2009-05-08 03:46:48 +00:00
|
|
|
JDEBUGF("len: %d\n", marker_size);
|
2009-05-01 23:24:23 +00:00
|
|
|
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 */
|
2009-05-08 03:46:48 +00:00
|
|
|
JDEBUGF(" dimensions: %dx%d\n", p_jpeg->x_size,
|
|
|
|
p_jpeg->y_size);
|
2009-05-01 23:24:23 +00:00
|
|
|
|
|
|
|
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 */
|
2009-05-08 03:46:48 +00:00
|
|
|
JDEBUGF("SOI\n");
|
|
|
|
break;
|
2009-05-01 23:24:23 +00:00
|
|
|
case 0xD9: /* End of Image */
|
2009-05-08 03:46:48 +00:00
|
|
|
JDEBUGF("EOI\n");
|
|
|
|
break;
|
2009-05-01 23:24:23 +00:00
|
|
|
case 0x01: /* for temp private use arith code */
|
2009-05-08 03:46:48 +00:00
|
|
|
JDEBUGF("private\n");
|
2009-05-01 23:24:23 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
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;
|
2009-05-08 03:46:48 +00:00
|
|
|
JDEBUGF("unhandled marker len %d\n", marker_size);
|
2009-05-01 23:24:23 +00:00
|
|
|
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++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-19 02:56:00 +00:00
|
|
|
/* zag[i] is the natural-order position of the i'th element of zigzag order. */
|
2009-05-01 23:24:23 +00:00
|
|
|
static const unsigned char zag[] =
|
|
|
|
{
|
2009-06-19 02:56:00 +00:00
|
|
|
#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,
|
2009-05-01 23:24:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
{
|
2009-06-11 23:48:30 +00:00
|
|
|
int shift, i, j;
|
2009-05-01 23:24:23 +00:00
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
2009-06-11 23:48:30 +00:00
|
|
|
shift = idct_tbl[p_jpeg->v_scale[i]].scale;
|
2009-05-01 23:24:23 +00:00
|
|
|
if (shift)
|
|
|
|
{
|
2009-06-11 23:48:30 +00:00
|
|
|
for (j = 0; j < 64; j++)
|
|
|
|
p_jpeg->quanttable[i][j] <<= shift;
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
2009-05-11 00:16:57 +00:00
|
|
|
if (UNLIKELY(byte == 0xFF)) /* legal marker can be byte stuffing or RSTm */
|
2009-05-01 23:24:23 +00:00
|
|
|
{ /* 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);
|
2009-05-11 00:16:57 +00:00
|
|
|
if (UNLIKELY(byte == 0xFF)) /* legal marker can be byte stuffing or RSTm */
|
2009-05-01 23:24:23 +00:00
|
|
|
{ /* 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
|
2009-05-11 00:16:48 +00:00
|
|
|
DEBUGF("read in: %04X\n", p_jpeg->bitbuf & 0xFFFF);
|
2009-05-01 23:24:23 +00:00
|
|
|
#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");
|
2009-06-07 21:27:05 +00:00
|
|
|
int mask = BIT_N(p_jpeg->bitbuf_bits - 1);
|
2009-05-01 23:24:23 +00:00
|
|
|
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))) &
|
2009-06-07 21:27:05 +00:00
|
|
|
(BIT_N(nbits)-1);
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
INLINE int peek_bits(struct jpeg *p_jpeg, int nbits)
|
|
|
|
{
|
|
|
|
#ifdef JPEG_BS_DEBUG
|
2009-06-07 21:27:05 +00:00
|
|
|
int mask = BIT_N(p_jpeg->bitbuf_bits - 1);
|
2009-05-01 23:24:23 +00:00
|
|
|
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))) &
|
2009-06-07 21:27:05 +00:00
|
|
|
(BIT_N(nbits)-1);
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
INLINE void drop_bits(struct jpeg *p_jpeg, int nbits)
|
|
|
|
{
|
|
|
|
#ifdef JPEG_BS_DEBUG
|
2009-06-07 21:27:05 +00:00
|
|
|
int mask = BIT_N(p_jpeg->bitbuf_bits - 1);
|
2009-05-01 23:24:23 +00:00
|
|
|
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
|
|
|
|
putc(p_jpeg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Figure F.12: extend sign bit. */
|
2009-05-08 04:19:10 +00:00
|
|
|
#if CONFIG_CPU == SH7034
|
|
|
|
/* SH1 lacks a variable-shift instruction */
|
2009-05-01 23:24:23 +00:00
|
|
|
#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
|
|
|
|
};
|
2009-05-08 04:19:10 +00:00
|
|
|
#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; \
|
2009-06-07 21:27:05 +00:00
|
|
|
x__ & BIT_N(s__- 1) ? x__ : x__ + (-1 << s__) + 1; \
|
2009-05-08 04:19:10 +00:00
|
|
|
})
|
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
|
|
|
|
/* Decode a single value */
|
2009-05-08 07:21:35 +00:00
|
|
|
#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 */ \
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
|
2009-05-08 07:21:35 +00:00
|
|
|
#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 */ \
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
|
2009-05-03 07:02:09 +00:00
|
|
|
static struct img_part *store_row_jpeg(void *jpeg_args)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
|
|
|
struct jpeg *p_jpeg = (struct jpeg*) jpeg_args;
|
2009-05-07 08:32:17 +00:00
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
|
|
int mcu_hscale = p_jpeg->h_scale[1];
|
|
|
|
int mcu_vscale = p_jpeg->v_scale[1];
|
|
|
|
#else
|
2009-05-08 03:46:48 +00:00
|
|
|
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);
|
2009-05-07 08:32:17 +00:00
|
|
|
#endif
|
|
|
|
unsigned int width = p_jpeg->x_mbl << mcu_hscale;
|
2009-05-01 23:24:23 +00:00
|
|
|
unsigned int b_width = width * JPEG_PIX_SZ;
|
2009-06-07 21:27:05 +00:00
|
|
|
int height = BIT_N(mcu_vscale);
|
2009-05-01 23:24:23 +00:00
|
|
|
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];
|
2009-05-07 08:32:17 +00:00
|
|
|
#ifdef HAVE_LCD_COLOR
|
2009-06-07 21:27:05 +00:00
|
|
|
unsigned mcu_width = BIT_N(mcu_hscale);
|
2009-05-07 08:32:17 +00:00
|
|
|
#endif
|
|
|
|
int mcu_offset = JPEG_PIX_SZ << mcu_hscale;
|
2009-05-01 23:24:23 +00:00
|
|
|
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];
|
2009-06-19 02:56:00 +00:00
|
|
|
/* decoded DCT coefficients */
|
|
|
|
int16_t block[IDCT_WS_SIZE] __attribute__((aligned(8)));
|
2009-05-01 23:24:23 +00:00
|
|
|
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 */
|
2009-06-19 02:56:00 +00:00
|
|
|
#ifdef JPEG_IDCT_TRANSPOSE
|
|
|
|
bool transpose = p_jpeg->v_scale[!!ci] > 2;
|
|
|
|
#endif
|
|
|
|
int k = 1; /* coefficient index */
|
|
|
|
int s, r; /* huffman values */
|
2009-05-01 23:24:23 +00:00
|
|
|
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 */
|
2009-05-08 07:21:35 +00:00
|
|
|
huff_decode_dc(p_jpeg, dctbl, s, r);
|
2009-05-01 23:24:23 +00:00
|
|
|
|
|
|
|
#ifndef HAVE_LCD_COLOR
|
|
|
|
if (!ci)
|
|
|
|
#endif
|
|
|
|
{
|
2009-05-08 07:21:35 +00:00
|
|
|
s = HUFF_EXTEND(r, s);
|
2009-05-01 23:24:23 +00:00
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
|
|
p_jpeg->last_dc_val[ci] += s;
|
|
|
|
/* output it (assumes zag[0] = 0) */
|
2009-06-11 23:48:30 +00:00
|
|
|
block[0] = MULTIPLY16(p_jpeg->last_dc_val[ci],
|
|
|
|
p_jpeg->quanttable[!!ci][0]);
|
2009-05-01 23:24:23 +00:00
|
|
|
#else
|
|
|
|
p_jpeg->last_dc_val += s;
|
|
|
|
/* output it (assumes zag[0] = 0) */
|
2009-06-11 23:48:30 +00:00
|
|
|
block[0] = MULTIPLY16(p_jpeg->last_dc_val,
|
|
|
|
p_jpeg->quanttable[0][0]);
|
2009-05-01 23:24:23 +00:00
|
|
|
#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 */
|
2009-06-14 01:19:16 +00:00
|
|
|
while(true)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
2009-05-08 07:21:35 +00:00
|
|
|
huff_decode_ac(p_jpeg, actbl, s);
|
2009-05-01 23:24:23 +00:00
|
|
|
r = s >> 4;
|
|
|
|
s &= 15;
|
2009-06-14 01:19:16 +00:00
|
|
|
k += r;
|
2009-05-01 23:24:23 +00:00
|
|
|
if (s)
|
|
|
|
{
|
|
|
|
check_bit_buffer(p_jpeg, s);
|
2009-06-14 01:19:16 +00:00
|
|
|
if (k >= p_jpeg->k_need[!!ci])
|
|
|
|
goto skip_rest;
|
2009-05-01 23:24:23 +00:00
|
|
|
r = get_bits(p_jpeg, s);
|
|
|
|
r = HUFF_EXTEND(r, s);
|
2009-06-14 01:19:16 +00:00
|
|
|
r = MULTIPLY16(r, p_jpeg->quanttable[!!ci][k]);
|
2009-06-19 02:56:00 +00:00
|
|
|
#ifdef JPEG_IDCT_TRANSPOSE
|
|
|
|
block[zag[transpose ? k : k + 64]] = r ;
|
|
|
|
#else
|
2009-06-14 01:19:16 +00:00
|
|
|
block[zag[k]] = r ;
|
2009-06-19 02:56:00 +00:00
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (r != 15)
|
2009-06-14 01:19:16 +00:00
|
|
|
goto block_end;
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
2009-06-14 01:19:16 +00:00
|
|
|
if ((++k) & 64)
|
|
|
|
goto block_end;
|
2009-05-01 23:24:23 +00:00
|
|
|
} /* for k */
|
|
|
|
}
|
|
|
|
for (; k < 64; k++)
|
|
|
|
{
|
2009-05-08 07:21:35 +00:00
|
|
|
huff_decode_ac(p_jpeg, actbl, s);
|
2009-05-01 23:24:23 +00:00
|
|
|
r = s >> 4;
|
|
|
|
s &= 15;
|
|
|
|
|
|
|
|
if (s)
|
|
|
|
{
|
|
|
|
k += r;
|
|
|
|
check_bit_buffer(p_jpeg, s);
|
2009-06-14 01:19:16 +00:00
|
|
|
skip_rest:
|
2009-05-01 23:24:23 +00:00
|
|
|
drop_bits(p_jpeg, s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (r != 15)
|
|
|
|
break;
|
|
|
|
k += r;
|
|
|
|
}
|
|
|
|
} /* for k */
|
2009-06-14 01:19:16 +00:00
|
|
|
block_end:
|
2009-05-01 23:24:23 +00:00
|
|
|
#ifndef HAVE_LCD_COLOR
|
|
|
|
if (!ci)
|
|
|
|
#endif
|
|
|
|
{
|
2009-06-07 21:27:05 +00:00
|
|
|
int idct_cols = BIT_N(MIN(p_jpeg->h_scale[!!ci], 3));
|
|
|
|
int idct_rows = BIT_N(p_jpeg->v_scale[!!ci]);
|
2009-05-01 23:24:23 +00:00
|
|
|
unsigned char *b_out = out + (ci ? ci : store_offs[blkn]);
|
2009-05-07 08:32:17 +00:00
|
|
|
if (idct_tbl[p_jpeg->v_scale[!!ci]].v_idct)
|
2009-06-19 02:56:00 +00:00
|
|
|
#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
|
2009-05-11 00:16:48 +00:00
|
|
|
idct_tbl[p_jpeg->v_scale[!!ci]].v_idct(block,
|
2009-06-14 02:28:35 +00:00
|
|
|
block + idct_cols);
|
2009-05-07 08:32:17 +00:00
|
|
|
idct_tbl[p_jpeg->h_scale[!!ci]].h_idct(block, b_out,
|
2009-06-14 02:28:35 +00:00
|
|
|
block + idct_rows * 8, b_width);
|
2009-06-19 02:56:00 +00:00
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
} /* 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;
|
2009-05-06 04:53:56 +00:00
|
|
|
if (p_jpeg->blocks == 1)
|
|
|
|
{
|
2009-05-01 23:24:23 +00:00
|
|
|
for (yp = 0; yp < height; yp++, row += b_width)
|
|
|
|
{
|
|
|
|
unsigned char *px = row;
|
2009-05-07 08:32:17 +00:00
|
|
|
for (xp = 0; xp < mcu_width; xp++, px += JPEG_PIX_SZ)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
*****************************************************************************/
|
2009-05-08 03:46:48 +00:00
|
|
|
#ifndef JPEG_FROM_MEM
|
2009-05-01 23:24:23 +00:00
|
|
|
int read_jpeg_file(const char* filename,
|
|
|
|
struct bitmap *bm,
|
|
|
|
int maxsize,
|
|
|
|
int format,
|
|
|
|
const struct custom_format *cformat)
|
|
|
|
{
|
|
|
|
int fd, ret;
|
|
|
|
fd = open(filename, O_RDONLY);
|
2009-05-11 00:16:48 +00:00
|
|
|
JDEBUGF("read_jpeg_file: filename: %s buffer len: %d cformat: %p\n",
|
|
|
|
filename, maxsize, cformat);
|
2009-05-01 23:24:23 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = read_jpeg_fd(fd, bm, maxsize, format, cformat);
|
|
|
|
close(fd);
|
|
|
|
return ret;
|
|
|
|
}
|
2009-05-08 03:46:48 +00:00
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
|
2009-05-07 08:32:17 +00:00
|
|
|
static int calc_scale(int in_size, int out_size)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
|
|
|
int scale = 0;
|
|
|
|
out_size <<= 3;
|
2009-05-07 08:32:17 +00:00
|
|
|
for (scale = 0; scale < 3; scale++)
|
2009-05-01 23:24:23 +00:00
|
|
|
{
|
|
|
|
if (out_size <= in_size)
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
in_size <<= 1;
|
|
|
|
}
|
|
|
|
return scale;
|
|
|
|
}
|
|
|
|
|
2009-05-08 03:46:48 +00:00
|
|
|
#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, unsigned long len,
|
|
|
|
#else
|
2009-05-01 23:24:23 +00:00
|
|
|
int read_jpeg_fd(int fd,
|
2009-05-08 03:46:48 +00:00
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
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;
|
2009-05-08 03:46:48 +00:00
|
|
|
#ifdef JPEG_FROM_MEM
|
|
|
|
struct jpeg *p_jpeg = &jpeg;
|
|
|
|
#else
|
|
|
|
struct jpeg *p_jpeg = (struct jpeg*)bm->data;
|
|
|
|
int tmp_size = maxsize;
|
2009-05-01 23:24:23 +00:00
|
|
|
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;
|
2009-05-08 03:46:48 +00:00
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
memset(p_jpeg, 0, sizeof(struct jpeg));
|
2009-05-08 03:46:48 +00:00
|
|
|
#ifdef JPEG_FROM_MEM
|
|
|
|
p_jpeg->data = data;
|
|
|
|
p_jpeg->len = len;
|
|
|
|
#else
|
2009-05-01 23:24:23 +00:00
|
|
|
p_jpeg->fd = fd;
|
2009-05-08 03:46:48 +00:00
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
status = process_markers(p_jpeg);
|
2009-05-11 00:16:48 +00:00
|
|
|
#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
|
2009-05-01 23:24:23 +00:00
|
|
|
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;
|
|
|
|
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;
|
|
|
|
}
|
2009-05-07 08:32:17 +00:00
|
|
|
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);
|
2009-06-07 21:27:05 +00:00
|
|
|
JDEBUGF("luma IDCT size: %dx%d\n", BIT_N(p_jpeg->h_scale[0]),
|
|
|
|
BIT_N(p_jpeg->v_scale[0]));
|
2009-05-09 10:10:26 +00:00
|
|
|
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)
|
2009-05-09 07:31:27 +00:00
|
|
|
resize = false;
|
2009-05-07 08:32:17 +00:00
|
|
|
#ifdef HAVE_LCD_COLOR
|
2009-05-01 23:24:23 +00:00
|
|
|
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;
|
2009-06-07 21:27:05 +00:00
|
|
|
JDEBUGF("chroma IDCT size: %dx%d\n", BIT_N(p_jpeg->h_scale[1]),
|
|
|
|
BIT_N(p_jpeg->v_scale[1]));
|
2009-05-07 08:32:17 +00:00
|
|
|
#endif
|
2009-05-11 00:16:48 +00:00
|
|
|
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);
|
2009-05-01 23:24:23 +00:00
|
|
|
fix_quant_tables(p_jpeg);
|
2009-06-07 21:27:05 +00:00
|
|
|
int decode_w = BIT_N(p_jpeg->h_scale[0]) - 1;
|
|
|
|
int decode_h = BIT_N(p_jpeg->v_scale[0]) - 1;
|
2009-05-01 23:24:23 +00:00
|
|
|
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;
|
2009-06-19 02:56:00 +00:00
|
|
|
#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];
|
2009-05-11 00:16:48 +00:00
|
|
|
JDEBUGF("need luma components to %d\n", p_jpeg->k_need[0]);
|
2009-05-07 08:32:17 +00:00
|
|
|
#ifdef HAVE_LCD_COLOR
|
2009-06-07 21:27:05 +00:00
|
|
|
decode_w = BIT_N(MIN(p_jpeg->h_scale[1],3)) - 1;
|
|
|
|
decode_h = BIT_N(MIN(p_jpeg->v_scale[1],3)) - 1;
|
2009-06-19 02:56:00 +00:00
|
|
|
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];
|
2009-05-11 00:16:48 +00:00
|
|
|
JDEBUGF("need chroma components to %d\n", p_jpeg->k_need[1]);
|
2009-05-07 08:32:17 +00:00
|
|
|
#endif
|
2009-05-01 23:24:23 +00:00
|
|
|
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;
|
2009-05-08 03:46:48 +00:00
|
|
|
#ifndef JPEG_FROM_MEM
|
2009-05-01 23:24:23 +00:00
|
|
|
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;
|
2009-05-08 03:46:48 +00:00
|
|
|
#endif
|
|
|
|
fix_huff_tables(p_jpeg);
|
2009-05-07 08:32:17 +00:00
|
|
|
#ifdef HAVE_LCD_COLOR
|
2009-05-01 23:24:23 +00:00
|
|
|
int decode_buf_size = (p_jpeg->x_mbl << p_jpeg->h_scale[1])
|
|
|
|
<< p_jpeg->v_scale[1];
|
2009-05-07 08:32:17 +00:00
|
|
|
#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
|
2009-05-01 23:24:23 +00:00
|
|
|
decode_buf_size *= JPEG_PIX_SZ;
|
2009-05-11 00:16:48 +00:00
|
|
|
JDEBUGF("decode buffer size: %d\n", decode_buf_size);
|
2009-05-01 23:24:23 +00:00
|
|
|
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;
|
2009-05-09 07:31:27 +00:00
|
|
|
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
|
2009-06-03 06:35:10 +00:00
|
|
|
if (p_jpeg->blocks > 1)
|
2009-05-09 07:31:27 +00:00
|
|
|
{
|
2009-06-03 06:35:10 +00:00
|
|
|
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;
|
|
|
|
}
|
2009-05-09 07:31:27 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
output_row_8(row, part->buf, &ctx);
|
|
|
|
}
|
2009-05-01 23:24:23 +00:00
|
|
|
return bm_size;
|
2009-05-09 07:31:27 +00:00
|
|
|
}
|
|
|
|
return 0;
|
2009-05-01 23:24:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**************** end JPEG code ********************/
|