Browse Source

code for verifying original PDF.js output

af/merge-core
Anton Firszov 9 years ago
parent
commit
8d726512c6
  1. 45
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  2. 0
      tests/ImageSharp.Tests/Formats/Jpg/pdfjs/baseline/ycck - Copy.jpg
  3. 89
      tests/ImageSharp.Tests/Formats/Jpg/pdfjs/jpeg-converter.htm
  4. 0
      tests/ImageSharp.Tests/Formats/Jpg/pdfjs/jpeg.htm
  5. 0
      tests/ImageSharp.Tests/Formats/Jpg/pdfjs/jpg.js
  6. 6
      tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageSimilarityReport.cs
  7. 5
      tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs
  8. 68
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs
  9. 13
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs
  10. 20
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
  11. 61
      tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceCodecTests.cs

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

@ -18,6 +18,7 @@ namespace SixLabors.ImageSharp.Tests
using SixLabors.ImageSharp.Formats.Jpeg.GolangPort;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs;
using Xunit;
using Xunit.Abstractions;
@ -45,6 +46,11 @@ namespace SixLabors.ImageSharp.Tests
private static readonly ImageComparer VeryTolerantJpegComparer =
ImageComparer.Tolerant(0.005f, pixelThresholdHammingDistance: 4);
// BUG: PDF.js output is wrong on spectral level!
private static readonly ImageComparer PdfJsProgressiveComparer =
ImageComparer.Tolerant(0.015f, pixelThresholdHammingDistance: 4);
public JpegDecoderTests(ITestOutputHelper output)
{
this.Output = output;
@ -108,7 +114,7 @@ namespace SixLabors.ImageSharp.Tests
{
image.DebugSave(provider);
image.CompareToReferenceOutput(provider, VeryTolerantJpegComparer, appendPixelTypeToFileName: false);
image.CompareToReferenceOutput(provider, PdfJsProgressiveComparer, appendPixelTypeToFileName: false);
}
}
@ -130,11 +136,12 @@ namespace SixLabors.ImageSharp.Tests
where TPixel : struct, IPixel<TPixel>
{
var reportingComparer = ImageComparer.Tolerant(0, 0);
ImageSimilarityReport report = image.GetReferenceOutputSimilarityReports(
provider,
reportingComparer,
appendPixelTypeToFileName: false).SingleOrDefault();
appendPixelTypeToFileName: false
).SingleOrDefault();
if (report != null && report.TotalNormalizedDifference.HasValue)
{
@ -258,5 +265,37 @@ namespace SixLabors.ImageSharp.Tests
Assert.Null(image.MetaData.ExifProfile);
}
}
// DEBUG ONLY!
// The PDF.js output should be saved by "tests\ImageSharp.Tests\Formats\Jpg\pdfjs\jpeg-converter.htm"
// into "\tests\Images\ActualOutput\JpegDecoderTests\"
[Theory]
[WithFile(TestImages.Jpeg.Progressive.Progress, PixelTypes.Rgba32, "PdfJsOriginal_progress.png")]
public void ValidateProgressivePdfJsOutput<TPixel>(TestImageProvider<TPixel> provider,
string pdfJsOriginalResultImage)
where TPixel : struct, IPixel<TPixel>
{
// tests\ImageSharp.Tests\Formats\Jpg\pdfjs\jpeg-converter.htm
string pdfJsOriginalResultPath = Path.Combine(
provider.Utility.GetTestOutputDir(),
pdfJsOriginalResultImage);
byte[] sourceBytes = TestFile.Create(TestImages.Jpeg.Progressive.Progress).Bytes;
provider.Utility.TestName = nameof(this.DecodeProgressiveJpeg);
var comparer = ImageComparer.Tolerant(0, 0);
using (Image<TPixel> expectedImage = provider.GetReferenceOutputImage<TPixel>(appendPixelTypeToFileName: false))
using (var pdfJsOriginalResult = Image.Load(pdfJsOriginalResultPath))
using (var pdfJsPortResult = Image.Load(sourceBytes, PdfJsJpegDecoder))
{
ImageSimilarityReport originalReport = comparer.CompareImagesOrFrames(expectedImage, pdfJsOriginalResult);
ImageSimilarityReport portReport = comparer.CompareImagesOrFrames(expectedImage, pdfJsPortResult);
this.Output.WriteLine($"Difference for PDF.js ORIGINAL: {originalReport.DifferencePercentage}");
this.Output.WriteLine($"Difference for PORT: {portReport.DifferencePercentage}");
}
}
}
}

