Browse Source

Add 16bit decoder tests.

af/merge-core
James Jackson-South 8 years ago
parent
commit
397490997f
  1. 8
      src/ImageSharp/Formats/Png/PngConfigurationModule.cs
  2. 143
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
  3. 5
      tests/ImageSharp.Tests/TestFile.cs
  4. 6
      tests/ImageSharp.Tests/TestImages.cs
  5. 20
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs
  6. 2
      tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs
  7. 13
      tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
  8. 3
      tests/Images/Input/Png/gray-16-tRNS.png
  9. 3
      tests/Images/Input/Png/gray-16.png
  10. 3
      tests/Images/Input/Png/gray-alpha-16.png
  11. 3
      tests/Images/Input/Png/rgb-16-alpha.png

8
src/ImageSharp/Formats/Png/PngConfigurationModule.cs

@ -9,11 +9,11 @@ namespace SixLabors.ImageSharp.Formats.Png
public sealed class PngConfigurationModule : IConfigurationModule public sealed class PngConfigurationModule : IConfigurationModule
{ {
/// <inheritdoc/> /// <inheritdoc/>
public void Configure(Configuration config) public void Configure(Configuration configuration)
{ {
config.ImageFormatsManager.SetEncoder(ImageFormats.Png, new PngEncoder()); configuration.ImageFormatsManager.SetEncoder(ImageFormats.Png, new PngEncoder());
config.ImageFormatsManager.SetDecoder(ImageFormats.Png, new PngDecoder()); configuration.ImageFormatsManager.SetDecoder(ImageFormats.Png, new PngDecoder());
config.ImageFormatsManager.AddImageFormatDetector(new PngImageFormatDetector()); configuration.ImageFormatsManager.AddImageFormatDetector(new PngImageFormatDetector());
} }
} }
} }

143
tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs

