diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index 2c7396f3ec..ffa3875057 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -349,13 +349,12 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Converts a byte array to a new array where each value in the original array is represented by the specified number of bits.
///
- /// The bytes to convert from. Cannot be null.
+ /// The bytes to convert from. Cannot be empty.
/// The number of bytes per scanline
/// The number of bits per value.
- /// The resulting array. Is never null.
- /// is null.
+ /// The resulting array.
/// is less than or equals than zero.
- private static Span ToArrayByBitsLength(Span source, int bytesPerScanline, int bits)
+ private static ReadOnlySpan ToArrayByBitsLength(ReadOnlySpan source, int bytesPerScanline, int bits)
{
Guard.MustBeGreaterThan(source.Length, 0, nameof(source));
Guard.MustBeGreaterThan(bits, 0, nameof(bits));
@@ -669,7 +668,7 @@ namespace SixLabors.ImageSharp.Formats.Png
}
Span rowSpan = image.GetPixelRowSpan(this.currentRow);
- this.ProcessInterlacedDefilteredScanline(this.scanline.Array, rowSpan, Adam7FirstColumn[this.pass], Adam7ColumnIncrement[this.pass]);
+ this.ProcessInterlacedDefilteredScanline(this.scanline.Span, rowSpan, Adam7FirstColumn[this.pass], Adam7ColumnIncrement[this.pass]);
this.SwapBuffers();
@@ -697,20 +696,20 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The pixel format.
/// The de-filtered scanline
/// The image
- private void ProcessDefilteredScanline(Span defilteredScanline, ImageFrame pixels)
+ private void ProcessDefilteredScanline(ReadOnlySpan defilteredScanline, ImageFrame pixels)
where TPixel : struct, IPixel
{
var color = default(TPixel);
Span rowSpan = pixels.GetPixelRowSpan(this.currentRow);
// Trim the first marker byte from the buffer
- Span scanlineBuffer = defilteredScanline.Slice(1, defilteredScanline.Length - 1);
+ ReadOnlySpan scanlineBuffer = defilteredScanline.Slice(1, defilteredScanline.Length - 1);
switch (this.pngColorType)
{
case PngColorType.Grayscale:
int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1);
- Span newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
+ ReadOnlySpan newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
for (int x = 0; x < this.header.Width; x++)
{
@@ -794,10 +793,10 @@ namespace SixLabors.ImageSharp.Formats.Png
}
else
{
- Span rgb24Span = scanlineBuffer.NonPortableCast();
+ ReadOnlySpan rgb24Span = scanlineBuffer.NonPortableCast();
for (int x = 0; x < this.header.Width; x++)
{
- ref Rgb24 rgb24 = ref rgb24Span[x];
+ ref readonly Rgb24 rgb24 = ref rgb24Span[x];
var rgba32 = default(Rgba32);
rgba32.Rgb = rgb24;
rgba32.A = (byte)(rgb24.Equals(this.rgb24Trans) ? 0 : 255);
@@ -838,7 +837,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The target buffer
/// The target length
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void From16BitTo8Bit(Span source, Span target, int length)
+ private void From16BitTo8Bit(ReadOnlySpan source, Span target, int length)
{
for (int i = 0, j = 0; i < length; i++, j += 2)
{
@@ -879,10 +878,10 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The type of pixel we are expanding to
/// The scanline
/// Thecurrent output image row
- private void ProcessScanlineFromPalette(Span defilteredScanline, Span row)
+ private void ProcessScanlineFromPalette(ReadOnlySpan defilteredScanline, Span row)
where TPixel : struct, IPixel
{
- Span newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth);
+ ReadOnlySpan newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth);
byte[] pal = this.palette;
var color = default(TPixel);
@@ -929,19 +928,19 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The current image row.
/// The column start index. Always 0 for none interlaced images.
/// The column increment. Always 1 for none interlaced images.
- private void ProcessInterlacedDefilteredScanline(byte[] defilteredScanline, Span rowSpan, int pixelOffset = 0, int increment = 1)
+ private void ProcessInterlacedDefilteredScanline(ReadOnlySpan defilteredScanline, Span rowSpan, int pixelOffset = 0, int increment = 1)
where TPixel : struct, IPixel
{
var color = default(TPixel);
// Trim the first marker byte from the buffer
- var scanlineBuffer = new Span(defilteredScanline, 1, defilteredScanline.Length - 1);
+ ReadOnlySpan scanlineBuffer = defilteredScanline.Slice(1, defilteredScanline.Length - 1);
switch (this.pngColorType)
{
case PngColorType.Grayscale:
int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1);
- Span newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
+ ReadOnlySpan newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
for (int x = pixelOffset, o = 0; x < this.header.Width; x += increment, o++)
{
@@ -974,7 +973,7 @@ namespace SixLabors.ImageSharp.Formats.Png
case PngColorType.Palette:
- Span newScanline = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
+ ReadOnlySpan newScanline = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
var rgba = default(Rgba32);
if (this.paletteAlpha != null && this.paletteAlpha.Length > 0)
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index a0e09e911e..0cded1d80c 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -255,7 +255,7 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// The pixel format.
/// The image row span.
- private void CollectGrayscaleBytes(Span rowSpan)
+ private void CollectGrayscaleBytes(ReadOnlySpan rowSpan)
where TPixel : struct, IPixel
{
byte[] rawScanlineArray = this.rawScanline.Array;
@@ -290,7 +290,7 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// The pixel format.
/// The row span.
- private void CollecTPixelBytes(Span rowSpan)
+ private void CollecTPixelBytes(ReadOnlySpan rowSpan)
where TPixel : struct, IPixel
{
if (this.bytesPerPixel == 4)
@@ -311,7 +311,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The row span.
/// The row.
/// The
- private IManagedByteBuffer EncodePixelRow(Span rowSpan, int row)
+ private IManagedByteBuffer EncodePixelRow(ReadOnlySpan rowSpan, int row)
where TPixel : struct, IPixel
{
switch (this.pngColorType)
@@ -554,15 +554,14 @@ namespace SixLabors.ImageSharp.Formats.Png
byte[] buffer;
int bufferLength;
- MemoryStream memoryStream = null;
- try
+
+ using (var memoryStream = new MemoryStream())
{
- memoryStream = new MemoryStream();
using (var deflateStream = new ZlibDeflateStream(memoryStream, this.compressionLevel))
{
for (int y = 0; y < this.height; y++)
{
- IManagedByteBuffer r = this.EncodePixelRow(pixels.GetPixelRowSpan(y), y);
+ IManagedByteBuffer r = this.EncodePixelRow(pixels.GetPixelRowSpan(y).AsReadOnlySpan(), y);
deflateStream.Write(r.Array, 0, resultLength);
IManagedByteBuffer temp = this.rawScanline;
@@ -574,10 +573,6 @@ namespace SixLabors.ImageSharp.Formats.Png
buffer = memoryStream.ToArray();
bufferLength = buffer.Length;
}
- finally
- {
- memoryStream?.Dispose();
- }
// Store the chunks in repeated 64k blocks.
// This reduces the memory load for decoding the image for many decoders.