Skip to content

Commit 20e5596

Browse files
Clean up and optimize
1 parent ca07754 commit 20e5596

File tree

1 file changed

+17
-16
lines changed

1 file changed

+17
-16
lines changed

src/ImageSharp/Formats/Gif/LzwDecoder.cs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)