0
tests/ImageSharp.Tests/TestImages/Formats/Jpg/baseline/ycck - Copy.jpg → tests/ImageSharp.Tests/Formats/Jpg/pdfjs/baseline/ycck - Copy.jpg

89
tests/ImageSharp.Tests/Formats/Jpg/pdfjs/jpeg-converter.htm

@ -0,0 +1,89 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<input type="file" id="files" />
<canvas id="canvas"></canvas>
<div id="output"></div>
<script src="jpg.js"></script>
<script>
(function (document) {
var input = document.getElementById("files"),
output = document.getElementById('output'),
canvas = document.getElementById("canvas"),
ctx = canvas.getContext('2d'),
fileData; // We need fileData to be visible to getBuffer.
// Eventhandler for file input.
function openfile(evt) {
var files = input.files;
// Pass the file to the blob, not the input[0].
fileData = new Blob([files[0]]);
// Pass getBuffer to promise.
var promise = new Promise(getBuffer);
// Wait for promise to be resolved, or log error.
promise.then(function (data) {
// Here you can pass the bytes to another function.
// output.innerHTML = data.toString();
// console.log(data);
var jpeg = new JpegImage();
jpeg.parse(data);
console.log(jpeg.width);
console.log(jpeg.height);
canvas.width = jpeg.width;
canvas.height = jpeg.height;
var d = jpeg.getData(jpeg.width, jpeg.height, true);
console.log(d.length);
var rgba = new Uint8Array(jpeg.width * jpeg.height * 4);
for(i = 0, j = 0; i < d.length; i += 3, j +=4){
rgba[j] = d[i];
rgba[j + 1] = d[i + 1];
rgba[j + 2] = d[i + 2];
rgba[j + 3] = 255;
}
var imageData = new ImageData(Uint8ClampedArray.from(rgba), jpeg.width, jpeg.height);
ctx.putImageData(imageData, 0 , 0);
// output.innerHTML = d.toString();
//console.log(new Date());
//console.log(d);
}).catch(function (err) {
console.log('Error: ', err);
});
}
/*
Create a function which will be passed to the promise
and resolve it when FileReader has finished loading the file.
*/
function getBuffer(resolve) {
var reader = new FileReader();
reader.readAsArrayBuffer(fileData);
reader.onload = function () {
var arrayBuffer = reader.result
var bytes = new Uint8Array(arrayBuffer);
resolve(bytes);
}
}
// Eventlistener for file input.
input.addEventListener('change', openfile, false);
}(document));
</script>
</body>
</html>

0
tests/ImageSharp.Tests/TestImages/Formats/Jpg/jpeg.htm → tests/ImageSharp.Tests/Formats/Jpg/pdfjs/jpeg.htm

0
tests/ImageSharp.Tests/TestImages/Formats/Jpg/jpg.js → tests/ImageSharp.Tests/Formats/Jpg/pdfjs/jpg.js

6
tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageSimilarityReport.cs

