mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-04-05 20:55:01 +08:00
Optimize Crc32 calculations
This commit is contained in:
parent
4ad6bfc74e
commit
0efa68a8e4
@ -1,12 +1,11 @@
|
||||
namespace UglyToad.PdfPig.Images.Png
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit Cyclic Redundancy Code used by the PNG for checking the data is intact.
|
||||
/// </summary>
|
||||
internal static class Crc32
|
||||
internal class Crc32
|
||||
{
|
||||
private const uint Polynomial = 0xEDB88320;
|
||||
|
||||
@ -49,21 +48,6 @@
|
||||
return crc32 ^ uint.MaxValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the CRC32 for data.
|
||||
/// </summary>
|
||||
public static uint Calculate(List<byte> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the combined CRC32 for data.
|
||||
/// </summary>
|
||||
@ -84,5 +68,30 @@
|
||||
|
||||
return crc32 ^ uint.MaxValue;
|
||||
}
|
||||
|
||||
|
||||
private uint state = uint.MaxValue;
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the CRC32 for data.
|
||||
/// </summary>
|
||||
public void Append(ReadOnlySpan<byte> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<byte> written = new List<byte>();
|
||||
private readonly Crc32 crc = new();
|
||||
|
||||
public override bool CanRead => inner.CanRead;
|
||||
|
||||
@ -33,7 +32,7 @@
|
||||
|
||||
public void WriteChunkHeader(ReadOnlySpan<byte> 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<byte> buffer)
|
||||
{
|
||||
written.AddRange(buffer);
|
||||
crc.Append(buffer);
|
||||
inner.Write(buffer);
|
||||
}
|
||||
#else
|
||||
public void Write(ReadOnlySpan<byte> 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<byte> buffer = stackalloc byte[4];
|
||||
|
||||
var result = crc.GetCurrentHashAsUInt32();
|
||||
|
||||
BinaryPrimitives.WriteUInt32BigEndian(buffer, result);
|
||||
|
||||
inner.Write(buffer);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user