Browse Source

Merge pull request #1676 from SixLabors/js/bmp-managed-byte-buffer

Update AllocatePaddedPixelRowBuffer to use IMemoryOwner<byte>
pull/1678/head
James Jackson-South 5 years ago
committed by GitHub
parent
commit
5b5bb110ca
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      src/ImageSharp/Common/Extensions/StreamExtensions.cs
  2. 170
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  3. 69
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  4. 157
      src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
  5. 92
      src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
  6. 8
      src/ImageSharp/Memory/MemoryAllocatorExtensions.cs

6
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 #if !SUPPORTS_SPAN_STREAM
// This is a port of the CoreFX implementation and is MIT Licensed: // 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 // https://github.com/dotnet/corefx/blob/17300169760c61a90cab8d913636c1058a30a8c1/src/Common/src/CoreLib/System/IO/Stream.cs#L742

170
src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

@ -928,20 +928,19 @@ namespace SixLabors.ImageSharp.Formats.Bmp
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
int padding = CalculatePadding(width, 3); int padding = CalculatePadding(width, 3);
using IMemoryOwner<byte> row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 3, padding);
Span<byte> 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(rowSpan);
{ int newY = Invert(y, height, inverted);
this.stream.Read(row); Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
int newY = Invert(y, height, inverted); PixelOperations<TPixel>.Instance.FromBgr24Bytes(
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY); this.Configuration,
PixelOperations<TPixel>.Instance.FromBgr24Bytes( rowSpan,
this.Configuration, pixelSpan,
row.GetSpan(), width);
pixelSpan,
width);
}
} }
} }
@ -957,20 +956,19 @@ namespace SixLabors.ImageSharp.Formats.Bmp
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
int padding = CalculatePadding(width, 4); int padding = CalculatePadding(width, 4);
using IMemoryOwner<byte> row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, padding);
Span<byte> 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(rowSpan);
{ int newY = Invert(y, height, inverted);
this.stream.Read(row); Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
int newY = Invert(y, height, inverted); PixelOperations<TPixel>.Instance.FromBgra32Bytes(
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY); this.Configuration,
PixelOperations<TPixel>.Instance.FromBgra32Bytes( rowSpan,
this.Configuration, pixelSpan,
row.GetSpan(), width);
pixelSpan,
width);
}
} }
} }
@ -987,87 +985,85 @@ namespace SixLabors.ImageSharp.Formats.Bmp
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
int padding = CalculatePadding(width, 4); int padding = CalculatePadding(width, 4);
using IMemoryOwner<byte> row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, padding);
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, padding)) using IMemoryOwner<Bgra32> bgraRow = this.memoryAllocator.Allocate<Bgra32>(width);
using (IMemoryOwner<Bgra32> bgraRow = this.memoryAllocator.Allocate<Bgra32>(width)) Span<byte> rowSpan = row.GetSpan();
Span<Bgra32> 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<Bgra32> bgraRowSpan = bgraRow.GetSpan(); this.stream.Read(rowSpan);
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<Bgra32>.Instance.FromBgra32Bytes(
this.Configuration,
row.GetSpan(),
bgraRowSpan,
width);
// Check each pixel in the row to see if it has an alpha value. PixelOperations<Bgra32>.Instance.FromBgra32Bytes(
for (int x = 0; x < width; x++) this.Configuration,
{ rowSpan,
Bgra32 bgra = bgraRowSpan[x]; bgraRowSpan,
if (bgra.A > 0) width);
{
hasAlpha = true;
break;
}
}
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; 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) if (hasAlpha)
{ {
for (int y = 0; y < height; y++) break;
{
this.stream.Read(row);
int newY = Invert(y, height, inverted);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
PixelOperations<TPixel>.Instance.FromBgra32Bytes(
this.Configuration,
row.GetSpan(),
pixelSpan,
width);
}
return;
} }
}
// 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++) for (int y = 0; y < height; y++)
{ {
this.stream.Read(row); this.stream.Read(rowSpan);
PixelOperations<Bgra32>.Instance.FromBgra32Bytes(
this.Configuration,
row.GetSpan(),
bgraRowSpan,
width);
int newY = Invert(y, height, inverted); int newY = Invert(y, height, inverted);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY); Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
for (int x = 0; x < width; x++) PixelOperations<TPixel>.Instance.FromBgra32Bytes(
{ this.Configuration,
Bgra32 bgra = bgraRowSpan[x]; rowSpan,
bgra.A = byte.MaxValue; pixelSpan,
ref TPixel pixel = ref pixelSpan[x]; width);
pixel.FromBgra32(bgra); }
}
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<Bgra32>.Instance.FromBgra32Bytes(
this.Configuration,
rowSpan,
bgraRowSpan,
width);
int newY = Invert(y, height, inverted);
Span<TPixel> 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);
} }
} }
} }