@ -21,65 +21,83 @@ namespace SixLabors.ImageSharp.Tests
private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32; private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32;
// Contains the png marker, IHDR and pHYs chunks of a 1x1 pixel 32bit png 1 a single black pixel. // Contains the png marker, IHDR and pHYs chunks of a 1x1 pixel 32bit png 1 a single black pixel.
private static byte[] raw1x1PngIHDRAndpHYs = private static readonly byte[] raw1x1PngIHDRAndpHYs =
{ {
// PNG Identifier // PNG Identifier
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A,
// IHDR // IHDR
0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x00, 0x00, 0x00,
// IHDR CRC // IHDR CRC
0x90, 0x77, 0x53, 0xDE, 0x90, 0x77, 0x53, 0xDE,
// pHYS // pHYS
0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0E, 0xC3, 0x00, 0x00, 0x0E, 0xC3, 0x01, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0E, 0xC3, 0x00, 0x00, 0x0E, 0xC3, 0x01,
// pHYS CRC // pHYS CRC
0xC7, 0x6F, 0xA8, 0x64 0xC7, 0x6F, 0xA8, 0x64
}; };
// Contains the png marker, IDAT and IEND chunks of a 1x1 pixel 32bit png 1 a single black pixel. // Contains the png marker, IDAT and IEND chunks of a 1x1 pixel 32bit png 1 a single black pixel.
private static byte[] raw1x1PngIDATAndIEND = private static readonly byte[] raw1x1PngIDATAndIEND =
{ {
// IDAT // IDAT
0x00, 0x00, 0x00, 0x0C, 0x49, 0x44, 0x41, 0x54, 0x18, 0x57, 0x63, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x49, 0x44, 0x41, 0x54, 0x18, 0x57, 0x63, 0x60, 0x60, 0x60, 0x00, 0x00,
0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01,
// IDAT CRC // IDAT CRC
0x5C, 0xCD, 0xFF, 0x69, 0x5C, 0xCD, 0xFF, 0x69,
// IEND // IEND
0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45,
0x4E, 0x44, 0x4E, 0x44,
// IEND CRC // IEND CRC
0xAE, 0x42, 0x60, 0x82 0xAE, 0x42, 0x60, 0x82
}; };
public static readonly string[] CommonTestImages = public static readonly string[] CommonTestImages =
{ {
TestImages.Png.Splash, TestImages.Png.Splash,
TestImages.Png.Indexed, TestImages.Png.Indexed,
TestImages.Png.FilterVar, TestImages.Png.FilterVar,
TestImages.Png.Bad.ChunkLength1, TestImages.Png.Bad.ChunkLength1,
TestImages.Png.Bad.CorruptedChunk, TestImages.Png.Bad.CorruptedChunk,
TestImages.Png.VimImage1,
TestImages.Png.VersioningImage1,
TestImages.Png.VersioningImage2,
TestImages.Png.SnakeGame,
TestImages.Png.Banner7Adam7InterlaceMode,
TestImages.Png.Banner8Index,
TestImages.Png.Bad.ChunkLength2,
TestImages.Png.VimImage2,
};
TestImages.Png.VimImage1,
TestImages.Png.VersioningImage1,
TestImages.Png.VersioningImage2,
TestImages.Png.SnakeGame, public static readonly string[] TestImages48Bpp =
TestImages.Png.Banner7Adam7InterlaceMode, {
TestImages.Png.Banner8Index, TestImages.Png.Rgb48Bpp,
TestImages.Png.Rgb48BppInterlaced
};
TestImages.Png.Bad.ChunkLength2, public static readonly string[] TestImages64Bpp =
TestImages.Png.VimImage2, {
}; TestImages.Png.Rgba64Bpp,
};
public static readonly string[] TestImagesGray16Bit =
{
TestImages.Png.Gray16Bit,
};
public static readonly string[] TestImages48Bpp = public static readonly string[] TestImagesGrayAlpha16Bit =
{ {
TestImages.Png.Rgb48Bpp, TestImages.Png.GrayAlpha16Bit,
TestImages.Png.Rgb48BppInterlaced TestImages.Png.GrayTrns16Bit
}; };
// This is a workaround for Mono-s decoder being incompatible with ours and GDI+. // This is a workaround for Mono-s decoder being incompatible with ours and GDI+.
// We shouldn't mix these with the Interleaved cases (which are also failing with Mono System.Drawing). Let's go AAA! // We shouldn't mix these with the Interleaved cases (which are also failing with Mono System.Drawing). Let's go AAA!
@ -142,20 +160,66 @@ namespace SixLabors.ImageSharp.Tests
} }
} }
// TODO: We need to decode these into Rgba64 properly, and do 'CompareToOriginal' in a Rgba64 mode! (See #285) [Theory]
[Theory(Skip = "Skipped for now until we can update the reference images from libpng samples.")] [WithFileCollection(nameof(TestImages48Bpp), PixelTypes.Rgb48)]
[WithFileCollection(nameof(TestImages48Bpp), PixelTypes.Rgba32)]
public void Decode_48Bpp<TPixel>(TestImageProvider<TPixel> provider) public void Decode_48Bpp<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
using (Image<TPixel> image = provider.GetImage(new PngDecoder())) using (Image<TPixel> image = provider.GetImage(new PngDecoder()))
{ {
image.DebugSave(provider); var encoder = new PngEncoder { ColorType = PngColorType.Rgb, BitDepth = PngBitDepth.Bit16 };
// Workaround a bug in mono-s System.Drawing PNG decoder. It can't deal with 48Bpp png-s :( if (!SkipVerification(provider))
if (!TestEnvironment.IsLinux && !TestEnvironment.IsMono)
{ {
image.CompareToOriginal(provider, ImageComparer.Exact); image.VerifyEncoder(provider, "png", null, encoder, customComparer: ImageComparer.Exact);
}
}
}
[Theory]
[WithFileCollection(nameof(TestImages64Bpp), PixelTypes.Rgba64)]
public void Decode_64Bpp<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(new PngDecoder()))
{
var encoder = new PngEncoder { ColorType = PngColorType.RgbWithAlpha, BitDepth = PngBitDepth.Bit16 };
if (!SkipVerification(provider))
{
image.VerifyEncoder(provider, "png", null, encoder, customComparer: ImageComparer.Exact);
}
}
}
[Theory]
[WithFileCollection(nameof(TestImagesGray16Bit), PixelTypes.Rgb48)]
public void Decode_Gray16Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(new PngDecoder()))
{
var encoder = new PngEncoder { ColorType = PngColorType.Grayscale, BitDepth = PngBitDepth.Bit16 };
if (!SkipVerification(provider))
{
image.VerifyEncoder(provider, "png", null, encoder, customComparer: ImageComparer.Exact);
}
}
}
[Theory]
[WithFileCollection(nameof(TestImagesGrayAlpha16Bit), PixelTypes.Rgba64)]
public void Decode_GrayAlpha16Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(new PngDecoder()))
{
var encoder = new PngEncoder { ColorType = PngColorType.GrayscaleWithAlpha, BitDepth = PngBitDepth.Bit16 };
if (!SkipVerification(provider))
{
image.VerifyEncoder(provider, "png", null, encoder, customComparer: ImageComparer.Exact);
} }
} }
} }
@ -233,7 +297,7 @@ namespace SixLabors.ImageSharp.Tests
[InlineData(TestImages.Png.Rgb48BppInterlaced, 48)] [InlineData(TestImages.Png.Rgb48BppInterlaced, 48)]
public void DetectPixelSize(string imagePath, int expectedPixelSize) public void DetectPixelSize(string imagePath, int expectedPixelSize)
{ {
TestFile testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using (var stream = new MemoryStream(testFile.Bytes, false))
{ {
Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel); Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel);
@ -257,10 +321,7 @@ namespace SixLabors.ImageSharp.Tests
var decoder = new PngDecoder(); var decoder = new PngDecoder();
ImageFormatException exception = Assert.Throws<ImageFormatException>(() => ImageFormatException exception = Assert.Throws<ImageFormatException>(() => decoder.Decode<Rgb24>(null, memStream));
{
decoder.Decode<Rgb24>(null, memStream);
});
Assert.Equal($"CRC Error. PNG {chunkName} chunk is corrupt!", exception.Message); Assert.Equal($"CRC Error. PNG {chunkName} chunk is corrupt!", exception.Message);
} }

