From 82fd63bb95cc3e63c045a0ca20a97f4de33e07f9 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 20 Jun 2021 10:47:54 +1000 Subject: [PATCH] Update AllocatePaddedPixelRowBuffer --- .../Common/Extensions/StreamExtensions.cs | 6 - src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 170 +++++++++--------- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 69 +++---- src/ImageSharp/Formats/Tga/TgaDecoderCore.cs | 157 ++++++++-------- src/ImageSharp/Formats/Tga/TgaEncoderCore.cs | 92 +++++----- .../Memory/MemoryAllocatorExtensions.cs | 8 +- 6 files changed, 246 insertions(+), 256 deletions(-) diff --git a/src/ImageSharp/Common/Extensions/StreamExtensions.cs b/src/ImageSharp/Common/Extensions/StreamExtensions.cs index f2367d488..47a0e0bbf 100644 --- a/src/ImageSharp/Common/Extensions/StreamExtensions.cs +++ b/src/ImageSharp/Common/Extensions/StreamExtensions.cs @@ -72,12 +72,6 @@ namespace SixLabors.ImageSharp } } - public static void Read(this Stream stream, IManagedByteBuffer buffer) - => stream.Read(buffer.Array, 0, buffer.Length()); - - public static void Write(this Stream stream, IManagedByteBuffer buffer) - => stream.Write(buffer.Array, 0, buffer.Length()); - #if !SUPPORTS_SPAN_STREAM // This is a port of the CoreFX implementation and is MIT Licensed: // https://github.com/dotnet/corefx/blob/17300169760c61a90cab8d913636c1058a30a8c1/src/Common/src/CoreLib/System/IO/Stream.cs#L742 diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index f6fefda48..03124781a 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -928,20 +928,19 @@ namespace SixLabors.ImageSharp.Formats.Bmp where TPixel : unmanaged, IPixel { int padding = CalculatePadding(width, 3); + using IMemoryOwner row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 3, padding); + Span rowSpan = row.GetSpan(); - using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 3, padding)) + for (int y = 0; y < height; y++) { - for (int y = 0; y < height; y++) - { - this.stream.Read(row); - int newY = Invert(y, height, inverted); - Span pixelSpan = pixels.GetRowSpan(newY); - PixelOperations.Instance.FromBgr24Bytes( - this.Configuration, - row.GetSpan(), - pixelSpan, - width); - } + this.stream.Read(rowSpan); + int newY = Invert(y, height, inverted); + Span pixelSpan = pixels.GetRowSpan(newY); + PixelOperations.Instance.FromBgr24Bytes( + this.Configuration, + rowSpan, + pixelSpan, + width); } } @@ -957,20 +956,19 @@ namespace SixLabors.ImageSharp.Formats.Bmp where TPixel : unmanaged, IPixel { int padding = CalculatePadding(width, 4); + using IMemoryOwner row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, padding); + Span rowSpan = row.GetSpan(); - using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, padding)) + for (int y = 0; y < height; y++) { - for (int y = 0; y < height; y++) - { - this.stream.Read(row); - int newY = Invert(y, height, inverted); - Span pixelSpan = pixels.GetRowSpan(newY); - PixelOperations.Instance.FromBgra32Bytes( - this.Configuration, - row.GetSpan(), - pixelSpan, - width); - } + this.stream.Read(rowSpan); + int newY = Invert(y, height, inverted); + Span pixelSpan = pixels.GetRowSpan(newY); + PixelOperations.Instance.FromBgra32Bytes( + this.Configuration, + rowSpan, + pixelSpan, + width); } } @@ -987,87 +985,85 @@ namespace SixLabors.ImageSharp.Formats.Bmp where TPixel : unmanaged, IPixel { int padding = CalculatePadding(width, 4); - - using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, padding)) - using (IMemoryOwner bgraRow = this.memoryAllocator.Allocate(width)) + using IMemoryOwner row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, padding); + using IMemoryOwner bgraRow = this.memoryAllocator.Allocate(width); + Span rowSpan = row.GetSpan(); + Span bgraRowSpan = bgraRow.GetSpan(); + long currentPosition = this.stream.Position; + bool hasAlpha = false; + + // Loop though the rows checking each pixel. We start by assuming it's + // an BGR0 image. If we hit a non-zero alpha value, then we know it's + // actually a BGRA image, and change tactics accordingly. + for (int y = 0; y < height; y++) { - Span bgraRowSpan = bgraRow.GetSpan(); - long currentPosition = this.stream.Position; - bool hasAlpha = false; - - // Loop though the rows checking each pixel. We start by assuming it's - // an BGR0 image. If we hit a non-zero alpha value, then we know it's - // actually a BGRA image, and change tactics accordingly. - for (int y = 0; y < height; y++) - { - this.stream.Read(row); - - PixelOperations.Instance.FromBgra32Bytes( - this.Configuration, - row.GetSpan(), - bgraRowSpan, - width); + this.stream.Read(rowSpan); - // Check each pixel in the row to see if it has an alpha value. - for (int x = 0; x < width; x++) - { - Bgra32 bgra = bgraRowSpan[x]; - if (bgra.A > 0) - { - hasAlpha = true; - break; - } - } + PixelOperations.Instance.FromBgra32Bytes( + this.Configuration, + rowSpan, + bgraRowSpan, + width); - if (hasAlpha) + // Check each pixel in the row to see if it has an alpha value. + for (int x = 0; x < width; x++) + { + Bgra32 bgra = bgraRowSpan[x]; + if (bgra.A > 0) { + hasAlpha = true; break; } } - // Reset our stream for a second pass. - this.stream.Position = currentPosition; - - // Process the pixels in bulk taking the raw alpha component value. if (hasAlpha) { - for (int y = 0; y < height; y++) - { - this.stream.Read(row); - - int newY = Invert(y, height, inverted); - Span pixelSpan = pixels.GetRowSpan(newY); - - PixelOperations.Instance.FromBgra32Bytes( - this.Configuration, - row.GetSpan(), - pixelSpan, - width); - } - - return; + break; } + } - // Slow path. We need to set each alpha component value to fully opaque. + // Reset our stream for a second pass. + this.stream.Position = currentPosition; + + // Process the pixels in bulk taking the raw alpha component value. + if (hasAlpha) + { for (int y = 0; y < height; y++) { - this.stream.Read(row); - PixelOperations.Instance.FromBgra32Bytes( - this.Configuration, - row.GetSpan(), - bgraRowSpan, - width); + this.stream.Read(rowSpan); int newY = Invert(y, height, inverted); Span pixelSpan = pixels.GetRowSpan(newY); - for (int x = 0; x < width; x++) - { - Bgra32 bgra = bgraRowSpan[x]; - bgra.A = byte.MaxValue; - ref TPixel pixel = ref pixelSpan[x]; - pixel.FromBgra32(bgra); - } + PixelOperations.Instance.FromBgra32Bytes( + this.Configuration, + rowSpan, + pixelSpan, + width); + } + + return; + } + + // Slow path. We need to set each alpha component value to fully opaque. + for (int y = 0; y < height; y++) + { + this.stream.Read(rowSpan); + PixelOperations.Instance.FromBgra32Bytes( + this.Configuration, + rowSpan, + bgraRowSpan, + width); + + int newY = Invert(y, height, inverted); + Span pixelSpan = pixels.GetRowSpan(newY); + + for (int x = 0; x < width; x++) + { + Bgra32 bgra = bgraRowSpan[x]; + bgra.A = byte.MaxValue; + ref TPixel pixel = ref pixelSpan[x]; + pixel.FromBgra32(bgra); } } } diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index b407ad221..7a18d847c 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -257,7 +257,8 @@ namespace SixLabors.ImageSharp.Formats.Bmp } } - private IManagedByteBuffer AllocateRow(int width, int bytesPerPixel) => this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, this.padding); + private IMemoryOwner AllocateRow(int width, int bytesPerPixel) + => this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, this.padding); /// /// Writes the 32bit color palette to the stream. @@ -268,18 +269,18 @@ namespace SixLabors.ImageSharp.Formats.Bmp private void Write32Bit(Stream stream, Buffer2D pixels) where TPixel : unmanaged, IPixel { - using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 4)) + using IMemoryOwner row = this.AllocateRow(pixels.Width, 4); + Span rowSpan = row.GetSpan(); + + for (int y = pixels.Height - 1; y >= 0; y--) { - for (int y = pixels.Height - 1; y >= 0; y--) - { - Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.ToBgra32Bytes( - this.configuration, - pixelSpan, - row.GetSpan(), - pixelSpan.Length); - stream.Write(row.Array, 0, row.Length()); - } + Span pixelSpan = pixels.GetRowSpan(y); + PixelOperations.Instance.ToBgra32Bytes( + this.configuration, + pixelSpan, + rowSpan, + pixelSpan.Length); + stream.Write(rowSpan); } } @@ -294,18 +295,18 @@ namespace SixLabors.ImageSharp.Formats.Bmp { int width = pixels.Width; int rowBytesWithoutPadding = width * 3; - using (IManagedByteBuffer row = this.AllocateRow(width, 3)) + using IMemoryOwner row = this.AllocateRow(width, 3); + Span rowSpan = row.GetSpan(); + + for (int y = pixels.Height - 1; y >= 0; y--) { - for (int y = pixels.Height - 1; y >= 0; y--) - { - Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.ToBgr24Bytes( - this.configuration, - pixelSpan, - row.Slice(0, rowBytesWithoutPadding), - width); - stream.Write(row.Array, 0, row.Length()); - } + Span pixelSpan = pixels.GetRowSpan(y); + PixelOperations.Instance.ToBgr24Bytes( + this.configuration, + pixelSpan, + row.Slice(0, rowBytesWithoutPadding), + width); + stream.Write(rowSpan); } } @@ -320,20 +321,20 @@ namespace SixLabors.ImageSharp.Formats.Bmp { int width = pixels.Width; int rowBytesWithoutPadding = width * 2; - using (IManagedByteBuffer row = this.AllocateRow(width, 2)) + using IMemoryOwner row = this.AllocateRow(width, 2); + Span rowSpan = row.GetSpan(); + + for (int y = pixels.Height - 1; y >= 0; y--) { - for (int y = pixels.Height - 1; y >= 0; y--) - { - Span pixelSpan = pixels.GetRowSpan(y); + Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.ToBgra5551Bytes( - this.configuration, - pixelSpan, - row.Slice(0, rowBytesWithoutPadding), - pixelSpan.Length); + PixelOperations.Instance.ToBgra5551Bytes( + this.configuration, + pixelSpan, + row.Slice(0, rowBytesWithoutPadding), + pixelSpan.Length); - stream.Write(row.Array, 0, row.Length()); - } + stream.Write(rowSpan); } } diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs index eef6e7362..f717c2230 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs @@ -373,22 +373,21 @@ namespace SixLabors.ImageSharp.Formats.Tga return; } - using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 1, 0)) + using IMemoryOwner row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 1, 0); + Span rowSpan = row.GetSpan(); + bool invertY = InvertY(origin); + if (invertY) { - bool invertY = InvertY(origin); - if (invertY) + for (int y = height - 1; y >= 0; y--) { - for (int y = height - 1; y >= 0; y--) - { - this.ReadL8Row(width, pixels, row, y); - } + this.ReadL8Row(width, pixels, rowSpan, y); } - else + } + else + { + for (int y = 0; y < height; y++) { - for (int y = 0; y < height; y++) - { - this.ReadL8Row(width, pixels, row, y); - } + this.ReadL8Row(width, pixels, rowSpan, y); } } } @@ -406,58 +405,57 @@ namespace SixLabors.ImageSharp.Formats.Tga { TPixel color = default; bool invertX = InvertX(origin); - using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 2, 0)) - { - for (int y = 0; y < height; y++) - { - int newY = InvertY(y, height, origin); - Span pixelSpan = pixels.GetRowSpan(newY); + using IMemoryOwner row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 2, 0); + Span rowSpan = row.GetSpan(); - if (invertX) - { - for (int x = width - 1; x >= 0; x--) - { - this.currentStream.Read(this.scratchBuffer, 0, 2); - if (!this.hasAlpha) - { - this.scratchBuffer[1] |= 1 << 7; - } - - if (this.fileHeader.ImageType == TgaImageType.BlackAndWhite) - { - color.FromLa16(Unsafe.As(ref this.scratchBuffer[0])); - } - else - { - color.FromBgra5551(Unsafe.As(ref this.scratchBuffer[0])); - } + for (int y = 0; y < height; y++) + { + int newY = InvertY(y, height, origin); + Span pixelSpan = pixels.GetRowSpan(newY); - pixelSpan[x] = color; - } - } - else + if (invertX) + { + for (int x = width - 1; x >= 0; x--) { - this.currentStream.Read(row); - Span rowSpan = row.GetSpan(); - + this.currentStream.Read(this.scratchBuffer, 0, 2); if (!this.hasAlpha) { - // We need to set the alpha component value to fully opaque. - for (int x = 1; x < rowSpan.Length; x += 2) - { - rowSpan[x] |= 1 << 7; - } + this.scratchBuffer[1] |= 1 << 7; } if (this.fileHeader.ImageType == TgaImageType.BlackAndWhite) { - PixelOperations.Instance.FromLa16Bytes(this.Configuration, rowSpan, pixelSpan, width); + color.FromLa16(Unsafe.As(ref this.scratchBuffer[0])); } else { - PixelOperations.Instance.FromBgra5551Bytes(this.Configuration, rowSpan, pixelSpan, width); + color.FromBgra5551(Unsafe.As(ref this.scratchBuffer[0])); + } + + pixelSpan[x] = color; + } + } + else + { + this.currentStream.Read(rowSpan); + + if (!this.hasAlpha) + { + // We need to set the alpha component value to fully opaque. + for (int x = 1; x < rowSpan.Length; x += 2) + { + rowSpan[x] |= 1 << 7; } } + + if (this.fileHeader.ImageType == TgaImageType.BlackAndWhite) + { + PixelOperations.Instance.FromLa16Bytes(this.Configuration, rowSpan, pixelSpan, width); + } + else + { + PixelOperations.Instance.FromBgra5551Bytes(this.Configuration, rowSpan, pixelSpan, width); + } } } } @@ -490,23 +488,22 @@ namespace SixLabors.ImageSharp.Formats.Tga return; } - using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 3, 0)) - { - bool invertY = InvertY(origin); + using IMemoryOwner row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 3, 0); + Span rowSpan = row.GetSpan(); + bool invertY = InvertY(origin); - if (invertY) + if (invertY) + { + for (int y = height - 1; y >= 0; y--) { - for (int y = height - 1; y >= 0; y--) - { - this.ReadBgr24Row(width, pixels, row, y); - } + this.ReadBgr24Row(width, pixels, rowSpan, y); } - else + } + else + { + for (int y = 0; y < height; y++) { - for (int y = 0; y < height; y++) - { - this.ReadBgr24Row(width, pixels, row, y); - } + this.ReadBgr24Row(width, pixels, rowSpan, y); } } } @@ -526,21 +523,21 @@ namespace SixLabors.ImageSharp.Formats.Tga bool invertX = InvertX(origin); if (this.tgaMetadata.AlphaChannelBits == 8 && !invertX) { - using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, 0)) + using IMemoryOwner row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, 0); + Span rowSpan = row.GetSpan(); + + if (InvertY(origin)) { - if (InvertY(origin)) + for (int y = height - 1; y >= 0; y--) { - for (int y = height - 1; y >= 0; y--) - { - this.ReadBgra32Row(width, pixels, row, y); - } + this.ReadBgra32Row(width, pixels, rowSpan, y); } - else + } + else + { + for (int y = 0; y < height; y++) { - for (int y = 0; y < height; y++) - { - this.ReadBgra32Row(width, pixels, row, y); - } + this.ReadBgra32Row(width, pixels, rowSpan, y); } } @@ -652,12 +649,12 @@ namespace SixLabors.ImageSharp.Formats.Tga } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadL8Row(int width, Buffer2D pixels, IManagedByteBuffer row, int y) + private void ReadL8Row(int width, Buffer2D pixels, Span row, int y) where TPixel : unmanaged, IPixel { this.currentStream.Read(row); Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.FromL8Bytes(this.Configuration, row.GetSpan(), pixelSpan, width); + PixelOperations.Instance.FromL8Bytes(this.Configuration, row, pixelSpan, width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -679,12 +676,12 @@ namespace SixLabors.ImageSharp.Formats.Tga } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadBgr24Row(int width, Buffer2D pixels, IManagedByteBuffer row, int y) + private void ReadBgr24Row(int width, Buffer2D pixels, Span row, int y) where TPixel : unmanaged, IPixel { this.currentStream.Read(row); Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.FromBgr24Bytes(this.Configuration, row.GetSpan(), pixelSpan, width); + PixelOperations.Instance.FromBgr24Bytes(this.Configuration, row, pixelSpan, width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -698,12 +695,12 @@ namespace SixLabors.ImageSharp.Formats.Tga } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadBgra32Row(int width, Buffer2D pixels, IManagedByteBuffer row, int y) + private void ReadBgra32Row(int width, Buffer2D pixels, Span row, int y) where TPixel : unmanaged, IPixel { this.currentStream.Read(row); Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.FromBgra32Bytes(this.Configuration, row.GetSpan(), pixelSpan, width); + PixelOperations.Instance.FromBgra32Bytes(this.Configuration, row, pixelSpan, width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs index 1d31ea9f4..4bf4ca60a 100644 --- a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers; using System.Buffers.Binary; using System.IO; using System.Runtime.CompilerServices; @@ -258,7 +259,8 @@ namespace SixLabors.ImageSharp.Formats.Tga return equalPixelCount; } - private IManagedByteBuffer AllocateRow(int width, int bytesPerPixel) => this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, 0); + private IMemoryOwner AllocateRow(int width, int bytesPerPixel) + => this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, 0); /// /// Writes the 8bit pixels uncompressed to the stream. @@ -269,18 +271,18 @@ namespace SixLabors.ImageSharp.Formats.Tga private void Write8Bit(Stream stream, Buffer2D pixels) where TPixel : unmanaged, IPixel { - using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 1)) + using IMemoryOwner row = this.AllocateRow(pixels.Width, 1); + Span rowSpan = row.GetSpan(); + + for (int y = pixels.Height - 1; y >= 0; y--) { - for (int y = pixels.Height - 1; y >= 0; y--) - { - Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.ToL8Bytes( - this.configuration, - pixelSpan, - row.GetSpan(), - pixelSpan.Length); - stream.Write(row.Array, 0, row.Length()); - } + Span pixelSpan = pixels.GetRowSpan(y); + PixelOperations.Instance.ToL8Bytes( + this.configuration, + pixelSpan, + rowSpan, + pixelSpan.Length); + stream.Write(rowSpan); } } @@ -293,18 +295,18 @@ namespace SixLabors.ImageSharp.Formats.Tga private void Write16Bit(Stream stream, Buffer2D pixels) where TPixel : unmanaged, IPixel { - using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 2)) + using IMemoryOwner row = this.AllocateRow(pixels.Width, 2); + Span rowSpan = row.GetSpan(); + + for (int y = pixels.Height - 1; y >= 0; y--) { - for (int y = pixels.Height - 1; y >= 0; y--) - { - Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.ToBgra5551Bytes( - this.configuration, - pixelSpan, - row.GetSpan(), - pixelSpan.Length); - stream.Write(row.Array, 0, row.Length()); - } + Span pixelSpan = pixels.GetRowSpan(y); + PixelOperations.Instance.ToBgra5551Bytes( + this.configuration, + pixelSpan, + rowSpan, + pixelSpan.Length); + stream.Write(rowSpan); } } @@ -317,18 +319,18 @@ namespace SixLabors.ImageSharp.Formats.Tga private void Write24Bit(Stream stream, Buffer2D pixels) where TPixel : unmanaged, IPixel { - using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 3)) + using IMemoryOwner row = this.AllocateRow(pixels.Width, 3); + Span rowSpan = row.GetSpan(); + + for (int y = pixels.Height - 1; y >= 0; y--) { - for (int y = pixels.Height - 1; y >= 0; y--) - { - Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.ToBgr24Bytes( - this.configuration, - pixelSpan, - row.GetSpan(), - pixelSpan.Length); - stream.Write(row.Array, 0, row.Length()); - } + Span pixelSpan = pixels.GetRowSpan(y); + PixelOperations.Instance.ToBgr24Bytes( + this.configuration, + pixelSpan, + rowSpan, + pixelSpan.Length); + stream.Write(rowSpan); } } @@ -341,18 +343,18 @@ namespace SixLabors.ImageSharp.Formats.Tga private void Write32Bit(Stream stream, Buffer2D pixels) where TPixel : unmanaged, IPixel { - using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 4)) + using IMemoryOwner row = this.AllocateRow(pixels.Width, 4); + Span rowSpan = row.GetSpan(); + + for (int y = pixels.Height - 1; y >= 0; y--) { - for (int y = pixels.Height - 1; y >= 0; y--) - { - Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.ToBgra32Bytes( - this.configuration, - pixelSpan, - row.GetSpan(), - pixelSpan.Length); - stream.Write(row.Array, 0, row.Length()); - } + Span pixelSpan = pixels.GetRowSpan(y); + PixelOperations.Instance.ToBgra32Bytes( + this.configuration, + pixelSpan, + rowSpan, + pixelSpan.Length); + stream.Write(rowSpan); } } diff --git a/src/ImageSharp/Memory/MemoryAllocatorExtensions.cs b/src/ImageSharp/Memory/MemoryAllocatorExtensions.cs index 922088b26..2f70ac05e 100644 --- a/src/ImageSharp/Memory/MemoryAllocatorExtensions.cs +++ b/src/ImageSharp/Memory/MemoryAllocatorExtensions.cs @@ -67,21 +67,21 @@ namespace SixLabors.ImageSharp.Memory } /// - /// Allocates padded buffers for BMP encoder/decoder. (Replacing old PixelRow/PixelArea). + /// Allocates padded buffers. Generally used by encoder/decoders. /// /// The . /// Pixel count in the row /// The pixel size in bytes, eg. 3 for RGB. /// The padding. - /// A . - internal static IManagedByteBuffer AllocatePaddedPixelRowBuffer( + /// A . + internal static IMemoryOwner AllocatePaddedPixelRowBuffer( this MemoryAllocator memoryAllocator, int width, int pixelSizeInBytes, int paddingInBytes) { int length = (width * pixelSizeInBytes) + paddingInBytes; - return memoryAllocator.AllocateManagedByteBuffer(length); + return memoryAllocator.Allocate(length); } ///