@@ -126,8 +126,11 @@ void ReadQuantisationTables(byte[] src) {
126126 }
127127 }
128128
129- const int HUFF_MAX_BITS = 16 ;
130- const int HUFF_MAX_VALS = 256 ;
129+ const int HUFF_MAX_BITS = 16 ;
130+ const int HUFF_MAX_VALS = 256 ;
131+ const int HUFF_FAST_BITS = 8 ;
132+ const int HUFF_FAST_LEN_SHIFT = 8 ;
133+
131134 void ReadHuffmanTable ( byte [ ] src ) {
132135 int offset = AdvanceOffset ( 2 ) ;
133136 int length = MemUtils . ReadU16_BE ( src , offset ) ;
@@ -136,7 +139,7 @@ void ReadHuffmanTable(byte[] src) {
136139 offset = AdvanceOffset ( length ) ;
137140
138141 // Can have more than one huffman table
139- while ( length > 0 )
142+ while ( length > 0 )
140143 {
141144 byte flags = src [ offset ++ ] ;
142145
@@ -154,6 +157,7 @@ int DecodeHuffmanTable(byte[] src, HuffmanTable table, ref int offset) {
154157 table . endCodewords = new ushort [ HUFF_MAX_BITS ] ;
155158 table . firstOffsets = new ushort [ HUFF_MAX_BITS ] ;
156159 table . values = new byte [ HUFF_MAX_VALS ] ;
160+ table . fast = new ushort [ 1 << HUFF_FAST_BITS ] ;
157161
158162 // Compute the codewords for the huffman tree.
159163 // Codewords are ordered, so consider this example tree:
@@ -191,7 +195,21 @@ int DecodeHuffmanTable(byte[] src, HuffmanTable table, ref int offset) {
191195 {
192196 for ( int j = 0 ; j < counts [ i ] ; j ++ )
193197 {
194- table . values [ valueIdx ++ ] = src [ offset ++ ] ;
198+ byte value = src [ offset ++ ] ;
199+ table . values [ valueIdx ++ ] = value ;
200+
201+ // Codeword too long to fast pack?
202+ int len = i + 1 ;
203+ if ( len > HUFF_FAST_BITS ) continue ;
204+
205+ ushort packed = ( ushort ) ( ( len << HUFF_FAST_LEN_SHIFT ) | value ) ;
206+ int codeword = table . firstCodewords [ i ] + j ;
207+ codeword <<= ( HUFF_FAST_BITS - len ) ;
208+
209+ for ( int k = 0 ; k < 1 << ( HUFF_FAST_BITS - len ) ; k ++ )
210+ {
211+ table . fast [ codeword + k ] = packed ;
212+ }
195213 }
196214 }
197215
@@ -472,17 +490,16 @@ void IDCT(int[] block, float* output) {
472490 int bit_cnt ;
473491 bool hit_end , hit_rst ;
474492
475- int ReadBits ( byte [ ] src , int count ) {
493+ void RefillBits ( byte [ ] src ) {
476494 while ( bit_cnt <= 24 && ! hit_end ) {
477495 byte next = src [ buf_offset ++ ] ;
478496 // JPEG byte stuffing
479- // TODO restart markers ?
480497 if ( next == 0xFF ) {
481498 byte type = src [ buf_offset ++ ] ;
482499
483500 if ( type == ( MARKER_IMAGE_END & 0xFF ) ) {
484501 next = 0 ;
485- hit_end = true ;
502+ hit_end = true ;
486503 buf_offset -= 2 ;
487504 } else if ( type >= ( MARKER_RST_MRKR0 & 0xFF ) && type <= ( MARKER_RST_MRKR7 & 0xFF ) ) {
488505 hit_rst = true ;
@@ -496,7 +513,10 @@ int ReadBits(byte[] src, int count) {
496513 bit_buf |= next ;
497514 bit_cnt += 8 ;
498515 }
499-
516+ }
517+
518+ // Duplicates PeekBits/ConsumeBits for faster functionality
519+ int ReadBits ( int count ) {
500520 int read = bit_cnt - count ;
501521 int bits = ( int ) ( bit_buf >> read ) ;
502522
@@ -505,6 +525,12 @@ int ReadBits(byte[] src, int count) {
505525 return bits ;
506526 }
507527
528+ int PeekBits ( int count ) {
529+ int read = bit_cnt - count ;
530+ int bits = ( int ) ( bit_buf >> read ) ;
531+ return bits ;
532+ }
533+
508534 void ConsumeBits ( int count ) {
509535 int read = bit_cnt - count ;
510536
@@ -513,12 +539,20 @@ void ConsumeBits(int count) {
513539 }
514540
515541 byte ReadHuffman ( HuffmanTable table , byte [ ] src ) {
516- int codeword = 0 ;
517- // TODO optimise
518- for ( int i = 0 ; i < HUFF_MAX_BITS ; i ++ )
542+ RefillBits ( src ) ;
543+ int codeword = PeekBits ( HUFF_FAST_BITS ) ;
544+
545+ int packed = table . fast [ codeword ] ;
546+ if ( packed != 0 ) {
547+ ConsumeBits ( packed >> HUFF_FAST_LEN_SHIFT ) ;
548+ return ( byte ) packed ;
549+ }
550+
551+ ConsumeBits ( HUFF_FAST_BITS ) ;
552+ for ( int i = HUFF_FAST_BITS ; i < HUFF_MAX_BITS ; i ++ )
519553 {
520554 codeword <<= 1 ;
521- codeword |= ReadBits ( src , 1 ) ;
555+ codeword |= ReadBits ( 1 ) ;
522556
523557 if ( codeword < table . endCodewords [ i ] ) {
524558 int offset = table . firstOffsets [ i ] + ( codeword - table . firstCodewords [ i ] ) ;
@@ -533,8 +567,9 @@ byte ReadHuffman(HuffmanTable table, byte[] src) {
533567
534568 int ReadBiasedValue ( byte [ ] src , int bits ) {
535569 if ( bits == 0 ) return 0 ;
570+ RefillBits ( src ) ;
536571
537- int value = ReadBits ( src , bits ) ;
572+ int value = ReadBits ( bits ) ;
538573 int midpoint = 1 << ( bits - 1 ) ;
539574
540575 // E.g. for two bits, bits/values are:
@@ -573,6 +608,8 @@ class HuffmanTable
573608 // Base offset into Values for codewords of each bit length.
574609 public ushort [ ] firstOffsets ;
575610 // Values/Symbols list
576- public byte [ ] values ;
611+ public byte [ ] values ;
612+ // Fast lookup table for huffman codes
613+ public ushort [ ] fast ;
577614 }
578615}
0 commit comments