diff --git a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs index 4a283260c5..291c61a814 100644 --- a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Formats.Tga cMapLength: 0, cMapDepth: 0, xOffset: 0, - yOffset: 0, + yOffset: this.useCompression ? (short)image.Height : (short)0, // When run length encoding is used, the origin should be top left instead of the default bottom left. width: (short)image.Width, height: (short)image.Height, pixelDepth: (byte)this.bitsPerPixel.Value, diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs index 54d94c7651..68a3fbe28a 100644 --- a/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs @@ -1,15 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.IO; - -using ImageMagick; - -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats.Tga; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using Xunit; @@ -27,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -39,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -51,7 +44,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -63,7 +56,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -75,7 +68,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -87,7 +80,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -99,7 +92,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -111,7 +104,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -123,7 +116,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -135,7 +128,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -147,7 +140,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -159,7 +152,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -171,7 +164,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -183,7 +176,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } @@ -195,44 +188,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga using (Image image = provider.GetImage(new TgaDecoder())) { image.DebugSave(provider); - CompareWithReferenceDecoder(provider, image); - } - } - - private void CompareWithReferenceDecoder(TestImageProvider provider, Image image) - where TPixel : struct, IPixel - { - string path = TestImageProvider.GetFilePathOrNull(provider); - if (path == null) - { - throw new InvalidOperationException("CompareToOriginal() works only with file providers!"); - } - - TestFile testFile = TestFile.Create(path); - Image magickImage = this.DecodeWithMagick(Configuration.Default, new FileInfo(testFile.FullPath)); - ImageComparer.Exact.VerifySimilarity(image, magickImage); - } - - private Image DecodeWithMagick(Configuration configuration, FileInfo fileInfo) - where TPixel : struct, IPixel - { - using (var magickImage = new MagickImage(fileInfo)) - { - var result = new Image(configuration, magickImage.Width, magickImage.Height); - Span resultPixels = result.GetPixelSpan(); - - using (IPixelCollection pixels = magickImage.GetPixelsUnsafe()) - { - byte[] data = pixels.ToByteArray(PixelMapping.RGBA); - - PixelOperations.Instance.FromRgba32Bytes( - configuration, - data, - resultPixels, - resultPixels.Length); - } - - return result; + TgaTestUtils.CompareWithReferenceDecoder(provider, image); } } } diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs index a92b50516d..4e1cea226d 100644 --- a/tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs @@ -14,6 +14,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga public class TgaEncoderTests { + public static readonly TheoryData BitsPerPixel = + new TheoryData + { + TgaBitsPerPixel.Pixel24, + TgaBitsPerPixel.Pixel32 + }; + public static readonly TheoryData TgaBitsPerPixelFiles = new TheoryData { @@ -69,5 +76,67 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga } } } + + [Theory] + [WithFile(Bit32, PixelTypes.Rgba32)] + public void Encode_Bit8_Works(TestImageProvider provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel8) + where TPixel : struct, IPixel => TestTgaEncoderCore(provider, bitsPerPixel); + + [Theory] + [WithFile(Bit32, PixelTypes.Rgba32)] + public void Encode_Bit16_Works(TestImageProvider provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel16) + where TPixel : struct, IPixel => TestTgaEncoderCore(provider, bitsPerPixel); + + [Theory] + [WithFile(Bit32, PixelTypes.Rgba32)] + public void Encode_Bit24_Works(TestImageProvider provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel24) + where TPixel : struct, IPixel => TestTgaEncoderCore(provider, bitsPerPixel); + + [Theory] + [WithFile(Bit32, PixelTypes.Rgba32)] + public void Encode_Bit32_Works(TestImageProvider provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel32) + where TPixel : struct, IPixel => TestTgaEncoderCore(provider, bitsPerPixel); + + [Theory] + [WithFile(Bit32, PixelTypes.Rgba32)] + public void Encode_Bit8_WithRunLengthEncoding_Works(TestImageProvider provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel8) + where TPixel : struct, IPixel => TestTgaEncoderCore(provider, bitsPerPixel, true); + + [Theory] + [WithFile(Bit32, PixelTypes.Rgba32)] + public void Encode_Bit16_WithRunLengthEncoding_Works(TestImageProvider provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel16) + where TPixel : struct, IPixel => TestTgaEncoderCore(provider, bitsPerPixel, true); + + [Theory] + [WithFile(Bit32, PixelTypes.Rgba32)] + public void Encode_Bit24_WithRunLengthEncoding_Works(TestImageProvider provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel24) + where TPixel : struct, IPixel => TestTgaEncoderCore(provider, bitsPerPixel, true); + + [Theory] + [WithFile(Bit32, PixelTypes.Rgba32)] + public void Encode_Bit32_WithRunLengthEncoding_Works(TestImageProvider provider, TgaBitsPerPixel bitsPerPixel = TgaBitsPerPixel.Pixel32) + where TPixel : struct, IPixel => TestTgaEncoderCore(provider, bitsPerPixel, true); + + private static void TestTgaEncoderCore( + TestImageProvider provider, + TgaBitsPerPixel bitsPerPixel, + bool useCompression = false) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var encoder = new TgaEncoder { BitsPerPixel = bitsPerPixel, Compress = useCompression}; + + using (var memStream = new MemoryStream()) + { + image.Save(memStream, encoder); + memStream.Position = 0; + using (var encodedImage = (Image)Image.Load(memStream)) + { + TgaTestUtils.CompareWithReferenceDecoder(provider, encodedImage); + } + } + } + } } } diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs new file mode 100644 index 0000000000..f127322fda --- /dev/null +++ b/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; + +using ImageMagick; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; + +namespace SixLabors.ImageSharp.Tests.Formats.Tga +{ + public static class TgaTestUtils + { + public static void CompareWithReferenceDecoder(TestImageProvider provider, Image image) + where TPixel : struct, IPixel + { + string path = TestImageProvider.GetFilePathOrNull(provider); + if (path == null) + { + throw new InvalidOperationException("CompareToOriginal() works only with file providers!"); + } + + TestFile testFile = TestFile.Create(path); + Image magickImage = DecodeWithMagick(Configuration.Default, new FileInfo(testFile.FullPath)); + ImageComparer.Exact.VerifySimilarity(image, magickImage); + } + + public static Image DecodeWithMagick(Configuration configuration, FileInfo fileInfo) + where TPixel : struct, IPixel + { + using (var magickImage = new MagickImage(fileInfo)) + { + var result = new Image(configuration, magickImage.Width, magickImage.Height); + Span resultPixels = result.GetPixelSpan(); + + using (IPixelCollection pixels = magickImage.GetPixelsUnsafe()) + { + byte[] data = pixels.ToByteArray(PixelMapping.RGBA); + + PixelOperations.Instance.FromRgba32Bytes( + configuration, + data, + resultPixels, + resultPixels.Length); + } + + return result; + } + } + } +}