Browse Source

Add tests for all supported png bit depths.

af/merge-core
James Jackson-South 8 years ago
parent
commit
0f412fc88b
  1. 160
      tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs
  2. 6
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs
  3. 8
      tests/ImageSharp.Tests/TestUtilities/Tests/MagickReferenceCodecTests.cs

160
tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs

@ -9,7 +9,6 @@ using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Processors.Quantization;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
@ -19,10 +18,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
{
public class PngEncoderTests
{
// This is bull. Failing online for no good reason.
// The images are an exact match. Maybe the submodule isn't updating?
private const float ToleranceThresholdForPaletteEncoder = 1.3F / 100;
public static readonly TheoryData<string, PngBitDepth> PngBitDepthFiles =
new TheoryData<string, PngBitDepth>
{
@ -137,19 +132,32 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
}
[Theory]
[WithTestPatternImages(24, 24, PixelTypes.Rgba64, PngColorType.Rgb)]
[WithTestPatternImages(24, 24, PixelTypes.Rgba64, PngColorType.RgbWithAlpha)]
[WithTestPatternImages(24, 24, PixelTypes.Rgba32, PngColorType.RgbWithAlpha)]
public void WorksWithBitDepth16<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType)
[WithTestPatternImages(24, 24, PixelTypes.Rgba32, PngColorType.Rgb, PngBitDepth.Bit8)]
[WithTestPatternImages(24, 24, PixelTypes.Rgba64, PngColorType.Rgb, PngBitDepth.Bit16)]
[WithTestPatternImages(24, 24, PixelTypes.Rgba32, PngColorType.RgbWithAlpha, PngBitDepth.Bit8)]
[WithTestPatternImages(24, 24, PixelTypes.Rgba64, PngColorType.RgbWithAlpha, PngBitDepth.Bit16)]
[WithTestPatternImages(24, 24, PixelTypes.Rgba32, PngColorType.Palette, PngBitDepth.Bit1)]
[WithTestPatternImages(24, 24, PixelTypes.Rgba32, PngColorType.Palette, PngBitDepth.Bit2)]
[WithTestPatternImages(24, 24, PixelTypes.Rgba32, PngColorType.Palette, PngBitDepth.Bit4)]
[WithTestPatternImages(24, 24, PixelTypes.Rgba32, PngColorType.Palette, PngBitDepth.Bit8)]
[WithTestPatternImages(24, 24, PixelTypes.Rgb24, PngColorType.Grayscale, PngBitDepth.Bit1)]
[WithTestPatternImages(24, 24, PixelTypes.Rgb24, PngColorType.Grayscale, PngBitDepth.Bit2)]
[WithTestPatternImages(24, 24, PixelTypes.Rgb24, PngColorType.Grayscale, PngBitDepth.Bit4)]
[WithTestPatternImages(24, 24, PixelTypes.Rgb24, PngColorType.Grayscale, PngBitDepth.Bit8)]
[WithTestPatternImages(24, 24, PixelTypes.Rgb48, PngColorType.Grayscale, PngBitDepth.Bit16)]
[WithTestPatternImages(24, 24, PixelTypes.Rgba32, PngColorType.GrayscaleWithAlpha, PngBitDepth.Bit8)]
[WithTestPatternImages(24, 24, PixelTypes.Rgba64, PngColorType.GrayscaleWithAlpha, PngBitDepth.Bit16)]
public void WorksWithAllBitDepths<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType, PngBitDepth pngBitDepth)
where TPixel : struct, IPixel<TPixel>
{
TestPngEncoderCore(
provider,
pngColorType,
PngFilterMethod.Adaptive,
PngBitDepth.Bit16,
pngBitDepth,
appendPngColorType: true,
appendPixelType: true);
appendPixelType: true,
appendPngBitDepth: true);
}
[Theory]
@ -166,87 +174,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
appendPaletteSize: true);
}
private static bool HasAlpha(PngColorType pngColorType) =>
pngColorType == PngColorType.GrayscaleWithAlpha || pngColorType == PngColorType.RgbWithAlpha;
private static void TestPngEncoderCore<TPixel>(
TestImageProvider<TPixel> provider,
PngColorType pngColorType,
PngFilterMethod pngFilterMethod,
PngBitDepth bitDepth,
int compressionLevel = 6,
int paletteSize = 255,
bool appendPngColorType = false,
bool appendPngFilterMethod = false,
bool appendPixelType = false,
bool appendCompressionLevel = false,
bool appendPaletteSize = false)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
if (!HasAlpha(pngColorType))
{
image.Mutate(c => c.MakeOpaque());
}
var encoder = new PngEncoder
{
ColorType = pngColorType,
FilterMethod = pngFilterMethod,
CompressionLevel = compressionLevel,
BitDepth = bitDepth,
Quantizer = new WuQuantizer(paletteSize)
};
string pngColorTypeInfo = appendPngColorType ? pngColorType.ToString() : string.Empty;
string pngFilterMethodInfo = appendPngFilterMethod ? pngFilterMethod.ToString() : string.Empty;
string compressionLevelInfo = appendCompressionLevel ? $"_C{compressionLevel}" : string.Empty;
string paletteSizeInfo = appendPaletteSize ? $"_PaletteSize-{paletteSize}" : string.Empty;
string debugInfo = $"{pngColorTypeInfo}{pngFilterMethodInfo}{compressionLevelInfo}{paletteSizeInfo}";
//string referenceInfo = $"{pngColorTypeInfo}";
// Does DebugSave & load reference CompareToReferenceInput():
string actualOutputFile = ((ITestImageProvider)provider).Utility.SaveTestOutputFile(image, "png", encoder, debugInfo, appendPixelType);
if (TestEnvironment.IsMono)
{
// There are bugs in mono's System.Drawing implementation, reference decoders are not always reliable!
return;
}
IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile);
string referenceOutputFile = ((ITestImageProvider)provider).Utility.GetReferenceOutputFileName("png", debugInfo, appendPixelType, true);
bool referenceOutputFileExists = File.Exists(referenceOutputFile);
using (var actualImage = Image.Load<TPixel>(actualOutputFile, referenceDecoder))
{
// TODO: Do we still need the reference output files?
Image<TPixel> referenceImage = referenceOutputFileExists
? Image.Load<TPixel>(referenceOutputFile, referenceDecoder)
: image;
float paletteToleranceHack = 80f / paletteSize;
paletteToleranceHack *= paletteToleranceHack;
ImageComparer comparer = pngColorType == PngColorType.Palette
? ImageComparer.Tolerant(ToleranceThresholdForPaletteEncoder * paletteToleranceHack)
: ImageComparer.Exact;
try
{
comparer.VerifySimilarity(referenceImage, actualImage);
}
finally
{
if (referenceOutputFileExists)
{
referenceImage.Dispose();
}
}
}
}
}
[Theory]
[WithBlankImages(1, 1, PixelTypes.Rgba32)]
public void WritesFileMarker<TPixel>(TestImageProvider<TPixel> provider)
@ -321,5 +248,54 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
}
}
}
private static void TestPngEncoderCore<TPixel>(
TestImageProvider<TPixel> provider,
PngColorType pngColorType,
PngFilterMethod pngFilterMethod,
PngBitDepth bitDepth,
int compressionLevel = 6,
int paletteSize = 255,
bool appendPngColorType = false,
bool appendPngFilterMethod = false,
bool appendPixelType = false,
bool appendCompressionLevel = false,
bool appendPaletteSize = false,
bool appendPngBitDepth = false)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
var encoder = new PngEncoder
{
ColorType = pngColorType,
FilterMethod = pngFilterMethod,
CompressionLevel = compressionLevel,
BitDepth = bitDepth,
Quantizer = new WuQuantizer(paletteSize)
};
string pngColorTypeInfo = appendPngColorType ? pngColorType.ToString() : string.Empty;
string pngFilterMethodInfo = appendPngFilterMethod ? pngFilterMethod.ToString() : string.Empty;
string compressionLevelInfo = appendCompressionLevel ? $"_C{compressionLevel}" : string.Empty;
string paletteSizeInfo = appendPaletteSize ? $"_PaletteSize-{paletteSize}" : string.Empty;
string pngBitDepthInfo = appendPngBitDepth ? bitDepth.ToString() : string.Empty;
string debugInfo = $"{pngColorTypeInfo}{pngFilterMethodInfo}{compressionLevelInfo}{paletteSizeInfo}{pngBitDepthInfo}";
string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "png", encoder, debugInfo, appendPixelType);
// Compare to the Magick reference decoder.
IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile);
// We compare using both our decoder and the reference decoder as pixel transformation
// occurrs within the encoder itself leaving the input image unaffected.
// This means we are benefiting from testing our decoder also.
using (var imageSharpImage = Image.Load<TPixel>(actualOutputFile, new PngDecoder()))
using (var referenceImage = Image.Load<TPixel>(actualOutputFile, referenceDecoder))
{
ImageComparer.Exact.VerifySimilarity(referenceImage, imageSharpImage);
}
}
}
}
}