5
tests/ImageSharp.Tests/TestFile.cs

@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Tests
/// </summary> /// </summary>
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
private static readonly Lazy<string> inputImagesDirectory = new Lazy<string>(() => TestEnvironment.InputImagesDirectoryFullPath); private static readonly Lazy<string> inputImagesDirectory = new Lazy<string>(() => TestEnvironment.InputImagesDirectoryFullPath);
/// <summary> /// <summary>
/// The image (lazy initialized value) /// The image (lazy initialized value)
/// </summary> /// </summary>
@ -74,9 +74,10 @@ namespace SixLabors.ImageSharp.Tests
private Image<Rgba32> Image => this.image ?? (this.image = ImageSharp.Image.Load<Rgba32>(this.Bytes)); private Image<Rgba32> Image => this.image ?? (this.image = ImageSharp.Image.Load<Rgba32>(this.Bytes));
/// <summary> /// <summary>
/// Gets the input image directory.
/// </summary> /// </summary>
private static string InputImagesDirectory => inputImagesDirectory.Value; private static string InputImagesDirectory => inputImagesDirectory.Value;
/// <summary> /// <summary>
/// Gets the full qualified path to the input test file. /// Gets the full qualified path to the input test file.
/// </summary> /// </summary>

6
tests/ImageSharp.Tests/TestImages.cs

