diff --git a/src/UglyToad.PdfPig/Images/Png/Crc32.cs b/src/UglyToad.PdfPig/Images/Png/Crc32.cs
index e75e2e7c..04055beb 100644
--- a/src/UglyToad.PdfPig/Images/Png/Crc32.cs
+++ b/src/UglyToad.PdfPig/Images/Png/Crc32.cs
@@ -1,12 +1,11 @@
namespace UglyToad.PdfPig.Images.Png
{
using System;
- using System.Collections.Generic;
///
/// 32-bit Cyclic Redundancy Code used by the PNG for checking the data is intact.
///
- internal static class Crc32
+ internal class Crc32
{
private const uint Polynomial = 0xEDB88320;
@@ -49,21 +48,6 @@
return crc32 ^ uint.MaxValue;
}
- ///
- /// Calculate the CRC32 for data.
- ///
- public static uint Calculate(List data)
- {
- var crc32 = uint.MaxValue;
- for (var i = 0; i < data.Count; i++)
- {
- var index = (crc32 ^ data[i]) & 0xFF;
- crc32 = (crc32 >> 8) ^ Lookup[index];
- }
-
- return crc32 ^ uint.MaxValue;
- }
-
///
/// Calculate the combined CRC32 for data.
///
@@ -84,5 +68,30 @@
return crc32 ^ uint.MaxValue;
}
+
+
+ private uint state = uint.MaxValue;
+
+ ///
+ /// Calculate the CRC32 for data.
+ ///
+ public void Append(ReadOnlySpan data)
+ {
+ for (var i = 0; i < data.Length; i++)
+ {
+ var index = (state ^ data[i]) & 0xFF;
+ state = (state >> 8) ^ Lookup[index];
+ }
+ }
+
+ public uint GetCurrentHashAsUInt32()
+ {
+ return state ^ uint.MaxValue;
+ }
+
+ public void Reset()
+ {
+ state = uint.MaxValue;
+ }
}
}
diff --git a/src/UglyToad.PdfPig/Images/Png/PngStreamWriteHelper.cs b/src/UglyToad.PdfPig/Images/Png/PngStreamWriteHelper.cs
index f09c52a1..68cb9479 100644
--- a/src/UglyToad.PdfPig/Images/Png/PngStreamWriteHelper.cs
+++ b/src/UglyToad.PdfPig/Images/Png/PngStreamWriteHelper.cs
@@ -1,14 +1,13 @@
namespace UglyToad.PdfPig.Images.Png
{
using System;
- using System.Collections.Generic;
+ using System.Buffers.Binary;
using System.IO;
- using System.Linq;
- internal class PngStreamWriteHelper : Stream
+ internal sealed class PngStreamWriteHelper : Stream
{
private readonly Stream inner;
- private readonly List written = new List();
+ private readonly Crc32 crc = new();
public override bool CanRead => inner.CanRead;
@@ -33,7 +32,7 @@
public void WriteChunkHeader(ReadOnlySpan header)
{
- written.Clear();
+ crc.Reset();
Write(header);
}
@@ -50,28 +49,33 @@
public override void Write(byte[] buffer, int offset, int count)
{
- written.AddRange(buffer.Skip(offset).Take(count));
+ crc.Append(buffer.AsSpan(offset, count));
inner.Write(buffer, offset, count);
}
#if NET8_0_OR_GREATER
public override void Write(ReadOnlySpan buffer)
{
- written.AddRange(buffer);
+ crc.Append(buffer);
inner.Write(buffer);
}
#else
public void Write(ReadOnlySpan buffer)
{
- written.AddRange(buffer.ToArray());
+ crc.Append(buffer);
inner.Write(buffer);
}
#endif
public void WriteCrc()
{
- var result = (int)Crc32.Calculate(written);
- StreamHelper.WriteBigEndianInt32(inner, result);
+ Span buffer = stackalloc byte[4];
+
+ var result = crc.GetCurrentHashAsUInt32();
+
+ BinaryPrimitives.WriteUInt32BigEndian(buffer, result);
+
+ inner.Write(buffer);
}
}
}
\ No newline at end of file