69
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<byte> AllocateRow(int width, int bytesPerPixel)
=> this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, this.padding);
/// <summary> /// <summary>
/// Writes the 32bit color palette to the stream. /// Writes the 32bit color palette to the stream.
@ -268,18 +269,18 @@ namespace SixLabors.ImageSharp.Formats.Bmp
private void Write32Bit<TPixel>(Stream stream, Buffer2D<TPixel> pixels) private void Write32Bit<TPixel>(Stream stream, Buffer2D<TPixel> pixels)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 4)) using IMemoryOwner<byte> row = this.AllocateRow(pixels.Width, 4);
Span<byte> rowSpan = row.GetSpan();
for (int y = pixels.Height - 1; y >= 0; y--)
{ {
for (int y = pixels.Height - 1; y >= 0; y--) Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
{ PixelOperations<TPixel>.Instance.ToBgra32Bytes(
Span<TPixel> pixelSpan = pixels.GetRowSpan(y); this.configuration,
PixelOperations<TPixel>.Instance.ToBgra32Bytes( pixelSpan,
this.configuration, rowSpan,
pixelSpan, pixelSpan.Length);
row.GetSpan(), stream.Write(rowSpan);
pixelSpan.Length);
stream.Write(row.Array, 0, row.Length());
}
} }
} }
@ -294,18 +295,18 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{ {
int width = pixels.Width; int width = pixels.Width;
int rowBytesWithoutPadding = width * 3; int rowBytesWithoutPadding = width * 3;
using (IManagedByteBuffer row = this.AllocateRow(width, 3)) using IMemoryOwner<byte> row = this.AllocateRow(width, 3);
Span<byte> rowSpan = row.GetSpan();
for (int y = pixels.Height - 1; y >= 0; y--)
{ {
for (int y = pixels.Height - 1; y >= 0; y--) Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
{ PixelOperations<TPixel>.Instance.ToBgr24Bytes(
Span<TPixel> pixelSpan = pixels.GetRowSpan(y); this.configuration,
PixelOperations<TPixel>.Instance.ToBgr24Bytes( pixelSpan,
this.configuration, row.Slice(0, rowBytesWithoutPadding),
pixelSpan, width);
row.Slice(0, rowBytesWithoutPadding), stream.Write(rowSpan);
width);
stream.Write(row.Array, 0, row.Length());
}
} }
} }
@ -320,20 +321,20 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{ {
int width = pixels.Width; int width = pixels.Width;
int rowBytesWithoutPadding = width * 2; int rowBytesWithoutPadding = width * 2;
using (IManagedByteBuffer row = this.AllocateRow(width, 2)) using IMemoryOwner<byte> row = this.AllocateRow(width, 2);
Span<byte> rowSpan = row.GetSpan();
for (int y = pixels.Height - 1; y >= 0; y--)
{ {
for (int y = pixels.Height - 1; y >= 0; y--) Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
{
Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
PixelOperations<TPixel>.Instance.ToBgra5551Bytes( PixelOperations<TPixel>.Instance.ToBgra5551Bytes(
this.configuration, this.configuration,
pixelSpan, pixelSpan,
row.Slice(0, rowBytesWithoutPadding), row.Slice(0, rowBytesWithoutPadding),
pixelSpan.Length); pixelSpan.Length);
stream.Write(row.Array, 0, row.Length()); stream.Write(rowSpan);
}
} }
} }

157
src/ImageSharp/Formats/Tga/TgaDecoderCore.cs