@ -24,6 +24,10 @@
public float? TotalNormalizedDifference { get; }
public string DifferencePercentage => this.TotalNormalizedDifference.HasValue
? $"{this.TotalNormalizedDifference.Value * 100:0.0000}%"
: "?";
public IImageBase ExpectedImage { get; }
public IImageBase ActualImage { get; }
@ -42,7 +46,7 @@
var sb = new StringBuilder();
if (this.TotalNormalizedDifference.HasValue)
{
sb.AppendLine($"Total difference: {this.TotalNormalizedDifference.Value * 100:0.0000}%");
sb.AppendLine($"Total difference: {this.DifferencePercentage}");
}
int max = Math.Min(5, this.Differences.Length);

5
tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs

@ -131,7 +131,7 @@ namespace SixLabors.ImageSharp.Tests
/// <param name="image">The image instance</param>
/// <param name="extension">The requested extension</param>
/// <param name="encoder">Optional encoder</param>
public void SaveTestOutputFile<TPixel>(
public string SaveTestOutputFile<TPixel>(
Image<TPixel> image,
string extension = null,
IImageEncoder encoder = null,
@ -146,6 +146,7 @@ namespace SixLabors.ImageSharp.Tests
{
image.Save(stream, encoder);
}
return path;
}
internal string GetReferenceOutputFileName(
@ -190,7 +191,7 @@ namespace SixLabors.ImageSharp.Tests
// return encoder;
//}
private string GetTestOutputDir()
internal string GetTestOutputDir()
{
string testGroupName = Path.GetFileNameWithoutExtension(this.TestGroupName);
return this.CreateOutputDirectory(testGroupName);

68
tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs

@ -52,7 +52,29 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
}
}
internal static unsafe Image<TPixel> FromSystemDrawingBitmap<TPixel>(System.Drawing.Bitmap bmp)
private static void FromRgb24<TPixel>(Span<Rgb24> source, Span<TPixel> dest)
where TPixel : struct, IPixel<TPixel>
{
int length = source.Length;
Guard.MustBeSizedAtLeast(dest, length, nameof(dest));
using (var rgbaBuffer = new Buffer<Rgb24>(length))
{
PixelOperations<Rgb24>.Instance.ToRgb24(source, rgbaBuffer, length);
for (int i = 0; i < length; i++)
{
ref Rgb24 s = ref rgbaBuffer[i];
ref TPixel d = ref dest[i];
var rgba = default(Rgba32);
s.ToRgba32(ref rgba);
d.PackFromRgba32(rgba);
}
}
}
internal static unsafe Image<TPixel> FromFromArgb32SystemDrawingBitmap<TPixel>(System.Drawing.Bitmap bmp)
where TPixel : struct, IPixel<TPixel>
{
int w = bmp.Width;
@ -62,7 +84,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
if (bmp.PixelFormat != PixelFormat.Format32bppArgb)
{
throw new ArgumentException("FromSystemDrawingBitmap(): pixel format not supported", nameof(bmp));
throw new ArgumentException($"FromFromArgb32SystemDrawingBitmap(): pixel format should be Argb32!", nameof(bmp));
}
BitmapData data = bmp.LockBits(fullRect, ImageLockMode.ReadWrite, bmp.PixelFormat);
@ -91,6 +113,48 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
return image;
}
/// <summary>
/// TODO: Doesn not work yet!
/// </summary>
internal static unsafe Image<TPixel> FromFromRgb24SystemDrawingBitmap<TPixel>(System.Drawing.Bitmap bmp)
where TPixel : struct, IPixel<TPixel>
{
int w = bmp.Width;
int h = bmp.Height;
var fullRect = new System.Drawing.Rectangle(0, 0, w, h);
if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
{
throw new ArgumentException($"FromFromArgb32SystemDrawingBitmap(): pixel format should be Rgb24!", nameof(bmp));
}
BitmapData data = bmp.LockBits(fullRect, ImageLockMode.ReadWrite, bmp.PixelFormat);
byte* sourcePtrBase = (byte*)data.Scan0;
long sourceRowByteCount = data.Stride;
long destRowByteCount = w * sizeof(Rgb24);
var image = new Image<TPixel>(w, h);
using (var workBuffer = new Buffer<Rgb24>(w))
{
var destPtr = (Rgb24*)workBuffer.Pin();
for (int y = 0; y < h; y++)
{
Span<TPixel> row = image.GetRowSpan(y);
byte* sourcePtr = sourcePtrBase + data.Stride * y;
Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount);
FromRgb24(workBuffer, row);
}
}
return image;
}
internal static unsafe System.Drawing.Bitmap ToSystemDrawingBitmap<TPixel>(Image<TPixel> image)
where TPixel : struct, IPixel<TPixel>
{

13
tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs

@ -9,6 +9,8 @@ using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using PixelFormat = System.Drawing.Imaging.PixelFormat;
namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
{
public class SystemDrawingReferenceDecoder : IImageDecoder
@ -20,9 +22,14 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
{
using (var sourceBitmap = new System.Drawing.Bitmap(stream))
{
if (sourceBitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb)
if (sourceBitmap.PixelFormat == PixelFormat.Format32bppArgb)
{
return SystemDrawingBridge.FromFromArgb32SystemDrawingBitmap<TPixel>(sourceBitmap);
}
if (sourceBitmap.PixelFormat == PixelFormat.Format24bppRgb)
{
return SystemDrawingBridge.FromSystemDrawingBitmap<TPixel>(sourceBitmap);
}
using (var convertedBitmap = new System.Drawing.Bitmap(
@ -39,7 +46,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
g.DrawImage(sourceBitmap, 0, 0, sourceBitmap.Width, sourceBitmap.Height);
}
return SystemDrawingBridge.FromSystemDrawingBitmap<TPixel>(convertedBitmap);
return SystemDrawingBridge.FromFromArgb32SystemDrawingBitmap<TPixel>(convertedBitmap);
}
}
}

20
tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

@ -90,6 +90,7 @@ namespace SixLabors.ImageSharp.Tests
/// <param name="extension">The extension</param>
/// <param name="grayscale">A boolean indicating whether we should debug save + compare against a grayscale image, smaller in size.</param>
/// <param name="appendPixelTypeToFileName">A boolean indicating whether to append the pixel type to the output file name.</param>
/// <param name="decoder">Custom decoder</param>
/// <returns></returns>
public static Image<TPixel> CompareToReferenceOutput<TPixel>(
this Image<TPixel> image,
@ -98,14 +99,16 @@ namespace SixLabors.ImageSharp.Tests
object testOutputDetails = null,
string extension = "png",
bool grayscale = false,
bool appendPixelTypeToFileName = true)
bool appendPixelTypeToFileName = true,
IImageDecoder decoder = null)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> referenceImage = GetReferenceOutputImage<TPixel>(
provider,
testOutputDetails,
extension,
appendPixelTypeToFileName))
appendPixelTypeToFileName,
decoder))
{
comparer.VerifySimilarity(referenceImage, image);
}
@ -116,7 +119,8 @@ namespace SixLabors.ImageSharp.Tests
public static Image<TPixel> GetReferenceOutputImage<TPixel>(this ITestImageProvider provider,
object testOutputDetails = null,
string extension = "png",
bool appendPixelTypeToFileName = true)
bool appendPixelTypeToFileName = true,
IImageDecoder decoder = null)
where TPixel : struct, IPixel<TPixel>
{
string referenceOutputFile = provider.Utility.GetReferenceOutputFileName(extension, testOutputDetails, appendPixelTypeToFileName);
@ -126,7 +130,9 @@ namespace SixLabors.ImageSharp.Tests
throw new Exception("Reference output file missing: " + referenceOutputFile);
}
return Image.Load<TPixel>(referenceOutputFile);
decoder = decoder ?? TestEnvironment.GetReferenceDecoder(referenceOutputFile);
return Image.Load<TPixel>(referenceOutputFile, decoder);
}
public static IEnumerable<ImageSimilarityReport> GetReferenceOutputSimilarityReports<TPixel>(
@ -135,13 +141,15 @@ namespace SixLabors.ImageSharp.Tests
ImageComparer comparer,
object testOutputDetails = null,
string extension = "png",
bool appendPixelTypeToFileName = true)
bool appendPixelTypeToFileName = true,
IImageDecoder decoder = null)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> referenceImage = provider.GetReferenceOutputImage<TPixel>(
testOutputDetails,
extension,
appendPixelTypeToFileName))
appendPixelTypeToFileName,
decoder))
{
return comparer.CompareImages(referenceImage, image);
}