6
tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs

@ -29,13 +29,13 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
{
if (magickImage.Depth == 8)
{
byte[] data = pixels.ToByteArray("RGBA");
byte[] data = pixels.ToByteArray(PixelMapping.RGBA);
PixelOperations<TPixel>.Instance.PackFromRgba32Bytes(data, resultPixels, resultPixels.Length);
}
else if (magickImage.Depth == 16)
{
ushort[] data = pixels.ToShortArray("RGBA");
ushort[] data = pixels.ToShortArray(PixelMapping.RGBA);
Span<byte> bytes = MemoryMarshal.Cast<ushort, byte>(data.AsSpan());
PixelOperations<TPixel>.Instance.PackFromRgba64Bytes(bytes, resultPixels, resultPixels.Length);

8
tests/ImageSharp.Tests/TestUtilities/Tests/MagickReferenceCodecTests.cs

@ -14,10 +14,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
public class MagickReferenceCodecTests
{
public MagickReferenceCodecTests(ITestOutputHelper output)
{
this.Output = output;
}
public MagickReferenceCodecTests(ITestOutputHelper output) => this.Output = output;
private ITestOutputHelper Output { get; }
@ -61,6 +58,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
[WithBlankImages(1, 1, PixelTypesToTest48, TestImages.Png.Rgb48Bpp)]
[WithBlankImages(1, 1, PixelTypesToTest48, TestImages.Png.Rgb48BppInterlaced)]
[WithBlankImages(1, 1, PixelTypesToTest48, TestImages.Png.Rgb48BppTrans)]
[WithBlankImages(1, 1, PixelTypesToTest48, TestImages.Png.Gray16Bit)]
public void MagickDecode_16BitDepthImage_IsApproximatelyEquivalentTo_SystemDrawingResult<TPixel>(TestImageProvider<TPixel> dummyProvider, string testImage)
where TPixel : struct, IPixel<TPixel>
{
@ -71,7 +69,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests
// 1020 == 4 * 255 (Equivalent to manhattan distance of 1+1+1+1=4 in Rgba32 space)
var comparer = ImageComparer.TolerantPercentage(1, 1020);
using (var mImage = Image.Load<TPixel>(path, magickDecoder))
using (var sdImage = Image.Load<TPixel>(path, sdDecoder))
{

Loading…
Cancel
Save