diff --git a/src/ImageSharp/Common/Extensions/StreamExtensions.cs b/src/ImageSharp/Common/Extensions/StreamExtensions.cs index 47a0e0bbf..1193eccee 100644 --- a/src/ImageSharp/Common/Extensions/StreamExtensions.cs +++ b/src/ImageSharp/Common/Extensions/StreamExtensions.cs @@ -4,7 +4,6 @@ using System; using System.Buffers; using System.IO; -using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp { diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 7a285eb70..9814d3444 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -80,32 +80,32 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The raw data of previous scanline. /// - private IManagedByteBuffer previousScanline; + private IMemoryOwner previousScanline; /// /// The raw data of current scanline. /// - private IManagedByteBuffer currentScanline; + private IMemoryOwner currentScanline; /// /// The common buffer for the filters. /// - private IManagedByteBuffer filterBuffer; + private IMemoryOwner filterBuffer; /// /// The ext buffer for the sub filter, . /// - private IManagedByteBuffer subFilter; + private IMemoryOwner subFilter; /// /// The ext buffer for the average filter, . /// - private IManagedByteBuffer averageFilter; + private IMemoryOwner averageFilter; /// /// The ext buffer for the Paeth filter, . /// - private IManagedByteBuffer paethFilter; + private IMemoryOwner paethFilter; /// /// Initializes a new instance of the class. @@ -278,21 +278,17 @@ namespace SixLabors.ImageSharp.Formats.Png else { // 1, 2, and 4 bit grayscale - using (IManagedByteBuffer temp = this.memoryAllocator.AllocateManagedByteBuffer( - rowSpan.Length, - AllocationOptions.Clean)) - { - int scaleFactor = 255 / (ColorNumerics.GetColorCountForBitDepth(this.bitDepth) - 1); - Span tempSpan = temp.GetSpan(); - - // We need to first create an array of luminance bytes then scale them down to the correct bit depth. - PixelOperations.Instance.ToL8Bytes( - this.configuration, - rowSpan, - tempSpan, - rowSpan.Length); - PngEncoderHelpers.ScaleDownFrom8BitArray(tempSpan, rawScanlineSpan, this.bitDepth, scaleFactor); - } + using IMemoryOwner temp = this.memoryAllocator.Allocate(rowSpan.Length, AllocationOptions.Clean); + int scaleFactor = 255 / (ColorNumerics.GetColorCountForBitDepth(this.bitDepth) - 1); + Span tempSpan = temp.GetSpan(); + + // We need to first create an array of luminance bytes then scale them down to the correct bit depth. + PixelOperations.Instance.ToL8Bytes( + this.configuration, + rowSpan, + tempSpan, + rowSpan.Length); + PngEncoderHelpers.ScaleDownFrom8BitArray(tempSpan, rawScanlineSpan, this.bitDepth, scaleFactor); } } } @@ -453,7 +449,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Apply filter for the raw scanline. /// - private IManagedByteBuffer FilterPixelBytes() + private IMemoryOwner FilterPixelBytes() { switch (this.options.FilterMethod) { @@ -490,8 +486,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// The row span. /// The quantized pixels. Can be null. /// The row. - /// The - private IManagedByteBuffer EncodePixelRow(ReadOnlySpan rowSpan, IndexedImageFrame quantized, int row) + /// The + private IMemoryOwner EncodePixelRow(ReadOnlySpan rowSpan, IndexedImageFrame quantized, int row) where TPixel : unmanaged, IPixel { this.CollectPixelBytes(rowSpan, quantized, row); @@ -502,7 +498,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// Encodes the indexed pixel data (with palette) for Adam7 interlaced mode. /// /// The row span. - private IManagedByteBuffer EncodeAdam7IndexedPixelRow(ReadOnlySpan rowSpan) + private IMemoryOwner EncodeAdam7IndexedPixelRow(ReadOnlySpan rowSpan) { // CollectPixelBytes if (this.bitDepth < 8) @@ -522,7 +518,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// to be most compressible, using lowest total variation as proxy for compressibility. /// /// The - private IManagedByteBuffer GetOptimalFilteredScanline() + private IMemoryOwner GetOptimalFilteredScanline() { // Palette images don't compress well with adaptive filtering. if (this.options.ColorType == PngColorType.Palette || this.bitDepth < 8) @@ -543,7 +539,7 @@ namespace SixLabors.ImageSharp.Formats.Png // That way the above comment would actually be true. It used to be anyway... // If we could use SIMD for none branching filters we could really speed it up. int lowestSum = currentSum; - IManagedByteBuffer actualResult = this.filterBuffer; + IMemoryOwner actualResult = this.filterBuffer; PaethFilter.Encode(scanSpan, prevSpan, this.paethFilter.GetSpan(), this.bytesPerPixel, out currentSum); @@ -612,8 +608,8 @@ namespace SixLabors.ImageSharp.Formats.Png int colorTableLength = paletteLength * Unsafe.SizeOf(); bool hasAlpha = false; - using IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength); - using IManagedByteBuffer alphaTable = this.memoryAllocator.AllocateManagedByteBuffer(paletteLength); + using IMemoryOwner colorTable = this.memoryAllocator.Allocate(colorTableLength); + using IMemoryOwner alphaTable = this.memoryAllocator.Allocate(paletteLength); ref Rgb24 colorTableRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(colorTable.GetSpan())); ref byte alphaTableRef = ref MemoryMarshal.GetReference(alphaTable.GetSpan()); @@ -640,12 +636,12 @@ namespace SixLabors.ImageSharp.Formats.Png Unsafe.Add(ref alphaTableRef, i) = alpha; } - this.WriteChunk(stream, PngChunkType.Palette, colorTable.Array, 0, colorTableLength); + this.WriteChunk(stream, PngChunkType.Palette, colorTable.GetSpan(), 0, colorTableLength); // Write the transparency data if (hasAlpha) { - this.WriteChunk(stream, PngChunkType.Transparency, alphaTable.Array, 0, paletteLength); + this.WriteChunk(stream, PngChunkType.Transparency, alphaTable.GetSpan(), 0, paletteLength); } } @@ -938,9 +934,9 @@ namespace SixLabors.ImageSharp.Formats.Png this.previousScanline?.Dispose(); this.currentScanline?.Dispose(); this.filterBuffer?.Dispose(); - this.previousScanline = this.memoryAllocator.AllocateManagedByteBuffer(bytesPerScanline, AllocationOptions.Clean); - this.currentScanline = this.memoryAllocator.AllocateManagedByteBuffer(bytesPerScanline, AllocationOptions.Clean); - this.filterBuffer = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean); + this.previousScanline = this.memoryAllocator.Allocate(bytesPerScanline, AllocationOptions.Clean); + this.currentScanline = this.memoryAllocator.Allocate(bytesPerScanline, AllocationOptions.Clean); + this.filterBuffer = this.memoryAllocator.Allocate(resultLength, AllocationOptions.Clean); } /// @@ -952,9 +948,9 @@ namespace SixLabors.ImageSharp.Formats.Png { int resultLength = this.filterBuffer.Length(); - this.subFilter = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean); - this.averageFilter = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean); - this.paethFilter = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean); + this.subFilter = this.memoryAllocator.Allocate(resultLength, AllocationOptions.Clean); + this.averageFilter = this.memoryAllocator.Allocate(resultLength, AllocationOptions.Clean); + this.paethFilter = this.memoryAllocator.Allocate(resultLength, AllocationOptions.Clean); } } @@ -974,10 +970,10 @@ namespace SixLabors.ImageSharp.Formats.Png for (int y = 0; y < this.height; y++) { - IManagedByteBuffer r = this.EncodePixelRow(pixels.GetPixelRowSpan(y), quantized, y); - deflateStream.Write(r.Array, 0, resultLength); + IMemoryOwner r = this.EncodePixelRow(pixels.GetPixelRowSpan(y), quantized, y); + deflateStream.Write(r.GetSpan(), 0, resultLength); - IManagedByteBuffer temp = this.currentScanline; + IMemoryOwner temp = this.currentScanline; this.currentScanline = this.previousScanline; this.previousScanline = temp; } @@ -1027,10 +1023,10 @@ namespace SixLabors.ImageSharp.Formats.Png // encode data // note: quantized parameter not used // note: row parameter not used - IManagedByteBuffer r = this.EncodePixelRow((ReadOnlySpan)destSpan, null, -1); - deflateStream.Write(r.Array, 0, resultLength); + IMemoryOwner r = this.EncodePixelRow((ReadOnlySpan)destSpan, null, -1); + deflateStream.Write(r.GetSpan(), 0, resultLength); - IManagedByteBuffer temp = this.currentScanline; + IMemoryOwner temp = this.currentScanline; this.currentScanline = this.previousScanline; this.previousScanline = temp; } @@ -1080,10 +1076,10 @@ namespace SixLabors.ImageSharp.Formats.Png } // encode data - IManagedByteBuffer r = this.EncodeAdam7IndexedPixelRow(destSpan); - deflateStream.Write(r.Array, 0, resultLength); + IMemoryOwner r = this.EncodeAdam7IndexedPixelRow(destSpan); + deflateStream.Write(r.GetSpan(), 0, resultLength); - IManagedByteBuffer temp = this.currentScanline; + IMemoryOwner temp = this.currentScanline; this.currentScanline = this.previousScanline; this.previousScanline = temp; } @@ -1103,7 +1099,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// The to write to. /// The type of chunk to write. /// The containing data. - private void WriteChunk(Stream stream, PngChunkType type, byte[] data) => this.WriteChunk(stream, type, data, 0, data?.Length ?? 0); + private void WriteChunk(Stream stream, PngChunkType type, Span data) + => this.WriteChunk(stream, type, data, 0, data.Length); /// /// Writes a chunk of a specified length to the stream at the given offset. @@ -1113,7 +1110,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The containing data. /// The position to offset the data at. /// The of the data to write. - private void WriteChunk(Stream stream, PngChunkType type, byte[] data, int offset, int length) + private void WriteChunk(Stream stream, PngChunkType type, Span data, int offset, int length) { BinaryPrimitives.WriteInt32BigEndian(this.buffer, length); BinaryPrimitives.WriteUInt32BigEndian(this.buffer.AsSpan(4, 4), (uint)type); @@ -1126,7 +1123,7 @@ namespace SixLabors.ImageSharp.Formats.Png { stream.Write(data, offset, length); - crc = Crc32.Calculate(crc, data.AsSpan(offset, length)); + crc = Crc32.Calculate(crc, data.Slice(offset, length)); } BinaryPrimitives.WriteUInt32BigEndian(this.buffer, crc);