@ -373,22 +373,21 @@ namespace SixLabors.ImageSharp.Formats.Tga
return; return;
} }
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 1, 0)) using IMemoryOwner<byte> row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 1, 0);
Span<byte> rowSpan = row.GetSpan();
bool invertY = InvertY(origin);
if (invertY)
{ {
bool invertY = InvertY(origin); for (int y = height - 1; y >= 0; y--)
if (invertY)
{ {
for (int y = height - 1; y >= 0; y--) this.ReadL8Row(width, pixels, rowSpan, y);
{
this.ReadL8Row(width, pixels, row, y);
}
} }
else }
else
{
for (int y = 0; y < height; y++)
{ {
for (int y = 0; y < height; y++) this.ReadL8Row(width, pixels, rowSpan, y);
{
this.ReadL8Row(width, pixels, row, y);
}
} }
} }
} }
@ -406,58 +405,57 @@ namespace SixLabors.ImageSharp.Formats.Tga
{ {
TPixel color = default; TPixel color = default;
bool invertX = InvertX(origin); bool invertX = InvertX(origin);
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 2, 0)) using IMemoryOwner<byte> row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 2, 0);
{ Span<byte> rowSpan = row.GetSpan();
for (int y = 0; y < height; y++)
{
int newY = InvertY(y, height, origin);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
if (invertX) for (int y = 0; y < height; y++)
{ {
for (int x = width - 1; x >= 0; x--) int newY = InvertY(y, height, origin);
{ Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
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<byte, La16>(ref this.scratchBuffer[0]));
}
else
{
color.FromBgra5551(Unsafe.As<byte, Bgra5551>(ref this.scratchBuffer[0]));
}
pixelSpan[x] = color; if (invertX)
} {
} for (int x = width - 1; x >= 0; x--)
else
{ {
this.currentStream.Read(row); this.currentStream.Read(this.scratchBuffer, 0, 2);
Span<byte> rowSpan = row.GetSpan();
if (!this.hasAlpha) if (!this.hasAlpha)
{ {
// We need to set the alpha component value to fully opaque. this.scratchBuffer[1] |= 1 << 7;
for (int x = 1; x < rowSpan.Length; x += 2)
{
rowSpan[x] |= 1 << 7;
}
} }
if (this.fileHeader.ImageType == TgaImageType.BlackAndWhite) if (this.fileHeader.ImageType == TgaImageType.BlackAndWhite)
{ {
PixelOperations<TPixel>.Instance.FromLa16Bytes(this.Configuration, rowSpan, pixelSpan, width); color.FromLa16(Unsafe.As<byte, La16>(ref this.scratchBuffer[0]));
} }
else else
{ {
PixelOperations<TPixel>.Instance.FromBgra5551Bytes(this.Configuration, rowSpan, pixelSpan, width); color.FromBgra5551(Unsafe.As<byte, Bgra5551>(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<TPixel>.Instance.FromLa16Bytes(this.Configuration, rowSpan, pixelSpan, width);
}
else
{
PixelOperations<TPixel>.Instance.FromBgra5551Bytes(this.Configuration, rowSpan, pixelSpan, width);
}
} }
} }
} }
@ -490,23 +488,22 @@ namespace SixLabors.ImageSharp.Formats.Tga
return; return;
} }
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 3, 0)) using IMemoryOwner<byte> row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 3, 0);
{ Span<byte> rowSpan = row.GetSpan();
bool invertY = InvertY(origin); 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, rowSpan, y);
{
this.ReadBgr24Row(width, pixels, row, y);
}
} }
else }
else
{
for (int y = 0; y < height; y++)
{ {
for (int y = 0; y < height; y++) this.ReadBgr24Row(width, pixels, rowSpan, y);
{
this.ReadBgr24Row(width, pixels, row, y);
}
} }
} }
} }
@ -526,21 +523,21 @@ namespace SixLabors.ImageSharp.Formats.Tga
bool invertX = InvertX(origin); bool invertX = InvertX(origin);
if (this.tgaMetadata.AlphaChannelBits == 8 && !invertX) if (this.tgaMetadata.AlphaChannelBits == 8 && !invertX)
{ {
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, 0)) using IMemoryOwner<byte> row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, 0);
Span<byte> 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, rowSpan, y);
{
this.ReadBgra32Row(width, pixels, row, y);
}
} }
else }
else
{
for (int y = 0; y < height; y++)
{ {
for (int y = 0; y < height; y++) this.ReadBgra32Row(width, pixels, rowSpan, y);
{
this.ReadBgra32Row(width, pixels, row, y);
}
} }
} }
@ -652,12 +649,12 @@ namespace SixLabors.ImageSharp.Formats.Tga
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadL8Row<TPixel>(int width, Buffer2D<TPixel> pixels, IManagedByteBuffer row, int y) private void ReadL8Row<TPixel>(int width, Buffer2D<TPixel> pixels, Span<byte> row, int y)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
this.currentStream.Read(row); this.currentStream.Read(row);
Span<TPixel> pixelSpan = pixels.GetRowSpan(y); Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
PixelOperations<TPixel>.Instance.FromL8Bytes(this.Configuration, row.GetSpan(), pixelSpan, width); PixelOperations<TPixel>.Instance.FromL8Bytes(this.Configuration, row, pixelSpan, width);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -679,12 +676,12 @@ namespace SixLabors.ImageSharp.Formats.Tga
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadBgr24Row<TPixel>(int width, Buffer2D<TPixel> pixels, IManagedByteBuffer row, int y) private void ReadBgr24Row<TPixel>(int width, Buffer2D<TPixel> pixels, Span<byte> row, int y)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
this.currentStream.Read(row); this.currentStream.Read(row);
Span<TPixel> pixelSpan = pixels.GetRowSpan(y); Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
PixelOperations<TPixel>.Instance.FromBgr24Bytes(this.Configuration, row.GetSpan(), pixelSpan, width); PixelOperations<TPixel>.Instance.FromBgr24Bytes(this.Configuration, row, pixelSpan, width);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -698,12 +695,12 @@ namespace SixLabors.ImageSharp.Formats.Tga
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadBgra32Row<TPixel>(int width, Buffer2D<TPixel> pixels, IManagedByteBuffer row, int y) private void ReadBgra32Row<TPixel>(int width, Buffer2D<TPixel> pixels, Span<byte> row, int y)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
this.currentStream.Read(row); this.currentStream.Read(row);
Span<TPixel> pixelSpan = pixels.GetRowSpan(y); Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
PixelOperations<TPixel>.Instance.FromBgra32Bytes(this.Configuration, row.GetSpan(), pixelSpan, width); PixelOperations<TPixel>.Instance.FromBgra32Bytes(this.Configuration, row, pixelSpan, width);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

92
src/ImageSharp/Formats/Tga/TgaEncoderCore.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
using System.Buffers;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -258,7 +259,8 @@ namespace SixLabors.ImageSharp.Formats.Tga
return equalPixelCount; return equalPixelCount;
} }
private IManagedByteBuffer AllocateRow(int width, int bytesPerPixel) => this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, 0); private IMemoryOwner<byte> AllocateRow(int width, int bytesPerPixel)
=> this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, 0);
/// <summary> /// <summary>
/// Writes the 8bit pixels uncompressed to the stream. /// Writes the 8bit pixels uncompressed to the stream.
@ -269,18 +271,18 @@ namespace SixLabors.ImageSharp.Formats.Tga
private void Write8Bit<TPixel>(Stream stream, Buffer2D<TPixel> pixels) private void Write8Bit<TPixel>(Stream stream, Buffer2D<TPixel> pixels)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 1)) using IMemoryOwner<byte> row = this.AllocateRow(pixels.Width, 1);
Span<byte> rowSpan = row.GetSpan();
for (int y = pixels.Height - 1; y >= 0; y--)
{ {
for (int y = pixels.Height - 1; y >= 0; y--) Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
{ PixelOperations<TPixel>.Instance.ToL8Bytes(
Span<TPixel> pixelSpan = pixels.GetRowSpan(y); this.configuration,
PixelOperations<TPixel>.Instance.ToL8Bytes( pixelSpan,
this.configuration, rowSpan,
pixelSpan, pixelSpan.Length);
row.GetSpan(), stream.Write(rowSpan);
pixelSpan.Length);
stream.Write(row.Array, 0, row.Length());
}
} }
} }
@ -293,18 +295,18 @@ namespace SixLabors.ImageSharp.Formats.Tga
private void Write16Bit<TPixel>(Stream stream, Buffer2D<TPixel> pixels) private void Write16Bit<TPixel>(Stream stream, Buffer2D<TPixel> pixels)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 2)) using IMemoryOwner<byte> row = this.AllocateRow(pixels.Width, 2);
Span<byte> rowSpan = row.GetSpan();
for (int y = pixels.Height - 1; y >= 0; y--)
{ {
for (int y = pixels.Height - 1; y >= 0; y--) Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
{ PixelOperations<TPixel>.Instance.ToBgra5551Bytes(
Span<TPixel> pixelSpan = pixels.GetRowSpan(y); this.configuration,
PixelOperations<TPixel>.Instance.ToBgra5551Bytes( pixelSpan,
this.configuration, rowSpan,
pixelSpan, pixelSpan.Length);
row.GetSpan(), stream.Write(rowSpan);
pixelSpan.Length);
stream.Write(row.Array, 0, row.Length());
}
} }
} }
@ -317,18 +319,18 @@ namespace SixLabors.ImageSharp.Formats.Tga
private void Write24Bit<TPixel>(Stream stream, Buffer2D<TPixel> pixels) private void Write24Bit<TPixel>(Stream stream, Buffer2D<TPixel> pixels)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 3)) using IMemoryOwner<byte> row = this.AllocateRow(pixels.Width, 3);
Span<byte> rowSpan = row.GetSpan();
for (int y = pixels.Height - 1; y >= 0; y--)
{ {
for (int y = pixels.Height - 1; y >= 0; y--) Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
{ PixelOperations<TPixel>.Instance.ToBgr24Bytes(
Span<TPixel> pixelSpan = pixels.GetRowSpan(y); this.configuration,
PixelOperations<TPixel>.Instance.ToBgr24Bytes( pixelSpan,
this.configuration, rowSpan,
pixelSpan, pixelSpan.Length);
row.GetSpan(), stream.Write(rowSpan);
pixelSpan.Length);
stream.Write(row.Array, 0, row.Length());
}
} }
} }
@ -341,18 +343,18 @@ namespace SixLabors.ImageSharp.Formats.Tga
private void Write32Bit<TPixel>(Stream stream, Buffer2D<TPixel> pixels) private void Write32Bit<TPixel>(Stream stream, Buffer2D<TPixel> pixels)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 4)) using IMemoryOwner<byte> row = this.AllocateRow(pixels.Width, 4);
Span<byte> rowSpan = row.GetSpan();
for (int y = pixels.Height - 1; y >= 0; y--)
{ {
for (int y = pixels.Height - 1; y >= 0; y--) Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
{ PixelOperations<TPixel>.Instance.ToBgra32Bytes(
Span<TPixel> pixelSpan = pixels.GetRowSpan(y); this.configuration,
PixelOperations<TPixel>.Instance.ToBgra32Bytes( pixelSpan,
this.configuration, rowSpan,
pixelSpan, pixelSpan.Length);
row.GetSpan(), stream.Write(rowSpan);
pixelSpan.Length);
stream.Write(row.Array, 0, row.Length());
}
} }
} }