@ -27,7 +27,11 @@ namespace SixLabors.ImageSharp.Tests
public const string Palette8Bpp = "Png/palette-8bpp.png"; public const string Palette8Bpp = "Png/palette-8bpp.png";
public const string Bpp1 = "Png/bpp1.png"; public const string Bpp1 = "Png/bpp1.png";
public const string Gray4Bpp = "Png/gray_4bpp.png"; public const string Gray4Bpp = "Png/gray_4bpp.png";
public const string Gray16Bit = "Png/gray-16.png";
public const string GrayAlpha16Bit = "Png/gray-alpha-16.png";
public const string GrayTrns16Bit = "Png/gray-16-tRNS.png";
public const string Rgb48Bpp = "Png/rgb-48bpp.png"; public const string Rgb48Bpp = "Png/rgb-48bpp.png";
public const string Rgba64Bpp = "Png/rgb-16-alpha.png";
public const string CalliphoraPartial = "Png/CalliphoraPartial.png"; public const string CalliphoraPartial = "Png/CalliphoraPartial.png";
public const string CalliphoraPartialGrayscale = "Png/CalliphoraPartialGrayscale.png"; public const string CalliphoraPartialGrayscale = "Png/CalliphoraPartialGrayscale.png";
public const string Bike = "Png/Bike.png"; public const string Bike = "Png/Bike.png";
@ -126,7 +130,7 @@ namespace SixLabors.ImageSharp.Tests
}; };
} }
public class Issues public static class Issues
{ {
public const string CriticalEOF214 = "Jpg/issues/Issue214-CriticalEOF.jpg"; public const string CriticalEOF214 = "Jpg/issues/Issue214-CriticalEOF.jpg";
public const string MissingFF00ProgressiveGirl159 = "Jpg/issues/Issue159-MissingFF00-Progressive-Girl.jpg"; public const string MissingFF00ProgressiveGirl159 = "Jpg/issues/Issue159-MissingFF00-Progressive-Girl.jpg";

20
tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs

@ -80,11 +80,12 @@ namespace SixLabors.ImageSharp.Tests
stride = 1; stride = 1;
} }
TPixel[] c = { TPixel[] c =
NamedColors<TPixel>.HotPink, {
NamedColors<TPixel>.Blue NamedColors<TPixel>.HotPink,
}; NamedColors<TPixel>.Blue
};
for (int y = top; y < bottom; y++) for (int y = top; y < bottom; y++)
{ {
int p = 0; int p = 0;
@ -112,10 +113,11 @@ namespace SixLabors.ImageSharp.Tests
int top = 0; int top = 0;
int bottom = pixels.Height / 2; int bottom = pixels.Height / 2;
int stride = pixels.Width / 6; int stride = pixels.Width / 6;
TPixel[] c = { TPixel[] c =
NamedColors<TPixel>.Black, {
NamedColors<TPixel>.White NamedColors<TPixel>.Black,
}; NamedColors<TPixel>.White
};
int p = 0; int p = 0;
for (int y = top; y < bottom; y++) for (int y = top; y < bottom; y++)

2
tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs

@ -56,6 +56,8 @@ namespace SixLabors.ImageSharp.Tests
Bgra32 = 1 << 20, Bgra32 = 1 << 20,
Rgb48 = 1 << 21,
// TODO: Add multi-flag entries by rules defined in PackedPixelConverterHelper // TODO: Add multi-flag entries by rules defined in PackedPixelConverterHelper
// "All" is handled as a separate, individual case instead of using bitwise OR // "All" is handled as a separate, individual case instead of using bitwise OR

13
tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs

@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Tests
private static Lazy<Configuration> configuration = new Lazy<Configuration>(CreateDefaultConfiguration); private static Lazy<Configuration> configuration = new Lazy<Configuration>(CreateDefaultConfiguration);
internal static Configuration Configuration => configuration.Value; internal static Configuration Configuration => configuration.Value;
internal static IImageDecoder GetReferenceDecoder(string filePath) internal static IImageDecoder GetReferenceDecoder(string filePath)
{ {
IImageFormat format = GetImageFormat(filePath); IImageFormat format = GetImageFormat(filePath);
@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests
internal static IImageFormat GetImageFormat(string filePath) internal static IImageFormat GetImageFormat(string filePath)
{ {
string extension = Path.GetExtension(filePath); string extension = Path.GetExtension(filePath);
IImageFormat format = Configuration.ImageFormatsManager.FindFormatByFileExtension(extension); IImageFormat format = Configuration.ImageFormatsManager.FindFormatByFileExtension(extension);
return format; return format;
} }
@ -60,11 +60,10 @@ namespace SixLabors.ImageSharp.Tests
if (!IsLinux) if (!IsLinux)
{ {
configuration.ConfigureCodecs( // System.Drawing on Windows can decode 48bit and 64bit pngs but
ImageFormats.Png, // it doesn't preserve the accuracy we require for comparison.
SystemDrawingReferenceDecoder.Instance, // This makes CompareToOriginal method non-useful.
SystemDrawingReferenceEncoder.Png, configuration.Configure(new PngConfigurationModule());
new PngImageFormatDetector());
configuration.ConfigureCodecs( configuration.ConfigureCodecs(
ImageFormats.Bmp, ImageFormats.Bmp,

3
tests/Images/Input/Png/gray-16-tRNS.png

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

3
tests/Images/Input/Png/gray-16.png

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

3
tests/Images/Input/Png/gray-alpha-16.png

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

3
tests/Images/Input/Png/rgb-16-alpha.png

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