X-Git-Url: https://git.sesse.net/?p=fjl;a=blobdiff_plain;f=dehuff.h;h=d93e7931ee17f081e734e7ff5397dd2f973f200d;hp=b79a79ace3fe976b2f38d8bf375b980b90ccafe7;hb=618548d1f2e076a3da21368e708cf887dcbd20d2;hpb=17eeadbf1a76c2ad38869255191c3696be3cfb60 diff --git a/dehuff.h b/dehuff.h index b79a79a..d93e793 100644 --- a/dehuff.h +++ b/dehuff.h @@ -5,6 +5,14 @@ #include #include +#include "input.h" + +// About 99% of all Huffman codes are <= 8 bits long (see codelen.txt), +// and it's what libjpeg uses. Thus, it seems like a reasonable size. +#define DEHUF_TABLE_BITS 8 +#define DEHUF_TABLE_SIZE (1 << DEHUF_TABLE_BITS) +static const int DEHUF_SLOW_PATH = -1; + // A function to read bytes from some input source. The bytes should be // already unstuffed (and thus without markers). // A return value of -1 indicates error, a return value of 0 indicates EOF. @@ -20,6 +28,15 @@ struct huffman_table { int maxcode[16]; int mincode[16]; unsigned valptr[16]; + + // Lookup table for fast decoding; given eight bits, + // return the symbol and length in bits. For longer codes, + // DEHUF_SLOW_PATH is returned. + + // Note that the codes we return are 8-bit, but the type of + // the lookup tables is int to avoid extra zero extending. + int lookup_table_codes[DEHUF_TABLE_SIZE]; + int lookup_table_length[DEHUF_TABLE_SIZE]; }; enum coefficient_class { @@ -29,6 +46,30 @@ enum coefficient_class { }; typedef struct huffman_table huffman_tables_t[NUM_COEFF_CLASSES][4]; +// Read Huffman tables from a stream, and compute the derived values. void read_huffman_tables(huffman_tables_t* dst, raw_input_func_t* input_func, void* userdata); +unsigned read_huffman_symbol_slow_path(const struct huffman_table* table, + struct bit_source* source); + +#include + +static inline unsigned read_huffman_symbol(const struct huffman_table* table, + struct bit_source* source) +{ + // FIXME: We can read past the end of the stream here in some edge + // cases. We need to define some guarantees in the layers above. + possibly_refill(source, DEHUF_TABLE_BITS); + unsigned lookup = peek_bits(source, DEHUF_TABLE_BITS); + int code = table->lookup_table_codes[lookup]; + int length = table->lookup_table_length[lookup]; + + if (code == DEHUF_SLOW_PATH) { + return read_huffman_symbol_slow_path(table, source); + } + + read_bits(source, length); + return code; +} + #endif /* !defined(_DEHUFF_H) */