Browse Source

Move calculation of x and y out of the for loops where possible

pull/1574/head
Brian Popow 6 years ago
parent
commit
b44640033b
  1. 326
      src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
  2. 134
      tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs
  3. 22
      tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs
  4. 43
      tests/ImageSharp.Tests/TestImages.cs
  5. 3
      tests/Images/Input/Tga/grayscale_LR.tga
  6. 3
      tests/Images/Input/Tga/grayscale_UL.tga
  7. 3
      tests/Images/Input/Tga/grayscale_rle_LR.tga
  8. 3
      tests/Images/Input/Tga/grayscale_rle_UL.tga
  9. 3
      tests/Images/Input/Tga/grayscale_rle_UR.tga
  10. 3
      tests/Images/Input/Tga/indexed_LR.tga
  11. 3
      tests/Images/Input/Tga/indexed_UL.tga
  12. 3
      tests/Images/Input/Tga/indexed_UR.tga
  13. 3
      tests/Images/Input/Tga/rgb_a_UL.tga
  14. 3
      tests/Images/Input/Tga/rgb_a_rle_UL.tga

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

@ -237,59 +237,69 @@ namespace SixLabors.ImageSharp.Formats.Tga
private void ReadPaletted<TPixel>(int width, int height, Buffer2D<TPixel> pixels, byte[] palette, int colorMapPixelSizeInBytes, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel<TPixel>
{
using (IManagedByteBuffer row = this.memoryAllocator.AllocateManagedByteBuffer(width, AllocationOptions.Clean))
TPixel color = default;
bool invertX = InvertX(origin);
for (int y = 0; y < height; y++)
{
TPixel color = default;
Span<byte> rowSpan = row.GetSpan();
int newY = InvertY(y, height, origin);
Span<TPixel> pixelRow = pixels.GetRowSpan(newY);
for (int y = 0; y < height; y++)
switch (colorMapPixelSizeInBytes)
{
this.currentStream.Read(row);
int newY = InvertY(y, height, origin);
Span<TPixel> pixelRow = pixels.GetRowSpan(newY);
switch (colorMapPixelSizeInBytes)
{
case 2:
case 2:
if (invertX)
{
for (int x = width - 1; x >= 0; x--)
{
this.ReadPalettedBgr16Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
}
else
{
for (int x = 0; x < width; x++)
{
int colorIndex = rowSpan[x];
Bgra5551 bgra = Unsafe.As<byte, Bgra5551>(ref palette[colorIndex * colorMapPixelSizeInBytes]);
if (!this.hasAlpha)
{
// Set alpha value to 1, to treat it as opaque for Bgra5551.
bgra.PackedValue = (ushort)(bgra.PackedValue | 0x8000);
}
color.FromBgra5551(bgra);
int newX = InvertX(x, width, origin);
pixelRow[newX] = color;
this.ReadPalettedBgr16Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
}
break;
break;
case 3:
case 3:
if (invertX)
{
for (int x = width - 1; x >= 0; x--)
{
this.ReadPalettedBgr24Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
}
else
{
for (int x = 0; x < width; x++)
{
int colorIndex = rowSpan[x];
color.FromBgr24(Unsafe.As<byte, Bgr24>(ref palette[colorIndex * colorMapPixelSizeInBytes]));
int newX = InvertX(x, width, origin);
pixelRow[newX] = color;
this.ReadPalettedBgr24Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
}
break;
break;
case 4:
case 4:
if (invertX)
{
for (int x = width - 1; x >= 0; x--)
{
this.ReadPalettedBgra32Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
}
else
{
for (int x = 0; x < width; x++)
{
int colorIndex = rowSpan[x];
color.FromBgra32(Unsafe.As<byte, Bgra32>(ref palette[colorIndex * colorMapPixelSizeInBytes]));
int newX = InvertX(x, width, origin);
pixelRow[newX] = color;
this.ReadPalettedBgra32Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
}
break;
}
break;
}
}
}
@ -374,20 +384,17 @@ namespace SixLabors.ImageSharp.Formats.Tga
private void ReadMonoChrome<TPixel>(int width, int height, Buffer2D<TPixel> pixels, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel<TPixel>
{
bool isXInverted = origin == TgaImageOrigin.BottomRight || origin == TgaImageOrigin.TopRight;
if (isXInverted)
bool invertX = InvertX(origin);
if (invertX)
{
TPixel color = default;
for (int y = 0; y < height; y++)
{
int newY = InvertY(y, height, origin);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
for (int x = 0; x < width; x++)
for (int x = width - 1; x >= 0; x--)
{
var pixelValue = (byte)this.currentStream.ReadByte();
color.FromL8(Unsafe.As<byte, L8>(ref pixelValue));
int newX = InvertX(x, width, origin);
pixelSpan[newX] = color;
this.ReadL8Pixel(color, x, pixelSpan);
}
}
@ -396,12 +403,20 @@ namespace SixLabors.ImageSharp.Formats.Tga
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 1, 0))
{
for (int y = 0; y < height; y++)
bool invertY = InvertY(origin);
if (invertY)
{
this.currentStream.Read(row);
int newY = InvertY(y, height, origin);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
PixelOperations<TPixel>.Instance.FromL8Bytes(this.configuration, row.GetSpan(), pixelSpan, width);
for (int y = height - 1; y >= 0; y--)
{
this.ReadL8Row(width, pixels, row, y);
}
}
else
{
for (int y = 0; y < height; y++)
{
this.ReadL8Row(width, pixels, row, y);
}
}
}
}
@ -418,7 +433,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel color = default;
bool isXInverted = origin == TgaImageOrigin.BottomRight || origin == TgaImageOrigin.TopRight;
bool invertX = InvertX(origin);
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 2, 0))
{
for (int y = 0; y < height; y++)
@ -426,9 +441,9 @@ namespace SixLabors.ImageSharp.Formats.Tga
int newY = InvertY(y, height, origin);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
if (isXInverted)
if (invertX)
{
for (int x = 0; x < width; x++)
for (int x = width - 1; x >= 0; x--)
{
this.currentStream.Read(this.scratchBuffer, 0, 2);
if (!this.hasAlpha)
@ -445,8 +460,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
color.FromBgra5551(Unsafe.As<byte, Bgra5551>(ref this.scratchBuffer[0]));
}
int newX = InvertX(x, width, origin);
pixelSpan[newX] = color;
pixelSpan[x] = color;
}
}
else
@ -487,20 +501,17 @@ namespace SixLabors.ImageSharp.Formats.Tga
private void ReadBgr24<TPixel>(int width, int height, Buffer2D<TPixel> pixels, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel<TPixel>
{
bool isXInverted = origin == TgaImageOrigin.BottomRight || origin == TgaImageOrigin.TopRight;
if (isXInverted)
bool invertX = InvertX(origin);
if (invertX)
{
TPixel color = default;
for (int y = 0; y < height; y++)
{
int newY = InvertY(y, height, origin);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
for (int x = 0; x < width; x++)
for (int x = width - 1; x >= 0; x--)
{
this.currentStream.Read(this.scratchBuffer, 0, 3);
color.FromBgr24(Unsafe.As<byte, Bgr24>(ref this.scratchBuffer[0]));
int newX = InvertX(x, width, origin);
pixelSpan[newX] = color;
this.ReadBgr24Pixel(color, x, pixelSpan);
}
}
@ -509,12 +520,21 @@ namespace SixLabors.ImageSharp.Formats.Tga
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 3, 0))
{
for (int y = 0; y < height; y++)
bool invertY = InvertY(origin);
if (invertY)
{
this.currentStream.Read(row);
int newY = InvertY(y, height, origin);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
PixelOperations<TPixel>.Instance.FromBgr24Bytes(this.configuration, row.GetSpan(), pixelSpan, width);
for (int y = height - 1; y >= 0; y--)
{
this.ReadBgr24Row(width, pixels, row, y);
}
}
else
{
for (int y = 0; y < height; y++)
{
this.ReadBgr24Row(width, pixels, row, y);
}
}
}
}
@ -531,41 +551,46 @@ namespace SixLabors.ImageSharp.Formats.Tga
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel color = default;
bool isXInverted = origin == TgaImageOrigin.BottomRight || origin == TgaImageOrigin.TopRight;
if (this.tgaMetadata.AlphaChannelBits == 8 && !isXInverted)
bool invertX = InvertX(origin);
if (this.tgaMetadata.AlphaChannelBits == 8 && !invertX)
{
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, 0))
{
for (int y = 0; y < height; y++)
if (InvertY(origin))
{
this.currentStream.Read(row);
int newY = InvertY(y, height, origin);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
PixelOperations<TPixel>.Instance.FromBgra32Bytes(this.configuration, row.GetSpan(), pixelSpan, width);
for (int y = height - 1; y >= 0; y--)
{
this.ReadBgra32Row(width, pixels, row, y);
}
}
else
{
for (int y = 0; y < height; y++)
{
this.ReadBgra32Row(width, pixels, row, y);
}
}
}
return;
}
var alphaBits = this.tgaMetadata.AlphaChannelBits;
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, 0))
for (int y = 0; y < height; y++)
{
for (int y = 0; y < height; y++)
int newY = InvertY(y, height, origin);
Span<TPixel> pixelRow = pixels.GetRowSpan(newY);
if (invertX)
{
for (int x = width - 1; x >= 0; x--)
{
this.ReadBgra32Pixel(x, color, pixelRow);
}
}
else
{
this.currentStream.Read(row);
int newY = InvertY(y, height, origin);
Span<TPixel> pixelRow = pixels.GetRowSpan(newY);
Span<byte> rowSpan = row.GetSpan();
for (int x = 0; x < width; x++)
{
int idx = x * 4;
var alpha = alphaBits == 0 ? byte.MaxValue : rowSpan[idx + 3];
color.FromBgra32(new Bgra32(rowSpan[idx + 2], rowSpan[idx + 1], rowSpan[idx], (byte)alpha));
int newX = InvertX(x, width, origin);
pixelRow[newX] = color;
this.ReadBgra32Pixel(x, color, pixelRow);
}
}
}
@ -657,6 +682,95 @@ namespace SixLabors.ImageSharp.Formats.Tga
this.metadata);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadL8Row<TPixel>(int width, Buffer2D<TPixel> pixels, IManagedByteBuffer row, int y)
where TPixel : unmanaged, IPixel<TPixel>
{
this.currentStream.Read(row);
Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
PixelOperations<TPixel>.Instance.FromL8Bytes(this.configuration, row.GetSpan(), pixelSpan, width);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadL8Pixel<TPixel>(TPixel color, int x, Span<TPixel> pixelSpan)
where TPixel : unmanaged, IPixel<TPixel>
{
var pixelValue = (byte)this.currentStream.ReadByte();
color.FromL8(Unsafe.As<byte, L8>(ref pixelValue));
pixelSpan[x] = color;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadBgr24Pixel<TPixel>(TPixel color, int x, Span<TPixel> pixelSpan)
where TPixel : unmanaged, IPixel<TPixel>
{
this.currentStream.Read(this.scratchBuffer, 0, 3);
color.FromBgr24(Unsafe.As<byte, Bgr24>(ref this.scratchBuffer[0]));
pixelSpan[x] = color;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadBgr24Row<TPixel>(int width, Buffer2D<TPixel> pixels, IManagedByteBuffer row, int y)
where TPixel : unmanaged, IPixel<TPixel>
{
this.currentStream.Read(row);
Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
PixelOperations<TPixel>.Instance.FromBgr24Bytes(this.configuration, row.GetSpan(), pixelSpan, width);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadBgra32Pixel<TPixel>(int x, TPixel color, Span<TPixel> pixelRow)
where TPixel : unmanaged, IPixel<TPixel>
{
this.currentStream.Read(this.scratchBuffer, 0, 4);
var alpha = this.tgaMetadata.AlphaChannelBits == 0 ? byte.MaxValue : this.scratchBuffer[3];
color.FromBgra32(new Bgra32(this.scratchBuffer[2], this.scratchBuffer[1], this.scratchBuffer[0], alpha));
pixelRow[x] = color;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadBgra32Row<TPixel>(int width, Buffer2D<TPixel> pixels, IManagedByteBuffer row, int y)
where TPixel : unmanaged, IPixel<TPixel>
{
this.currentStream.Read(row);
Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
PixelOperations<TPixel>.Instance.FromBgra32Bytes(this.configuration, row.GetSpan(), pixelSpan, width);
}
private void ReadPalettedBgr16Pixel<TPixel>(byte[] palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span<TPixel> pixelRow)
where TPixel : unmanaged, IPixel<TPixel>
{
int colorIndex = this.currentStream.ReadByte();
Bgra5551 bgra = default;
bgra.FromBgra5551(Unsafe.As<byte, Bgra5551>(ref palette[colorIndex * colorMapPixelSizeInBytes]));
if (!this.hasAlpha)
{
// Set alpha value to 1, to treat it as opaque for Bgra5551.
bgra.PackedValue = (ushort)(bgra.PackedValue | 0x8000);
}
color.FromBgra5551(bgra);
pixelRow[x] = color;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadPalettedBgr24Pixel<TPixel>(byte[] palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span<TPixel> pixelRow)
where TPixel : unmanaged, IPixel<TPixel>
{
int colorIndex = this.currentStream.ReadByte();
color.FromBgr24(Unsafe.As<byte, Bgr24>(ref palette[colorIndex * colorMapPixelSizeInBytes]));
pixelRow[x] = color;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadPalettedBgra32Pixel<TPixel>(byte[] palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span<TPixel> pixelRow)
where TPixel : unmanaged, IPixel<TPixel>
{
int colorIndex = this.currentStream.ReadByte();
color.FromBgra32(Unsafe.As<byte, Bgra32>(ref palette[colorIndex * colorMapPixelSizeInBytes]));
pixelRow[x] = color;
}
/// <summary>
/// Produce uncompressed tga data from a run length encoded stream.
/// </summary>
@ -710,14 +824,30 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// <returns>The <see cref="int"/> representing the inverted value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int InvertY(int y, int height, TgaImageOrigin origin)
{
if (InvertY(origin))
{
return height - y - 1;
}
return y;
}
/// <summary>
/// Indicates whether the y coordinates needs to be inverted, to keep a top left origin.
/// </summary>
/// <param name="origin">The image origin.</param>
/// <returns>True, if y coordinate needs to be inverted.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool InvertY(TgaImageOrigin origin)
{
switch (origin)
{
case TgaImageOrigin.BottomLeft:
case TgaImageOrigin.BottomRight:
return height - y - 1;
return true;
default:
return y;
return false;
}
}
@ -730,14 +860,30 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// <returns>The <see cref="int"/> representing the inverted value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int InvertX(int x, int width, TgaImageOrigin origin)
{
if (InvertX(origin))
{
return width - x - 1;
}
return x;
}
/// <summary>
/// Indicates whether the x coordinates needs to be inverted, to keep a top left origin.
/// </summary>
/// <param name="origin">The image origin.</param>
/// <returns>True, if x coordinate needs to be inverted.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool InvertX(TgaImageOrigin origin)
{
switch (origin)
{
case TgaImageOrigin.TopRight:
case TgaImageOrigin.BottomRight:
return width - x - 1;
return true;
default:
return x;
return false;
}
}

134
tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs

@ -20,8 +20,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
private static TgaDecoder TgaDecoder => new TgaDecoder();
[Theory]
[WithFile(Gray8Bit, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_Gray_8Bit<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(Gray8BitTopLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_Gray_WithTopLeftOrigin_8Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
@ -68,8 +68,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Gray8BitRle, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_8Bit<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(Gray8BitRleTopLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithTopLeftOrigin_8Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
@ -80,7 +80,43 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Gray16Bit, PixelTypes.Rgba32)]
[WithFile(Gray8BitRleTopRight, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithTopRightOrigin_8Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
{
image.DebugSave(provider);
TgaTestUtils.CompareWithReferenceDecoder(provider, image);
}
}
[Theory]
[WithFile(Gray8BitRleBottomLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithBottomLeftOrigin_8Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
{
image.DebugSave(provider);
TgaTestUtils.CompareWithReferenceDecoder(provider, image);
}
}
[Theory]
[WithFile(Gray8BitRleBottomRight, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithBottomRightOrigin_8Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
{
image.DebugSave(provider);
TgaTestUtils.CompareWithReferenceDecoder(provider, image);
}
}
[Theory]
[WithFile(Gray16BitTopLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_Gray_16Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
@ -140,7 +176,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Gray16BitRle, PixelTypes.Rgba32)]
[WithFile(Gray16BitRleTopLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_16Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
@ -248,8 +284,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Bit24, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_24Bit<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(Bit24TopLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithTopLeftOrigin_24Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
@ -344,8 +380,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Bit32, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_32Bit<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(Bit32TopLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithTopLeftOrigin_32Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
{
image.DebugSave(provider);
TgaTestUtils.CompareWithReferenceDecoder(provider, image);
}
}
[Theory]
[WithFile(Bit32TopRight, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithTopRightOrigin_32Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
@ -380,8 +428,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Bit32TopRight, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithTopRightOrigin_32Bit<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(Bit16RleBottomLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_WithBottomLeftOrigin_16Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
@ -392,8 +440,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Bit16Rle, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_16Bit<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(Bit24RleBottomLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_WithBottomLeftOrigin_24Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
@ -404,8 +452,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Bit24Rle, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_24Bit<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(Bit32RleTopLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_WithTopLeftOrigin_32Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
@ -416,8 +464,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Bit32Rle, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_32Bit<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(Bit32RleBottomLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_RunLengthEncoded_WithBottomLeftOrigin_32Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
@ -452,8 +500,32 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Bit16Pal, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithPalette_16Bit<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(Bit16PalBottomLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithPaletteBottomLeftOrigin_16Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
{
image.DebugSave(provider);
TgaTestUtils.CompareWithReferenceDecoder(provider, image);
}
}
[Theory]
[WithFile(Bit24PalTopLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithPaletteTopLeftOrigin_24Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
{
image.DebugSave(provider);
TgaTestUtils.CompareWithReferenceDecoder(provider, image);
}
}
[Theory]
[WithFile(Bit24PalTopRight, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithPaletteTopRightOrigin_24Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
@ -464,8 +536,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Bit24Pal, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithPalette_24Bit<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(Bit24PalBottomLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithPaletteBottomLeftOrigin_24Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
@ -476,7 +548,19 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Bit32Pal, PixelTypes.Rgba32)]
[WithFile(Bit24PalBottomRight, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithPaletteBottomRightOrigin_24Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(TgaDecoder))
{
image.DebugSave(provider);
TgaTestUtils.CompareWithReferenceDecoder(provider, image);
}
}
[Theory]
[WithFile(Bit32PalTopLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithPalette_32Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
@ -554,7 +638,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
[Theory]
[WithFile(Bit16BottomLeft, PixelTypes.Rgba32)]
[WithFile(Bit24BottomLeft, PixelTypes.Rgba32)]
[WithFile(Bit32, PixelTypes.Rgba32)]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaDecoder_DegenerateMemoryRequest_ShouldTranslateTo_ImageFormatException<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
@ -565,7 +649,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
[Theory]
[WithFile(Bit24BottomLeft, PixelTypes.Rgba32)]
[WithFile(Bit32, PixelTypes.Rgba32)]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_WithLimitedAllocatorBufferCapacity<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{

22
tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs

@ -25,10 +25,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
public static readonly TheoryData<string, TgaBitsPerPixel> TgaBitsPerPixelFiles =
new TheoryData<string, TgaBitsPerPixel>
{
{ Gray8Bit, TgaBitsPerPixel.Pixel8 },
{ Gray8BitBottomLeft, TgaBitsPerPixel.Pixel8 },
{ Bit16BottomLeft, TgaBitsPerPixel.Pixel16 },
{ Bit24BottomLeft, TgaBitsPerPixel.Pixel24 },
{ Bit32, TgaBitsPerPixel.Pixel32 },
{ Bit32BottomLeft, TgaBitsPerPixel.Pixel32 },
};
[Theory]
@ -79,51 +79,51 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
[WithFile(Bit32, PixelTypes.Rgba32)]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit8_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel8)
// Using tolerant comparer here. The results from magick differ slightly. Maybe a different ToGrey method is used. The image looks otherwise ok.
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.None, useExactComparer: false, compareTolerance: 0.03f);
[Theory]
[WithFile(Bit32, PixelTypes.Rgba32)]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit16_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel16)
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.None, useExactComparer: false);
[Theory]
[WithFile(Bit32, PixelTypes.Rgba32)]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit24_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel24)
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.None);
[Theory]
[WithFile(Bit32, PixelTypes.Rgba32)]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit32_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel32)
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.None);
[Theory]
[WithFile(Bit32, PixelTypes.Rgba32)]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit8_WithRunLengthEncoding_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel8)
// Using tolerant comparer here. The results from magick differ slightly. Maybe a different ToGrey method is used. The image looks otherwise ok.
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.RunLength, useExactComparer: false, compareTolerance: 0.03f);
[Theory]
[WithFile(Bit32, PixelTypes.Rgba32)]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit16_WithRunLengthEncoding_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel16)
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.RunLength, useExactComparer: false);
[Theory]
[WithFile(Bit32, PixelTypes.Rgba32)]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit24_WithRunLengthEncoding_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel24)
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.RunLength);
[Theory]
[WithFile(Bit32, PixelTypes.Rgba32)]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
public void TgaEncoder_Bit32_WithRunLengthEncoding_Works<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel32)
where TPixel : unmanaged, IPixel<TPixel> => TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.RunLength);
[Theory]
[WithFile(Bit32, PixelTypes.Rgba32, TgaBitsPerPixel.Pixel32)]
[WithFile(Bit32BottomLeft, PixelTypes.Rgba32, TgaBitsPerPixel.Pixel32)]
[WithFile(Bit24BottomLeft, PixelTypes.Rgba32, TgaBitsPerPixel.Pixel24)]
public void TgaEncoder_WorksWithDiscontiguousBuffers<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel)
where TPixel : unmanaged, IPixel<TPixel>

43
tests/ImageSharp.Tests/TestImages.cs

@ -375,53 +375,62 @@ namespace SixLabors.ImageSharp.Tests
public static class Tga
{
public const string Gray8Bit = "Tga/targa_8bit.tga";
public const string Gray8BitBottomLeft = "Tga/grayscale_LL.tga";
public const string Gray8BitTopLeft = "Tga/grayscale_UL.tga";
public const string Gray8BitTopRight = "Tga/grayscale_UR.tga";
public const string Gray8BitBottomRight = "Tga/grayscale_UR.tga";
public const string Gray8BitRle = "Tga/targa_8bit_rle.tga";
public const string Gray8BitBottomLeft = "Tga/targa_8bit.tga";
public const string Gray8BitBottomRight = "Tga/grayscale_LR.tga";
public const string Gray8BitRleTopLeft = "Tga/grayscale_rle_UL.tga";
public const string Gray8BitRleTopRight = "Tga/grayscale_rle_UR.tga";
public const string Gray8BitRleBottomLeft = "Tga/targa_8bit_rle.tga";
public const string Gray8BitRleBottomRight = "Tga/grayscale_rle_LR.tga";
public const string Bit15 = "Tga/rgb15.tga";
public const string Bit15Rle = "Tga/rgb15rle.tga";
public const string Bit16BottomLeft = "Tga/targa_16bit.tga";
public const string Bit16PalRle = "Tga/ccm8.tga";
public const string Bit16RleBottomLeft = "Tga/targa_16bit_rle.tga";
public const string Bit16PalBottomLeft = "Tga/targa_16bit_pal.tga";
public const string Gray16Bit = "Tga/grayscale_a_UL.tga";
public const string Gray16BitTopLeft = "Tga/grayscale_a_UL.tga";
public const string Gray16BitBottomLeft = "Tga/grayscale_a_LL.tga";
public const string Gray16BitBottomRight = "Tga/grayscale_a_LR.tga";
public const string Gray16BitTopRight = "Tga/grayscale_a_UR.tga";
public const string Gray16BitRle = "Tga/grayscale_a_rle_UL.tga";
public const string Gray16BitRleTopLeft = "Tga/grayscale_a_rle_UL.tga";
public const string Gray16BitRleBottomLeft = "Tga/grayscale_a_rle_LL.tga";
public const string Gray16BitRleBottomRight = "Tga/grayscale_a_rle_LR.tga";
public const string Gray16BitRleTopRight = "Tga/grayscale_a_rle_UR.tga";
public const string Bit24 = "Tga/rgb24_top_left.tga";
public const string Bit24TopLeft = "Tga/rgb24_top_left.tga";
public const string Bit24BottomLeft = "Tga/targa_24bit.tga";
public const string Bit24BottomRight = "Tga/rgb_LR.tga";
public const string Bit24TopRight = "Tga/rgb_UR.tga";
public const string Bit24TopLeft = "Tga/targa_24bit_pal_origin_topleft.tga";
public const string Bit24RleTopLeft = "Tga/targa_24bit_rle_origin_topleft.tga";
public const string Bit24RleBottomLeft = "Tga/targa_24bit_rle.tga";
public const string Bit24RleTopRight = "Tga/rgb_rle_UR.tga";
public const string Bit24RleBottomRight = "Tga/rgb_rle_LR.tga";
public const string Bit32 = "Tga/targa_32bit.tga";
public const string Bit32BottomLeft = "Tga/rgb_a_LL.tga";
public const string Bit24PalTopLeft = "Tga/targa_24bit_pal_origin_topleft.tga";
public const string Bit24PalTopRight = "Tga/indexed_UR.tga";
public const string Bit24PalBottomLeft = "Tga/targa_24bit_pal.tga";
public const string Bit24PalBottomRight = "Tga/indexed_LR.tga";
public const string Bit32TopLeft = "Tga/rgb_a_UL.tga";
public const string Bit32BottomLeft = "Tga/targa_32bit.tga";
public const string Bit32TopRight = "Tga/rgb_a_UR.tga";
public const string Bit32BottomRight = "Tga/rgb_a_LR.tga";
public const string Bit32Pal = "Tga/indexed_a_UL.tga";
public const string Bit32PalTopLeft = "Tga/indexed_a_UL.tga";
public const string Bit32PalBottomLeft = "Tga/indexed_a_LL.tga";
public const string Bit32PalBottomRight = "Tga/indexed_a_LR.tga";
public const string Bit32PalTopRight = "Tga/indexed_a_UR.tga";
public const string Bit32RleTopLeft = "Tga/rgb_a_rle_UL.tga";
public const string Bit32RleTopRight = "Tga/rgb_a_rle_UR.tga";
public const string Bit32RleBottomRight = "Tga/rgb_a_rle_LR.tga";
public const string Bit16Rle = "Tga/targa_16bit_rle.tga";
public const string Bit24Rle = "Tga/targa_24bit_rle.tga";
public const string Bit32Rle = "Tga/targa_32bit_rle.tga";
public const string Bit16Pal = "Tga/targa_16bit_pal.tga";
public const string Bit24Pal = "Tga/targa_24bit_pal.tga";
public const string Bit32RleBottomLeft = "Tga/targa_32bit_rle.tga";
public const string NoAlphaBits16Bit = "Tga/16bit_noalphabits.tga";
public const string NoAlphaBits16BitRle = "Tga/16bit_rle_noalphabits.tga";

3
tests/Images/Input/Tga/grayscale_LR.tga

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ed269c8f3bb462d963188d7352ebe85ab20357ac7803e5ac4d7110a23b9e6ddb
size 65580

3
tests/Images/Input/Tga/grayscale_UL.tga

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:72c6e1e09b923455e0c8cd14c37b358eb578bc14a0a8fcedde3ab81769960eb7
size 65580

3
tests/Images/Input/Tga/grayscale_rle_LR.tga

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a897be6870be2cd183e7678e954767fd12a763c7bfce0f2246f1b7cc1ad08804
size 31165

3
tests/Images/Input/Tga/grayscale_rle_UL.tga

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3f11be4af2283059e869543949588fe19db0e36dec64157ad9a61711cb5e6428
size 31198

3
tests/Images/Input/Tga/grayscale_rle_UR.tga

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f5aa67ec6d3408fd469ec8e7c5613daf130be893e0b76dee2994a2c32ddae471
size 31054

3
tests/Images/Input/Tga/indexed_LR.tga

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e6d5219fadf7d8b743d35c7e16f11e1182f76351757ff962e0a27f81c357b1fb
size 66315

3
tests/Images/Input/Tga/indexed_UL.tga

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7f42dd07528f9e4f7914a570c027cc845edfe6d3fcdfa45ec8f21bc254cc1f1f
size 66315

3
tests/Images/Input/Tga/indexed_UR.tga

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:90d8caa10d3a05f845f94b176a77a2ed85e25b3d460527c96abfe793870c89b8
size 66315

3
tests/Images/Input/Tga/rgb_a_UL.tga

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1a167af1f8d64119e206593f8944c0b7901393a1b97d703c0121b8a59cae03f4
size 262188

3
tests/Images/Input/Tga/rgb_a_rle_UL.tga

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:be1323021deead462ef38c17eea5d59aea7467ae33b91bd65b542085e74aa4e4
size 98427
Loading…
Cancel
Save