61
tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceCodecTests.cs

@ -1,6 +1,8 @@
namespace SixLabors.ImageSharp.Tests
{
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs;
using Xunit;
@ -32,20 +34,75 @@ namespace SixLabors.ImageSharp.Tests
[Theory]
[WithBlankImages(1, 1, PixelTypes.Rgba32 | PixelTypes.Bgra32)]
public void FromSystemDrawingBitmap<TPixel>(TestImageProvider<TPixel> dummyProvider)
public void FromFromArgb32SystemDrawingBitmap<TPixel>(TestImageProvider<TPixel> dummyProvider)
where TPixel : struct, IPixel<TPixel>
{
string path = TestFile.GetInputFileFullPath(TestImages.Png.Splash);
using (var sdBitmap = new System.Drawing.Bitmap(path))
{
using (Image<TPixel> image = SystemDrawingBridge.FromSystemDrawingBitmap<TPixel>(sdBitmap))
using (Image<TPixel> image = SystemDrawingBridge.FromFromArgb32SystemDrawingBitmap<TPixel>(sdBitmap))
{
image.DebugSave(dummyProvider);
}
}
}
private static string SavePng<TPixel>(TestImageProvider<TPixel> provider, PngColorType pngColorType)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> sourceImage = provider.GetImage())
{
if (pngColorType != PngColorType.RgbWithAlpha)
{
sourceImage.Mutate(c => c.Alpha(1));
}
var encoder = new PngEncoder() { PngColorType = pngColorType };
return provider.Utility.SaveTestOutputFile(sourceImage, "png", encoder);
}
}
[Theory]
[WithTestPatternImages(100, 100, PixelTypes.Rgba32)]
public void FromFromArgb32SystemDrawingBitmap2<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
string path = SavePng(provider, PngColorType.RgbWithAlpha);
using (var sdBitmap = new System.Drawing.Bitmap(path))
{
using (Image<TPixel> original = provider.GetImage())
using (Image<TPixel> resaved = SystemDrawingBridge.FromFromArgb32SystemDrawingBitmap<TPixel>(sdBitmap))
{
ImageComparer comparer = ImageComparer.Exact;
comparer.VerifySimilarity(original, resaved);
}
}
}
[Theory(Skip = "Doesen't work yet :(")]
[WithTestPatternImages(100, 100, PixelTypes.Rgba32)]
public void FromFromRgb24SystemDrawingBitmap2<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
string path = SavePng(provider, PngColorType.Rgb);
using (Image<TPixel> original = provider.GetImage())
{
original.Mutate(c => c.Alpha(1));
using (var sdBitmap = new System.Drawing.Bitmap(path))
{
using (Image<TPixel> resaved = SystemDrawingBridge.FromFromRgb24SystemDrawingBitmap<TPixel>(sdBitmap))
{
resaved.Mutate(c => c.Alpha(1));
ImageComparer comparer = ImageComparer.Exact;
comparer.VerifySimilarity(original, resaved);
}
}
}
}
[Theory]
[WithBlankImages(1, 1, PixelTypes.Rgba32 | PixelTypes.Bgra32)]
public void OpenWithReferenceDecoder<TPixel>(TestImageProvider<TPixel> dummyProvider)

Loading…
Cancel
Save