diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index a426208944..dce94b5cec 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -671,7 +671,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
/// A delegate to get more data from the inner stream for .
/// The frame control
/// The cancellation token.
- private void ReadScanlines(int chunkLength, ImageFrame image, PngMetadata pngMetadata, Func getData, FrameControl frameControl, CancellationToken cancellationToken)
+ private void ReadScanlines(int chunkLength, ImageFrame image, PngMetadata pngMetadata, Func getData, in FrameControl frameControl, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel
{
using ZlibInflateStream deframeStream = new(this.currentStream, getData);
@@ -763,7 +763,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
/// The current image.
/// The png metadata.
/// The cancellation token.
- private void DecodeInterlacedPixelData(FrameControl frameControl, DeflateStream compressedStream, ImageFrame image, PngMetadata pngMetadata, CancellationToken cancellationToken)
+ private void DecodeInterlacedPixelData(in FrameControl frameControl, DeflateStream compressedStream, ImageFrame image, PngMetadata pngMetadata, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel
{
int currentRow = Adam7.FirstRow[0] + frameControl.YOffset;
@@ -864,7 +864,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
/// The de-filtered scanline
/// The image
/// The png metadata.
- private void ProcessDefilteredScanline(FrameControl frameControl, int currentRow, ReadOnlySpan defilteredScanline, ImageFrame pixels, PngMetadata pngMetadata)
+ private void ProcessDefilteredScanline(in FrameControl frameControl, int currentRow, ReadOnlySpan defilteredScanline, ImageFrame pixels, PngMetadata pngMetadata)
where TPixel : unmanaged, IPixel
{
Span rowSpan = pixels.PixelBuffer.DangerousGetRowSpan(currentRow);
@@ -961,7 +961,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
/// The png metadata.
/// The column start index. Always 0 for none interlaced images.
/// The column increment. Always 1 for none interlaced images.
- private void ProcessInterlacedDefilteredScanline(FrameControl frameControl, ReadOnlySpan defilteredScanline, Span rowSpan, PngMetadata pngMetadata, int pixelOffset = 0, int increment = 1)
+ private void ProcessInterlacedDefilteredScanline(in FrameControl frameControl, ReadOnlySpan defilteredScanline, Span rowSpan, PngMetadata pngMetadata, int pixelOffset = 0, int increment = 1)
where TPixel : unmanaged, IPixel
{
// Trim the first marker byte from the buffer
diff --git a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs
index 67a1f7c82d..85fc2b120e 100644
--- a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs
+++ b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs
@@ -17,7 +17,7 @@ internal static class PngScanlineProcessor
{
public static void ProcessGrayscaleScanline(
int bitDepth,
- FrameControl frameControl,
+ in FrameControl frameControl,
ReadOnlySpan scanlineSpan,
Span rowSpan,
bool hasTrans,
@@ -37,7 +37,7 @@ internal static class PngScanlineProcessor
public static void ProcessInterlacedGrayscaleScanline(
int bitDepth,
- FrameControl frameControl,
+ in FrameControl frameControl,
ReadOnlySpan scanlineSpan,
Span rowSpan,
uint pixelOffset,
@@ -110,7 +110,7 @@ internal static class PngScanlineProcessor
public static void ProcessGrayscaleWithAlphaScanline(
int bitDepth,
- FrameControl frameControl,
+ in FrameControl frameControl,
ReadOnlySpan scanlineSpan,
Span rowSpan,
uint bytesPerPixel,
@@ -128,7 +128,7 @@ internal static class PngScanlineProcessor
public static void ProcessInterlacedGrayscaleWithAlphaScanline(
int bitDepth,
- FrameControl frameControl,
+ in FrameControl frameControl,
ReadOnlySpan scanlineSpan,
Span rowSpan,
uint pixelOffset,
@@ -172,7 +172,7 @@ internal static class PngScanlineProcessor
}
public static void ProcessPaletteScanline(
- FrameControl frameControl,
+ in FrameControl frameControl,
ReadOnlySpan scanlineSpan,
Span rowSpan,
ReadOnlySpan palette,
@@ -188,7 +188,7 @@ internal static class PngScanlineProcessor
paletteAlpha);
public static void ProcessInterlacedPaletteScanline(
- FrameControl frameControl,
+ in FrameControl frameControl,
ReadOnlySpan scanlineSpan,
Span rowSpan,
uint pixelOffset,
@@ -240,7 +240,7 @@ internal static class PngScanlineProcessor
public static void ProcessRgbScanline(
int bitDepth,
- FrameControl frameControl,
+ in FrameControl frameControl,
ReadOnlySpan scanlineSpan,
Span rowSpan,
int bytesPerPixel,
@@ -248,84 +248,23 @@ internal static class PngScanlineProcessor
bool hasTrans,
Rgb48 rgb48Trans,
Rgb24 rgb24Trans)
- where TPixel : unmanaged, IPixel
- {
- 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 rgb24Span = MemoryMarshal.Cast(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 source = MemoryMarshal.Cast(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 =>
+ ProcessInterlacedRgbScanline(
+ bitDepth,
+ frameControl,
+ scanlineSpan,
+ rowSpan,
+ 0,
+ 1,
+ bytesPerPixel,
+ bytesPerSample,
+ hasTrans,
+ rgb48Trans,
+ rgb24Trans);
public static void ProcessInterlacedRgbScanline(
int bitDepth,
- FrameControl frameControl,
+ in FrameControl frameControl,
ReadOnlySpan scanlineSpan,
Span rowSpan,
uint pixelOffset,
@@ -413,51 +352,25 @@ internal static class PngScanlineProcessor
public static void ProcessRgbaScanline(
int bitDepth,
- FrameControl frameControl,
+ in FrameControl frameControl,
ReadOnlySpan scanlineSpan,
Span rowSpan,
int bytesPerPixel,
int bytesPerSample)
- where TPixel : unmanaged, IPixel
- {
- 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 source = MemoryMarshal.Cast(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 =>
+ ProcessInterlacedRgbaScanline(
+ bitDepth,
+ frameControl,
+ scanlineSpan,
+ rowSpan,
+ 0,
+ 1,
+ bytesPerPixel,
+ bytesPerSample);
public static void ProcessInterlacedRgbaScanline(
int bitDepth,
- FrameControl frameControl,
+ in FrameControl frameControl,
ReadOnlySpan scanlineSpan,
Span 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)