summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2007-03-20 07:03:30 +0000
committerDavid Schleef <ds@schleef.org>2007-03-20 07:03:30 +0000
commit31d9b45318bfb755ae917e59efe32cca4696aa30 (patch)
treeb37a9049eb5d99b2e097db477d6b5091077d1e03 /examples
parenta594920948be3773523c626d1148c14b85d0764c (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.am2
-rw-r--r--examples/jpeg/bits.h128
-rw-r--r--examples/jpeg/huffman.c34
-rw-r--r--examples/jpeg/huffman.h10
-rw-r--r--examples/jpeg/jpeg.c783
-rw-r--r--examples/jpeg/jpeg.h52
-rw-r--r--examples/jpeg/jpeg_bits.c154
-rw-r--r--examples/jpeg/jpeg_internal.h60
-rw-r--r--examples/jpeg/jpeg_markers.h44
-rw-r--r--examples/jpeg/jpeg_tables.c54
-rw-r--r--examples/jpeg/test.c2
-rw-r--r--examples/jpeg/test_rgb.c2
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);