Browse Source

OrigJpegDecoder -> GolangJpegDecoder + test cleanup

pull/571/head
Anton Firszov 8 years ago
parent
commit
87da33dab1
  1. 2
      src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoder.cs
  2. 2
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg.cs
  3. 2
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegMultiple.cs
  4. 2
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs
  5. 126
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs
  6. 56
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  7. 2
      tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs
  8. 10
      tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs

2
src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoder.cs → src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoder.cs

@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
/// <summary>
/// Image decoder for generating an image out of a jpg stream.
/// </summary>
internal sealed class OrigJpegDecoder : IImageDecoder, IJpegDecoderOptions, IImageInfoDetector
internal sealed class GolangJpegDecoder : IImageDecoder, IJpegDecoderOptions, IImageInfoDetector
{
/// <summary>
/// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.

2
tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg.cs

@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
using (var memoryStream = new MemoryStream(this.jpegBytes))
{
using (var image = Image.Load<Rgba32>(memoryStream, new OrigJpegDecoder()))
using (var image = Image.Load<Rgba32>(memoryStream, new GolangJpegDecoder()))
{
return new CoreSize(image.Width, image.Height);
}

2
tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegMultiple.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Description = "DecodeJpegMultiple - ImageSharp")]
public void DecodeJpegImageSharpOrig()
{
this.ForEachStream(ms => Image.Load<Rgba32>(ms, new OrigJpegDecoder()));
this.ForEachStream(ms => Image.Load<Rgba32>(ms, new GolangJpegDecoder()));
}
[Benchmark(Description = "DecodeJpegMultiple - ImageSharp PDFJs")]

2
tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs

@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
using (var memoryStream = new MemoryStream(this.jpegBytes))
{
var decoder = new OrigJpegDecoder();
var decoder = new GolangJpegDecoder();
return decoder.Identify(Configuration.Default, memoryStream);
}

126
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs

@ -11,6 +11,7 @@ using Xunit;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats.Jpeg;
@ -50,7 +51,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
TestMetaDataImpl(
useIdentify,
OrigJpegDecoder,
GolangJpegDecoder,
imagePath,
expectedPixelSize,
exifProfilePresent,
@ -75,6 +76,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
iccProfilePresent);
}
private static void TestImageInfo(string imagePath, IImageDecoder decoder, bool useIdentify, Action<IImageInfo> test)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
IImageInfo imageInfo = useIdentify
? ((IImageInfoDetector)decoder).Identify(Configuration.Default, stream)
: decoder.Decode<Rgba32>(Configuration.Default, stream);
test(imageInfo);
}
}
private static void TestMetaDataImpl(
bool useIdentify,
IImageDecoder decoder,
@ -83,51 +96,50 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
bool exifProfilePresent,
bool iccProfilePresent)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
IImageInfo imageInfo = useIdentify
? ((IImageInfoDetector)decoder).Identify(Configuration.Default, stream)
: decoder.Decode<Rgba32>(Configuration.Default, stream);
TestImageInfo(
imagePath,
decoder,
useIdentify,
imageInfo =>
{
Assert.NotNull(imageInfo);
Assert.NotNull(imageInfo.PixelType);
Assert.NotNull(imageInfo);
Assert.NotNull(imageInfo.PixelType);
if (useIdentify)
{
Assert.Equal(expectedPixelSize, imageInfo.PixelType.BitsPerPixel);
}
else
{
// When full Image<TPixel> decoding is performed, BitsPerPixel will match TPixel
int bpp32 = Unsafe.SizeOf<Rgba32>() * 8;
Assert.Equal(bpp32, imageInfo.PixelType.BitsPerPixel);
}
if (useIdentify)
{
Assert.Equal(expectedPixelSize, imageInfo.PixelType.BitsPerPixel);
}
else
{
// When full Image<TPixel> decoding is performed, BitsPerPixel will match TPixel
int bpp32 = Unsafe.SizeOf<Rgba32>() * 8;
Assert.Equal(bpp32, imageInfo.PixelType.BitsPerPixel);
}
ExifProfile exifProfile = imageInfo.MetaData.ExifProfile;
ExifProfile exifProfile = imageInfo.MetaData.ExifProfile;
if (exifProfilePresent)
{
Assert.NotNull(exifProfile);
Assert.NotEmpty(exifProfile.Values);
}
else
{
Assert.Null(exifProfile);
}
if (exifProfilePresent)
{
Assert.NotNull(exifProfile);
Assert.NotEmpty(exifProfile.Values);
}
else
{
Assert.Null(exifProfile);
}
IccProfile iccProfile = imageInfo.MetaData.IccProfile;
IccProfile iccProfile = imageInfo.MetaData.IccProfile;
if (iccProfilePresent)
{
Assert.NotNull(iccProfile);
Assert.NotEmpty(iccProfile.Entries);
}
else
{
Assert.Null(iccProfile);
}
}
if (iccProfilePresent)
{
Assert.NotNull(iccProfile);
Assert.NotEmpty(iccProfile.Entries);
}
else
{
Assert.Null(iccProfile);
}
});
}
[Theory]
@ -154,5 +166,37 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
}
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Decoder_Reads_Correct_Resolution_From_Jfif(bool useIdentify)
{
TestImageInfo(TestImages.Jpeg.Baseline.Floorplan, DefaultJpegDecoder, useIdentify,
imageInfo =>
{
Assert.Equal(300, imageInfo.MetaData.HorizontalResolution);
Assert.Equal(300, imageInfo.MetaData.VerticalResolution);
});
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Decoder_Reads_Correct_Resolution_From_Exif(bool useIdentify)
{
TestImageInfo(TestImages.Jpeg.Baseline.Jpeg420Exif, DefaultJpegDecoder, useIdentify,
imageInfo =>
{
Assert.Equal(72, imageInfo.MetaData.HorizontalResolution);
Assert.Equal(72, imageInfo.MetaData.VerticalResolution);
});
using (Image<Rgba32> image = TestFile.Create(TestImages.Jpeg.Baseline.Jpeg420Exif).CreateImage())
{
Assert.Equal(72, image.MetaData.HorizontalResolution);
Assert.Equal(72, image.MetaData.VerticalResolution);
}
}
}
}

