@@ -28,12 +28,10 @@ internal class HuffmanScanDecoder
2828 private readonly JpegFrame frame ;
2929 private readonly HuffmanTable [ ] dcHuffmanTables ;
3030 private readonly HuffmanTable [ ] acHuffmanTables ;
31- private readonly FastACTable [ ] fastACTables ;
3231
33- private readonly JpegStreamReader stream ;
32+ private readonly DoubleBufferedStreamReader stream ;
3433 private readonly HuffmanScanBuffer scanBuffer ;
3534 private readonly JpegComponent [ ] components ;
36- private readonly ZigZag dctZigZag ;
3735
3836 // The restart interval.
3937 private readonly int restartInterval ;
@@ -59,26 +57,26 @@ internal class HuffmanScanDecoder
5957 // The End-Of-Block countdown for ending the sequence prematurely when the remaining coefficients are zero.
6058 private int eobrun ;
6159
60+ private ZigZag dctZigZag ;
61+
6262 /// <summary>
6363 /// Initializes a new instance of the <see cref="HuffmanScanDecoder"/> class.
6464 /// </summary>
6565 /// <param name="stream">The input stream.</param>
6666 /// <param name="frame">The image frame.</param>
6767 /// <param name="dcHuffmanTables">The DC Huffman tables.</param>
6868 /// <param name="acHuffmanTables">The AC Huffman tables.</param>
69- /// <param name="fastACTables">The fast AC decoding tables.</param>
7069 /// <param name="componentsLength">The length of the components. Different to the array length.</param>
7170 /// <param name="restartInterval">The reset interval.</param>
7271 /// <param name="spectralStart">The spectral selection start.</param>
7372 /// <param name="spectralEnd">The spectral selection end.</param>
7473 /// <param name="successiveHigh">The successive approximation bit high end.</param>
7574 /// <param name="successiveLow">The successive approximation bit low end.</param>
7675 public HuffmanScanDecoder (
77- JpegStreamReader stream ,
76+ DoubleBufferedStreamReader stream ,
7877 JpegFrame frame ,
7978 HuffmanTable [ ] dcHuffmanTables ,
8079 HuffmanTable [ ] acHuffmanTables ,
81- FastACTable [ ] fastACTables ,
8280 int componentsLength ,
8381 int restartInterval ,
8482 int spectralStart ,
@@ -92,7 +90,6 @@ public HuffmanScanDecoder(
9290 this . frame = frame ;
9391 this . dcHuffmanTables = dcHuffmanTables ;
9492 this . acHuffmanTables = acHuffmanTables ;
95- this . fastACTables = fastACTables ;
9693 this . components = frame . Components ;
9794 this . componentsLength = componentsLength ;
9895 this . restartInterval = restartInterval ;
@@ -164,9 +161,6 @@ private unsafe void ParseBaselineDataInterleaved()
164161 ref HuffmanTable acHuffmanTable = ref this . acHuffmanTables [ component . ACHuffmanTableId ] ;
165162 dcHuffmanTable . Configure ( ) ;
166163 acHuffmanTable . Configure ( ) ;
167-
168- ref FastACTable fastAcTable = ref this . fastACTables [ component . ACHuffmanTableId ] ;
169- fastAcTable . Derive ( ref acHuffmanTable ) ;
170164 }
171165
172166 for ( int j = 0 ; j < mcusPerColumn ; j ++ )
@@ -183,8 +177,6 @@ private unsafe void ParseBaselineDataInterleaved()
183177
184178 ref HuffmanTable dcHuffmanTable = ref this . dcHuffmanTables [ component . DCHuffmanTableId ] ;
185179 ref HuffmanTable acHuffmanTable = ref this . acHuffmanTables [ component . ACHuffmanTableId ] ;
186- ref FastACTable fastAcTable = ref this . fastACTables [ component . ACHuffmanTableId ] ;
187- ref short fastACRef = ref fastAcTable . Lookahead [ 0 ] ;
188180
189181 int h = component . HorizontalSamplingFactor ;
190182 int v = component . VerticalSamplingFactor ;
@@ -199,18 +191,13 @@ private unsafe void ParseBaselineDataInterleaved()
199191
200192 for ( int x = 0 ; x < h ; x ++ )
201193 {
202- // if (this.jpegBuffer.Eof)
203- // {
204- // return;
205- // }
206194 int blockCol = ( mcuCol * h ) + x ;
207195
208196 this . DecodeBlockBaseline (
209197 component ,
210198 ref Unsafe . Add ( ref blockRef , blockCol ) ,
211199 ref dcHuffmanTable ,
212- ref acHuffmanTable ,
213- ref fastACRef ) ;
200+ ref acHuffmanTable ) ;
214201 }
215202 }
216203 }
@@ -240,10 +227,6 @@ private unsafe void ParseBaselineDataNonInterleaved()
240227 dcHuffmanTable . Configure ( ) ;
241228 acHuffmanTable . Configure ( ) ;
242229
243- ref FastACTable fastAcTable = ref this . fastACTables [ component . ACHuffmanTableId ] ;
244- fastAcTable . Derive ( ref acHuffmanTable ) ;
245- ref short fastACRef = ref fastAcTable . Lookahead [ 0 ] ;
246-
247230 int mcu = 0 ;
248231 for ( int j = 0 ; j < h ; j ++ )
249232 {
@@ -252,16 +235,11 @@ private unsafe void ParseBaselineDataNonInterleaved()
252235
253236 for ( int i = 0 ; i < w ; i ++ )
254237 {
255- // if (this.jpegBuffer.Eof)
256- // {
257- // return;
258- // }
259238 this . DecodeBlockBaseline (
260239 component ,
261240 ref Unsafe . Add ( ref blockRef , i ) ,
262241 ref dcHuffmanTable ,
263- ref acHuffmanTable ,
264- ref fastACRef ) ;
242+ ref acHuffmanTable ) ;
265243
266244 // Every data block is an MCU, so countdown the restart interval
267245 mcu ++ ;
@@ -447,10 +425,6 @@ ref Unsafe.Add(ref blockRef, i),
447425 ref HuffmanTable acHuffmanTable = ref this . acHuffmanTables [ component . ACHuffmanTableId ] ;
448426 acHuffmanTable . Configure ( ) ;
449427
450- ref FastACTable fastAcTable = ref this . fastACTables [ component . ACHuffmanTableId ] ;
451- fastAcTable . Derive ( ref acHuffmanTable ) ;
452- ref short fastACRef = ref fastAcTable . Lookahead [ 0 ] ;
453-
454428 int mcu = 0 ;
455429 for ( int j = 0 ; j < h ; j ++ )
456430 {
@@ -466,8 +440,7 @@ ref Unsafe.Add(ref blockRef, i),
466440
467441 this . DecodeBlockProgressiveAC (
468442 ref Unsafe . Add ( ref blockRef , i ) ,
469- ref acHuffmanTable ,
470- ref fastACRef ) ;
443+ ref acHuffmanTable ) ;
471444
472445 // Every data block is an MCU, so countdown the restart interval
473446 mcu ++ ;
@@ -481,11 +454,11 @@ private void DecodeBlockBaseline(
481454 JpegComponent component ,
482455 ref Block8x8 block ,
483456 ref HuffmanTable dcTable ,
484- ref HuffmanTable acTable ,
485- ref short fastACRef )
457+ ref HuffmanTable acTable )
486458 {
487459 ref short blockDataRef = ref Unsafe . As < Block8x8 , short > ( ref block ) ;
488460 HuffmanScanBuffer buffer = this . scanBuffer ;
461+ ref ZigZag zigzag = ref this . dctZigZag ;
489462
490463 // DC
491464 int t = this . DecodeHuffman ( buffer , ref dcTable ) ;
@@ -510,7 +483,7 @@ private void DecodeBlockBaseline(
510483 {
511484 i += r ;
512485 s = Receive ( buffer , s ) ;
513- Unsafe . Add ( ref blockDataRef , this . dctZigZag [ i ++ ] ) = ( short ) s ;
486+ Unsafe . Add ( ref blockDataRef , zigzag [ i ++ ] ) = ( short ) s ;
514487 }
515488 else
516489 {
@@ -556,10 +529,7 @@ private static int Receive(HuffmanScanBuffer buffer, int nbits)
556529 return Extend ( GetBits ( buffer , nbits ) , nbits ) ;
557530 }
558531
559- private void DecodeBlockProgressiveDC (
560- JpegComponent component ,
561- ref Block8x8 block ,
562- ref HuffmanTable dcTable )
532+ private void DecodeBlockProgressiveDC ( JpegComponent component , ref Block8x8 block , ref HuffmanTable dcTable )
563533 {
564534 ref short blockDataRef = ref Unsafe . As < Block8x8 , short > ( ref block ) ;
565535 HuffmanScanBuffer buffer = this . scanBuffer ;
@@ -585,10 +555,7 @@ private void DecodeBlockProgressiveDC(
585555 }
586556 }
587557
588- private void DecodeBlockProgressiveAC (
589- ref Block8x8 block ,
590- ref HuffmanTable acTable ,
591- ref short fastACRef )
558+ private void DecodeBlockProgressiveAC ( ref Block8x8 block , ref HuffmanTable acTable )
592559 {
593560 ref short blockDataRef = ref Unsafe . As < Block8x8 , short > ( ref block ) ;
594561 if ( this . successiveHigh == 0 )
@@ -602,6 +569,7 @@ private void DecodeBlockProgressiveAC(
602569 }
603570
604571 HuffmanScanBuffer buffer = this . scanBuffer ;
572+ ref ZigZag zigzag = ref this . dctZigZag ;
605573 int start = this . spectralStart ;
606574 int end = this . spectralEnd ;
607575 int low = this . successiveLow ;
@@ -617,7 +585,7 @@ private void DecodeBlockProgressiveAC(
617585 if ( s != 0 )
618586 {
619587 s = Receive ( buffer , s ) ;
620- Unsafe . Add ( ref blockDataRef , this . dctZigZag [ i ] ) = ( short ) ( s << low ) ;
588+ Unsafe . Add ( ref blockDataRef , zigzag [ i ] ) = ( short ) ( s << low ) ;
621589 }
622590 else
623591 {
@@ -647,6 +615,7 @@ private void DecodeBlockProgressiveACRefined(ref short blockDataRef, ref Huffman
647615 {
648616 // Refinement scan for these AC coefficients
649617 HuffmanScanBuffer buffer = this . scanBuffer ;
618+ ref ZigZag zigzag = ref this . dctZigZag ;
650619 int start = this . spectralStart ;
651620 int end = this . spectralEnd ;
652621
@@ -693,8 +662,7 @@ private void DecodeBlockProgressiveACRefined(ref short blockDataRef, ref Huffman
693662
694663 do
695664 {
696- // C++ TO C# CONVERTER TODO TASK: Pointer arithmetic is detected on this variable, so pointers on this variable are left unchanged:
697- ref short coef = ref Unsafe . Add ( ref blockDataRef , this . dctZigZag [ k ] ) ;
665+ ref short coef = ref Unsafe . Add ( ref blockDataRef , zigzag [ k ] ) ;
698666 if ( coef != 0 )
699667 {
700668 buffer . CheckBits ( ) ;
@@ -720,7 +688,7 @@ private void DecodeBlockProgressiveACRefined(ref short blockDataRef, ref Huffman
720688
721689 if ( ( s != 0 ) && ( k < 64 ) )
722690 {
723- Unsafe . Add ( ref blockDataRef , this . dctZigZag [ k ] ) = ( short ) s ;
691+ Unsafe . Add ( ref blockDataRef , zigzag [ k ] ) = ( short ) s ;
724692 }
725693 }
726694 }
@@ -729,7 +697,7 @@ private void DecodeBlockProgressiveACRefined(ref short blockDataRef, ref Huffman
729697 {
730698 for ( ; k <= end ; k ++ )
731699 {
732- ref short coef = ref Unsafe . Add ( ref blockDataRef , this . dctZigZag [ k ] ) ;
700+ ref short coef = ref Unsafe . Add ( ref blockDataRef , zigzag [ k ] ) ;
733701
734702 if ( coef != 0 )
735703 {
@@ -786,9 +754,9 @@ private bool HandleRestart()
786754
787755 internal sealed class HuffmanScanBuffer
788756 {
789- private readonly JpegStreamReader stream ;
757+ private readonly DoubleBufferedStreamReader stream ;
790758
791- public HuffmanScanBuffer ( JpegStreamReader stream )
759+ public HuffmanScanBuffer ( DoubleBufferedStreamReader stream )
792760 {
793761 this . stream = stream ;
794762 this . Reset ( ) ;
@@ -857,15 +825,19 @@ public bool HasRestart()
857825 return m >= JpegConstants . Markers . RST0 && m <= JpegConstants . Markers . RST7 ;
858826 }
859827
860- [ MethodImpl ( InliningOptions . ColdPath ) ]
828+ [ MethodImpl ( InliningOptions . ShortMethod ) ]
861829 public void FillBuffer ( )
862830 {
863831 // Attempt to load at least the minimum number of required bits into the buffer.
864832 // We fail to do so only if we hit a marker or reach the end of the input stream.
865- //
866- // TODO: JpegStreamReader we could keep track of marker positions within the
867- // stream and we could use that knowledge to do a fast cast of bytes to a ulong
868- // avoiding this loop.
833+ // TODO: Investigate whether a faster path can be taken here.
834+ this . Remain += 48 ;
835+ this . Data = ( this . Data << 48 ) | this . GetBytes ( ) ;
836+ }
837+
838+ [ MethodImpl ( InliningOptions . ColdPath ) ]
839+ private ulong GetBytes ( )
840+ {
869841 ulong temp = 0 ;
870842 for ( int i = 0 ; i < 6 ; i ++ )
871843 {
@@ -910,8 +882,7 @@ public void FillBuffer()
910882 temp = ( temp << 8 ) | ( ulong ) ( long ) b ;
911883 }
912884
913- this . Remain += 48 ;
914- this . Data = ( this . Data << 48 ) | temp ;
885+ return temp ;
915886 }
916887 }
917888 }
0 commit comments