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="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="frameControl">The frame control</param>
/// <param name="cancellationToken">The cancellation token.</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> where TPixel : unmanaged, IPixel<TPixel>
{ {
using ZlibInflateStream deframeStream = new(this.currentStream, getData); 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="image">The current image.</param>
/// <param name="pngMetadata">The png metadata.</param> /// <param name="pngMetadata">The png metadata.</param>
/// <param name="cancellationToken">The cancellation token.</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> where TPixel : unmanaged, IPixel<TPixel>
{ {
int currentRow = Adam7.FirstRow[0] + frameControl.YOffset; 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="defilteredScanline">The de-filtered scanline</param>
/// <param name="pixels">The image</param> /// <param name="pixels">The image</param>
/// <param name="pngMetadata">The png metadata.</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> where TPixel : unmanaged, IPixel<TPixel>
{ {
Span<TPixel> rowSpan = pixels.PixelBuffer.DangerousGetRowSpan(currentRow); 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="pngMetadata">The png metadata.</param>
/// <param name="pixelOffset">The column start index. Always 0 for none interlaced images.</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> /// <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> where TPixel : unmanaged, IPixel<TPixel>
{ {
// Trim the first marker byte from the buffer // 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>( public static void ProcessGrayscaleScanline<TPixel>(
int bitDepth, int bitDepth,
FrameControl frameControl, in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan, ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan, Span<TPixel> rowSpan,
bool hasTrans, bool hasTrans,
@ -37,7 +37,7 @@ internal static class PngScanlineProcessor
public static void ProcessInterlacedGrayscaleScanline<TPixel>( public static void ProcessInterlacedGrayscaleScanline<TPixel>(
int bitDepth, int bitDepth,
FrameControl frameControl, in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan, ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan, Span<TPixel> rowSpan,
uint pixelOffset, uint pixelOffset,
@ -110,7 +110,7 @@ internal static class PngScanlineProcessor
public static void ProcessGrayscaleWithAlphaScanline<TPixel>( public static void ProcessGrayscaleWithAlphaScanline<TPixel>(
int bitDepth, int bitDepth,
FrameControl frameControl, in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan, ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan, Span<TPixel> rowSpan,
uint bytesPerPixel, uint bytesPerPixel,
@ -128,7 +128,7 @@ internal static class PngScanlineProcessor
public static void ProcessInterlacedGrayscaleWithAlphaScanline<TPixel>( public static void ProcessInterlacedGrayscaleWithAlphaScanline<TPixel>(
int bitDepth, int bitDepth,
FrameControl frameControl, in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan, ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan, Span<TPixel> rowSpan,
uint pixelOffset, uint pixelOffset,
@ -172,7 +172,7 @@ internal static class PngScanlineProcessor
} }
public static void ProcessPaletteScanline<TPixel>( public static void ProcessPaletteScanline<TPixel>(
FrameControl frameControl, in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan, ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan, Span<TPixel> rowSpan,
ReadOnlySpan<byte> palette, ReadOnlySpan<byte> palette,
@ -188,7 +188,7 @@ internal static class PngScanlineProcessor
paletteAlpha); paletteAlpha);
public static void ProcessInterlacedPaletteScanline<TPixel>( public static void ProcessInterlacedPaletteScanline<TPixel>(
FrameControl frameControl, in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan, ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan, Span<TPixel> rowSpan,
uint pixelOffset, uint pixelOffset,
@ -240,7 +240,7 @@ internal static class PngScanlineProcessor
public static void ProcessRgbScanline<TPixel>( public static void ProcessRgbScanline<TPixel>(
int bitDepth, int bitDepth,
FrameControl frameControl, in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan, ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan, Span<TPixel> rowSpan,
int bytesPerPixel, int bytesPerPixel,
@ -248,84 +248,23 @@ internal static class PngScanlineProcessor
bool hasTrans, bool hasTrans,
Rgb48 rgb48Trans, Rgb48 rgb48Trans,
Rgb24 rgb24Trans) Rgb24 rgb24Trans)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel> =>
{ ProcessInterlacedRgbScanline(
uint offset = (uint)frameControl.XOffset; bitDepth,
TPixel pixel = default; frameControl,
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan); scanlineSpan,
rowSpan,
if (bitDepth == 16) 0,
{ 1,
if (!hasTrans) bytesPerPixel,
{ bytesPerSample,
Rgb48 rgb48 = default; hasTrans,
int o = 0; rgb48Trans,
for (nuint x = offset; x < frameControl.XLimit; x++, o += bytesPerPixel) rgb24Trans);
{
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);
}
}
}
public static void ProcessInterlacedRgbScanline<TPixel>( public static void ProcessInterlacedRgbScanline<TPixel>(
int bitDepth, int bitDepth,
FrameControl frameControl, in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan, ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan, Span<TPixel> rowSpan,
uint pixelOffset, uint pixelOffset,
@ -413,51 +352,25 @@ internal static class PngScanlineProcessor
public static void ProcessRgbaScanline<TPixel>( public static void ProcessRgbaScanline<TPixel>(
int bitDepth, int bitDepth,
FrameControl frameControl, in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan, ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan, Span<TPixel> rowSpan,
int bytesPerPixel, int bytesPerPixel,
int bytesPerSample) int bytesPerSample)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel> =>
{ ProcessInterlacedRgbaScanline(
uint offset = (uint)frameControl.XOffset; bitDepth,
TPixel pixel = default; frameControl,
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan); scanlineSpan,
rowSpan,
if (bitDepth == 16) 0,
{ 1,
Rgba64 rgba64 = default; bytesPerPixel,
int o = 0; bytesPerSample);
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);
}
}
}
public static void ProcessInterlacedRgbaScanline<TPixel>( public static void ProcessInterlacedRgbaScanline<TPixel>(
int bitDepth, int bitDepth,
FrameControl frameControl, in FrameControl frameControl,
ReadOnlySpan<byte> scanlineSpan, ReadOnlySpan<byte> scanlineSpan,
Span<TPixel> rowSpan, Span<TPixel> rowSpan,
uint pixelOffset, uint pixelOffset,
@ -468,7 +381,6 @@ internal static class PngScanlineProcessor
{ {
uint offset = pixelOffset + (uint)frameControl.XOffset; uint offset = pixelOffset + (uint)frameControl.XOffset;
TPixel pixel = default; TPixel pixel = default;
ref byte scanlineSpanRef = ref MemoryMarshal.GetReference(scanlineSpan);
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan); ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
if (bitDepth == 16) if (bitDepth == 16)
@ -488,6 +400,7 @@ internal static class PngScanlineProcessor
} }
else else
{ {
ref byte scanlineSpanRef = ref MemoryMarshal.GetReference(scanlineSpan);
Rgba32 rgba = default; Rgba32 rgba = default;
int o = 0; int o = 0;
for (nuint x = offset; x < frameControl.XLimit; x += increment, o += bytesPerPixel) for (nuint x = offset; x < frameControl.XLimit; x += increment, o += bytesPerPixel)

Loading…
Cancel
Save