@@ -78,6 +78,7 @@ internal sealed class LzwDecoder : IDisposable
7878 public LzwDecoder ( MemoryAllocator memoryAllocator , BufferedReadStream stream , int minCodeSize )
7979 {
8080 this . stream = stream ?? throw new ArgumentNullException ( nameof ( stream ) ) ;
81+ Guard . IsTrue ( IsValidMinCodeSize ( minCodeSize ) , nameof ( minCodeSize ) , "Invalid minimum code size." ) ;
8182
8283 this . prefixOwner = memoryAllocator . Allocate < int > ( MaxStackSize , AllocationOptions . Clean ) ;
8384 this . suffixOwner = memoryAllocator . Allocate < int > ( MaxStackSize , AllocationOptions . Clean ) ;
@@ -92,12 +93,15 @@ public LzwDecoder(MemoryAllocator memoryAllocator, BufferedReadStream stream, in
9293 this . endCode = this . clearCode + 1 ;
9394 this . availableCode = this . clearCode + 2 ;
9495
95- Span < int > suffix = this . suffixOwner . GetSpan ( ) ;
96- int max = Math . Min ( this . clearCode , suffix . Length ) ;
97- for ( this . code = 0 ; this . code < max ; this . code ++ )
96+ // Fill the suffix buffer with the initial values represented by the number of colors.
97+ Span < int > suffix = this . suffixOwner . GetSpan ( ) [ ..this . clearCode ] ;
98+ int i ;
99+ for ( i = 0 ; i < suffix . Length ; i ++ )
98100 {
99- suffix [ this . code ] = ( byte ) this . code ;
101+ suffix [ i ] = i ;
100102 }
103+
104+ this . code = i ;
101105 }
102106
103107 /// <summary>
@@ -112,8 +116,7 @@ public static bool IsValidMinCodeSize(int minCodeSize)
112116 // It is possible to specify a larger LZW minimum code size than the palette length in bits
113117 // which may leave a gap in the codes where no colors are assigned.
114118 // http://www.matthewflickinger.com/lab/whatsinagif/lzw_image_data.asp#lzw_compression
115- int clearCode = 1 << minCodeSize ;
116- if ( minCodeSize < 2 || minCodeSize > MaximumLzwBits || clearCode > MaxStackSize )
119+ if ( minCodeSize < 2 || minCodeSize > MaximumLzwBits || 1 << minCodeSize > MaxStackSize )
117120 {
118121 // Don't attempt to decode the frame indices.
119122 // Theoretically we could determine a min code size from the length of the provided
@@ -137,7 +140,6 @@ public void DecodePixelRow(Span<byte> indices)
137140 Span < int > suffix = this . suffixOwner . GetSpan ( ) ;
138141 Span < int > pixelStack = this . pixelStackOwner . GetSpan ( ) ;
139142 Span < byte > buffer = this . bufferOwner . GetSpan ( ) ;
140- int maxTop = this . pixelStackOwner . Length ( ) - 1 ;
141143
142144 // Cache frequently accessed instance fields into locals.
143145 // This helps avoid repeated field loads inside the tight loop.
@@ -157,8 +159,8 @@ public void DecodePixelRow(Span<byte> indices)
157159 int clearCode = this . clearCode ;
158160 int endCode = this . endCode ;
159161
160- int xyz = 0 ;
161- while ( xyz < indices . Length )
162+ int i = 0 ;
163+ while ( i < indices . Length )
162164 {
163165 if ( top == 0 )
164166 {
@@ -220,7 +222,7 @@ public void DecodePixelRow(Span<byte> indices)
220222 code = oldCode ;
221223 }
222224
223- while ( code > clearCode && top < maxTop )
225+ while ( code > clearCode && top < MaxStackSize )
224226 {
225227 pixelStack [ top ++ ] = suffix [ code ] ;
226228 code = prefix [ code ] ;
@@ -251,7 +253,7 @@ public void DecodePixelRow(Span<byte> indices)
251253 top -- ;
252254
253255 // Clear missing pixels.
254- indices [ xyz ++ ] = ( byte ) pixelStack [ top ] ;
256+ indices [ i ++ ] = ( byte ) pixelStack [ top ] ;
255257 }
256258
257259 // Write back the local values to the instance fields.
@@ -279,7 +281,6 @@ public void SkipIndices(int length)
279281 Span < int > suffix = this . suffixOwner . GetSpan ( ) ;
280282 Span < int > pixelStack = this . pixelStackOwner . GetSpan ( ) ;
281283 Span < byte > buffer = this . bufferOwner . GetSpan ( ) ;
282- int maxTop = this . pixelStackOwner . Length ( ) - 1 ;
283284
284285 // Cache frequently accessed instance fields into locals.
285286 // This helps avoid repeated field loads inside the tight loop.
@@ -299,8 +300,8 @@ public void SkipIndices(int length)
299300 int clearCode = this . clearCode ;
300301 int endCode = this . endCode ;
301302
302- int xyz = 0 ;
303- while ( xyz < length )
303+ int i = 0 ;
304+ while ( i < length )
304305 {
305306 if ( top == 0 )
306307 {
@@ -362,7 +363,7 @@ public void SkipIndices(int length)
362363 code = oldCode ;
363364 }
364365
365- while ( code > clearCode && top < maxTop )
366+ while ( code > clearCode && top < MaxStackSize )
366367 {
367368 pixelStack [ top ++ ] = suffix [ code ] ;
368369 code = prefix [ code ] ;
@@ -393,7 +394,7 @@ public void SkipIndices(int length)
393394 top -- ;
394395
395396 // Skip missing pixels.
396- xyz ++ ;
397+ i ++ ;
397398 }
398399
399400 // Write back the local values to the instance fields.
0 commit comments