Commit 34257c7d authored by mrbean-bremen's avatar mrbean-bremen Committed by mrbean-bremen
Browse files

Added image comparison unit tests for most of the passing tests

- first try for a matching comparison test
- compares down-scaled gray-scale images pixel-wise
- see #378
parent e4aae797
BaseName
color-prof-01-f
color-prop-01-b
color-prop-02-f
color-prop-03-t
color-prop-04-t
color-prop-05-t
coords-coord-01-t
coords-coord-02-t
coords-trans-01-b
coords-trans-02-t
coords-trans-03-t
coords-trans-04-t
coords-trans-05-t
coords-trans-06-t
coords-trans-07-t
coords-trans-08-t
coords-trans-09-t
coords-trans-10-f
coords-trans-11-f
coords-trans-12-f
coords-trans-13-f
coords-trans-14-f
coords-transformattr-01-f
coords-transformattr-02-f
coords-transformattr-03-f
coords-transformattr-04-f
coords-transformattr-05-f
coords-units-01-b
coords-units-02-b
coords-units-03-b
coords-viewattr-01-b
coords-viewattr-02-b
coords-viewattr-03-b
coords-viewattr-04-f
extend-namespace-01-f
filters-background-01-f
filters-blend-01-b
filters-color-01-b
filters-color-02-b
filters-composite-02-b
filters-composite-03-f
filters-composite-04-f
filters-composite-05-f
filters-comptran-01-b
filters-conv-01-f
filters-conv-02-f
filters-conv-03-f
filters-conv-04-f
filters-conv-05-f
filters-diffuse-01-f
filters-displace-01-f
filters-displace-02-f
filters-example-01-b
filters-felem-01-b
filters-felem-02-f
filters-gauss-01-b
filters-gauss-02-f
filters-gauss-03-f
filters-image-01-b
filters-image-02-b
filters-image-03-f
filters-image-04-f
filters-image-05-f
filters-light-01-f
filters-light-02-f
filters-light-03-f
filters-light-04-f
filters-light-05-f
filters-morph-01-f
filters-offset-01-b
filters-offset-02-b
filters-overview-01-b
filters-overview-02-b
filters-overview-03-b
filters-specular-01-f
filters-tile-01-b
filters-turb-01-f
filters-turb-02-f
fonts-desc-01-t
fonts-desc-02-t
fonts-desc-03-t
fonts-desc-04-t
fonts-desc-05-t
fonts-elem-01-t
fonts-elem-02-t
fonts-elem-03-b
fonts-elem-04-b
fonts-elem-05-t
fonts-elem-06-t
fonts-elem-07-b
fonts-glyph-02-t
fonts-glyph-03-t
fonts-glyph-04-t
fonts-kern-01-t
fonts-overview-201-t
imp-path-01-f
masking-filter-01-f
masking-intro-01-f
masking-mask-01-b
masking-mask-02-f
masking-opacity-01-b
masking-path-01-b
masking-path-02-b
masking-path-03-b
masking-path-04-b
masking-path-05-f
masking-path-06-b
masking-path-07-b
masking-path-08-b
masking-path-09-b
masking-path-10-b
masking-path-11-b
masking-path-12-f
masking-path-13-f
masking-path-14-f
metadata-example-01-t
painting-control-01-f
painting-control-02-f
painting-control-03-f
painting-control-04-f
painting-control-05-f
painting-control-06-f
painting-fill-01-t
painting-fill-02-t
painting-fill-03-t
painting-fill-04-t
painting-fill-05-b
painting-marker-01-f
painting-marker-02-f
painting-marker-03-f
painting-marker-04-f
painting-marker-05-f
painting-marker-06-f
painting-marker-07-f
painting-marker-properties-01-f
painting-render-01-b
painting-render-02-b
painting-stroke-01-t
painting-stroke-02-t
painting-stroke-03-t
painting-stroke-04-t
painting-stroke-05-t
painting-stroke-06-t
painting-stroke-07-t
painting-stroke-08-t
painting-stroke-09-t
painting-stroke-10-t
paths-data-01-t
paths-data-02-t
paths-data-03-f
paths-data-04-t
paths-data-05-t
paths-data-06-t
paths-data-07-t
paths-data-08-t
paths-data-09-t
paths-data-10-t
paths-data-12-t
paths-data-13-t
paths-data-14-t
paths-data-15-t
paths-data-16-t
paths-data-17-f
paths-data-18-f
paths-data-19-f
paths-data-20-f
pservers-grad-01-b
pservers-grad-02-b
pservers-grad-03-b
pservers-grad-04-b
pservers-grad-05-b
pservers-grad-06-b
pservers-grad-07-b
pservers-grad-08-b
pservers-grad-09-b
pservers-grad-10-b
pservers-grad-11-b
pservers-grad-12-b
pservers-grad-13-b
pservers-grad-14-b
pservers-grad-15-b
pservers-grad-16-b
pservers-grad-17-b
pservers-grad-18-b
pservers-grad-20-b
pservers-grad-21-b
pservers-grad-22-b
pservers-grad-23-f
pservers-grad-24-f
pservers-grad-stops-01-f
pservers-pattern-01-b
pservers-pattern-02-f
pservers-pattern-03-f
pservers-pattern-04-f
pservers-pattern-05-f
pservers-pattern-06-f
pservers-pattern-07-f
pservers-pattern-08-f
pservers-pattern-09-f
render-elems-01-t
render-elems-02-t
render-elems-03-t
render-elems-06-t
render-elems-07-t
render-elems-08-t
render-groups-01-b
render-groups-03-t
shapes-circle-01-t
shapes-circle-02-t
shapes-ellipse-01-t
shapes-ellipse-02-t
shapes-ellipse-03-f
shapes-grammar-01-f
shapes-intro-01-t
shapes-intro-02-f
shapes-line-01-t
shapes-line-02-f
shapes-polygon-01-t
shapes-polygon-02-t
shapes-polygon-03-t
shapes-polyline-01-t
shapes-polyline-02-t
shapes-rect-01-t
shapes-rect-02-t
shapes-rect-03-t
shapes-rect-04-f
shapes-rect-05-f
shapes-rect-06-f
shapes-rect-07-f
struct-cond-01-t
struct-cond-02-t
struct-cond-03-t
struct-cond-overview-02-f
struct-cond-overview-03-f
struct-cond-overview-04-f
struct-cond-overview-05-f
struct-defs-01-t
struct-frag-01-t
struct-frag-02-t
struct-frag-03-t
struct-frag-04-t
struct-frag-05-t
struct-frag-06-t
struct-group-01-t
struct-group-02-b
struct-group-03-t
struct-image-01-t
struct-image-02-b
struct-image-03-t
struct-image-04-t
struct-image-05-b
struct-image-06-t
struct-image-07-t
struct-image-08-t
struct-image-09-t
struct-image-10-t
struct-image-11-b
struct-image-12-b
struct-image-13-f
struct-image-14-f
struct-image-15-f
struct-image-17-b
struct-image-18-f
struct-image-19-f
struct-svg-01-f
struct-svg-02-f
struct-svg-03-f
struct-symbol-01-b
styling-class-01-f
styling-css-01-b
styling-css-02-b
styling-css-03-b
styling-css-04-f
styling-css-05-b
styling-css-06-b
styling-css-07-f
styling-css-08-f
styling-css-09-f
styling-css-10-f
styling-elem-01-b
styling-inherit-01-b
styling-pres-01-t
styling-pres-02-f
styling-pres-03-f
styling-pres-04-f
styling-pres-05-f
svgdom-over-01-f
text-align-01-b
text-align-02-b
text-align-03-b
text-align-04-b
text-align-05-b
text-align-06-b
text-align-07-t
text-align-08-b
text-altglyph-01-b
text-altglyph-02-b
text-altglyph-03-b
text-bidi-01-t
text-deco-01-b
text-fonts-01-t
text-fonts-02-t
text-fonts-03-t
text-fonts-04-t
text-fonts-05-f
text-fonts-202-t
text-fonts-203-t
text-fonts-204-t
text-intro-01-t
text-intro-02-b
text-intro-03-b
text-intro-04-t
text-intro-05-t
text-intro-06-t
text-intro-07-t
text-intro-09-b
text-intro-10-f
text-intro-11-t
text-intro-12-t
text-path-01-b
text-path-02-b
text-spacing-01-b
text-text-01-b
text-text-03-b
text-text-04-t
text-text-05-t
text-text-06-t
text-text-07-t
text-text-08-b
text-text-09-t
text-text-10-t
text-text-11-t
text-text-12-t
text-tref-01-b
text-tref-02-b
text-tref-03-b
text-tselect-01-b
text-tselect-02-f
text-tselect-03-f
text-tspan-01-b
text-tspan-02-b
text-ws-01-t
text-ws-02-t
text-ws-03-t
types-basic-01-f
types-basic-02-f
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
namespace Svg.UnitTests
{
/// <summary>
/// </summary>
[TestClass]
public class ImageComparisonTest
{
public TestContext TestContext { get; set; }
/// <summary>
/// Compares SVG images against reference PNG images from the W3C SVG 1.1 test suite.
/// This tests 158 out of 179 passing tests - the rest will not pass
/// the test for several reasons.
/// Note that with the current test there are still a lot of false positives,
/// so this is not a definitive test for image equality yet.
/// </summary>
[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV",
@"|DataDirectory|\..\..\PassingTests.csv",
"PassingTests#csv", DataAccessMethod.Sequential)]
public void CompareSvgImageWithReference()
{
var basePath = TestContext.TestRunDirectory;
while (!basePath.ToLower().EndsWith("svg"))
{
basePath = Path.GetDirectoryName(basePath);
}
basePath = Path.Combine(basePath, "Tests", "W3CTestSuite");
var svgBasePath = Path.Combine(basePath, "svg");
var baseName = TestContext.DataRow[0] as string;
var svgPath = Path.Combine(basePath, "svg", baseName + ".svg");
var pngPath = Path.Combine(basePath, "png", baseName + ".png");
var pngImage = Image.FromFile(pngPath);
var svgImage = LoadSvgImage(baseName, svgPath);
Assert.AreNotEqual(null, pngImage, "Failed to load " + pngPath);
Assert.AreNotEqual(null, svgImage, "Failed to load " + svgPath);
var difference = svgImage.PercentageDifference(pngImage);
Assert.IsTrue(difference < 0.05,
baseName + ": Difference is " + (difference * 100.0).ToString() + "%");
}
/// <summary>
/// Enable this test to output the calculate percentage difference
/// of all considered W3C tests.
/// Can be used to enhance the difference calculation.
/// </summary>
// [TestClass]
public void RecordDiffForAllSvgImagesWithReference()
{
var basePath = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(
TestContext.TestRunDirectory)));
basePath = Path.Combine(basePath, "Tests", "W3CTestSuite");
var svgBasePath = Path.Combine(basePath, "svg");
string[] lines = File.ReadAllLines(@"..\..\..\..\Tests\Svg.UnitTests\all.csv");
foreach (var baseName in lines)
{
var svgPath = Path.Combine(basePath, "svg", baseName + ".svg");
var pngPath = Path.Combine(basePath, "png", baseName + ".png");
if (File.Exists(pngPath) && File.Exists(svgPath))
{
var pngImage = Image.FromFile(pngPath);
var svgImage = LoadSvgImage(baseName, svgPath);
if (pngImage != null && svgImage != null)
{
var difference = svgImage.PercentageDifference(pngImage);
Console.WriteLine(baseName + " " + (difference * 100.0).ToString());
}
}
}
}
/// <summary>
/// Load the SVG image the same way as in the SVGW3CTestRunner.
/// </summary>
private static Image LoadSvgImage(string fileName, string svgPath)
{
var doc = new SvgDocument();
Image svgImage;
try
{
doc = SvgDocument.Open(svgPath);
var img = new Bitmap(480, 360);
doc.Draw(img);
svgImage = img;
}
catch (Exception)
{
svgImage = null;
}
return svgImage;
}
}
/// <summary>
/// Taken from https://web.archive.org/web/20130111215043/http://www.switchonthecode.com/tutorials/csharp-tutorial-convert-a-color-image-to-grayscale
/// and slightly modified.
/// Image width and height, default threshold and handling of alpha values have been adapted.
/// </summary>
public static class ExtensionMethods
{
private static int ImageWidth = 64;
private static int ImageHeight = 64;
public static float PercentageDifference(this Image img1, Image img2, byte threshold = 10)
{
byte[,] differences = img1.GetDifferences(img2);
int diffPixels = 0;
foreach (byte b in differences)
{
if (b > threshold) { diffPixels++; }
}
return diffPixels / (float)(ImageWidth * ImageHeight);
}
public static Image Resize(this Image originalImage, int newWidth, int newHeight)
{
Image smallVersion = new Bitmap(newWidth, newHeight);
using (Graphics g = Graphics.FromImage(smallVersion))
{
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(originalImage, 0, 0, newWidth, newHeight);
}
return smallVersion;
}
public static byte[,] GetGrayScaleValues(this Image img)
{
using (Bitmap thisOne = (Bitmap)img.Resize(ImageWidth, ImageHeight).GetGrayScaleVersion())
{
byte[,] grayScale = new byte[ImageWidth, ImageHeight];
for (int y = 0; y < ImageHeight; y++)
{
for (int x = 0; x < ImageWidth; x++)
{
var pixel = thisOne.GetPixel(x, y);
var alpha = thisOne.GetPixel(x, y).A;
var gray = thisOne.GetPixel(x, y).R;
grayScale[x, y] = (byte)Math.Abs(gray * alpha / 255);
}
}
return grayScale;
}
}
//the colormatrix needed to grayscale an image
static readonly ColorMatrix ColorMatrix = new ColorMatrix(new float[][]
{
new float[] {.3f, .3f, .3f, 0, 0},
new float[] {.59f, .59f, .59f, 0, 0},
new float[] {.11f, .11f, .11f, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
});
public static Image GetGrayScaleVersion(this Image original)
{
//create a blank bitmap the same size as original
//https://web.archive.org/web/20130111215043/http://www.switchonthecode.com/tutorials/csharp-tutorial-convert-a-color-image-to-grayscale
Bitmap newBitmap = new Bitmap(original.Width, original.Height);
//get a graphics object from the new image
using (Graphics g = Graphics.FromImage(newBitmap))
{
//create some image attributes
ImageAttributes attributes = new ImageAttributes();
//set the color matrix attribute
attributes.SetColorMatrix(ColorMatrix);
//draw the original image on the new image
//using the grayscale color matrix
g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
}
return newBitmap;
}
public static byte[,] GetDifferences(this Image img1, Image img2)
{
Bitmap thisOne = (Bitmap)img1.Resize(ImageWidth, ImageHeight).GetGrayScaleVersion();
Bitmap theOtherOne = (Bitmap)img2.Resize(ImageWidth, ImageHeight).GetGrayScaleVersion();
byte[,] differences = new byte[ImageWidth, ImageHeight];
byte[,] firstGray = thisOne.GetGrayScaleValues();
byte[,] secondGray = theOtherOne.GetGrayScaleValues();
for (int y = 0; y < ImageHeight; y++)
{
for (int x = 0; x < ImageWidth; x++)
{
differences[x, y] = (byte)Math.Abs(firstGray[x, y] - secondGray[x, y]);
}
}
thisOne.Dispose();
theOtherOne.Dispose();
return differences;
}
}
}
......@@ -55,7 +55,7 @@ namespace Svg.UnitTests
throw ex.InnerException;
}
}
Assert.Inconclusive("This test was expected to throw and SVGMemoryException, however this is higly dependent on the file and machine under test. This is not a fail reason.");
Assert.Inconclusive("This test was expected to throw an SVGMemoryException, however this is higly dependent on the file and machine under test. This is not a fail reason.");
}
}
}
BaseName
color-prop-01-b
color-prop-02-f
color-prop-03-t
color-prop-05-t
coords-coord-01-t
coords-coord-02-t
coords-trans-01-b
coords-trans-02-t
coords-trans-03-t
coords-trans-04-t
coords-trans-05-t
coords-trans-06-t
coords-trans-07-t
coords-trans-08-t
coords-trans-09-t
coords-trans-10-f
coords-trans-11-f
coords-trans-12-f
coords-trans-13-f
coords-trans-14-f
coords-transformattr-01-f
coords-transformattr-02-f
coords-transformattr-03-f
coords-transformattr-04-f
coords-transformattr-05-f
coords-units-01-b
coords-units-02-b
coords-viewattr-01-b
coords-viewattr-02-b
coords-viewattr-03-b
fonts-desc-01-t
fonts-elem-01-t
fonts-elem-03-b
fonts-elem-05-t
fonts-elem-06-t
fonts-overview-201-t
masking-path-01-b
masking-path-05-f
masking-path-13-f
masking-path-14-f
metadata-example-01-t
painting-control-01-f
painting-control-03-f
painting-control-04-f
painting-fill-01-t
painting-fill-02-t
painting-fill-03-t
painting-fill-05-b
painting-stroke-01-t
painting-stroke-02-t
painting-stroke-09-t
painting-stroke-10-t
paths-data-01-t
paths-data-02-t
paths-data-03-f
paths-data-04-t
paths-data-05-t
paths-data-06-t
paths-data-07-t
paths-data-08-t
paths-data-09-t
paths-data-10-t
paths-data-12-t
paths-data-13-t
paths-data-14-t
paths-data-15-t
paths-data-16-t
paths-data-17-f
paths-data-18-f
paths-data-19-f
paths-data-20-f
pservers-grad-01-b
pservers-grad-02-b
pservers-grad-03-b
pservers-grad-04-b
pservers-grad-06-b
pservers-grad-07-b
pservers-grad-08-b
pservers-grad-09-b
pservers-grad-10-b
pservers-grad-11-b
pservers-grad-12-b
pservers-grad-14-b
pservers-grad-15-b
pservers-grad-16-b
pservers-grad-20-b
pservers-grad-22-b
pservers-grad-23-f
pservers-grad-24-f
pservers-grad-stops-01-f
pservers-pattern-01-b
pservers-pattern-02-f
pservers-pattern-04-f
pservers-pattern-05-f
pservers-pattern-06-f
pservers-pattern-07-f
pservers-pattern-08-f
render-elems-01-t
render-elems-02-t
render-elems-03-t
render-elems-06-t
render-elems-07-t
render-elems-08-t
shapes-circle-01-t
shapes-circle-02-t
shapes-ellipse-01-t
shapes-ellipse-02-t
shapes-ellipse-03-f
shapes-grammar-01-f
shapes-intro-01-t
shapes-intro-02-f
shapes-line-01-t
shapes-line-02-f
shapes-polygon-01-t
shapes-polygon-02-t
shapes-polygon-03-t
shapes-polyline-01-t
shapes-polyline-02-t
shapes-rect-01-t
shapes-rect-02-t
shapes-rect-04-f
shapes-rect-05-f
shapes-rect-06-f
shapes-rect-07-f
struct-defs-01-t
struct-frag-06-t
struct-group-01-t
struct-group-02-b
struct-image-01-t
struct-image-04-t
struct-image-06-t
struct-image-17-b
styling-class-01-f
styling-css-01-b
styling-css-02-b
styling-css-03-b
styling-css-07-f
styling-pres-01-t
text-align-01-b
text-align-02-b
text-align-03-b
text-fonts-01-t
text-fonts-02-t
text-fonts-03-t
text-fonts-05-f
text-intro-04-t
text-path-01-b
text-path-02-b
text-text-04-t
text-text-05-t
text-text-07-t
text-text-08-b
text-text-09-t
text-text-10-t
text-text-11-t
text-tref-01-b
text-tspan-01-b
types-basic-01-f
......@@ -10,7 +10,7 @@ namespace Svg.UnitTests
/// Based on Issue 204.
/// </summary>
/// <remarks>
/// Test use the following embedded resources:
/// Test uses the following embedded resources:
/// - Issue204_PrivateFont\Text.svg
/// - Issue204_PrivateFont\BrushScriptMT2.ttf
/// </remarks>
......@@ -19,16 +19,13 @@ namespace Svg.UnitTests
{
private const string PrivateFontSvg = "Issue204_PrivateFont.Text.svg";
private const string PrivateFont = "Issue204_PrivateFont.BrushScriptMT2.ttf";
//private const string PrivateFontName = "Brush Script MT2";
protected override int ExpectedSize { get { return 3200; } } //3512
[TestMethod]
[Ignore]
public void TestPrivateFont()
{
// FIXME: Currently throws because of zero size
AddFontFromResource(SvgElement.PrivateFonts, GetFullResourceString(PrivateFont));
LoadSvg(GetXMLDocFromResource(GetFullResourceString(PrivateFontSvg)));
}
......@@ -40,7 +37,7 @@ namespace Svg.UnitTests
var fontData = Marshal.AllocCoTaskMem(fontBytes.Length);
Marshal.Copy(fontBytes, 0, fontData, fontBytes.Length);
privateFontCollection.AddMemoryFont(fontData, fontBytes.Length); // Add font to collection.
Marshal.FreeCoTaskMem(fontData); // Do not forget to frees the memory block.
Marshal.FreeCoTaskMem(fontData); // Do not forget to free the memory block.
}
}
}
......@@ -44,6 +44,7 @@
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
......@@ -67,6 +68,7 @@
<Compile Include="SvgTestHelper.cs" />
<Compile Include="SvgTextTests.cs" />
<Compile Include="SvgTextElementDeepCopyTest.cs" />
<Compile Include="ImageComparisonTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Source\Svg.csproj">
......@@ -76,6 +78,8 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\Issue204_PrivateFont\BrushScriptMT2.ttf" />
<None Include="AllTests.csv" />
<None Include="PassingTests.csv" />
<None Include="svgkey.snk" />
</ItemGroup>
<ItemGroup>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment