Browse Source

Optimize code

pull/2511/head
Poker 3 years ago
parent
commit
316a8395b6
No known key found for this signature in database GPG Key ID: 720AFAD63099D9CB
  1. 8
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  2. 155
      src/ImageSharp/Formats/Png/PngScanlineProcessor.cs

8
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -671,7 +671,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
/// <param name="getData">A delegate to get more data from the inner stream for <see cref="ZlibInflateStream"/>.</param>
/// <param name="frameControl">The frame control</param>
/// <param name="cancellationToken">The cancellation token.</param>
private void ReadScanlines<TPixel>(int chunkLength, ImageFrame<TPixel> image, PngMetadata pngMetadata, Func<int> getData, FrameControl frameControl, CancellationToken cancellationToken)
private void ReadScanlines<TPixel>(int chunkLength, ImageFrame<TPixel> image, PngMetadata pngMetadata, Func<int> getData, in FrameControl frameControl, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
using ZlibInflateStream deframeStream = new(this.currentStream, getData);
@ -763,7 +763,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
/// <param name="image">The current image.</param>
/// <param name="pngMetadata">The png metadata.</param>
/// <param name="cancellationToken">The cancellation token.</param>
private void DecodeInterlacedPixelData<TPixel>(FrameControl frameControl, DeflateStream compressedStream, ImageFrame<TPixel> image, PngMetadata pngMetadata, CancellationToken cancellationToken)
private void DecodeInterlacedPixelData<TPixel>(in FrameControl frameControl, DeflateStream compressedStream, ImageFrame<TPixel> image, PngMetadata pngMetadata, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
int currentRow = Adam7.FirstRow[0] + frameControl.YOffset;
@ -864,7 +864,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
/// <param name="defilteredScanline">The de-filtered scanline</param>
/// <param name="pixels">The image</param>
/// <param name="pngMetadata">The png metadata.</param>
private void ProcessDefilteredScanline<TPixel>(FrameControl frameControl, int currentRow, ReadOnlySpan<byte> defilteredScanline, ImageFrame<TPixel> pixels, PngMetadata pngMetadata)
private void ProcessDefilteredScanline<TPixel>(in FrameControl frameControl, int currentRow, ReadOnlySpan<byte> defilteredScanline, ImageFrame<TPixel> pixels, PngMetadata pngMetadata)
where TPixel : unmanaged, IPixel<TPixel>
{
Span<TPixel> rowSpan = pixels.PixelBuffer.DangerousGetRowSpan(currentRow);
@ -961,7 +961,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
/// <param name="pngMetadata">The png metadata.</param>
/// <param name="pixelOffset">The column start index. Always 0 for none interlaced images.</param>
/// <param name="increment">The column increment. Always 1 for none interlaced images.</param>
private void ProcessInterlacedDefilteredScanline<TPixel>(FrameControl frameControl, ReadOnlySpan<byte> defilteredScanline, Span<TPixel> rowSpan, PngMetadata pngMetadata, int pixelOffset = 0, int increment = 1)
private void ProcessInterlacedDefilteredScanline<TPixel>(in FrameControl frameControl, ReadOnlySpan<byte> defilteredScanline, Span<TPixel> rowSpan, PngMetadata pngMetadata, int pixelOffset = 0, int increment = 1)
where TPixel : unmanaged, IPixel<TPixel>
{
// Trim the first marker byte from the buffer

155
src/ImageSharp/Formats/Png/PngScanlineProcessor.cs

@ -17,7 +17,7 @@ internal static class PngScanlineProcessor
{
public static void ProcessGrayscaleScanline<TPixel>(
int bitDepth,
FrameControl frameControl,
in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan,
bool hasTrans,
@ -37,7 +37,7 @@ internal static class PngScanlineProcessor
public static void ProcessInterlacedGrayscaleScanline<TPixel>(
int bitDepth,
FrameControl frameControl,
in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan,
uint pixelOffset,
@ -110,7 +110,7 @@ internal static class PngScanlineProcessor
public static void ProcessGrayscaleWithAlphaScanline<TPixel>(
int bitDepth,
FrameControl frameControl,
in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan,
uint bytesPerPixel,
@ -128,7 +128,7 @@ internal static class PngScanlineProcessor
public static void ProcessInterlacedGrayscaleWithAlphaScanline<TPixel>(
int bitDepth,
FrameControl frameControl,
in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan,
uint pixelOffset,
@ -172,7 +172,7 @@ internal static class PngScanlineProcessor
}
public static void ProcessPaletteScanline<TPixel>(
FrameControl frameControl,
in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan,
ReadOnlySpan<byte> palette,
@ -188,7 +188,7 @@ internal static class PngScanlineProcessor
paletteAlpha);
public static void ProcessInterlacedPaletteScanline<TPixel>(
FrameControl frameControl,
in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan,
uint pixelOffset,
@ -240,7 +240,7 @@ internal static class PngScanlineProcessor
public static void ProcessRgbScanline<TPixel>(
int bitDepth,
FrameControl frameControl,
in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan,
int bytesPerPixel,
@ -248,84 +248,23 @@ internal static class PngScanlineProcessor
bool hasTrans,
Rgb48 rgb48Trans,
Rgb24 rgb24Trans)
where TPixel : unmanaged, IPixel<TPixel>
{
uint offset = (uint)frameControl.XOffset;
TPixel pixel = default;
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
if (bitDepth == 16)
{
if (!hasTrans)
{
Rgb48 rgb48 = default;
int o = 0;
for (nuint x = offset; x < frameControl.XLimit; x++, o += bytesPerPixel)
{
rgb48.R = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o, bytesPerSample));
rgb48.G = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o + bytesPerSample, bytesPerSample));
rgb48.B = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o + (2 * bytesPerSample), bytesPerSample));
pixel.FromRgb48(rgb48);
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
else
{
Rgb48 rgb48 = default;
Rgba64 rgba64 = default;
int o = 0;
for (nuint x = offset; x < frameControl.XLimit; x++, o += bytesPerPixel)
{
rgb48.R = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o, bytesPerSample));
rgb48.G = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o + bytesPerSample, bytesPerSample));
rgb48.B = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o + (2 * bytesPerSample), bytesPerSample));
rgba64.Rgb = rgb48;
rgba64.A = rgb48.Equals(rgb48Trans) ? ushort.MinValue : ushort.MaxValue;
pixel.FromRgba64(rgba64);
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
return;
}
if (hasTrans)
{
Rgba32 rgba32 = default;
ReadOnlySpan<Rgb24> rgb24Span = MemoryMarshal.Cast<byte, Rgb24>(scanlineSpan);
ref Rgb24 rgb24SpanRef = ref MemoryMarshal.GetReference(rgb24Span);
for (nuint x = offset; x < frameControl.XLimit; x++)
{
ref readonly Rgb24 rgb24 = ref Unsafe.Add(ref rgb24SpanRef, x);
rgba32.Rgb = rgb24;
rgba32.A = rgb24.Equals(rgb24Trans) ? byte.MinValue : byte.MaxValue;
pixel.FromRgba32(rgba32);
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
else
{
ReadOnlySpan<Rgb24> source = MemoryMarshal.Cast<byte, Rgb24>(scanlineSpan)[..frameControl.Width];
ref Rgb24 sourceBaseRef = ref MemoryMarshal.GetReference(source);
ref TPixel destBaseRef = ref MemoryMarshal.GetReference(rowSpan);
for (nuint i = offset; i < frameControl.XLimit; i++)
{
ref Rgb24 sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i);
dp.FromRgb24(sp);
}
}
}
where TPixel : unmanaged, IPixel<TPixel> =>
ProcessInterlacedRgbScanline(
bitDepth,
frameControl,
scanlineSpan,
rowSpan,
0,
1,
bytesPerPixel,
bytesPerSample,
hasTrans,
rgb48Trans,
rgb24Trans);
public static void ProcessInterlacedRgbScanline<TPixel>(
int bitDepth,
FrameControl frameControl,
in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan,
uint pixelOffset,
@ -413,51 +352,25 @@ internal static class PngScanlineProcessor
public static void ProcessRgbaScanline<TPixel>(
int bitDepth,
FrameControl frameControl,
in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan,
int bytesPerPixel,
int bytesPerSample)
where TPixel : unmanaged, IPixel<TPixel>
{
uint offset = (uint)frameControl.XOffset;
TPixel pixel = default;
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
if (bitDepth == 16)
{
Rgba64 rgba64 = default;
int o = 0;
for (nuint x = offset; x < frameControl.XLimit; x++, o += bytesPerPixel)
{
rgba64.R = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o, bytesPerSample));
rgba64.G = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o + bytesPerSample, bytesPerSample));
rgba64.B = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o + (2 * bytesPerSample), bytesPerSample));
rgba64.A = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o + (3 * bytesPerSample), bytesPerSample));
pixel.FromRgba64(rgba64);
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
else
{
ReadOnlySpan<Rgba32> source = MemoryMarshal.Cast<byte, Rgba32>(scanlineSpan)[..frameControl.Width];
ref Rgba32 sourceBaseRef = ref MemoryMarshal.GetReference(source);
ref TPixel destBaseRef = ref MemoryMarshal.GetReference(rowSpan);
for (nuint i = offset; i < frameControl.XLimit; i++)
{
ref Rgba32 sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i);
dp.FromRgba32(sp);
}
}
}
where TPixel : unmanaged, IPixel<TPixel> =>
ProcessInterlacedRgbaScanline(
bitDepth,
frameControl,
scanlineSpan,
rowSpan,
0,
1,
bytesPerPixel,
bytesPerSample);
public static void ProcessInterlacedRgbaScanline<TPixel>(
int bitDepth,
FrameControl frameControl,
in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan,
uint pixelOffset,
@ -468,7 +381,6 @@ internal static class PngScanlineProcessor
{
uint offset = pixelOffset + (uint)frameControl.XOffset;
TPixel pixel = default;
ref byte scanlineSpanRef = ref MemoryMarshal.GetReference(scanlineSpan);
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
if (bitDepth == 16)
@ -488,6 +400,7 @@ internal static class PngScanlineProcessor
}
else
{
ref byte scanlineSpanRef = ref MemoryMarshal.GetReference(scanlineSpan);
Rgba32 rgba = default;
int o = 0;
for (nuint x = offset; x < frameControl.XLimit; x += increment, o += bytesPerPixel)

Loading…
Cancel
Save