8
src/ImageSharp/Memory/MemoryAllocatorExtensions.cs

@ -67,21 +67,21 @@ namespace SixLabors.ImageSharp.Memory
} }
/// <summary> /// <summary>
/// Allocates padded buffers for BMP encoder/decoder. (Replacing old PixelRow/PixelArea). /// Allocates padded buffers. Generally used by encoder/decoders.
/// </summary> /// </summary>
/// <param name="memoryAllocator">The <see cref="MemoryAllocator"/>.</param> /// <param name="memoryAllocator">The <see cref="MemoryAllocator"/>.</param>
/// <param name="width">Pixel count in the row</param> /// <param name="width">Pixel count in the row</param>
/// <param name="pixelSizeInBytes">The pixel size in bytes, eg. 3 for RGB.</param> /// <param name="pixelSizeInBytes">The pixel size in bytes, eg. 3 for RGB.</param>
/// <param name="paddingInBytes">The padding.</param> /// <param name="paddingInBytes">The padding.</param>
/// <returns>A <see cref="IManagedByteBuffer"/>.</returns> /// <returns>A <see cref="IMemoryOwner{Byte}"/>.</returns>
internal static IManagedByteBuffer AllocatePaddedPixelRowBuffer( internal static IMemoryOwner<byte> AllocatePaddedPixelRowBuffer(
this MemoryAllocator memoryAllocator, this MemoryAllocator memoryAllocator,
int width, int width,
int pixelSizeInBytes, int pixelSizeInBytes,
int paddingInBytes) int paddingInBytes)
{ {
int length = (width * pixelSizeInBytes) + paddingInBytes; int length = (width * pixelSizeInBytes) + paddingInBytes;
return memoryAllocator.AllocateManagedByteBuffer(length); return memoryAllocator.Allocate<byte>(length);
} }
/// <summary> /// <summary>

Loading…
Cancel
Save