@@ -78,6 +78,7 @@ internal sealed class LzwDecoder : IDisposable
78
78
public LzwDecoder ( MemoryAllocator memoryAllocator , BufferedReadStream stream , int minCodeSize )
79
79
{
80
80
this . stream = stream ?? throw new ArgumentNullException ( nameof ( stream ) ) ;
81
+ Guard . IsTrue ( IsValidMinCodeSize ( minCodeSize ) , nameof ( minCodeSize ) , "Invalid minimum code size." ) ;
81
82
82
83
this . prefixOwner = memoryAllocator . Allocate < int > ( MaxStackSize , AllocationOptions . Clean ) ;
83
84
this . suffixOwner = memoryAllocator . Allocate < int > ( MaxStackSize , AllocationOptions . Clean ) ;
@@ -92,12 +93,15 @@ public LzwDecoder(MemoryAllocator memoryAllocator, BufferedReadStream stream, in
92
93
this . endCode = this . clearCode + 1 ;
93
94
this . availableCode = this . clearCode + 2 ;
94
95
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 ++ )
98
100
{
99
- suffix [ this . code ] = ( byte ) this . code ;
101
+ suffix [ i ] = i ;
100
102
}
103
+
104
+ this . code = i ;
101
105
}
102
106
103
107
/// <summary>
@@ -112,8 +116,7 @@ public static bool IsValidMinCodeSize(int minCodeSize)
112
116
// It is possible to specify a larger LZW minimum code size than the palette length in bits
113
117
// which may leave a gap in the codes where no colors are assigned.
114
118
// 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 )
117
120
{
118
121
// Don't attempt to decode the frame indices.
119
122
// Theoretically we could determine a min code size from the length of the provided
@@ -137,7 +140,6 @@ public void DecodePixelRow(Span<byte> indices)
137
140
Span < int > suffix = this . suffixOwner . GetSpan ( ) ;
138
141
Span < int > pixelStack = this . pixelStackOwner . GetSpan ( ) ;
139
142
Span < byte > buffer = this . bufferOwner . GetSpan ( ) ;
140
- int maxTop = this . pixelStackOwner . Length ( ) - 1 ;
141
143
142
144
// Cache frequently accessed instance fields into locals.
143
145
// This helps avoid repeated field loads inside the tight loop.
@@ -157,8 +159,8 @@ public void DecodePixelRow(Span<byte> indices)
157
159
int clearCode = this . clearCode ;
158
160
int endCode = this . endCode ;
159
161
160
- int xyz = 0 ;
161
- while ( xyz < indices . Length )
162
+ int i = 0 ;
163
+ while ( i < indices . Length )
162
164
{
163
165
if ( top == 0 )
164
166
{
@@ -220,7 +222,7 @@ public void DecodePixelRow(Span<byte> indices)
220
222
code = oldCode ;
221
223
}
222
224
223
- while ( code > clearCode && top < maxTop )
225
+ while ( code > clearCode && top < MaxStackSize )
224
226
{
225
227
pixelStack [ top ++ ] = suffix [ code ] ;
226
228
code = prefix [ code ] ;
@@ -251,7 +253,7 @@ public void DecodePixelRow(Span<byte> indices)
251
253
top -- ;
252
254
253
255
// Clear missing pixels.
254
- indices [ xyz ++ ] = ( byte ) pixelStack [ top ] ;
256
+ indices [ i ++ ] = ( byte ) pixelStack [ top ] ;
255
257
}
256
258
257
259
// Write back the local values to the instance fields.
@@ -279,7 +281,6 @@ public void SkipIndices(int length)
279
281
Span < int > suffix = this . suffixOwner . GetSpan ( ) ;
280
282
Span < int > pixelStack = this . pixelStackOwner . GetSpan ( ) ;
281
283
Span < byte > buffer = this . bufferOwner . GetSpan ( ) ;
282
- int maxTop = this . pixelStackOwner . Length ( ) - 1 ;
283
284
284
285
// Cache frequently accessed instance fields into locals.
285
286
// This helps avoid repeated field loads inside the tight loop.
@@ -299,8 +300,8 @@ public void SkipIndices(int length)
299
300
int clearCode = this . clearCode ;
300
301
int endCode = this . endCode ;
301
302
302
- int xyz = 0 ;
303
- while ( xyz < length )
303
+ int i = 0 ;
304
+ while ( i < length )
304
305
{
305
306
if ( top == 0 )
306
307
{
@@ -362,7 +363,7 @@ public void SkipIndices(int length)
362
363
code = oldCode ;
363
364
}
364
365
365
- while ( code > clearCode && top < maxTop )
366
+ while ( code > clearCode && top < MaxStackSize )
366
367
{
367
368
pixelStack [ top ++ ] = suffix [ code ] ;
368
369
code = prefix [ code ] ;
@@ -393,7 +394,7 @@ public void SkipIndices(int length)
393
394
top -- ;
394
395
395
396
// Skip missing pixels.
396
- xyz ++ ;
397
+ i ++ ;
397
398
}
398
399
399
400
// Write back the local values to the instance fields.
0 commit comments