56
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -115,10 +115,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
private ITestOutputHelper Output { get; }
private static OrigJpegDecoder OrigJpegDecoder => new OrigJpegDecoder();
private static GolangJpegDecoder GolangJpegDecoder => new GolangJpegDecoder();
private static PdfJsJpegDecoder PdfJsJpegDecoder => new PdfJsJpegDecoder();
private static JpegDecoder DefaultJpegDecoder => new JpegDecoder();
[Fact]
public void ParseStream_BasicPropertiesAreCorrect1_PdfJs()
{
@ -151,7 +153,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
// For 32 bit test enviroments:
provider.Configuration.MemoryManager = ArrayPoolMemoryManager.CreateWithModeratePooling();
IImageDecoder decoder = useOldDecoder ? (IImageDecoder)OrigJpegDecoder : PdfJsJpegDecoder;
IImageDecoder decoder = useOldDecoder ? (IImageDecoder)GolangJpegDecoder : PdfJsJpegDecoder;
using (Image<TPixel> image = provider.GetImage(decoder))
{
image.DebugSave(provider);
@ -176,7 +178,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
// For 32 bit test enviroments:
provider.Configuration.MemoryManager = ArrayPoolMemoryManager.CreateWithModeratePooling();
using (Image<TPixel> image = provider.GetImage(OrigJpegDecoder))
using (Image<TPixel> image = provider.GetImage(GolangJpegDecoder))
{
image.DebugSave(provider);
provider.Utility.TestName = DecodeBaselineJpegOutputName;
@ -240,11 +242,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Theory]
[WithFile(TestImages.Jpeg.Issues.CriticalEOF214, PixelTypes.Rgba32)]
public void DecodeBaselineJpeg_CriticalEOF_ShouldThrow_Orig<TPixel>(TestImageProvider<TPixel> provider)
public void DecodeBaselineJpeg_CriticalEOF_ShouldThrow_Golang<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
// TODO: We need a public ImageDecoderException class in ImageSharp!
Assert.ThrowsAny<Exception>(() => provider.GetImage(OrigJpegDecoder));
Assert.ThrowsAny<Exception>(() => provider.GetImage(GolangJpegDecoder));
}
[Theory]
[WithFile(TestImages.Jpeg.Issues.CriticalEOF214, PixelTypes.Rgba32)]
public void DecodeBaselineJpeg_CriticalEOF_ShouldThrow_PdfJs<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
// TODO: We need a public ImageDecoderException class in ImageSharp!
Assert.ThrowsAny<Exception>(() => provider.GetImage(PdfJsJpegDecoder));
}
public const string DecodeProgressiveJpegOutputName = "DecodeProgressiveJpeg";
@ -254,15 +265,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void DecodeProgressiveJpeg_Orig<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
if (SkipTest(provider))
if (TestEnvironment.RunsOnCI && !TestEnvironment.Is64BitProcess)
{
// skipping to avoid OutOfMemoryException on CI
return;
}
// For 32 bit test enviroments:
provider.Configuration.MemoryManager = ArrayPoolMemoryManager.CreateWithModeratePooling();
using (Image<TPixel> image = provider.GetImage(OrigJpegDecoder))
using (Image<TPixel> image = provider.GetImage(GolangJpegDecoder))
{
image.DebugSave(provider);
@ -281,7 +293,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void DecodeProgressiveJpeg_PdfJs<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
if (TestEnvironment.RunsOnCI && !TestEnvironment.Is64BitProcess)
if (SkipTest(provider))
{
// skipping to avoid OutOfMemoryException on CI
return;
@ -329,7 +341,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.Output.WriteLine(provider.SourceFileOrDescription);
provider.Utility.TestName = testName;
using (Image<TPixel> image = provider.GetImage(OrigJpegDecoder))
using (Image<TPixel> image = provider.GetImage(GolangJpegDecoder))
{
string d = this.GetDifferenceInPercentageString(image, provider);
@ -365,7 +377,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[WithSolidFilledImages(16, 16, 255, 0, 0, PixelTypes.Rgba32, JpegSubsample.Ratio444, 75)]
[WithSolidFilledImages(16, 16, 255, 0, 0, PixelTypes.Rgba32, JpegSubsample.Ratio444, 100)]
[WithSolidFilledImages(8, 8, 255, 0, 0, PixelTypes.Rgba32, JpegSubsample.Ratio444, 100)]
public void DecodeGenerated_Orig<TPixel>(
public void DecodeGenerated<TPixel>(
TestImageProvider<TPixel> provider,
JpegSubsample subsample,
int quality)
@ -383,30 +395,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
}
var mirror = Image.Load<TPixel>(data, OrigJpegDecoder);
var mirror = Image.Load<TPixel>(data, GolangJpegDecoder);
mirror.DebugSave(provider, $"_{subsample}_Q{quality}");
}
[Fact]
public void Decoder_Reads_Correct_Resolution_From_Jfif()
{
using (Image<Rgba32> image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage())
{
Assert.Equal(300, image.MetaData.HorizontalResolution);
Assert.Equal(300, image.MetaData.VerticalResolution);
}
}
[Fact]
public void Decoder_Reads_Correct_Resolution_From_Exif()
{
using (Image<Rgba32> image = TestFile.Create(TestImages.Jpeg.Baseline.Jpeg420Exif).CreateImage())
{
Assert.Equal(72, image.MetaData.HorizontalResolution);
Assert.Equal(72, image.MetaData.VerticalResolution);
}
}
// DEBUG ONLY!
// The PDF.js output should be saved by "tests\ImageSharp.Tests\Formats\Jpg\pdfjs\jpeg-converter.htm"
// into "\tests\Images\ActualOutput\JpegDecoderTests\"

2
tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs

@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
//[MemberData(nameof(DecodeJpegData))]
public void DecodeJpeg_Original(string fileName)
{
this.DecodeJpegBenchmarkImpl(fileName, new OrigJpegDecoder());
this.DecodeJpegBenchmarkImpl(fileName, new GolangJpegDecoder());
}
// [Theory] // Benchmark, enable manually

10
tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs

@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public static readonly string[] AllTestJpegs = BaselineTestJpegs.Concat(ProgressiveTestJpegs).ToArray();
[Theory]
[Theory(Skip = "Debug only, enable manually!")]
[WithFileCollection(nameof(AllTestJpegs), PixelTypes.Rgba32)]
public void PdfJsDecoder_ParseStream_SaveSpectralResult<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
}
[Theory]
[Theory(Skip = "Debug only, enable manually!")]
[WithFileCollection(nameof(AllTestJpegs), PixelTypes.Rgba32)]
public void OriginalDecoder_ParseStream_SaveSpectralResult<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
LibJpegTools.SpectralData imageSharpData)
where TPixel : struct, IPixel<TPixel>
{
var libJpegData = LibJpegTools.ExtractSpectralData(provider.SourceFileOrDescription);
LibJpegTools.SpectralData libJpegData = LibJpegTools.ExtractSpectralData(provider.SourceFileOrDescription);
bool equality = libJpegData.Equals(imageSharpData);
this.Output.WriteLine("Spectral data equality: " + equality);
@ -145,7 +145,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Theory]
[WithFileCollection(nameof(AllTestJpegs), PixelTypes.Rgba32)]
public void VerifySpectralResults_OriginalDecoder<TPixel>(TestImageProvider<TPixel> provider)
public void VerifySpectralCorrectness_Golang<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
if (!TestEnvironment.IsWindows)
@ -153,7 +153,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
return;
}
var decoder = new GolangJpegDecoderCore(Configuration.Default, new JpegDecoder());
var decoder = new GolangJpegDecoderCore(Configuration.Default, new GolangJpegDecoder());
byte[] sourceBytes = TestFile.Create(provider.SourceFileOrDescription).Bytes;

Loading…
Cancel
Save