diff --git a/src/ImageSharp/Formats/Png/PngChunk.cs b/src/ImageSharp/Formats/Png/PngChunk.cs index fd11ba1b6..7b5f390f1 100644 --- a/src/ImageSharp/Formats/Png/PngChunk.cs +++ b/src/ImageSharp/Formats/Png/PngChunk.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.Memory; +using System.Buffers; namespace SixLabors.ImageSharp.Formats.Png { @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// internal readonly struct PngChunk { - public PngChunk(int length, PngChunkType type, IManagedByteBuffer data = null) + public PngChunk(int length, PngChunkType type, IMemoryOwner data = null) { this.Length = length; this.Type = type; @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// Gets the data bytes appropriate to the chunk type, if any. /// This field can be of zero length or null. /// - public IManagedByteBuffer Data { get; } + public IMemoryOwner Data { get; } /// /// Gets a value indicating whether the given chunk is critical to decoding diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index c2c336c03..a80cea7f9 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers; using System.Buffers.Binary; using System.Collections.Generic; using System.IO; @@ -84,12 +85,12 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Previous scanline processed. /// - private IManagedByteBuffer previousScanline; + private IMemoryOwner previousScanline; /// /// The current scanline that is being processed. /// - private IManagedByteBuffer scanline; + private IMemoryOwner scanline; /// /// The index of the current scanline being processed. @@ -149,7 +150,7 @@ namespace SixLabors.ImageSharp.Formats.Png switch (chunk.Type) { case PngChunkType.Header: - this.ReadHeaderChunk(pngMetadata, chunk.Data.Array); + this.ReadHeaderChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.Physical: this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); @@ -168,29 +169,29 @@ namespace SixLabors.ImageSharp.Formats.Png break; case PngChunkType.Palette: var pal = new byte[chunk.Length]; - Buffer.BlockCopy(chunk.Data.Array, 0, pal, 0, chunk.Length); + chunk.Data.GetSpan().CopyTo(pal); this.palette = pal; break; case PngChunkType.Transparency: var alpha = new byte[chunk.Length]; - Buffer.BlockCopy(chunk.Data.Array, 0, alpha, 0, chunk.Length); + chunk.Data.GetSpan().CopyTo(alpha); this.paletteAlpha = alpha; this.AssignTransparentMarkers(alpha, pngMetadata); break; case PngChunkType.Text: - this.ReadTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length)); + this.ReadTextChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.CompressedText: - this.ReadCompressedTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length)); + this.ReadCompressedTextChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.InternationalText: - this.ReadInternationalTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length)); + this.ReadInternationalTextChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.Exif: if (!this.ignoreMetadata) { var exifData = new byte[chunk.Length]; - Buffer.BlockCopy(chunk.Data.Array, 0, exifData, 0, chunk.Length); + chunk.Data.GetSpan().CopyTo(exifData); metadata.ExifProfile = new ExifProfile(exifData); } @@ -239,7 +240,7 @@ namespace SixLabors.ImageSharp.Formats.Png switch (chunk.Type) { case PngChunkType.Header: - this.ReadHeaderChunk(pngMetadata, chunk.Data.Array); + this.ReadHeaderChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.Physical: this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); @@ -251,19 +252,19 @@ namespace SixLabors.ImageSharp.Formats.Png this.SkipChunkDataAndCrc(chunk); break; case PngChunkType.Text: - this.ReadTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length)); + this.ReadTextChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.CompressedText: - this.ReadCompressedTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length)); + this.ReadCompressedTextChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.InternationalText: - this.ReadInternationalTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length)); + this.ReadInternationalTextChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.Exif: if (!this.ignoreMetadata) { var exifData = new byte[chunk.Length]; - Buffer.BlockCopy(chunk.Data.Array, 0, exifData, 0, chunk.Length); + chunk.Data.GetSpan().CopyTo(exifData); metadata.ExifProfile = new ExifProfile(exifData); } @@ -312,7 +313,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The number of bits per value. /// The new array. /// The resulting array. - private bool TryScaleUpTo8BitArray(ReadOnlySpan source, int bytesPerScanline, int bits, out IManagedByteBuffer buffer) + private bool TryScaleUpTo8BitArray(ReadOnlySpan source, int bytesPerScanline, int bits, out IMemoryOwner buffer) { if (bits >= 8) { @@ -320,9 +321,9 @@ namespace SixLabors.ImageSharp.Formats.Png return false; } - buffer = this.memoryAllocator.AllocateManagedByteBuffer(bytesPerScanline * 8 / bits, AllocationOptions.Clean); + buffer = this.memoryAllocator.Allocate(bytesPerScanline * 8 / bits, AllocationOptions.Clean); ref byte sourceRef = ref MemoryMarshal.GetReference(source); - ref byte resultRef = ref buffer.Array[0]; + ref byte resultRef = ref buffer.GetReference(); int mask = 0xFF >> (8 - bits); int resultOffset = 0; @@ -504,7 +505,8 @@ namespace SixLabors.ImageSharp.Formats.Png { while (this.currentRow < this.header.Height) { - int bytesRead = compressedStream.Read(this.scanline.Array, this.currentRowBytesRead, this.bytesPerScanline - this.currentRowBytesRead); + Span scanlineSpan = this.scanline.GetSpan(); + int bytesRead = compressedStream.Read(scanlineSpan, this.currentRowBytesRead, this.bytesPerScanline - this.currentRowBytesRead); this.currentRowBytesRead += bytesRead; if (this.currentRowBytesRead < this.bytesPerScanline) { @@ -512,7 +514,6 @@ namespace SixLabors.ImageSharp.Formats.Png } this.currentRowBytesRead = 0; - Span scanlineSpan = this.scanline.GetSpan(); switch ((FilterType)scanlineSpan[0]) { @@ -576,7 +577,7 @@ namespace SixLabors.ImageSharp.Formats.Png while (this.currentRow < this.header.Height) { - int bytesRead = compressedStream.Read(this.scanline.Array, this.currentRowBytesRead, bytesPerInterlaceScanline - this.currentRowBytesRead); + int bytesRead = compressedStream.Read(this.scanline.GetSpan(), this.currentRowBytesRead, bytesPerInterlaceScanline - this.currentRowBytesRead); this.currentRowBytesRead += bytesRead; if (this.currentRowBytesRead < bytesPerInterlaceScanline) { @@ -653,7 +654,7 @@ namespace SixLabors.ImageSharp.Formats.Png ReadOnlySpan trimmed = defilteredScanline.Slice(1, defilteredScanline.Length - 1); // Convert 1, 2, and 4 bit pixel data into the 8 bit equivalent. - ReadOnlySpan scanlineSpan = this.TryScaleUpTo8BitArray(trimmed, this.bytesPerScanline - 1, this.header.BitDepth, out IManagedByteBuffer buffer) + ReadOnlySpan scanlineSpan = this.TryScaleUpTo8BitArray(trimmed, this.bytesPerScanline - 1, this.header.BitDepth, out IMemoryOwner buffer) ? buffer.GetSpan() : trimmed; @@ -735,7 +736,7 @@ namespace SixLabors.ImageSharp.Formats.Png ReadOnlySpan trimmed = defilteredScanline.Slice(1, defilteredScanline.Length - 1); // Convert 1, 2, and 4 bit pixel data into the 8 bit equivalent. - ReadOnlySpan scanlineSpan = this.TryScaleUpTo8BitArray(trimmed, this.bytesPerScanline, this.header.BitDepth, out IManagedByteBuffer buffer) + ReadOnlySpan scanlineSpan = this.TryScaleUpTo8BitArray(trimmed, this.bytesPerScanline, this.header.BitDepth, out IMemoryOwner buffer) ? buffer.GetSpan() : trimmed; @@ -1189,12 +1190,12 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The length of the chunk data to read. [MethodImpl(InliningOptions.ShortMethod)] - private IManagedByteBuffer ReadChunkData(int length) + private IMemoryOwner ReadChunkData(int length) { // We rent the buffer here to return it afterwards in Decode() - IManagedByteBuffer buffer = this.Configuration.MemoryAllocator.AllocateManagedByteBuffer(length, AllocationOptions.Clean); + IMemoryOwner buffer = this.Configuration.MemoryAllocator.Allocate(length, AllocationOptions.Clean); - this.currentStream.Read(buffer.Array, 0, length); + this.currentStream.Read(buffer.GetSpan(), 0, length); return buffer; } @@ -1274,7 +1275,7 @@ namespace SixLabors.ImageSharp.Formats.Png private void SwapBuffers() { - IManagedByteBuffer temp = this.previousScanline; + IMemoryOwner temp = this.previousScanline; this.previousScanline = this.scanline; this.scanline = temp; }