From 5e03cffd5f9e981a57ae55e1a85d85ecbfdb63c0 Mon Sep 17 00:00:00 2001 From: Oliver Schinagl Date: Sun, 5 Jun 2005 16:10:43 +0000 Subject: --- src/c_huffman.c | 707 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 542 insertions(+), 165 deletions(-) diff --git a/src/c_huffman.c b/src/c_huffman.c index fceed82..ec2943c 100644 --- a/src/c_huffman.c +++ b/src/c_huffman.c @@ -1,86 +1,301 @@ #include #include -#include "config.h" #include "morecfg.h" - #include "jpeglib.h" -#include "jpegint.h" #include "c_huffman.h" +#include +#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) + + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +void ERRORREPORT(void) +{ + printf("Error"); +} + /* Expanded entropy encoder object for Huffman encoding. * * The savable_state subrecord contains fields that change within an MCU, * but must not be updated permanently until we complete the MCU. */ typedef struct { - INT32 put_buffer; /* current bit-accumulation buffer */ - int put_bits; /* # of bits now in it */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state; #define ASSIGN_STATE(dest,src) ((dest) = (src)) - +/* typedef struct { - struct jpeg_entropy_encoder pub; /* public fields */ + //struct jpeg_entropy_encoder pub; // public fields - savable_state saved; /* Bit buffer & DC state at start of MCU */ + savable_state saved; // Bit buffer & DC state at start of MCU - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - int next_restart_num; /* next restart number to write (0-7) */ + // These fields are NOT loaded into local working state. + unsigned int restarts_to_go; // MCUs left in this restart interval + int next_restart_num; // next restart number to write (0-7) - /* Pointers to derived tables (these workspaces have image lifespan) */ - c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; - c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + // Pointers to derived tables (these workspaces have image lifespan) + c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; -#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ - long * dc_count_ptrs[NUM_HUFF_TBLS]; - long * ac_count_ptrs[NUM_HUFF_TBLS]; -#endif } huff_entropy_encoder; typedef huff_entropy_encoder * huff_entropy_ptr; - +*/ /* Working state while writing an MCU. * This struct contains all the fields that are needed by subroutines. */ typedef struct { - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - savable_state cur; /* Current bit buffer & DC state */ - j_compress_ptr cinfo; /* dump_buffer needs access to this */ + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + // j_compress_ptr cinfo; /* dump_buffer needs access to this */ } working_state; -/* Forward declarations */ -static boolean encode_mcu_huff JPP((j_compress_ptr cinfo, JBLOCKROW *MCU_data)); -static void finish_pass_huff JPP((j_compress_ptr cinfo)); +// /////////////////////////////////////////// +// Huffman Tables allocated here +// +// ////////////////////////////////////////// + +JHUFF_TBL dc_Huffman_Table[2]; +JHUFF_TBL ac_Huffman_Table[2]; + +c_derived_tbl dc_derived_table; +c_derived_tbl ac_derived_table; + +/* + * Huffman table setup routines + */ + + LOCAL(void) +add_huff_table (JHUFF_TBL *htblptr, const UINT8 *bits, const UINT8 *val) + /* Define a Huffman table */ +{ + int nsymbols, len; + + /* Copy the number-of-symbols-of-each-code-length counts */ + MEMCOPY((htblptr)->bits, bits, SIZEOF((htblptr)->bits)); + + /* Validate the counts. We do this here mainly so we can copy the right + * number of symbols from the val[] array, without risking marching off + * the end of memory. jchuff.c will do a more thorough test later. + */ + nsymbols = 0; + for (len = 1; len <= 16; len++) + nsymbols += bits[len]; + if (nsymbols < 1 || nsymbols > 256) + { + perror("Bad Huffman code table entry"); + exit(0); + } + //ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + MEMCOPY((htblptr)->huffval, val, nsymbols * SIZEOF(UINT8)); + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (htblptr)->sent_table = FALSE; +} + + + LOCAL(void) +std_huff_tables () + /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ + /* IMPORTANT: these are only valid for 8-bit data precision! */ +{ + static const UINT8 bits_dc_luminance[17] = + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_luminance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_dc_chrominance[17] = + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_chrominance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_ac_luminance[17] = + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; + static const UINT8 val_ac_luminance[] = + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + static const UINT8 bits_ac_chrominance[17] = + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + static const UINT8 val_ac_chrominance[] = + { 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 }; + + add_huff_table(&dc_Huffman_Table[0], bits_dc_luminance, val_dc_luminance); + add_huff_table(&ac_Huffman_Table[0], bits_ac_luminance, val_ac_luminance); + add_huff_table(&dc_Huffman_Table[1], bits_dc_chrominance, val_dc_chrominance); + add_huff_table(&dc_Huffman_Table[1], bits_ac_chrominance, val_ac_chrominance); +} + + + GLOBAL(void) +jpeg_make_c_derived_tbl (JHUFF_TBL *htbl, boolean isDC, + c_derived_tbl * pdtbl) +{ + c_derived_tbl *dtbl; + int p, i, l, lastp, si, maxsymbol; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + if (htbl == NULL) + ERRORREPORT(); + + + dtbl = pdtbl; + + // Figure C.1: make table of Huffman code length for each symbol + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERRORREPORT(); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + lastp = p; + + // Figure C.2: generate the codes themselves + // We also validate that the counts represent a legal Huffman code tree. + // + // + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + */ + if (((INT32) code) >= (((INT32) 1) << si)) + ERRORREPORT(); + code <<= 1; + si++; + } + + /* Figure C.3: generate encoding tables */ + /* These are code and size indexed by symbol value */ + + /* Set all codeless symbols to have code length 0; + * this lets us detect duplicate VAL entries here, and later + * allows emit_bits to detect any attempt to emit such symbols. + */ + MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); + + /* This is also a convenient place to check for out-of-range + * and duplicated VAL entries. We allow 0..255 for AC symbols + * but only 0..15 for DC. (We could constrain them further + * based on data depth and mode, but this seems enough.) + */ + maxsymbol = isDC ? 15 : 255; + + for (p = 0; p < lastp; p++) { + i = htbl->huffval[p]; + if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) + ERRORREPORT(); + dtbl->ehufco[i] = huffcode[p]; + dtbl->ehufsi[i] = huffsize[p]; + } +} + + + /* Outputting bytes to the file */ /* Emit a byte, taking 'action' if must suspend. */ #define emit_byte(state,val,action) \ - { *(state)->next_output_byte++ = (JOCTET) (val); \ - if (--(state)->free_in_buffer == 0) \ - if (! dump_buffer(state)) \ - { action; } } +{ *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer(state)) \ + { action; } } /* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ static boolean dump_buffer(working_state * state) { - struct jpeg_destination_mgr * dest = state->cinfo->dest; - - if (! (*dest->empty_output_buffer) (state->cinfo)) { - return FALSE; - } - /* After a successful buffer dump, must reset buffer pointers */ + // TODO + // + /* + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) { + return FALSE; + } + // After a successful buffer dump, must reset buffer pointers state->next_output_byte = dest->next_output_byte; state->free_in_buffer = dest->free_in_buffer; return TRUE; + +*/ + return TRUE; } @@ -106,16 +321,16 @@ inline static boolean emit_bits(working_state * state, unsigned int code, int si } put_buffer &= (((INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ - + while (put_bits >= 8) { int c = (int) ((put_buffer >> 16) & 0xFF); - emit_byte(state, c, return FALSE); + emit_byte(state, c, return FALSE); if (c == 0xFF) { /* need to stuff a zero byte? */ emit_byte(state, 0, return FALSE); } @@ -132,29 +347,60 @@ inline static boolean emit_bits(working_state * state, unsigned int code, int si /* * Initialize for a Huffman-compressed scan. */ +/* + static void start_pass_huff (j_compress_ptr cinfo) { + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; -static void start_pass_huff (j_compress_ptr cinfo) { - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - - entropy->pub.encode_mcu = encode_mcu_huff; - entropy->pub.finish_pass = finish_pass_huff; +//entropy->pub.encode_mcu = encode_mcu_huff; +//entropy->pub.finish_pass = finish_pass_huff; - /* Initialize bit buffer to empty */ - entropy->saved.put_buffer = 0; - entropy->saved.put_bits = 0; +// Initialize bit buffer to empty +entropy->saved.put_buffer = 0; +entropy->saved.put_bits = 0; - /* Initialize restart stuff */ - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num = 0; +// Initialize restart stuff +entropy->restarts_to_go = cinfo->restart_interval; +entropy->next_restart_num = 0; } +*/ -static boolean flush_bits (working_state * state) { - if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ - return FALSE; - state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ - state->cur.put_bits = 0; - return TRUE; -} + static boolean flush_bits (working_state * state) { + if (! emit_bits(state, 0x7F, 7)) // fill any partial byte with ones + return FALSE; + state->cur.put_buffer = 0; // and reset bit-buffer to empty + state->cur.put_bits = 0; + return TRUE; + } + + +/* + * jpeg_natural_order[i] is the natural-order position of the i'th element + * of zigzag order. + * + * When reading corrupted data, the Huffman decoders could attempt + * to reference an entry beyond the end of this array (if the decoded + * zero run length reaches past the end of the block). To prevent + * wild stores without adding an inner-loop test, we put some extra + * "63"s after the real entries. This will cause the extra coefficient + * to be stored in location 63 of the block, not somewhere random. + * The worst case would be a run-length of 15, which means we need 16 + * fake entries. + */ + +const int jpeg_natural_order[DCTSIZE2+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +int bitCounter; int encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, c_derived_tbl *dctbl, c_derived_tbl *actbl) { @@ -162,17 +408,18 @@ int encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, c_de register int nbits; register int k, r, i; + bitCounter = 0; // TODEBUG /* Encode the DC coefficient difference per section F.1.2.1 */ temp = temp2 = block[0] - last_dc_val; - if (temp < 0) { + if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* For a negative input, want temp2 = bitwise complement of abs(input) */ /* This code assumes we are on a two's complement machine */ temp2--; } - + /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; while (temp) { @@ -187,11 +434,12 @@ int encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, c_de exit(0); /* ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); */ } - + /* Emit the Huffman-coded symbol for the number of bits */ if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) { return FALSE; } + bitCounter += dctbl->ehufsi[nbits]; // TODEBUG /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ @@ -199,12 +447,13 @@ int encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, c_de if (! emit_bits(state, (unsigned int) temp2, nbits)) { return FALSE; } + bitCounter += nbits; // TODEBUG } /* Encode the AC coefficients per section F.1.2.2 */ - + r = 0; /* r = run length of zeros */ - + for (k = 1; k < DCTSIZE2; k++) { if ((temp = block[jpeg_natural_order[k]]) == 0) { r++; @@ -215,15 +464,16 @@ int encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, c_de return FALSE; } r -= 16; + bitCounter += actbl->ehufsi[0xF0]; // TODEBUG } - + temp2 = temp; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* This code assumes we are on a two's complement machine */ temp2--; } - + /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 1; /* there must be at least one 1 bit */ while ((temp >>= 1)) { @@ -235,19 +485,20 @@ int encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, c_de exit(0); /* ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); */ } - + /* Emit Huffman symbol for run length / number of bits */ i = (r << 4) + nbits; if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) { return FALSE; } + bitCounter += actbl->ehufsi[i]; // TODEBUG /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (! emit_bits(state, (unsigned int) temp2, nbits)) { return FALSE; } - + bitCounter += nbits; // TODEBUG r = 0; } } @@ -255,135 +506,261 @@ int encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val, c_de /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) { if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) { - return FALSE; + return FALSE; } + printf("END"); } + printf("\n Bitcounter = %d (%d)",bitCounter,bitCounter/8); return TRUE; } /* * Emit a restart marker & resynchronize predictions. */ +/* + static boolean emit_restart (working_state * state, int restart_num) { + int ci; -static boolean emit_restart (working_state * state, int restart_num) { - int ci; - - if (! flush_bits(state)) - return FALSE; + if (! flush_bits(state)) + return FALSE; - emit_byte(state, 0xFF, return FALSE); - emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) - state->cur.last_dc_val[ci] = 0; +// Re-initialize DC predictions to 0 +for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) +state->cur.last_dc_val[ci] = 0; - /* The restart counter is not updated until we successfully write the MCU. */ +// The restart counter is not updated until we successfully write the MCU. - return TRUE; +return TRUE; } - +*/ /* * Encode and output one MCU's worth of Huffman-compressed coefficients. */ +/* + static boolean encode_mcu_huff ( j_compress_ptr cinfo , JBLOCKROW *MCU_data) { + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + int blkn, ci; + jpeg_component_info * compptr; + +// Load up working state +state.next_output_byte = cinfo->dest->next_output_byte; +state.free_in_buffer = cinfo->dest->free_in_buffer; +ASSIGN_STATE(state.cur, entropy->saved); +state.cinfo = cinfo; + +// Emit restart marker if needed +if (cinfo->restart_interval) { +if (entropy->restarts_to_go == 0) +if (! emit_restart(&state, entropy->next_restart_num)) +return FALSE; +} -static boolean encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - working_state state; - int blkn, ci; - jpeg_component_info * compptr; - - /* Load up working state */ - state.next_output_byte = cinfo->dest->next_output_byte; - state.free_in_buffer = cinfo->dest->free_in_buffer; - ASSIGN_STATE(state.cur, entropy->saved); - state.cinfo = cinfo; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! emit_restart(&state, entropy->next_restart_num)) - return FALSE; - } - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - if (! encode_one_block(&state, - MCU_data[blkn][0], state.cur.last_dc_val[ci], - entropy->dc_derived_tbls[compptr->dc_tbl_no], - entropy->ac_derived_tbls[compptr->ac_tbl_no])) - return FALSE; - /* Update last_dc_val */ - state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; - } - - /* Completed MCU, so update state */ - cinfo->dest->next_output_byte = state.next_output_byte; - cinfo->dest->free_in_buffer = state.free_in_buffer; - ASSIGN_STATE(entropy->saved, state.cur); - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; +// Encode the MCU data blocks +for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { +ci = cinfo->MCU_membership[blkn]; +compptr = cinfo->cur_comp_info[ci]; +if (! encode_one_block(&state, +MCU_data[blkn][0], state.cur.last_dc_val[ci], +entropy->dc_derived_tbls[compptr->dc_tbl_no], +entropy->ac_derived_tbls[compptr->ac_tbl_no])) +return FALSE; +// Update last_dc_val +state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; } +// Completed MCU, so update state +cinfo->dest->next_output_byte = state.next_output_byte; +cinfo->dest->free_in_buffer = state.free_in_buffer; +ASSIGN_STATE(entropy->saved, state.cur); + +// Update restart-interval state too +if (cinfo->restart_interval) { +if (entropy->restarts_to_go == 0) { +entropy->restarts_to_go = cinfo->restart_interval; +entropy->next_restart_num++; +entropy->next_restart_num &= 7; +} +entropy->restarts_to_go--; +} + +return TRUE; +} +*/ /* * Finish up at the end of a Huffman-compressed scan. */ +/* + static void finish_pass_huff (j_compress_ptr cinfo) { + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + +// Load up working state ... flush_bits needs it +state.next_output_byte = cinfo->dest->next_output_byte; +state.free_in_buffer = cinfo->dest->free_in_buffer; +ASSIGN_STATE(state.cur, entropy->saved); +state.cinfo = cinfo; + +// Flush out the last data +if (! flush_bits(&state)) +perror("Suspension not allowed here"); +exit(0); +// ERREXIT(cinfo, JERR_CANT_SUSPEND); + +// Update state +cinfo->dest->next_output_byte = state.next_output_byte; +cinfo->dest->free_in_buffer = state.free_in_buffer; +ASSIGN_STATE(entropy->saved, state.cur); +} +*/ + + -static void finish_pass_huff (j_compress_ptr cinfo) { - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - working_state state; - - /* Load up working state ... flush_bits needs it */ - state.next_output_byte = cinfo->dest->next_output_byte; - state.free_in_buffer = cinfo->dest->free_in_buffer; - ASSIGN_STATE(state.cur, entropy->saved); - state.cinfo = cinfo; - - /* Flush out the last data */ - if (! flush_bits(&state)) - perror("Suspension not allowed here"); - exit(0); - /* ERREXIT(cinfo, JERR_CANT_SUSPEND); */ - - /* Update state */ - cinfo->dest->next_output_byte = state.next_output_byte; - cinfo->dest->free_in_buffer = state.free_in_buffer; - ASSIGN_STATE(entropy->saved, state.cur); +//int dataToCode[64]; + +static int lastDCValue; +static working_state savedHuffstate; +unsigned char outputBufferHuffman[500]; + +void encode_huffBlock64_init(void) +{ + std_huff_tables(); + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(dc_Huffman_Table, TRUE, + &dc_derived_table); + jpeg_make_c_derived_tbl(ac_Huffman_Table, FALSE, + &ac_derived_table); +} + + +void encode_huffBlock64_start(void) +{ + lastDCValue = 0; + // Initialise buffer + savedHuffstate.next_output_byte = outputBufferHuffman; + savedHuffstate.free_in_buffer = 500; // TODO: + // savedHuffstate.cinfo = NULL; } +void encode_huffBlock64(short * data) +{ + working_state state; + + // Load up working state ... flush_bits needs it + state.next_output_byte = savedHuffstate.next_output_byte; + state.free_in_buffer = savedHuffstate.free_in_buffer; + ASSIGN_STATE(state.cur, savedHuffstate.cur); + + encode_one_block(&state, data, savedHuffstate.cur.last_dc_val[0], &dc_derived_table, &ac_derived_table); + + // Update last_dc_val + savedHuffstate.cur.last_dc_val[0] = data[0]; // Different for YUV TODO if all colours used + + // Completed MCU, so update state + savedHuffstate.next_output_byte = state.next_output_byte; + savedHuffstate.free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(savedHuffstate.cur, state.cur); + + + +} +void encode_huffBlock64_end(void ) +{ + working_state state; + + // Load up working state ... flush_bits needs it + savedHuffstate.next_output_byte = state.next_output_byte; + savedHuffstate.free_in_buffer = state.free_in_buffer ; + ASSIGN_STATE(savedHuffstate.cur, state.cur); + + if (! flush_bits(&state)) + { + perror("Suspension not allowed here"); + exit(0); + } +} /* - * Module initialization routine for Huffman entropy encoding. - */ + typedef struct { + unsigned int ehufco[256]; // code for each symbol + char ehufsi[256]; // length of code for each symbol +// If no code has been allocated for a symbol S, ehufsi[S] contains 0 +} c_derived_tbl; +*/ +void dump_Table(void) +{ + int i,j; + printf("\n DC Derived Table Code\n\n "); + for (i=0; i < 32; i++) + { + for(j=0;j < 8; j++) + { + printf("%4x\t",dc_derived_table.ehufco[ ((i * 8) + j)]); + } + printf("\n"); + } + printf("\n DC Derived Table Symbol\n\n "); + for (i=0; i < 32; i++) + { + for(j=0;j < 8; j++) + { + printf("%d\t",dc_derived_table.ehufsi[ ((i * 8) + j)]); + } + printf("\n"); + } + printf("\n AC Derived Table Code\n\n"); + for (i=0; i < 32; i++) + { + for(j=0;j < 8; j++) + { + printf("%4x\t",ac_derived_table.ehufco[ ((i * 8) + j)]); + } + printf("\n"); + } + printf("\n AC Derived Table Symbol\n\n "); + for (i=0; i < 32; i++) + { + for(j=0;j < 8; j++) + { + printf("%d\t",ac_derived_table.ehufsi[ ((i * 8) + j)]); + } + printf("\n"); + } -void jinit_huff_encoder(j_compress_ptr cinfo) { - huff_entropy_ptr entropy; - int i; +} - entropy = (huff_entropy_ptr) malloc((size_t) sizeof(huff_entropy_encoder)); +void dump_Encoded(void) +{ + int i,j; + printf("\n Huffman coded\n\n "); + for (i=0; i < 50; i++) + { + for(j=0;j < 10; j++) + { + printf("%4x\t",outputBufferHuffman[ ((i * 10) + j)]); + } + printf("\n"); + } +} + +void Test_dhuffman(short * data) +{ - cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; - entropy->pub.start_pass = start_pass_huff; + // dump_Encoded(); + + encode_huffBlock64_init(); + + dump_Table(); + encode_huffBlock64_start(); + encode_huffBlock64(data); + encode_huffBlock64_end(); + dump_Encoded(); - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; -#ifdef ENTROPY_OPT_SUPPORTED - entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; -#endif - } } + -- cgit v0.12