diff options
author | David Schleef <ds@schleef.org> | 2007-03-20 07:03:30 +0000 |
---|---|---|
committer | David Schleef <ds@schleef.org> | 2007-03-20 07:03:30 +0000 |
commit | 31d9b45318bfb755ae917e59efe32cca4696aa30 (patch) | |
tree | b37a9049eb5d99b2e097db477d6b5091077d1e03 /examples | |
parent | a594920948be3773523c626d1148c14b85d0764c (diff) |
* examples/jpeg/Makefile.am:
* examples/jpeg/bits.h:
* examples/jpeg/huffman.c:
* examples/jpeg/huffman.h:
* examples/jpeg/jpeg.c:
* examples/jpeg/jpeg.h:
* examples/jpeg/jpeg_bits.c:
* examples/jpeg/jpeg_internal.h:
* examples/jpeg/jpeg_markers.h:
* examples/jpeg/jpeg_tables.c:
* examples/jpeg/test.c:
* examples/jpeg/test_rgb.c:
Major hacking on the jpeg decoder.
Diffstat (limited to 'examples')
-rw-r--r-- | examples/jpeg/Makefile.am | 2 | ||||
-rw-r--r-- | examples/jpeg/bits.h | 128 | ||||
-rw-r--r-- | examples/jpeg/huffman.c | 34 | ||||
-rw-r--r-- | examples/jpeg/huffman.h | 10 | ||||
-rw-r--r-- | examples/jpeg/jpeg.c | 783 | ||||
-rw-r--r-- | examples/jpeg/jpeg.h | 52 | ||||
-rw-r--r-- | examples/jpeg/jpeg_bits.c | 154 | ||||
-rw-r--r-- | examples/jpeg/jpeg_internal.h | 60 | ||||
-rw-r--r-- | examples/jpeg/jpeg_markers.h | 44 | ||||
-rw-r--r-- | examples/jpeg/jpeg_tables.c | 54 | ||||
-rw-r--r-- | examples/jpeg/test.c | 2 | ||||
-rw-r--r-- | examples/jpeg/test_rgb.c | 2 |
12 files changed, 820 insertions, 505 deletions
diff --git a/examples/jpeg/Makefile.am b/examples/jpeg/Makefile.am index c244c74..433d213 100644 --- a/examples/jpeg/Makefile.am +++ b/examples/jpeg/Makefile.am @@ -3,7 +3,7 @@ noinst_LTLIBRARIES = libjpeg.la noinst_PROGRAMS = jpeg_test jpeg_rgb_test -libjpeg_la_SOURCES = jpeg.c huffman.c jpeg_rgb_decoder.c +libjpeg_la_SOURCES = jpeg.c jpeg_bits.c huffman.c jpeg_rgb_decoder.c jpeg_tables.c libjpeg_la_CFLAGS = $(LIBOIL_CFLAGS) noinst_HEADERS = bits.h huffman.h jpeg.h jpeg_debug.h \ diff --git a/examples/jpeg/bits.h b/examples/jpeg/bits.h index 95f4e90..90cdcec 100644 --- a/examples/jpeg/bits.h +++ b/examples/jpeg/bits.h @@ -2,119 +2,31 @@ #ifndef __BITS_H__ #define __BITS_H__ -typedef struct bits_struct bits_t; -struct bits_struct { +typedef struct _JpegBits JpegBits; +struct _JpegBits { unsigned char *ptr; int idx; unsigned char *end; + int error; }; -static inline int bits_needbits(bits_t *b, int n_bytes) -{ - if(b->ptr==NULL)return 1; - if(b->ptr + n_bytes > b->end)return 1; - - return 0; -} - -static inline int getbit(bits_t *b) -{ - int r; - - r = ((*b->ptr)>>(7-b->idx))&1; - - b->idx++; - if(b->idx>=8){ - b->ptr++; - b->idx = 0; - } - - return r; -} - -static inline unsigned int getbits(bits_t *b, int n) -{ - unsigned long r = 0; - int i; - - for(i=0;i<n;i++){ - r <<=1; - r |= getbit(b); - } - - return r; -} - -static inline unsigned int peekbits(bits_t *b, int n) -{ - bits_t tmp = *b; - - return getbits(&tmp, n); -} - -static inline int getsbits(bits_t *b, int n) -{ - unsigned long r = 0; - int i; - - if(n==0)return 0; - r = -getbit(b); - for(i=1;i<n;i++){ - r <<=1; - r |= getbit(b); - } - - return r; -} - -static inline unsigned int peek_u8(bits_t *b) -{ - return *b->ptr; -} - -static inline unsigned int get_u8(bits_t *b) -{ - return *b->ptr++; -} - -static inline unsigned int get_u16(bits_t *b) -{ - unsigned int r; - - r = b->ptr[0] | (b->ptr[1]<<8); - b->ptr+=2; - - return r; -} - -static inline unsigned int get_be_u16(bits_t *b) -{ - unsigned int r; - - r = (b->ptr[0]<<8) | b->ptr[1]; - b->ptr+=2; - - return r; -} - -static inline unsigned int get_u32(bits_t *b) -{ - unsigned int r; - - r = b->ptr[0] | (b->ptr[1]<<8) | (b->ptr[2]<<16) | (b->ptr[3]<<24); - b->ptr+=4; - - return r; -} - -static inline void syncbits(bits_t *b) -{ - if(b->idx){ - b->ptr++; - b->idx=0; - } - -} +int jpeg_bits_error (JpegBits *bits); +int jpeg_bits_get_u8 (JpegBits *bits); +void jpeg_bits_skip (JpegBits *bits, int n); +int jpeg_bits_get_u16_be (JpegBits *bits); +int jpeg_bits_available (JpegBits *bits); + +int bits_needbits(JpegBits *b, int n_bytes); +int getbit(JpegBits *b); +unsigned int getbits(JpegBits *b, int n); +unsigned int peekbits(JpegBits *b, int n); +int getsbits(JpegBits *b, int n); +unsigned int peek_u8(JpegBits *b); +unsigned int get_u8(JpegBits *b); +unsigned int get_u16(JpegBits *b); +unsigned int get_be_u16(JpegBits *b); +unsigned int get_u32(JpegBits *b); +void syncbits(JpegBits *b); #endif diff --git a/examples/jpeg/huffman.c b/examples/jpeg/huffman.c index e69c552..b978e83 100644 --- a/examples/jpeg/huffman.c +++ b/examples/jpeg/huffman.c @@ -12,8 +12,6 @@ #include "huffman.h" #include "jpeg_debug.h" -#define DEBUG printf - /* misc helper function definitions */ static char *sprintbits (char *str, unsigned int bits, int n); @@ -41,21 +39,10 @@ huffman_table_dump (HuffmanTable * table) } } -HuffmanTable * -huffman_table_new (void) -{ - HuffmanTable *table; - - table = malloc (sizeof(HuffmanTable)); - memset (table, 0, sizeof(HuffmanTable)); - - return table; -} - void -huffman_table_free (HuffmanTable * table) +huffman_table_init (HuffmanTable *table) { - free (table); + memset (table, 0, sizeof(HuffmanTable)); } void @@ -72,7 +59,7 @@ huffman_table_add (HuffmanTable * table, uint32_t code, int n_bits, int value) } unsigned int -huffman_table_decode_jpeg (HuffmanTable * tab, bits_t * bits) +huffman_table_decode_jpeg (HuffmanTable * tab, JpegBits * bits) { unsigned int code; int i; @@ -96,7 +83,7 @@ huffman_table_decode_jpeg (HuffmanTable * tab, bits_t * bits) int huffman_table_decode_macroblock (short *block, HuffmanTable * dc_tab, - HuffmanTable * ac_tab, bits_t * bits) + HuffmanTable * ac_tab, JpegBits * bits) { int r, s, x, rs; int k; @@ -154,24 +141,15 @@ huffman_table_decode_macroblock (short *block, HuffmanTable * dc_tab, int huffman_table_decode (HuffmanTable * dc_tab, HuffmanTable * ac_tab, - bits_t * bits) + JpegBits * bits) { - short zz[64]; + int16_t zz[64]; int ret; - int i; - short *q; while (bits->ptr < bits->end) { ret = huffman_table_decode_macroblock (zz, dc_tab, ac_tab, bits); if (ret < 0) return -1; - - q = zz; - for (i = 0; i < 8; i++) { - DEBUG ("%3d %3d %3d %3d %3d %3d %3d %3d", - q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7]); - q += 8; - } } return 0; diff --git a/examples/jpeg/huffman.h b/examples/jpeg/huffman.h index e3bd94a..97507f5 100644 --- a/examples/jpeg/huffman.h +++ b/examples/jpeg/huffman.h @@ -22,15 +22,15 @@ struct _HuffmanTable { }; +void huffman_table_init(HuffmanTable *table); + void huffman_table_dump(HuffmanTable *table); -HuffmanTable *huffman_table_new(void); -void huffman_table_free(HuffmanTable *table); void huffman_table_add(HuffmanTable *table, uint32_t code, int n_bits, int value); -unsigned int huffman_table_decode_jpeg(HuffmanTable *tab, bits_t *bits); +unsigned int huffman_table_decode_jpeg(HuffmanTable *tab, JpegBits *bits); int huffman_table_decode_macroblock(short *block, HuffmanTable *dc_tab, - HuffmanTable *ac_tab, bits_t *bits); -int huffman_table_decode(HuffmanTable *dc_tab, HuffmanTable *ac_tab, bits_t *bits); + HuffmanTable *ac_tab, JpegBits *bits); +int huffman_table_decode(HuffmanTable *dc_tab, HuffmanTable *ac_tab, JpegBits *bits); #endif diff --git a/examples/jpeg/jpeg.c b/examples/jpeg/jpeg.c index afe5489..8030095 100644 --- a/examples/jpeg/jpeg.c +++ b/examples/jpeg/jpeg.c @@ -18,302 +18,152 @@ #define MAX(a,b) ((a)>(b) ? (a) : (b)) -#define JPEG_MARKER_STUFFED 0x00 -#define JPEG_MARKER_TEM 0x01 -#define JPEG_MARKER_RES 0x02 - -#define JPEG_MARKER_SOF_0 0xc0 -#define JPEG_MARKER_SOF_1 0xc1 -#define JPEG_MARKER_SOF_2 0xc2 -#define JPEG_MARKER_SOF_3 0xc3 -#define JPEG_MARKER_DHT 0xc4 -#define JPEG_MARKER_SOF_5 0xc5 -#define JPEG_MARKER_SOF_6 0xc6 -#define JPEG_MARKER_SOF_7 0xc7 -#define JPEG_MARKER_JPG 0xc8 -#define JPEG_MARKER_SOF_9 0xc9 -#define JPEG_MARKER_SOF_10 0xca -#define JPEG_MARKER_SOF_11 0xcb -#define JPEG_MARKER_DAC 0xcc -#define JPEG_MARKER_SOF_13 0xcd -#define JPEG_MARKER_SOF_14 0xce -#define JPEG_MARKER_SOF_15 0xcf - -#define JPEG_MARKER_RST_0 0xd0 -#define JPEG_MARKER_RST_1 0xd1 -#define JPEG_MARKER_RST_2 0xd2 -#define JPEG_MARKER_RST_3 0xd3 -#define JPEG_MARKER_RST_4 0xd4 -#define JPEG_MARKER_RST_5 0xd5 -#define JPEG_MARKER_RST_6 0xd6 -#define JPEG_MARKER_RST_7 0xd7 -#define JPEG_MARKER_SOI 0xd8 -#define JPEG_MARKER_EOI 0xd9 -#define JPEG_MARKER_SOS 0xda -#define JPEG_MARKER_DQT 0xdb -#define JPEG_MARKER_DNL 0xdc -#define JPEG_MARKER_DRI 0xdd -#define JPEG_MARKER_DHP 0xde -#define JPEG_MARKER_EXP 0xdf -#define JPEG_MARKER_APP(x) (0xe0 + (x)) -#define JPEG_MARKER_JPG_(x) (0xf0 + (x)) -#define JPEG_MARKER_COM 0xfe - -#define JPEG_MARKER_JFIF JPEG_MARKER_APP(0) - -struct jpeg_marker_struct -{ - int tag; - int (*func) (JpegDecoder * dec, bits_t * bits); - char *name; - unsigned int flags; -}; -static struct jpeg_marker_struct jpeg_markers[] = { - {0xc0, jpeg_decoder_sof_baseline_dct, - "baseline DCT"}, - {0xc4, jpeg_decoder_define_huffman_table, - "define Huffman table(s)"}, - {0xd8, jpeg_decoder_soi, - "start of image"}, - {0xd9, jpeg_decoder_eoi, - "end of image"}, - {0xda, jpeg_decoder_sos, - "start of scan", JPEG_ENTROPY_SEGMENT}, - {0xdb, jpeg_decoder_define_quant_table, - "define quantization table"}, - {0xe0, jpeg_decoder_application0, - "application segment 0"}, - - {0x00, NULL, "illegal"}, - {0x01, NULL, "TEM"}, - {0x02, NULL, "RES"}, - - {0xc1, NULL, "extended sequential DCT"}, - {0xc2, NULL, "progressive DCT"}, - {0xc3, NULL, "lossless (sequential)"}, - {0xc5, NULL, "differential sequential DCT"}, - {0xc6, NULL, "differential progressive DCT"}, - {0xc7, NULL, "differential lossless (sequential)"}, - {0xc8, NULL, "reserved"}, - {0xc9, NULL, "extended sequential DCT (arith)"}, - {0xca, NULL, "progressive DCT (arith)"}, - {0xcb, NULL, "lossless (sequential) (arith)"}, - {0xcc, NULL, "define arithmetic coding conditioning(s)"}, - {0xcd, NULL, "differential sequential DCT (arith)"}, - {0xce, NULL, "differential progressive DCT (arith)"}, - {0xcf, NULL, "differential lossless (sequential) (arith)"}, - - {0xd0, jpeg_decoder_restart, "restart0", JPEG_ENTROPY_SEGMENT}, - {0xd1, jpeg_decoder_restart, "restart1", JPEG_ENTROPY_SEGMENT}, - {0xd2, jpeg_decoder_restart, "restart2", JPEG_ENTROPY_SEGMENT}, - {0xd3, jpeg_decoder_restart, "restart3", JPEG_ENTROPY_SEGMENT}, - {0xd4, jpeg_decoder_restart, "restart4", JPEG_ENTROPY_SEGMENT}, - {0xd5, jpeg_decoder_restart, "restart5", JPEG_ENTROPY_SEGMENT}, - {0xd6, jpeg_decoder_restart, "restart6", JPEG_ENTROPY_SEGMENT}, - {0xd7, jpeg_decoder_restart, "restart7", JPEG_ENTROPY_SEGMENT}, - - {0xdc, NULL, "define number of lines"}, - {0xdd, jpeg_decoder_restart_interval, "define restart interval"}, - {0xde, NULL, "define hierarchical progression"}, - {0xdf, NULL, "expand reference component(s)"}, - - {0xe1, jpeg_decoder_application_misc, "application segment 1"}, - {0xe2, jpeg_decoder_application_misc, "application segment 2"}, - {0xe3, jpeg_decoder_application_misc, "application segment 3"}, - {0xe4, jpeg_decoder_application_misc, "application segment 4"}, - {0xe5, jpeg_decoder_application_misc, "application segment 5"}, - {0xe6, jpeg_decoder_application_misc, "application segment 6"}, - {0xe7, jpeg_decoder_application_misc, "application segment 7"}, - {0xe8, jpeg_decoder_application_misc, "application segment 8"}, - {0xe9, jpeg_decoder_application_misc, "application segment 9"}, - {0xea, jpeg_decoder_application_misc, "application segment a"}, - {0xeb, jpeg_decoder_application_misc, "application segment b"}, - {0xec, jpeg_decoder_application_misc, "application segment c"}, - {0xed, jpeg_decoder_application_misc, "application segment d"}, - {0xee, jpeg_decoder_application_misc, "application segment e"}, - {0xef, jpeg_decoder_application_misc, "application segment f"}, - - {0xf0, NULL, "JPEG extension 0"}, - {0xfe, jpeg_decoder_comment, "comment"}, - - {0x00, NULL, "illegal"}, -}; -static const int n_jpeg_markers = - sizeof (jpeg_markers) / sizeof (jpeg_markers[0]); - -static unsigned char std_tables[] = { - 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, - - 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, -}; +extern uint8_t jpeg_standard_tables[]; +extern int jpeg_standard_tables_size; + +void jpeg_decoder_error(JpegDecoder *dec, char *fmt, ...); + +void jpeg_decoder_define_huffman_tables (JpegDecoder * dec); +void jpeg_decoder_define_arithmetic_conditioning (JpegDecoder *dec); +void jpeg_decoder_define_quantization_tables (JpegDecoder *dec); +void jpeg_decoder_define_restart_interval (JpegDecoder *dec); + +void jpeg_decoder_start_of_frame (JpegDecoder * dec, int marker); /* misc helper function declarations */ -static void dumpbits (bits_t * bits); +static void dumpbits (JpegBits * bits); static char *sprintbits (char *str, unsigned int bits, int n); static void huffman_table_load_std_jpeg (JpegDecoder * dec); +static void jpeg_decoder_verify_header (JpegDecoder *dec); +static void jpeg_decoder_calculate_stuff (JpegDecoder *dec); -int -jpeg_decoder_soi (JpegDecoder * dec, bits_t * bits) -{ - return 0; -} -int -jpeg_decoder_eoi (JpegDecoder * dec, bits_t * bits) -{ - return 0; -} -int -jpeg_decoder_sof_baseline_dct (JpegDecoder * dec, bits_t * bits) +static void +jpeg_decoder_verify_header (JpegDecoder *dec) { + int max_quant_table = 0; int i; - int length; - int image_size; - int rowstride; - int max_h_oversample = 0, max_v_oversample = 0; - OIL_DEBUG ("start of frame (baseline DCT)"); + if (dec->sof_type != JPEG_MARKER_SOF_0) { + OIL_ERROR("only handle baseline DCT"); + dec->error = TRUE; + } - length = get_be_u16 (bits); - bits->end = bits->ptr + length - 2; + if (dec->width < 1) { + OIL_ERROR("height can't be 0"); + dec->error = TRUE; + } - dec->depth = get_u8 (bits); - dec->height = get_be_u16 (bits); - dec->width = get_be_u16 (bits); - dec->n_components = get_u8 (bits); + switch (dec->sof_type) { + case JPEG_MARKER_SOF_0: + /* baseline DCT */ + max_quant_table = 3; + if (dec->depth != 8) { + OIL_ERROR("depth must be 8 (%d)", dec->depth); + dec->error = TRUE; + } + break; + case JPEG_MARKER_SOF_1: + /* extended DCT */ + max_quant_table = 3; + if (dec->depth != 8 && dec->depth != 12) { + OIL_ERROR("depth must be 8 or 12 (%d)", dec->depth); + dec->error = TRUE; + } + break; + case JPEG_MARKER_SOF_2: + /* progressive DCT */ + max_quant_table = 3; + if (dec->depth != 8 && dec->depth != 12) { + OIL_ERROR("depth must be 8 or 12 (%d)", dec->depth); + dec->error = TRUE; + } + break; + case JPEG_MARKER_SOF_3: + /* lossless DCT */ + max_quant_table = 0; + if (dec->depth < 2 || dec->depth > 16) { + OIL_ERROR("depth must be between 2 and 16 (%d)", dec->depth); + dec->error = TRUE; + } + break; + default: + break; + } - OIL_DEBUG ( - "frame_length=%d depth=%d height=%d width=%d n_components=%d", length, - dec->depth, dec->height, dec->width, dec->n_components); + if (dec->n_components < 0 || dec->n_components > 255) { + OIL_ERROR("n_components must be in the range 0-255 (%d)", + dec->n_components); + dec->error = TRUE; + } + if (dec->sof_type == JPEG_MARKER_SOF_2 && dec->n_components > 4) { + OIL_ERROR("n_components must be <= 4 for progressive DCT (%d)", + dec->n_components); + dec->error = TRUE; + } for (i = 0; i < dec->n_components; i++) { - dec->components[i].id = get_u8 (bits); - dec->components[i].h_oversample = getbits (bits, 4); - dec->components[i].v_oversample = getbits (bits, 4); - dec->components[i].quant_table = get_u8 (bits); + if (dec->components[i].id < 0 || dec->components[i].id > 255) { + OIL_ERROR("component ID out of range"); + dec->error = TRUE; + break; + } + if (dec->components[i].h_sample < 1 || dec->components[i].h_sample > 4 || + dec->components[i].v_sample < 1 || dec->components[i].v_sample > 4) { + OIL_ERROR("sample factor(s) for component %d out of range %d %d", + i, dec->components[i].h_sample, dec->components[i].v_sample); + dec->error = TRUE; + break; + } + if (dec->components[i].quant_table < 0 || + dec->components[i].quant_table > max_quant_table) { + OIL_ERROR("quant table for component %d out of range (%d)", + i, dec->components[i].quant_table); + dec->error = TRUE; + break; + } + } +} - OIL_DEBUG ( - "[%d] id=%d h_oversample=%d v_oversample=%d quant_table=%d", i, - dec->components[i].id, dec->components[i].h_oversample, - dec->components[i].v_oversample, dec->components[i].quant_table); +static void +jpeg_decoder_calculate_stuff (JpegDecoder *dec) +{ + int max_h_sample = 0; + int max_v_sample = 0; + int i; - max_h_oversample = MAX (max_h_oversample, dec->components[i].h_oversample); - max_v_oversample = MAX (max_v_oversample, dec->components[i].v_oversample); + for (i=0; i < dec->n_components; i++) { + max_h_sample = MAX (max_h_sample, dec->components[i].h_sample); + max_v_sample = MAX (max_v_sample, dec->components[i].v_sample); } + dec->width_blocks = - (dec->width + 8 * max_h_oversample - 1) / (8 * max_h_oversample); + (dec->width + 8 * max_h_sample - 1) / (8 * max_h_sample); dec->height_blocks = - (dec->height + 8 * max_v_oversample - 1) / (8 * max_v_oversample); + (dec->height + 8 * max_v_sample - 1) / (8 * max_v_sample); for (i = 0; i < dec->n_components; i++) { - dec->components[i].h_subsample = max_h_oversample / - dec->components[i].h_oversample; - dec->components[i].v_subsample = max_v_oversample / - dec->components[i].v_oversample; + dec->components[i].h_subsample = max_h_sample / + dec->components[i].h_sample; + dec->components[i].v_subsample = max_v_sample / + dec->components[i].v_sample; - rowstride = dec->width_blocks * 8 * max_h_oversample / +#if 0 + rowstride = dec->width_blocks * 8 * max_h_sample / dec->components[i].h_subsample; image_size = rowstride * - (dec->height_blocks * 8 * max_v_oversample / + (dec->height_blocks * 8 * max_v_sample / dec->components[i].v_subsample); dec->components[i].rowstride = rowstride; dec->components[i].image = malloc (image_size); +#endif } - - if (bits->end != bits->ptr) - OIL_DEBUG ("endptr != bits"); - - return length; } -int -jpeg_decoder_define_quant_table (JpegDecoder * dec, bits_t * bits) -{ - int length; - int pq; - int tq; - int i; - short *q; - - OIL_DEBUG ("define quantization table"); - - length = get_be_u16 (bits); - bits->end = bits->ptr + length - 2; - - while (bits->ptr < bits->end) { - pq = getbits (bits, 4); - tq = getbits (bits, 4); - - q = dec->quant_table[tq]; - if (pq) { - for (i = 0; i < 64; i++) { - q[i] = get_be_u16 (bits); - } - } else { - for (i = 0; i < 64; i++) { - q[i] = get_u8 (bits); - } - } - - OIL_DEBUG ("quant table index %d:", tq); - for (i = 0; i < 8; i++) { - OIL_DEBUG ("%3d %3d %3d %3d %3d %3d %3d %3d", - q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7]); - q += 8; - } - } - - return length; -} void generate_code_table (int *huffsize) @@ -340,23 +190,24 @@ generate_code_table (int *huffsize) } -HuffmanTable * -huffman_table_new_jpeg (bits_t * bits) +int +huffman_table_init_jpeg (HuffmanTable *table, JpegBits * bits) { int n_symbols; int huffsize[16]; int i, j, k; - HuffmanTable *table; unsigned int symbol; + int n = 0; - table = huffman_table_new (); + huffman_table_init (table); /* huffsize[i] is the number of symbols that have length * (i+1) bits. Maximum bit length is 16 bits, so there are * 16 entries. */ n_symbols = 0; for (i = 0; i < 16; i++) { - huffsize[i] = get_u8 (bits); + huffsize[i] = jpeg_bits_get_u8 (bits); + n++; n_symbols += huffsize[i]; } @@ -369,7 +220,8 @@ huffman_table_new_jpeg (bits_t * bits) k = 0; for (i = 0; i < 16; i++) { for (j = 0; j < huffsize[i]; j++) { - huffman_table_add (table, symbol, i + 1, get_u8 (bits)); + huffman_table_add (table, symbol, i + 1, jpeg_bits_get_u8 (bits)); + n++; symbol++; k++; } @@ -377,8 +229,9 @@ huffman_table_new_jpeg (bits_t * bits) * number of bits we think it is. This is only triggered * for bad huffsize[] arrays. */ if (symbol >= (1 << (i + 1))) { + /* FIXME jpeg_decoder_error() */ OIL_DEBUG ("bad huffsize[] array"); - return NULL; + return -1; } symbol <<= 1; @@ -386,48 +239,11 @@ huffman_table_new_jpeg (bits_t * bits) huffman_table_dump (table); - return table; -} - -int -jpeg_decoder_define_huffman_table (JpegDecoder * dec, bits_t * bits) -{ - int length; - int tc; - int th; - HuffmanTable *hufftab; - - OIL_DEBUG ("define huffman table"); - - length = get_be_u16 (bits); - bits->end = bits->ptr + length - 2; - - while (bits->ptr < bits->end) { - tc = getbits (bits, 4); - th = getbits (bits, 4); - - OIL_DEBUG ("huff table index %d:", th); - OIL_DEBUG ("type %d (%s)", tc, tc ? "ac" : "dc"); - - hufftab = huffman_table_new_jpeg (bits); - if (tc) { - if (dec->ac_huff_table[th]) { - huffman_table_free (dec->ac_huff_table[th]); - } - dec->ac_huff_table[th] = hufftab; - } else { - if (dec->dc_huff_table[th]) { - huffman_table_free (dec->dc_huff_table[th]); - } - dec->dc_huff_table[th] = hufftab; - } - } - - return length; + return n; } static void -dumpbits (bits_t * bits) +dumpbits (JpegBits * bits) { int i; int j; @@ -461,7 +277,7 @@ jpeg_decoder_find_component_by_id (JpegDecoder * dec, int id) } int -jpeg_decoder_sos (JpegDecoder * dec, bits_t * bits) +jpeg_decoder_sos (JpegDecoder * dec, JpegBits * bits) { int length; int i; @@ -499,8 +315,8 @@ jpeg_decoder_sos (JpegDecoder * dec, bits_t * bits) ac_table = getbits (bits, 4); index = jpeg_decoder_find_component_by_id (dec, component_id); - h_subsample = dec->components[index].h_oversample; - v_subsample = dec->components[index].v_oversample; + h_subsample = dec->components[index].h_sample; + v_subsample = dec->components[index].v_sample; quant_index = dec->components[index].quant_table; for (y = 0; y < v_subsample; y++) { @@ -546,7 +362,7 @@ jpeg_decoder_sos (JpegDecoder * dec, bits_t * bits) } int -jpeg_decoder_application0 (JpegDecoder * dec, bits_t * bits) +jpeg_decoder_application0 (JpegDecoder * dec, JpegBits * bits) { int length; @@ -591,7 +407,7 @@ jpeg_decoder_application0 (JpegDecoder * dec, bits_t * bits) } int -jpeg_decoder_application_misc (JpegDecoder * dec, bits_t * bits) +jpeg_decoder_application_misc (JpegDecoder * dec, JpegBits * bits) { int length; @@ -609,7 +425,7 @@ jpeg_decoder_application_misc (JpegDecoder * dec, bits_t * bits) } int -jpeg_decoder_comment (JpegDecoder * dec, bits_t * bits) +jpeg_decoder_comment (JpegDecoder * dec, JpegBits * bits) { int length; @@ -626,7 +442,7 @@ jpeg_decoder_comment (JpegDecoder * dec, bits_t * bits) } int -jpeg_decoder_restart_interval (JpegDecoder * dec, bits_t * bits) +jpeg_decoder_restart_interval (JpegDecoder * dec, JpegBits * bits) { int length; @@ -642,7 +458,7 @@ jpeg_decoder_restart_interval (JpegDecoder * dec, bits_t * bits) } int -jpeg_decoder_restart (JpegDecoder * dec, bits_t * bits) +jpeg_decoder_restart (JpegDecoder * dec, JpegBits * bits) { OIL_DEBUG ("restart"); @@ -650,9 +466,9 @@ jpeg_decoder_restart (JpegDecoder * dec, bits_t * bits) } void -jpeg_decoder_decode_entropy_segment (JpegDecoder * dec, bits_t * bits) +jpeg_decoder_decode_entropy_segment (JpegDecoder * dec, JpegBits * bits) { - bits_t b2, *bits2 = &b2; + JpegBits b2, *bits2 = &b2; short block[64]; short block2[64]; unsigned char *newptr; @@ -716,8 +532,8 @@ jpeg_decoder_decode_entropy_segment (JpegDecoder * dec, bits_t * bits) quant_index = dec->scan_list[i].quant_table; ret = huffman_table_decode_macroblock (block, - dec->dc_huff_table[dc_table_index], - dec->ac_huff_table[ac_table_index], bits2); + &dec->dc_huff_table[dc_table_index], + &dec->ac_huff_table[ac_table_index], bits2); if (ret < 0) { OIL_DEBUG ("%d,%d: component=%d dc_table=%d ac_table=%d", x, y, @@ -728,7 +544,7 @@ jpeg_decoder_decode_entropy_segment (JpegDecoder * dec, bits_t * bits) } OIL_DEBUG ("using quant table %d", quant_index); - oil_mult8x8_s16 (block2, block, dec->quant_table[quant_index], + oil_mult8x8_s16 (block2, block, dec->quant_tables[quant_index].quantizer, sizeof (short) * 8, sizeof(short) * 8, sizeof (short) * 8); dec->dc[component_index] += block2[0]; block2[0] = dec->dc[component_index]; @@ -738,10 +554,10 @@ jpeg_decoder_decode_entropy_segment (JpegDecoder * dec, bits_t * bits) oil_trans8x8_s16 (block, sizeof (short) * 8, block2, sizeof (short) * 8); ptr = dec->components[component_index].image + - x * dec->components[component_index].h_oversample + + x * dec->components[component_index].h_sample + dec->scan_list[i].offset + dec->components[component_index].rowstride * y * - dec->components[component_index].v_oversample; + dec->components[component_index].v_sample; oil_clipconv8x8_u8_s16 (ptr, dec->components[component_index].rowstride, @@ -783,12 +599,7 @@ jpeg_decoder_free (JpegDecoder * dec) { int i; - huffman_table_free (dec->dc_huff_table[0]); - huffman_table_free (dec->ac_huff_table[0]); - huffman_table_free (dec->dc_huff_table[1]); - huffman_table_free (dec->ac_huff_table[1]); - - for (i = 0; i < JPEG_N_COMPONENTS; i++) { + for (i = 0; i < JPEG_MAX_COMPONENTS; i++) { if (dec->components[i].image) free (dec->components[i].image); } @@ -799,6 +610,298 @@ jpeg_decoder_free (JpegDecoder * dec) free (dec); } +void +jpeg_decoder_error(JpegDecoder *dec, char *fmt, ...) +{ + /* FIXME */ + dec->error_message = strdup(fmt); + OIL_ERROR("decoder error: %d", fmt); + dec->error = TRUE; +} + +int +jpeg_decoder_get_marker (JpegDecoder *dec, int *marker) +{ + int a,b; + JpegBits *bits = &dec->bits; + + a = jpeg_bits_get_u8(bits); + if (a != 0xff) { + jpeg_decoder_error(dec, "expected marker"); + return FALSE; + } + + do { + b = jpeg_bits_get_u8 (bits); + } while (b == 0xff && jpeg_bits_error(bits)); + + *marker = b; + return TRUE; +} + +void +jpeg_decoder_skip (JpegDecoder *dec) +{ + int length; + + length = jpeg_bits_get_u16_be (&dec->bits); + jpeg_bits_skip (&dec->bits, length - 2); +} + +int +jpeg_decoder_decode (JpegDecoder *dec) +{ + JpegBits *bits; + int marker; + + dec->error = FALSE; + + bits = &dec->bits; + + /* Note: The spec is ambiguous as to whether fill bytes can preceed + * the first marker. We'll assume yes. */ + if (!jpeg_decoder_get_marker (dec, &marker)) { + return FALSE; + } + if (marker != JPEG_MARKER_SOI) { + jpeg_decoder_error(dec, "not a JPEG image"); + return FALSE; + } + + /* Interpret markers up to the start of frame */ + while (1) { + if (!jpeg_decoder_get_marker (dec, &marker)) { + return FALSE; + } + + if (marker == JPEG_MARKER_DEFINE_HUFFMAN_TABLES) { + jpeg_decoder_define_huffman_tables (dec); + } else if (marker == JPEG_MARKER_DEFINE_ARITHMETIC_CONDITIONING) { + jpeg_decoder_define_arithmetic_conditioning (dec); + } else if (marker == JPEG_MARKER_DEFINE_QUANTIZATION_TABLES) { + jpeg_decoder_define_quantization_tables (dec); + } else if (marker == JPEG_MARKER_DEFINE_RESTART_INTERVAL) { + jpeg_decoder_define_restart_interval (dec); + } else if (JPEG_MARKER_IS_APP(marker)) { + /* FIXME decode app segment */ + jpeg_decoder_skip (dec); + } else if (marker == JPEG_MARKER_COMMENT) { + jpeg_decoder_skip (dec); + } else if (JPEG_MARKER_IS_START_OF_FRAME(marker)) { + break; + } else { + jpeg_decoder_error(dec, "unexpected marker 0x%02x", marker); + return FALSE; + } + } + + jpeg_decoder_start_of_frame(dec, marker); + + jpeg_decoder_verify_header (dec); + jpeg_decoder_calculate_stuff (dec); + + /* In this section, we loop over parse units until we reach the end + * of the image. */ + while (1) { + if (!jpeg_decoder_get_marker (dec, &marker)) { + return FALSE; + } + + /* FIXME */ + if (marker == JPEG_MARKER_EOI) { + return TRUE; + } + /* decode frame */ + /* FIXME */ + //jpeg_decoder_decode_frame (dec); + } + + return TRUE; +} + +/* handle markers */ + +void +jpeg_decoder_define_huffman_tables (JpegDecoder * dec) +{ + JpegBits *bits = &dec->bits; + int length; + int tc; + int th; + int x; + HuffmanTable *hufftab; + + OIL_DEBUG ("define huffman tables"); + + length = jpeg_bits_get_u16_be (bits); + if (length < 2) { + jpeg_decoder_error(dec, "length too short"); + return; + } + length -= 2; + + while (length > 0) { + x = jpeg_bits_get_u8 (bits); + length--; + + tc = x >> 4; + th = x & 0xf; + + OIL_DEBUG ("huff table type %d (%s) index %d", tc, tc ? "ac" : "dc", th); + if (tc > 1 || th > 3) { + jpeg_decoder_error(dec, "huffman table type or index out of range"); + return; + } + + if (tc) { + hufftab = &dec->ac_huff_table[th]; + length -= huffman_table_init_jpeg (hufftab, bits); + } else { + hufftab = &dec->dc_huff_table[th]; + length -= huffman_table_init_jpeg (hufftab, bits); + } + } + if (length < 0) { + jpeg_decoder_error(dec, "huffman table overran available bytes"); + return; + } +} + +void +jpeg_decoder_define_quantization_tables (JpegDecoder *dec) +{ + JpegBits *bits = &dec->bits; + JpegQuantTable *table; + int length; + int pq; + int tq; + int i; + + OIL_INFO ("define quantization table"); + + length = jpeg_bits_get_u16_be (bits); + if (length < 2) { + jpeg_decoder_error(dec, "length too short"); + return; + } + length -= 2; + + while (length > 0) { + int x; + + x = jpeg_bits_get_u8 (bits); + length--; + pq = x >> 4; + tq = x & 0xf; + + if (pq > 1) { + jpeg_decoder_error (dec, "bad pq value"); + return; + } + if (tq > 3) { + jpeg_decoder_error (dec, "bad tq value"); + return; + } + + table = &dec->quant_tables[tq]; + if (pq) { + for (i = 0; i < 64; i++) { + table->quantizer[i] = jpeg_bits_get_u16_be (bits); + length -= 2; + } + } else { + for (i = 0; i < 64; i++) { + table->quantizer[i] = jpeg_bits_get_u8 (bits); + length -= 1; + } + } + } + if (length < 0) { + jpeg_decoder_error(dec, "quantization table overran available bytes"); + return; + } +} + +void +jpeg_decoder_define_restart_interval (JpegDecoder *dec) +{ + JpegBits *bits = &dec->bits; + int length; + + length = jpeg_bits_get_u16_be (bits); + if (length != 4) { + jpeg_decoder_error(dec, "length supposed to be 4 (%d)", length); + return; + } + + /* FIXME this needs to be checked somewhere */ + dec->restart_interval = jpeg_bits_get_u16_be (bits); +} + +void +jpeg_decoder_define_arithmetic_conditioning (JpegDecoder *dec) +{ + /* we don't handle arithmetic coding, so skip it */ + jpeg_decoder_skip (dec); +} + +void +jpeg_decoder_start_of_frame (JpegDecoder * dec, int marker) +{ + JpegBits *bits = &dec->bits; + int i; + int length; + + OIL_INFO ("start of frame"); + + dec->sof_type = marker; + + length = jpeg_bits_get_u16_be (bits); + + if (jpeg_bits_available(bits) < length) { + jpeg_decoder_error(dec, "not enough data for start_of_frame (%d < %d)", + length, jpeg_bits_available(bits)); + return; + } + + dec->depth = jpeg_bits_get_u8 (bits); + dec->height = jpeg_bits_get_u16_be (bits); + dec->width = jpeg_bits_get_u16_be (bits); + dec->n_components = jpeg_bits_get_u8 (bits); + + OIL_DEBUG ( + "frame_length=%d depth=%d height=%d width=%d n_components=%d", length, + dec->depth, dec->height, dec->width, dec->n_components); + + if (dec->n_components * 3 + 8 != length) { + jpeg_decoder_error(dec, "inconsistent header"); + return; + } + + for (i = 0; i < dec->n_components; i++) { + dec->components[i].id = get_u8 (bits); + dec->components[i].h_sample = getbits (bits, 4); + dec->components[i].v_sample = getbits (bits, 4); + dec->components[i].quant_table = get_u8 (bits); + + OIL_DEBUG ( + "[%d] id=%d h_sample=%d v_sample=%d quant_table=%d", i, + dec->components[i].id, dec->components[i].h_sample, + dec->components[i].v_sample, dec->components[i].quant_table); + } +} + + + + + + + + + + + + int jpeg_decoder_addbits (JpegDecoder * dec, unsigned char *data, unsigned int len) { @@ -874,11 +977,12 @@ jpeg_decoder_get_component_subsampling (JpegDecoder * dec, int id, return 0; } +#if 0 int jpeg_decoder_parse (JpegDecoder * dec) { - bits_t *bits = &dec->bits; - bits_t b2; + JpegBits *bits = &dec->bits; + JpegBits b2; unsigned int x; unsigned int tag; int i; @@ -923,6 +1027,7 @@ jpeg_decoder_parse (JpegDecoder * dec) return 0; } +#endif /* misc helper functins */ @@ -945,15 +1050,17 @@ sprintbits (char *str, unsigned int bits, int n) static void huffman_table_load_std_jpeg (JpegDecoder * dec) { - bits_t b, *bits = &b; + JpegBits b, *bits = &b; - bits->ptr = std_tables; + bits->ptr = jpeg_standard_tables; bits->idx = 0; - bits->end = std_tables + sizeof (std_tables); + bits->end = jpeg_standard_tables + jpeg_standard_tables_size; - dec->dc_huff_table[0] = huffman_table_new_jpeg (bits); - dec->ac_huff_table[0] = huffman_table_new_jpeg (bits); - dec->dc_huff_table[1] = huffman_table_new_jpeg (bits); - dec->ac_huff_table[1] = huffman_table_new_jpeg (bits); + huffman_table_init_jpeg (&dec->dc_huff_table[0], bits); + huffman_table_init_jpeg (&dec->ac_huff_table[0], bits); + huffman_table_init_jpeg (&dec->dc_huff_table[1], bits); + huffman_table_init_jpeg (&dec->ac_huff_table[1], bits); } + + diff --git a/examples/jpeg/jpeg.h b/examples/jpeg/jpeg.h index fac03bc..de6b235 100644 --- a/examples/jpeg/jpeg.h +++ b/examples/jpeg/jpeg.h @@ -2,13 +2,63 @@ #ifndef _JPEG_DECODER_H_ #define _JPEG_DECODER_H_ + +#define JPEG_MARKER_STUFFED 0x00 +#define JPEG_MARKER_TEM 0x01 +#define JPEG_MARKER_RES 0x02 + +#define JPEG_MARKER_SOF_0 0xc0 +#define JPEG_MARKER_SOF_1 0xc1 +#define JPEG_MARKER_SOF_2 0xc2 +#define JPEG_MARKER_SOF_3 0xc3 +#define JPEG_MARKER_DEFINE_HUFFMAN_TABLES 0xc4 +#define JPEG_MARKER_SOF_5 0xc5 +#define JPEG_MARKER_SOF_6 0xc6 +#define JPEG_MARKER_SOF_7 0xc7 +#define JPEG_MARKER_JPG 0xc8 +#define JPEG_MARKER_SOF_9 0xc9 +#define JPEG_MARKER_SOF_10 0xca +#define JPEG_MARKER_SOF_11 0xcb +#define JPEG_MARKER_DEFINE_ARITHMETIC_CONDITIONING 0xcc +#define JPEG_MARKER_SOF_13 0xcd +#define JPEG_MARKER_SOF_14 0xce +#define JPEG_MARKER_SOF_15 0xcf + +#define JPEG_MARKER_RST_0 0xd0 +#define JPEG_MARKER_RST_1 0xd1 +#define JPEG_MARKER_RST_2 0xd2 +#define JPEG_MARKER_RST_3 0xd3 +#define JPEG_MARKER_RST_4 0xd4 +#define JPEG_MARKER_RST_5 0xd5 +#define JPEG_MARKER_RST_6 0xd6 +#define JPEG_MARKER_RST_7 0xd7 + +#define JPEG_MARKER_SOI 0xd8 +#define JPEG_MARKER_EOI 0xd9 +#define JPEG_MARKER_SOS 0xda +#define JPEG_MARKER_DEFINE_QUANTIZATION_TABLES 0xdb +#define JPEG_MARKER_DNL 0xdc +#define JPEG_MARKER_DEFINE_RESTART_INTERVAL 0xdd +#define JPEG_MARKER_DHP 0xde +#define JPEG_MARKER_EXP 0xdf +#define JPEG_MARKER_APP(x) (0xe0 + (x)) +#define JPEG_MARKER_JPG_(x) (0xf0 + (x)) +#define JPEG_MARKER_COMMENT 0xfe + +#define JPEG_MARKER_JFIF JPEG_MARKER_APP(0) + +#define JPEG_MARKER_IS_START_OF_FRAME(x) ((x)>=0xc0 && (x) <= 0xcf && (x)!=0xc4 && (x)!=0xc8 && (x)!=0xcc) +#define JPEG_MARKER_IS_APP(x) ((x)>=0xe0 && (x) <= 0xef) +#define JPEG_MARKER_IS_RESET(x) ((x)>=0xd0 && (x)<=0xd7) + + typedef struct _JpegDecoder JpegDecoder; JpegDecoder *jpeg_decoder_new(void); void jpeg_decoder_free(JpegDecoder *dec); int jpeg_decoder_addbits(JpegDecoder *dec, unsigned char *data, unsigned int len); -int jpeg_decoder_parse(JpegDecoder *dec); +int jpeg_decoder_decode (JpegDecoder *dec); int jpeg_decoder_get_image_size(JpegDecoder *dec, int *width, int *height); int jpeg_decoder_get_component_size(JpegDecoder *dec, int id, int *width, int *height); diff --git a/examples/jpeg/jpeg_bits.c b/examples/jpeg/jpeg_bits.c new file mode 100644 index 0000000..005bfa8 --- /dev/null +++ b/examples/jpeg/jpeg_bits.c @@ -0,0 +1,154 @@ + +#include <stdio.h> + +#include "bits.h" + +/* FIXME */ +#define TRUE 1 +#define FALSE 0 + +int jpeg_bits_error (JpegBits *bits) +{ + return bits->error; +} + +int jpeg_bits_get_u8 (JpegBits *bits) +{ + if (bits->ptr < bits->end) { + return *bits->ptr++; + } + bits->error = TRUE; + return 0; +} + +void jpeg_bits_skip (JpegBits *bits, int n) +{ + bits->ptr += n; + if (bits->ptr > bits->end) { + bits->error = TRUE; + bits->ptr = bits->end; + } +} + +int jpeg_bits_get_u16_be (JpegBits *bits) +{ + int x; + + x = jpeg_bits_get_u8 (bits) << 8; + x |= jpeg_bits_get_u8 (bits); + + return x; +} + +int jpeg_bits_available (JpegBits *bits) +{ + return bits->end - bits->ptr; +} + +int bits_needbits(JpegBits *b, int n_bytes) +{ + if(b->ptr==NULL)return 1; + if(b->ptr + n_bytes > b->end)return 1; + + return 0; +} + +int getbit(JpegBits *b) +{ + int r; + + r = ((*b->ptr)>>(7-b->idx))&1; + + b->idx++; + if(b->idx>=8){ + b->ptr++; + b->idx = 0; + } + + return r; +} + +unsigned int getbits(JpegBits *b, int n) +{ + unsigned long r = 0; + int i; + + for(i=0;i<n;i++){ + r <<=1; + r |= getbit(b); + } + + return r; +} + +unsigned int peekbits(JpegBits *b, int n) +{ + JpegBits tmp = *b; + + return getbits(&tmp, n); +} + +int getsbits(JpegBits *b, int n) +{ + unsigned long r = 0; + int i; + + if(n==0)return 0; + r = -getbit(b); + for(i=1;i<n;i++){ + r <<=1; + r |= getbit(b); + } + + return r; +} + +unsigned int peek_u8(JpegBits *b) +{ + return *b->ptr; +} + +unsigned int get_u8(JpegBits *b) +{ + return *b->ptr++; +} + +unsigned int get_u16(JpegBits *b) +{ + unsigned int r; + + r = b->ptr[0] | (b->ptr[1]<<8); + b->ptr+=2; + + return r; +} + +unsigned int get_be_u16(JpegBits *b) +{ + unsigned int r; + + r = (b->ptr[0]<<8) | b->ptr[1]; + b->ptr+=2; + + return r; +} + +unsigned int get_u32(JpegBits *b) +{ + unsigned int r; + + r = b->ptr[0] | (b->ptr[1]<<8) | (b->ptr[2]<<16) | (b->ptr[3]<<24); + b->ptr+=4; + + return r; +} + +void syncbits(JpegBits *b) +{ + if(b->idx){ + b->ptr++; + b->idx=0; + } + +} + diff --git a/examples/jpeg/jpeg_internal.h b/examples/jpeg/jpeg_internal.h index 2ff43f2..523a276 100644 --- a/examples/jpeg/jpeg_internal.h +++ b/examples/jpeg/jpeg_internal.h @@ -7,22 +7,37 @@ #include "bits.h" #include "jpeg_debug.h" +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif -//#define N_COMPONENTS 256 -#define JPEG_N_COMPONENTS 4 +#define JPEG_MAX_COMPONENTS 256 typedef struct _JpegScan JpegScan; +typedef struct _JpegQuantTable JpegQuantTable; #define JPEG_ENTROPY_SEGMENT 0x0001 #define JPEG_LENGTH 0x0002 +struct _JpegQuantTable { + int pq; + int16_t quantizer[64]; +}; + struct _JpegDecoder { int width; int height; int depth; int n_components; - bits_t bits; + JpegBits bits; + int error; + char *error_message; + + int sof_type; int width_blocks; int height_blocks; @@ -34,18 +49,19 @@ struct _JpegDecoder { struct{ int id; - int h_oversample; - int v_oversample; + int h_sample; + int v_sample; + int quant_table; + int h_subsample; int v_subsample; - int quant_table; unsigned char *image; int rowstride; - } components[JPEG_N_COMPONENTS]; + } components[JPEG_MAX_COMPONENTS]; - short quant_table[4][64]; - HuffmanTable *dc_huff_table[4]; - HuffmanTable *ac_huff_table[4]; + JpegQuantTable quant_tables[4]; + HuffmanTable dc_huff_table[4]; + HuffmanTable ac_huff_table[4]; int scan_list_length; struct{ @@ -79,18 +95,18 @@ struct _JpegScan { /* jpeg.c */ -int jpeg_decoder_sof_baseline_dct(JpegDecoder *dec, bits_t *bits); -int jpeg_decoder_define_quant_table(JpegDecoder *dec, bits_t *bits); -int jpeg_decoder_define_huffman_table(JpegDecoder *dec, bits_t *bits); -int jpeg_decoder_sos(JpegDecoder *dec, bits_t *bits); -int jpeg_decoder_soi(JpegDecoder *dec, bits_t *bits); -int jpeg_decoder_eoi(JpegDecoder *dec, bits_t *bits); -int jpeg_decoder_application0(JpegDecoder *dec, bits_t *bits); -int jpeg_decoder_application_misc(JpegDecoder *dec, bits_t *bits); -int jpeg_decoder_comment(JpegDecoder *dec, bits_t *bits); -int jpeg_decoder_restart_interval(JpegDecoder *dec, bits_t *bits); -int jpeg_decoder_restart(JpegDecoder *dec, bits_t *bits); -void jpeg_decoder_decode_entropy_segment(JpegDecoder *dec, bits_t *bits); +int jpeg_decoder_sof_baseline_dct(JpegDecoder *dec, JpegBits *bits); +int jpeg_decoder_define_quant_table(JpegDecoder *dec, JpegBits *bits); +int jpeg_decoder_define_huffman_table(JpegDecoder *dec, JpegBits *bits); +int jpeg_decoder_sos(JpegDecoder *dec, JpegBits *bits); +int jpeg_decoder_soi(JpegDecoder *dec, JpegBits *bits); +int jpeg_decoder_eoi(JpegDecoder *dec, JpegBits *bits); +int jpeg_decoder_application0(JpegDecoder *dec, JpegBits *bits); +int jpeg_decoder_application_misc(JpegDecoder *dec, JpegBits *bits); +int jpeg_decoder_comment(JpegDecoder *dec, JpegBits *bits); +int jpeg_decoder_restart_interval(JpegDecoder *dec, JpegBits *bits); +int jpeg_decoder_restart(JpegDecoder *dec, JpegBits *bits); +void jpeg_decoder_decode_entropy_segment(JpegDecoder *dec, JpegBits *bits); #endif diff --git a/examples/jpeg/jpeg_markers.h b/examples/jpeg/jpeg_markers.h new file mode 100644 index 0000000..584cb23 --- /dev/null +++ b/examples/jpeg/jpeg_markers.h @@ -0,0 +1,44 @@ + +#define JPEG_MARKER_STUFFED 0x00 +#define JPEG_MARKER_TEM 0x01 +#define JPEG_MARKER_RES 0x02 + +#define JPEG_MARKER_SOF_0 0xc0 +#define JPEG_MARKER_SOF_1 0xc1 +#define JPEG_MARKER_SOF_2 0xc2 +#define JPEG_MARKER_SOF_3 0xc3 +#define JPEG_MARKER_DHT 0xc4 +#define JPEG_MARKER_SOF_5 0xc5 +#define JPEG_MARKER_SOF_6 0xc6 +#define JPEG_MARKER_SOF_7 0xc7 +#define JPEG_MARKER_JPG 0xc8 +#define JPEG_MARKER_SOF_9 0xc9 +#define JPEG_MARKER_SOF_10 0xca +#define JPEG_MARKER_SOF_11 0xcb +#define JPEG_MARKER_DAC 0xcc +#define JPEG_MARKER_SOF_13 0xcd +#define JPEG_MARKER_SOF_14 0xce +#define JPEG_MARKER_SOF_15 0xcf + +#define JPEG_MARKER_RST_0 0xd0 +#define JPEG_MARKER_RST_1 0xd1 +#define JPEG_MARKER_RST_2 0xd2 +#define JPEG_MARKER_RST_3 0xd3 +#define JPEG_MARKER_RST_4 0xd4 +#define JPEG_MARKER_RST_5 0xd5 +#define JPEG_MARKER_RST_6 0xd6 +#define JPEG_MARKER_RST_7 0xd7 +#define JPEG_MARKER_SOI 0xd8 +#define JPEG_MARKER_EOI 0xd9 +#define JPEG_MARKER_SOS 0xda +#define JPEG_MARKER_DQT 0xdb +#define JPEG_MARKER_DNL 0xdc +#define JPEG_MARKER_DRI 0xdd +#define JPEG_MARKER_DHP 0xde +#define JPEG_MARKER_EXP 0xdf +#define JPEG_MARKER_APP(x) (0xe0 + (x)) +#define JPEG_MARKER_JPG_(x) (0xf0 + (x)) +#define JPEG_MARKER_COM 0xfe + +#define JPEG_MARKER_JFIF JPEG_MARKER_APP(0) + diff --git a/examples/jpeg/jpeg_tables.c b/examples/jpeg/jpeg_tables.c new file mode 100644 index 0000000..bd2d22a --- /dev/null +++ b/examples/jpeg/jpeg_tables.c @@ -0,0 +1,54 @@ + +unsigned char jpeg_standard_tables[] = { + 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, + + 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, +}; + +int jpeg_standard_tables_size = sizeof(jpeg_standard_tables); + diff --git a/examples/jpeg/test.c b/examples/jpeg/test.c index 0ebdae0..fb4bf31 100644 --- a/examples/jpeg/test.c +++ b/examples/jpeg/test.c @@ -32,7 +32,7 @@ main (int argc, char *argv[]) data = getfile (fn, &len); jpeg_decoder_addbits (dec, data, len); - jpeg_decoder_parse (dec); + jpeg_decoder_decode (dec); jpeg_decoder_get_component_ptr (dec, 1, &ptr, &rowstride); jpeg_decoder_get_component_size (dec, 1, &width, &height); diff --git a/examples/jpeg/test_rgb.c b/examples/jpeg/test_rgb.c index a6c4c86..4e5250a 100644 --- a/examples/jpeg/test_rgb.c +++ b/examples/jpeg/test_rgb.c @@ -41,7 +41,7 @@ main (int argc, char *argv[]) } jpeg_decoder_addbits (dec, data, len); - jpeg_decoder_parse (dec); + jpeg_decoder_decode (dec); jpeg_decoder_get_image_size (dec, &width, &height); |