Browse Source

Merge branch 'master' into js/dither-all-the-things

af/merge-core
James Jackson-South 8 years ago
committed by GitHub
parent
commit
59d6a7defb
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .travis.yml
  2. 2
      .vscode/launch.json
  3. 4
      .vscode/tasks.json
  4. 32
      ImageSharp.sln
  5. 12
      samples/AvatarWithRoundedCorner/AvatarWithRoundedCorner.csproj
  6. 111
      samples/AvatarWithRoundedCorner/Program.cs
  7. 3
      samples/AvatarWithRoundedCorner/fb.jpg
  8. 12
      samples/ChangeDefaultEncoderOptions/ChangeDefaultEncoderOptions.csproj
  9. 23
      samples/ChangeDefaultEncoderOptions/Program.cs
  10. 3
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
  11. 4
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs
  12. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs
  13. 9
      src/ImageSharp/MetaData/ImageProperty.cs
  14. 9
      src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs
  15. 4
      src/ImageSharp/MetaData/Profiles/Exif/Rational.cs
  16. 4
      src/ImageSharp/MetaData/Profiles/Exif/SignedRational.cs
  17. 13
      tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj
  18. 4
      tests/ImageSharp.Benchmarks/benchmark.sh
  19. 4
      tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj
  20. 6
      tests/ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs
  21. 6
      tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs
  22. 4
      tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs
  23. 4
      tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs
  24. 4
      tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs
  25. 4
      tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs
  26. 65
      tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs
  27. 260
      tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs
  28. 11
      tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.SpectralData.cs
  29. 32
      tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs
  30. 13
      tests/ImageSharp.Tests/Image/ImageLoadTests.cs
  31. 23
      tests/ImageSharp.Tests/Image/ImageSaveTests.cs
  32. 28
      tests/ImageSharp.Tests/Image/MockImageFormatDetector.cs
  33. 10
      tests/ImageSharp.Tests/ImageSharp.Tests.csproj
  34. 6
      tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs
  35. 57
      tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs

4
.travis.yml

@ -6,7 +6,7 @@ matrix:
- os: linux # Ubuntu 14.04
dist: trusty
sudo: required
dotnet: 1.0.4
dotnet: 2.1.4
mono: latest
# - os: osx # OSX 10.11
# osx_image: xcode7.3.1
@ -21,7 +21,7 @@ branches:
script:
- git submodule -q update --init
- dotnet restore
- dotnet test tests/ImageSharp.Tests/ImageSharp.Tests.csproj -c Release -f "netcoreapp1.1"
- dotnet test tests/ImageSharp.Tests/ImageSharp.Tests.csproj -c Release -f "netcoreapp2.0"
env:
global:

2
.vscode/launch.json

@ -10,7 +10,7 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceRoot}/samples/AvatarWithRoundedCorner/bin/Debug/netcoreapp1.1/AvatarWithRoundedCorner.dll",
"program": "${workspaceRoot}/tests/ImageSharp.Benchmarks/bin/Debug/netcoreapp2.0/ImageSharp.Benchmarks.dll",
"args": [],
"cwd": "${workspaceRoot}/samples/AvatarWithRoundedCorner",
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window

4
.vscode/tasks.json

@ -16,13 +16,13 @@
{
"taskName": "build benchmark",
"suppressTaskName": true,
"args": [ "build", "tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj", "-f", "netcoreapp1.1", "-c", "Release" ],
"args": [ "build", "tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj", "-f", "netcoreapp2.0", "-c", "Release" ],
"showOutput": "always",
"problemMatcher": "$msCompile"
},
{
"taskName": "test",
"args": ["tests/ImageSharp.Tests/ImageSharp.Tests.csproj", "-c", "release", "-f", "netcoreapp1.1"],
"args": ["tests/ImageSharp.Tests/ImageSharp.Tests.csproj", "-c", "release", "-f", "netcoreapp2.0"],
"isTestCommand": true,
"showOutput": "always",
"problemMatcher": "$msCompile"

32
ImageSharp.sln

@ -43,12 +43,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Tests", "tests\I
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Benchmarks", "tests\ImageSharp.Benchmarks\ImageSharp.Benchmarks.csproj", "{2BF743D8-2A06-412D-96D7-F448F00C5EA5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{7CC6D57E-B916-43B8-B315-A0BB92F260A2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvatarWithRoundedCorner", "samples\AvatarWithRoundedCorner\AvatarWithRoundedCorner.csproj", "{844FC582-4E78-4371-847D-EFD4D1103578}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChangeDefaultEncoderOptions", "samples\ChangeDefaultEncoderOptions\ChangeDefaultEncoderOptions.csproj", "{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Sandbox46", "tests\ImageSharp.Sandbox46\ImageSharp.Sandbox46.csproj", "{561B880A-D9EE-44EF-90F5-817C54A9D9AB}"
EndProject
Global
@ -112,30 +106,6 @@ Global
{2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release|x64.Build.0 = Release|Any CPU
{2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release|x86.ActiveCfg = Release|Any CPU
{2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release|x86.Build.0 = Release|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Debug|Any CPU.Build.0 = Debug|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Debug|x64.ActiveCfg = Debug|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Debug|x64.Build.0 = Debug|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Debug|x86.ActiveCfg = Debug|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Debug|x86.Build.0 = Debug|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Release|Any CPU.ActiveCfg = Release|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Release|Any CPU.Build.0 = Release|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Release|x64.ActiveCfg = Release|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Release|x64.Build.0 = Release|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Release|x86.ActiveCfg = Release|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Release|x86.Build.0 = Release|Any CPU
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|x64.ActiveCfg = Debug|Any CPU
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|x64.Build.0 = Debug|Any CPU
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|x86.ActiveCfg = Debug|Any CPU
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|x86.Build.0 = Debug|Any CPU
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|Any CPU.Build.0 = Release|Any CPU
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|x64.ActiveCfg = Release|Any CPU
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|x64.Build.0 = Release|Any CPU
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|x86.ActiveCfg = Release|Any CPU
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|x86.Build.0 = Release|Any CPU
{561B880A-D9EE-44EF-90F5-817C54A9D9AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{561B880A-D9EE-44EF-90F5-817C54A9D9AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{561B880A-D9EE-44EF-90F5-817C54A9D9AB}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -158,8 +128,6 @@ Global
{2E33181E-6E28-4662-A801-E2E7DC206029} = {815C0625-CD3D-440F-9F80-2D83856AB7AE}
{EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC}
{2BF743D8-2A06-412D-96D7-F448F00C5EA5} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC}
{844FC582-4E78-4371-847D-EFD4D1103578} = {7CC6D57E-B916-43B8-B315-A0BB92F260A2}
{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0} = {7CC6D57E-B916-43B8-B315-A0BB92F260A2}
{561B880A-D9EE-44EF-90F5-817C54A9D9AB} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution

12
samples/AvatarWithRoundedCorner/AvatarWithRoundedCorner.csproj

@ -1,12 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\ImageSharp.Drawing\ImageSharp.Drawing.csproj" />
</ItemGroup>
</Project>

111
samples/AvatarWithRoundedCorner/Program.cs

@ -1,111 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Primitives;
using SixLabors.Shapes;
namespace AvatarWithRoundedCorner
{
static class Program
{
static void Main(string[] args)
{
System.IO.Directory.CreateDirectory("output");
using (var img = Image.Load("fb.jpg"))
{
// as generate returns a new IImage make sure we dispose of it
using (Image<Rgba32> destRound = img.Clone(x => x.ConvertToAvatar(new Size(200, 200), 20)))
{
destRound.Save("output/fb.png");
}
using (Image<Rgba32> destRound = img.Clone(x => x.ConvertToAvatar(new Size(200, 200), 100)))
{
destRound.Save("output/fb-round.png");
}
using (Image<Rgba32> destRound = img.Clone(x => x.ConvertToAvatar(new Size(200, 200), 150)))
{
destRound.Save("output/fb-rounder.png");
}
using (Image<Rgba32> destRound = img.CloneAndConvertToAvatarWithoutApply(new Size(200, 200), 150))
{
destRound.Save("output/fb-rounder-without-apply.png");
}
// the original `img` object has not been altered at all.
}
}
// 1. The short way:
// Implements a full image mutating pipeline operating on IImageProcessingContext<Rgba32>
// We need the dimensions of the resized image to deduce 'IPathCollection' needed to build the corners,
// so we implement an "inline" image processor by utilizing 'ImageExtensions.Apply()'
private static IImageProcessingContext<Rgba32> ConvertToAvatar(this IImageProcessingContext<Rgba32> processingContext, Size size, float cornerRadius)
{
return processingContext.Resize(new ResizeOptions
{
Size = size,
Mode = ResizeMode.Crop
}).Apply(i => ApplyRoundedCorners(i, cornerRadius));
}
// 2. A more verbose way, avoiding 'Apply()':
// First we create a resized clone of the image, then we draw the corners on that instance with Mutate().
private static Image<Rgba32> CloneAndConvertToAvatarWithoutApply(this Image<Rgba32> image, Size size, float cornerRadius)
{
Image<Rgba32> result = image.Clone(
ctx => ctx.Resize(
new ResizeOptions
{
Size = size,
Mode = ResizeMode.Crop
}));
ApplyRoundedCorners(result, cornerRadius);
return result;
}
// This method can be seen as an inline implementation of an `IImageProcessor`:
// (The combination of `IImageOperations.Apply()` + this could be replaced with an `IImageProcessor`)
public static void ApplyRoundedCorners(Image<Rgba32> img, float cornerRadius)
{
IPathCollection corners = BuildCorners(img.Width, img.Height, cornerRadius);
// mutating in here as we already have a cloned original
img.Mutate(x => x.Fill(Rgba32.Transparent, corners, new GraphicsOptions(true)
{
BlenderMode = PixelBlenderMode.Src // enforces that any part of this shape that has color is punched out of the background
}));
}
public static IPathCollection BuildCorners(int imageWidth, int imageHeight, float cornerRadius)
{
// first create a square
var rect = new RectangularePolygon(-0.5f, -0.5f, cornerRadius, cornerRadius);
// then cut out of the square a circle so we are left with a corner
IPath cornerToptLeft = rect.Clip(new EllipsePolygon(cornerRadius - 0.5f, cornerRadius - 0.5f, cornerRadius));
// corner is now a corner shape positions top left
//lets make 3 more positioned correctly, we can do that by translating the orgional artound the center of the image
var center = new Vector2(imageWidth / 2F, imageHeight / 2F);
float rightPos = imageWidth - cornerToptLeft.Bounds.Width + 1;
float bottomPos = imageHeight - cornerToptLeft.Bounds.Height + 1;
// move it across the widthof the image - the width of the shape
IPath cornerTopRight = cornerToptLeft.RotateDegree(90).Translate(rightPos, 0);
IPath cornerBottomLeft = cornerToptLeft.RotateDegree(-90).Translate(0, bottomPos);
IPath cornerBottomRight = cornerToptLeft.RotateDegree(180).Translate(rightPos, bottomPos);
return new PathCollection(cornerToptLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight);
}
}
}

3
samples/AvatarWithRoundedCorner/fb.jpg

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

12
samples/ChangeDefaultEncoderOptions/ChangeDefaultEncoderOptions.csproj

@ -1,12 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\ImageSharp\ImageSharp.csproj" />
</ItemGroup>
</Project>

23
samples/ChangeDefaultEncoderOptions/Program.cs

@ -1,23 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
namespace ChangeDefaultEncoderOptions
{
class Program
{
static void Main(string[] args)
{
// lets switch out the default encoder for jpeg to one
// that saves at 90 quality and ignores the matadata
Configuration.Default.SetEncoder(ImageFormats.Jpeg, new JpegEncoder()
{
Quality = 90,
IgnoreMetadata = true
});
}
}
}

3
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs

@ -184,8 +184,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
Rgb rgb = YCbCrAndRgbConverter.Convert(color);
// Adaptation
// TODO: Check this!
return rgb.WorkingSpace.Equals(this.TargetRgbWorkingSpace) ? rgb : this.Adapt(rgb);
return this.Adapt(rgb);
}
}
}

4
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs

@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
internal abstract class LinearRgbAndCieXyzConverterBase
{
/// <summary>
/// Geturns the correct matrix to convert between the Rgb and CieXyz color space.
/// Returns the correct matrix to convert between the Rgb and CieXyz color space.
/// </summary>
/// <param name="workingSpace">The Rgb working space.</param>
/// <returns>The <see cref="Matrix4x4"/> based on the chromaticity and working space.</returns>
@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
Vector3 vector = Vector3.Transform(workingSpace.WhitePoint.Vector, inverseXyzMatrix);
// Use transposed Rows/Coloumns
// Use transposed Rows/Columns
// TODO: Is there a built in method for this multiplication?
return new Matrix4x4
{

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs

@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
public CieXyz Convert(LinearRgb input)
{
DebugGuard.NotNull(input, nameof(input));
Guard.IsTrue(input.WorkingSpace.Equals(this.SourceWorkingSpace), nameof(input.WorkingSpace), "Input and source working spaces must be equal.");
DebugGuard.IsTrue(input.WorkingSpace.Equals(this.SourceWorkingSpace), nameof(input.WorkingSpace), "Input and source working spaces must be equal.");
Vector3 vector = Vector3.Transform(input.Vector, this.conversionMatrix);
return new CieXyz(vector);

9
src/ImageSharp/MetaData/ImageProperty.cs

@ -71,7 +71,12 @@ namespace SixLabors.ImageSharp.MetaData
/// </returns>
public static bool operator ==(ImageProperty left, ImageProperty right)
{
return Equals(left, right);
if (ReferenceEquals(left, right))
{
return true;
}
return left.Equals(right);
}
/// <summary>
@ -90,7 +95,7 @@ namespace SixLabors.ImageSharp.MetaData
/// </returns>
public static bool operator !=(ImageProperty left, ImageProperty right)
{
return !Equals(left, right);
return !(left == right);
}
/// <summary>

9
src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs

@ -188,7 +188,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
/// </returns>
public static bool operator ==(ExifValue left, ExifValue right)
{
return ExifValue.Equals(left, right);
if (ReferenceEquals(left, right))
{
return true;
}
return left.Equals(right);
}
/// <summary>
@ -205,7 +210,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
/// </returns>
public static bool operator !=(ExifValue left, ExifValue right)
{
return !ExifValue.Equals(left, right);
return !(left == right);
}
/// <inheritdoc />

4
src/ImageSharp/MetaData/Profiles/Exif/Rational.cs

@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
/// <returns>The <see cref="bool"/></returns>
public static bool operator ==(Rational left, Rational right)
{
return Rational.Equals(left, right);
return left.Equals(right);
}
/// <summary>
@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
/// <returns>The <see cref="bool"/></returns>
public static bool operator !=(Rational left, Rational right)
{
return !Rational.Equals(left, right);
return !left.Equals(right);
}
/// <summary>

4
src/ImageSharp/MetaData/Profiles/Exif/SignedRational.cs

@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
/// <returns>The <see cref="bool"/></returns>
public static bool operator ==(SignedRational left, SignedRational right)
{
return SignedRational.Equals(left, right);
return left.Equals(right);
}
/// <summary>
@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
/// <returns>The <see cref="bool"/></returns>
public static bool operator !=(SignedRational left, SignedRational right)
{
return !SignedRational.Equals(left, right);
return !left.Equals(right);
}
/// <summary>

13
tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp1.1;net461</TargetFrameworks>
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<RootNamespace>SixLabors.ImageSharp.Benchmarks</RootNamespace>
@ -15,17 +15,12 @@
<Compile Include="..\ImageSharp.Tests\TestUtilities\TestEnvironment.cs" Link="Tests\TestEnvironment.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.10.12" />
<PackageReference Include="Colourful" Version="1.1.2" />
<PackageReference Include="System.Numerics.Vectors" Version="4.4.0" />
<PackageReference Include="System.Drawing.Common" Version="4.5.0-preview2-26202-05" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net461'">
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.10.9" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netcoreapp1.1'">
<PackageReference Include="BenchmarkDotNet" Version="0.10.9" />
<PackageReference Include="System.Reflection" Version="4.3.0" />
<PackageReference Include="CoreCompat.System.Drawing" Version="1.0.0-beta006" />
<PackageReference Include="runtime.linux-x64.CoreCompat.System.Drawing" Version="1.0.0-beta009" />
<PackageReference Include="System.Numerics.Vectors" Version="4.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\ImageSharp.Drawing\ImageSharp.Drawing.csproj" />

4
tests/ImageSharp.Benchmarks/benchmark.sh

@ -1,7 +1,7 @@
#!/bin/bash
# Build in release mode
dotnet build -c Release -f netcoreapp1.1
dotnet build -c Release -f netcoreapp2.0
# Run benchmarks
dotnet bin/Release/netcoreapp1.1/ImageSharp.Benchmarks.dll
dotnet bin/Release/netcoreapp2.0/ImageSharp.Benchmarks.dll

4
tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj

@ -18,8 +18,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BitMiracle.LibJpeg.NET" Version="1.4.280" />
<PackageReference Include="xunit" Version="2.3.0-beta4-build3742" />
<PackageReference Include="Moq" Version="4.7.99" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="Moq" Version="4.8.1" />
<!--<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />-->
<!--<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />-->
</ItemGroup>

6
tests/ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs

@ -19,6 +19,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
{
private static readonly IEqualityComparer<float> FloatRoundingComparer = new FloatRoundingComparer(3);
private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F);
[Theory]
[InlineData(0, 0, 0, 0, 0, 0)]
[InlineData(1, 1, 1, 1, 1, 1)]
@ -34,7 +36,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
Rgb output = converter.Adapt(input);
// Assert
Assert.Equal(expectedOutput.WorkingSpace, output.WorkingSpace);
Assert.Equal(expectedOutput.WorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(expectedOutput.R, output.R, FloatRoundingComparer);
Assert.Equal(expectedOutput.G, output.G, FloatRoundingComparer);
Assert.Equal(expectedOutput.B, output.B, FloatRoundingComparer);
@ -55,7 +57,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
Rgb output = converter.Adapt(input);
// Assert
Assert.Equal(expectedOutput.WorkingSpace, output.WorkingSpace);
Assert.Equal(expectedOutput.WorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(expectedOutput.R, output.R, FloatRoundingComparer);
Assert.Equal(expectedOutput.G, output.G, FloatRoundingComparer);
Assert.Equal(expectedOutput.B, output.B, FloatRoundingComparer);

6
tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs

@ -19,6 +19,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
{
private static readonly IEqualityComparer<float> FloatRoundingComparer = new FloatRoundingComparer(6);
private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F);
/// <summary>
/// Tests conversion from <see cref="CieXyz"/> (<see cref="Illuminants.D50"/>)
/// to <see cref="Rgb"/> (<see cref="Rgb.DefaultWorkingSpace">default sRGB working space</see>).
@ -40,7 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
Rgb output = converter.ToRgb(input);
// Assert
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace);
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(r, output.R, FloatRoundingComparer);
Assert.Equal(g, output.G, FloatRoundingComparer);
Assert.Equal(b, output.B, FloatRoundingComparer);
@ -68,7 +70,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
Rgb output = converter.ToRgb(input);
// Assert
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace);
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(r, output.R, FloatRoundingComparer);
Assert.Equal(g, output.G, FloatRoundingComparer);
Assert.Equal(b, output.B, FloatRoundingComparer);

4
tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs

@ -22,6 +22,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter();
private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F);
/// <summary>
/// Tests conversion from <see cref="Cmyk"/> to <see cref="Rgb"/>.
/// </summary>
@ -38,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
Rgb output = Converter.ToRgb(input);
// Assert
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace);
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(r, output.R, FloatRoundingComparer);
Assert.Equal(g, output.G, FloatRoundingComparer);
Assert.Equal(b, output.B, FloatRoundingComparer);

4
tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs

@ -22,6 +22,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter();
private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F);
/// <summary>
/// Tests conversion from <see cref="Hsl"/> to <see cref="Rgb"/>.
/// </summary>
@ -41,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
Rgb output = Converter.ToRgb(input);
// Assert
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace);
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(r, output.R, FloatRoundingComparer);
Assert.Equal(g, output.G, FloatRoundingComparer);
Assert.Equal(b, output.B, FloatRoundingComparer);

4
tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs

@ -21,6 +21,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter();
private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F);
/// <summary>
/// Tests conversion from <see cref="Hsv"/> to <see cref="Rgb"/>.
/// </summary>
@ -40,7 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
Rgb output = Converter.ToRgb(input);
// Assert
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace);
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(r, output.R, FloatRoundingComparer);
Assert.Equal(g, output.G, FloatRoundingComparer);
Assert.Equal(b, output.B, FloatRoundingComparer);

4
tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs

@ -20,6 +20,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter();
private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F);
/// <summary>
/// Tests conversion from <see cref="YCbCr"/> to <see cref="Rgb"/>.
/// </summary>
@ -36,7 +38,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
Rgb output = Converter.ToRgb(input);
// Assert
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace);
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(r, output.R, FloatRoundingComparer);
Assert.Equal(g, output.G, FloatRoundingComparer);
Assert.Equal(b, output.B, FloatRoundingComparer);

65
tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs

@ -1,16 +1,14 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Pens;
using SixLabors.ImageSharp.Drawing.Processors;
using SixLabors.ImageSharp.PixelFormats;
using Moq;
using Xunit;
using SixLabors.ImageSharp.Drawing.Brushes;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Tests.Drawing
{
@ -25,18 +23,18 @@ namespace SixLabors.ImageSharp.Tests.Drawing
[InlineData(false, 16, 4)] // we always do 4 sub=pixels when antialising is off.
public void MinimumAntialiasSubpixelDepth(bool antialias, int antialiasSubpixelDepth, int expectedAntialiasSubpixelDepth)
{
SixLabors.Primitives.Rectangle bounds = new SixLabors.Primitives.Rectangle(0, 0, 1, 1);
var bounds = new SixLabors.Primitives.Rectangle(0, 0, 1, 1);
Mock<IBrush<Rgba32>> brush = new Mock<IBrush<Rgba32>>();
Mock<Region> region = new Mock<Region>();
var brush = new Mock<IBrush<Rgba32>>();
var region = new Mock<Region>();
region.Setup(x => x.Bounds).Returns(bounds);
GraphicsOptions options = new GraphicsOptions(antialias)
var options = new GraphicsOptions(antialias)
{
AntialiasSubpixelDepth = 1
};
FillRegionProcessor<Rgba32> processor = new FillRegionProcessor<Rgba32>(brush.Object, region.Object, options);
Image<Rgba32> img = new Image<Rgba32>(1, 1);
var processor = new FillRegionProcessor<Rgba32>(brush.Object, region.Object, options);
var img = new Image<Rgba32>(1, 1);
processor.Apply(img, bounds);
region.Verify(x => x.Scan(It.IsAny<float>(), It.IsAny<float[]>(), It.IsAny<int>()), Times.Exactly(4));
@ -45,31 +43,11 @@ namespace SixLabors.ImageSharp.Tests.Drawing
[Fact]
public void FillOffCanvas()
{
SixLabors.Primitives.Rectangle bounds = new SixLabors.Primitives.Rectangle(-100, -10, 10, 10);
Mock<IBrush<Rgba32>> brush = new Mock<IBrush<Rgba32>>();
Mock<Region> region = new Mock<Region>();
region.Setup(x => x.Bounds).Returns(bounds);
region.Setup(x => x.MaxIntersections).Returns(10);
region.Setup(x => x.Scan(It.IsAny<float>(), It.IsAny<float[]>(), It.IsAny<int>()))
.Returns<float, Span<float>>((y, span) =>
{
if (y < 5)
{
span[0] = -10f;
span[1] = 100f;
return 2;
}
return 0;
});
GraphicsOptions options = new GraphicsOptions(true)
{
};
FillRegionProcessor<Rgba32> processor = new FillRegionProcessor<Rgba32>(brush.Object, region.Object, options);
Image<Rgba32> img = new Image<Rgba32>(10, 10);
var bounds = new Rectangle(-100, -10, 10, 10);
var brush = new Mock<IBrush<Rgba32>>();
var options = new GraphicsOptions(true);
var processor = new FillRegionProcessor<Rgba32>(brush.Object, new MockRegion(), options);
var img = new Image<Rgba32>(10, 10);
processor.Apply(img, bounds);
}
@ -85,5 +63,24 @@ namespace SixLabors.ImageSharp.Tests.Drawing
}));
}
}
// Mocking the region throws an error in netcore2.0
private class MockRegion : Region
{
public override Rectangle Bounds => new Rectangle(-100, -10, 10, 10);
public override int MaxIntersections => 10;
public override int Scan(float y, float[] buffer, int offset)
{
if (y < 5)
{
buffer[0] = -10f;
buffer[1] = 100f;
return 2;
}
return 0;
}
}
}
}

260
tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs

@ -39,10 +39,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[MemberData(nameof(CommonConversionData))]
public void ConvertFromYCbCrBasic(int inputBufferLength, int resultBufferLength, int seed)
{
ValidateConversion(new JpegColorConverter.FromYCbCrBasic(), 3, inputBufferLength, resultBufferLength, seed, ValidateYCbCr);
ValidateRgbToYCbCrConversion(
new JpegColorConverter.FromYCbCrBasic(),
3,
inputBufferLength,
resultBufferLength,
seed);
}
private static void ValidateYCbCr(JpegColorConverter.ComponentValues values, Span<Vector4> result, int i)
private static void ValidateYCbCr(JpegColorConverter.ComponentValues values, Vector4[] result, int i)
{
float y = values.Component0[i];
float cb = values.Component1[i];
@ -63,20 +68,27 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(8, 3)]
public void FromYCbCrSimd_ConvertCore(int size, int seed)
{
ValidateConversion(JpegColorConverter.FromYCbCrSimd.ConvertCore, 3, size, size, seed, ValidateYCbCr);
JpegColorConverter.ComponentValues values = CreateRandomValues(3, size, seed);
Vector4[] result = new Vector4[size];
JpegColorConverter.FromYCbCrSimd.ConvertCore(values, result);
for (int i = 0; i < size; i++)
{
ValidateYCbCr(values, result, i);
}
}
[Theory]
[MemberData(nameof(CommonConversionData))]
public void FromYCbCrSimd(int inputBufferLength, int resultBufferLength, int seed)
{
ValidateConversion(
ValidateRgbToYCbCrConversion(
new JpegColorConverter.FromYCbCrSimd(),
3,
inputBufferLength,
resultBufferLength,
seed,
ValidateYCbCr);
seed);
}
[Theory]
@ -91,13 +103,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
//JpegColorConverter.FromYCbCrSimdAvx2.LogPlz = s => this.Output.WriteLine(s);
ValidateConversion(
ValidateRgbToYCbCrConversion(
new JpegColorConverter.FromYCbCrSimdAvx2(),
3,
inputBufferLength,
resultBufferLength,
seed,
ValidateYCbCr);
seed);
}
@ -105,10 +116,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[MemberData(nameof(CommonConversionData))]
public void ConvertFromYCbCr_WithDefaultConverter(int inputBufferLength, int resultBufferLength, int seed)
{
ValidateConversion(JpegColorSpace.YCbCr, 3, inputBufferLength, resultBufferLength, seed, ValidateYCbCr);
ValidateConversion(
JpegColorSpace.YCbCr,
3,
inputBufferLength,
resultBufferLength,
seed);
}
// Becnhmark, for local execution only
// Benchmark, for local execution only
//[Theory]
//[InlineData(false)]
//[InlineData(true)]
@ -120,11 +136,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
JpegColorConverter.ComponentValues values = CreateRandomValues(3, count, 1);
Vector4[] result = new Vector4[count];
JpegColorConverter converter = simd ? (JpegColorConverter)new JpegColorConverter.FromYCbCrSimd() : new JpegColorConverter.FromYCbCrBasic();
JpegColorConverter converter = simd ? (JpegColorConverter)new JpegColorConverter.FromYCbCrSimd() : new JpegColorConverter.FromYCbCrBasic();
// Warm up:
converter.ConvertToRGBA(values, result);
using (new MeasureGuard(this.Output, $"{converter.GetType().Name} x {times}"))
{
for (int i = 0; i < times; i++)
@ -141,79 +157,79 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
var v = new Vector4(0, 0, 0, 1F);
var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F);
ValidateConversion(
JpegColorSpace.Cmyk,
4,
inputBufferLength,
resultBufferLength,
seed,
(values, result, i) =>
{
float c = values.Component0[i];
float m = values.Component1[i];
float y = values.Component2[i];
float k = values.Component3[i] / 255F;
v.X = c * k;
v.Y = m * k;
v.Z = y * k;
v.W = 1F;
v *= scale;
Vector4 rgba = result[i];
var actual = new Rgb(rgba.X, rgba.Y, rgba.Z);
var expected = new Rgb(v.X, v.Y, v.Z);
Assert.True(actual.AlmostEquals(expected, Precision));
Assert.Equal(1, rgba.W);
});
var converter = JpegColorConverter.GetConverter(JpegColorSpace.Cmyk);
JpegColorConverter.ComponentValues values = CreateRandomValues(4, inputBufferLength, seed);
Vector4[] result = new Vector4[resultBufferLength];
converter.ConvertToRGBA(values, result);
for (int i = 0; i < resultBufferLength; i++)
{
float c = values.Component0[i];
float m = values.Component1[i];
float y = values.Component2[i];
float k = values.Component3[i] / 255F;
v.X = c * k;
v.Y = m * k;
v.Z = y * k;
v.W = 1F;
v *= scale;
Vector4 rgba = result[i];
var actual = new Rgb(rgba.X, rgba.Y, rgba.Z);
var expected = new Rgb(v.X, v.Y, v.Z);
Assert.True(actual.AlmostEquals(expected, Precision));
Assert.Equal(1, rgba.W);
}
}
[Theory]
[MemberData(nameof(CommonConversionData))]
public void ConvertFromGrayScale(int inputBufferLength, int resultBufferLength, int seed)
{
ValidateConversion(
JpegColorSpace.GrayScale,
1,
inputBufferLength,
resultBufferLength,
seed,
(values, result, i) =>
{
float y = values.Component0[i];
Vector4 rgba = result[i];
var actual = new Rgb(rgba.X, rgba.Y, rgba.Z);
var expected = new Rgb(y / 255F, y / 255F, y / 255F);
Assert.True(actual.AlmostEquals(expected, Precision));
Assert.Equal(1, rgba.W);
});
var converter = JpegColorConverter.GetConverter(JpegColorSpace.GrayScale);
JpegColorConverter.ComponentValues values = CreateRandomValues(1, inputBufferLength, seed);
Vector4[] result = new Vector4[resultBufferLength];
converter.ConvertToRGBA(values, result);
for (int i = 0; i < resultBufferLength; i++)
{
float y = values.Component0[i];
Vector4 rgba = result[i];
var actual = new Rgb(rgba.X, rgba.Y, rgba.Z);
var expected = new Rgb(y / 255F, y / 255F, y / 255F);
Assert.True(actual.AlmostEquals(expected, Precision));
Assert.Equal(1, rgba.W);
}
}
[Theory]
[MemberData(nameof(CommonConversionData))]
public void ConvertFromRgb(int inputBufferLength, int resultBufferLength, int seed)
{
ValidateConversion(
JpegColorSpace.RGB,
3,
inputBufferLength,
resultBufferLength,
seed,
(values, result, i) =>
{
float r = values.Component0[i];
float g = values.Component1[i];
float b = values.Component2[i];
Vector4 rgba = result[i];
var actual = new Rgb(rgba.X, rgba.Y, rgba.Z);
var expected = new Rgb(r / 255F, g / 255F, b / 255F);
Assert.True(actual.AlmostEquals(expected, Precision));
Assert.Equal(1, rgba.W);
});
var converter = JpegColorConverter.GetConverter(JpegColorSpace.RGB);
JpegColorConverter.ComponentValues values = CreateRandomValues(3, inputBufferLength, seed);
Vector4[] result = new Vector4[resultBufferLength];
converter.ConvertToRGBA(values, result);
for (int i = 0; i < resultBufferLength; i++)
{
float r = values.Component0[i];
float g = values.Component1[i];
float b = values.Component2[i];
Vector4 rgba = result[i];
var actual = new Rgb(rgba.X, rgba.Y, rgba.Z);
var expected = new Rgb(r / 255F, g / 255F, b / 255F);
Assert.True(actual.AlmostEquals(expected, Precision));
Assert.Equal(1, rgba.W);
}
}
[Theory]
@ -223,35 +239,35 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
var v = new Vector4(0, 0, 0, 1F);
var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F);
ValidateConversion(
JpegColorSpace.Ycck,
4,
inputBufferLength,
resultBufferLength,
seed,
(values, result, i) =>
{
float y = values.Component0[i];
float cb = values.Component1[i] - 128F;
float cr = values.Component2[i] - 128F;
float k = values.Component3[i] / 255F;
v.X = (255F - (float)Math.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k;
v.Y = (255F - (float)Math.Round(
y - (0.344136F * cb) - (0.714136F * cr),
MidpointRounding.AwayFromZero)) * k;
v.Z = (255F - (float)Math.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k;
v.W = 1F;
v *= scale;
Vector4 rgba = result[i];
var actual = new Rgb(rgba.X, rgba.Y, rgba.Z);
var expected = new Rgb(v.X, v.Y, v.Z);
Assert.True(actual.AlmostEquals(expected, Precision));
Assert.Equal(1, rgba.W);
});
var converter = JpegColorConverter.GetConverter(JpegColorSpace.Ycck);
JpegColorConverter.ComponentValues values = CreateRandomValues(4, inputBufferLength, seed);
Vector4[] result = new Vector4[resultBufferLength];
converter.ConvertToRGBA(values, result);
for (int i = 0; i < resultBufferLength; i++)
{
float y = values.Component0[i];
float cb = values.Component1[i] - 128F;
float cr = values.Component2[i] - 128F;
float k = values.Component3[i] / 255F;
v.X = (255F - (float)Math.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k;
v.Y = (255F - (float)Math.Round(
y - (0.344136F * cb) - (0.714136F * cr),
MidpointRounding.AwayFromZero)) * k;
v.Z = (255F - (float)Math.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k;
v.W = 1F;
v *= scale;
Vector4 rgba = result[i];
var actual = new Rgb(rgba.X, rgba.Y, rgba.Z);
var expected = new Rgb(v.X, v.Y, v.Z);
Assert.True(actual.AlmostEquals(expected, Precision));
Assert.Equal(1, rgba.W);
}
}
private static JpegColorConverter.ComponentValues CreateRandomValues(
@ -269,7 +285,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
for (int j = 0; j < inputBufferLength; j++)
{
values[j] = (float)rnd.NextDouble() * (maxVal-minVal)+minVal;
values[j] = (float)rnd.NextDouble() * (maxVal - minVal) + minVal;
}
// no need to dispose when buffer is not array owner
@ -283,51 +299,31 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
int componentCount,
int inputBufferLength,
int resultBufferLength,
int seed,
Action<JpegColorConverter.ComponentValues, Span<Vector4>, int> validatePixelValue)
int seed)
{
ValidateConversion(
ValidateRgbToYCbCrConversion(
JpegColorConverter.GetConverter(colorSpace),
componentCount,
inputBufferLength,
resultBufferLength,
seed,
validatePixelValue);
seed);
}
private static void ValidateConversion(
private static void ValidateRgbToYCbCrConversion(
JpegColorConverter converter,
int componentCount,
int inputBufferLength,
int resultBufferLength,
int seed,
Action<JpegColorConverter.ComponentValues, Span<Vector4>, int> validatePixelValue)
{
ValidateConversion(
converter.ConvertToRGBA,
componentCount,
inputBufferLength,
resultBufferLength,
seed,
validatePixelValue);
}
private static void ValidateConversion(
Action<JpegColorConverter.ComponentValues, Span<Vector4>> doConvert,
int componentCount,
int inputBufferLength,
int resultBufferLength,
int seed,
Action<JpegColorConverter.ComponentValues, Span<Vector4>, int> validatePixelValue)
int seed)
{
JpegColorConverter.ComponentValues values = CreateRandomValues(componentCount, inputBufferLength, seed);
Vector4[] result = new Vector4[resultBufferLength];
doConvert(values, result);
converter.ConvertToRGBA(values, result);
for (int i = 0; i < resultBufferLength; i++)
{
validatePixelValue(values, result, i);
ValidateYCbCr(values, result, i);
}
}
}

11
tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.SpectralData.cs

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
this.ComponentCount = components.Length;
this.Components = components;
}
public static SpectralData LoadFromImageSharpDecoder(PdfJsJpegDecoderCore decoder)
{
PdfJsFrameComponent[] srcComponents = decoder.Frame.Components;
@ -137,12 +137,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
public static bool operator ==(SpectralData left, SpectralData right)
{
return Object.Equals(left, right);
if (ReferenceEquals(left, right))
{
return true;
}
return left.Equals(right);
}
public static bool operator !=(SpectralData left, SpectralData right)
{
return !Object.Equals(left, right);
return !(left == right);
}
}
}

32
tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs

@ -5,7 +5,6 @@ using System;
using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.PixelFormats;
using Moq;
using Xunit;
@ -18,10 +17,10 @@ namespace SixLabors.ImageSharp.Tests
{
private readonly Mock<IFileSystem> fileSystem;
private readonly string FilePath;
private readonly Mock<IImageFormatDetector> localMimeTypeDetector;
private readonly IImageFormatDetector localMimeTypeDetector;
private readonly Mock<IImageFormat> localImageFormatMock;
public IImageFormat localImageFormat => localImageFormatMock.Object;
public IImageFormat localImageFormat => this.localImageFormatMock.Object;
public Configuration LocalConfiguration { get; private set; }
public byte[] Marker { get; private set; }
public MemoryStream DataStream { get; private set; }
@ -32,9 +31,7 @@ namespace SixLabors.ImageSharp.Tests
{
this.localImageFormatMock = new Mock<IImageFormat>();
this.localMimeTypeDetector = new Mock<IImageFormatDetector>();
this.localMimeTypeDetector.Setup(x => x.HeaderSize).Returns(1);
this.localMimeTypeDetector.Setup(x => x.DetectFormat(It.IsAny<ReadOnlySpan<byte>>())).Returns(localImageFormatMock.Object);
this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormatMock.Object);
this.fileSystem = new Mock<IFileSystem>();
@ -42,7 +39,8 @@ namespace SixLabors.ImageSharp.Tests
{
FileSystem = this.fileSystem.Object
};
this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector.Object);
this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector);
TestFormat.RegisterGlobalTestFormat();
this.Marker = Guid.NewGuid().ToByteArray();
@ -58,49 +56,49 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public void DiscoverImageFormatByteArray()
{
var type = Image.DetectFormat(DataStream.ToArray());
IImageFormat type = Image.DetectFormat(this.DataStream.ToArray());
Assert.Equal(TestFormat.GlobalTestFormat, type);
}
[Fact]
public void DiscoverImageFormatByteArray_WithConfig()
{
var type = Image.DetectFormat(this.LocalConfiguration, DataStream.ToArray());
Assert.Equal(localImageFormat, type);
IImageFormat type = Image.DetectFormat(this.LocalConfiguration, this.DataStream.ToArray());
Assert.Equal(this.localImageFormat, type);
}
[Fact]
public void DiscoverImageFormatFile()
{
var type = Image.DetectFormat(this.FilePath);
IImageFormat type = Image.DetectFormat(this.FilePath);
Assert.Equal(TestFormat.GlobalTestFormat, type);
}
[Fact]
public void DiscoverImageFormatFilePath_WithConfig()
{
var type = Image.DetectFormat(this.LocalConfiguration, FilePath);
Assert.Equal(localImageFormat, type);
IImageFormat type = Image.DetectFormat(this.LocalConfiguration, this.FilePath);
Assert.Equal(this.localImageFormat, type);
}
[Fact]
public void DiscoverImageFormatStream()
{
var type = Image.DetectFormat(this.DataStream);
IImageFormat type = Image.DetectFormat(this.DataStream);
Assert.Equal(TestFormat.GlobalTestFormat, type);
}
[Fact]
public void DiscoverImageFormatFileStream_WithConfig()
{
var type = Image.DetectFormat(this.LocalConfiguration, DataStream);
Assert.Equal(localImageFormat, type);
IImageFormat type = Image.DetectFormat(this.LocalConfiguration, this.DataStream);
Assert.Equal(this.localImageFormat, type);
}
[Fact]
public void DiscoverImageFormatNoDetectorsRegisterdShouldReturnNull()
{
var type = Image.DetectFormat(new Configuration(), DataStream);
IImageFormat type = Image.DetectFormat(new Configuration(), this.DataStream);
Assert.Null(type);
}
}

13
tests/ImageSharp.Tests/Image/ImageLoadTests.cs

@ -14,13 +14,13 @@ namespace SixLabors.ImageSharp.Tests
/// <summary>
/// Tests the <see cref="Image"/> class.
/// </summary>
public class ImageLoadTests : IDisposable
public partial class ImageLoadTests : IDisposable
{
private readonly Mock<IFileSystem> fileSystem;
private Image<Rgba32> returnImage;
private Mock<IImageDecoder> localDecoder;
private readonly string FilePath;
private readonly Mock<IImageFormatDetector> localMimeTypeDetector;
private readonly IImageFormatDetector localMimeTypeDetector;
private readonly Mock<IImageFormat> localImageFormatMock;
public Configuration LocalConfiguration { get; private set; }
@ -35,10 +35,7 @@ namespace SixLabors.ImageSharp.Tests
this.localImageFormatMock = new Mock<IImageFormat>();
this.localDecoder = new Mock<IImageDecoder>();
this.localMimeTypeDetector = new Mock<IImageFormatDetector>();
this.localMimeTypeDetector.Setup(x => x.HeaderSize).Returns(1);
this.localMimeTypeDetector.Setup(x => x.DetectFormat(It.IsAny<ReadOnlySpan<byte>>())).Returns(localImageFormatMock.Object);
this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormatMock.Object);
this.localDecoder.Setup(x => x.Decode<Rgba32>(It.IsAny<Configuration>(), It.IsAny<Stream>()))
.Callback<Configuration, Stream>((c, s) =>
@ -57,8 +54,8 @@ namespace SixLabors.ImageSharp.Tests
{
FileSystem = this.fileSystem.Object
};
this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector.Object);
this.LocalConfiguration.SetDecoder(localImageFormatMock.Object, this.localDecoder.Object);
this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector);
this.LocalConfiguration.SetDecoder(this.localImageFormatMock.Object, this.localDecoder.Object);
TestFormat.RegisterGlobalTestFormat();
this.Marker = Guid.NewGuid().ToByteArray();

23
tests/ImageSharp.Tests/Image/ImageSaveTests.cs

@ -24,17 +24,14 @@ namespace SixLabors.ImageSharp.Tests
private readonly Mock<IFileSystem> fileSystem;
private readonly Mock<IImageEncoder> encoder;
private readonly Mock<IImageEncoder> encoderNotInFormat;
private Mock<IImageFormatDetector> localMimeTypeDetector;
private IImageFormatDetector localMimeTypeDetector;
private Mock<IImageFormat> localImageFormat;
public ImageSaveTests()
{
this.localImageFormat = new Mock<IImageFormat>();
this.localImageFormat.Setup(x => x.FileExtensions).Returns(new[] { "png" });
this.localMimeTypeDetector = new Mock<IImageFormatDetector>();
this.localMimeTypeDetector.Setup(x => x.HeaderSize).Returns(1);
this.localMimeTypeDetector.Setup(x => x.DetectFormat(It.IsAny<Span<byte>>())).Returns(localImageFormat.Object);
this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormat.Object);
this.encoder = new Mock<IImageEncoder>();
@ -45,8 +42,8 @@ namespace SixLabors.ImageSharp.Tests
{
FileSystem = this.fileSystem.Object
};
config.AddImageFormatDetector(this.localMimeTypeDetector.Object);
config.SetEncoder(localImageFormat.Object, this.encoder.Object);
config.AddImageFormatDetector(this.localMimeTypeDetector);
config.SetEncoder(this.localImageFormat.Object, this.encoder.Object);
this.Image = new Image<Rgba32>(config, 1, 1);
}
@ -57,7 +54,7 @@ namespace SixLabors.ImageSharp.Tests
{
using (Image<TPixel> image = provider.GetImage())
{
TPixel[] buffer = new TPixel[image.Width*image.Height];
TPixel[] buffer = new TPixel[image.Width * image.Height];
image.SavePixelData(buffer);
image.ComparePixelBufferTo(buffer);
@ -73,14 +70,14 @@ namespace SixLabors.ImageSharp.Tests
{
using (Image<TPixel> image = provider.GetImage())
{
byte[] buffer = new byte[image.Width*image.Height*Unsafe.SizeOf<TPixel>()];
byte[] buffer = new byte[image.Width * image.Height * Unsafe.SizeOf<TPixel>()];
image.SavePixelData(buffer);
image.ComparePixelBufferTo(buffer.AsSpan().NonPortableCast<byte, TPixel>());
}
}
[Fact]
public void SavePixelData_Rgba32_WhenBufferIsTooSmall_Throws()
{
@ -91,7 +88,7 @@ namespace SixLabors.ImageSharp.Tests
img[0, 1] = Rgba32.Red;
img[1, 1] = Rgba32.Blue;
var buffer = new byte[2 * 2]; // width * height * bytes per pixel
byte[] buffer = new byte[2 * 2]; // width * height * bytes per pixel
Assert.Throws<ArgumentOutOfRangeException>(() =>
{
@ -125,7 +122,7 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public void ToBase64String()
{
var str = this.Image.ToBase64String(localImageFormat.Object);
string str = this.Image.ToBase64String(this.localImageFormat.Object);
this.encoder.Verify(x => x.Encode<Rgba32>(this.Image, It.IsAny<Stream>()));
}
@ -134,7 +131,7 @@ namespace SixLabors.ImageSharp.Tests
public void SaveStreamWithMime()
{
Stream stream = new MemoryStream();
this.Image.Save(stream, localImageFormat.Object);
this.Image.Save(stream, this.localImageFormat.Object);
this.encoder.Verify(x => x.Encode<Rgba32>(this.Image, stream));
}

28
tests/ImageSharp.Tests/Image/MockImageFormatDetector.cs

@ -0,0 +1,28 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Formats;
namespace SixLabors.ImageSharp.Tests
{
/// <summary>
/// You can't mock the "DetectFormat" method due to the ReadOnlySpan{byte} parameter.
/// </summary>
public class MockImageFormatDetector : IImageFormatDetector
{
private IImageFormat localImageFormatMock;
public MockImageFormatDetector(IImageFormat imageFormat)
{
this.localImageFormatMock = imageFormat;
}
public int HeaderSize => 1;
public IImageFormat DetectFormat(ReadOnlySpan<byte> header)
{
return this.localImageFormatMock;
}
}
}

10
tests/ImageSharp.Tests/ImageSharp.Tests.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<TargetFramework>netcoreapp2.0</TargetFramework>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<DebugType Condition="$(codecov) != ''">full</DebugType>
<DebugType Condition="$(codecov) == ''">portable</DebugType>
@ -16,14 +16,14 @@
<None Include="PixelFormats\PixelOperationsTests.Blender.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CoreCompat.System.Drawing" Version="1.0.0-beta006" />
<PackageReference Include="System.Drawing.Common" Version="4.5.0-preview2-26202-05" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<PackageReference Include="Moq" Version="4.7.145" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="xunit" Version="2.3.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0" />
<PackageReference Include="Moq" Version="4.7.137" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<PackageReference Include="Moq" Version="4.8.1" />
<!--<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta001">
<PrivateAssets>All</PrivateAssets>
</PackageReference>-->

6
tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs

@ -387,13 +387,13 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
internal static void TestOperation<TSource, TDest>(
TSource[] source,
TDest[] expected,
Action<Span<TSource>, Buffer<TDest>> action)
Action<Buffer<TSource>, Buffer<TDest>> action)
where TSource : struct
where TDest : struct
{
using (TestBuffers<TSource, TDest> buffers = new TestBuffers<TSource, TDest>(source, expected))
using (var buffers = new TestBuffers<TSource, TDest>(source, expected))
{
action(buffers.Source, buffers.ActualDestBuffer);
action(buffers.SourceBuffer, buffers.ActualDestBuffer);
buffers.Verify();
}
}

57
tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs

@ -4,10 +4,18 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce;
namespace SixLabors.ImageSharp.Tests
{
internal struct ApproximateFloatComparer : IEqualityComparer<float>, IEqualityComparer<Vector4>
internal struct ApproximateFloatComparer :
IEqualityComparer<float>,
IEqualityComparer<Vector4>,
IEqualityComparer<CieXyChromaticityCoordinates>,
IEqualityComparer<RgbPrimariesChromaticityCoordinates>,
IEqualityComparer<CieXyz>,
IEqualityComparer<IRgbWorkingSpace>
{
private readonly float Eps;
@ -37,5 +45,52 @@ namespace SixLabors.ImageSharp.Tests
{
throw new InvalidOperationException();
}
public bool Equals(CieXyChromaticityCoordinates x, CieXyChromaticityCoordinates y)
{
return this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y);
}
public int GetHashCode(CieXyChromaticityCoordinates obj)
{
throw new NotImplementedException();
}
public bool Equals(RgbPrimariesChromaticityCoordinates x, RgbPrimariesChromaticityCoordinates y)
{
return this.Equals(x.R, y.R) && this.Equals(x.G, y.G) && this.Equals(x.B, y.B);
}
public int GetHashCode(RgbPrimariesChromaticityCoordinates obj)
{
throw new NotImplementedException();
}
public bool Equals(CieXyz x, CieXyz y)
{
return this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y) && this.Equals(x.Z, y.Z);
}
public int GetHashCode(CieXyz obj)
{
throw new NotImplementedException();
}
public bool Equals(IRgbWorkingSpace x, IRgbWorkingSpace y)
{
if (x is IRgbWorkingSpace g1 && y is IRgbWorkingSpace g2)
{
return this.Equals(g1.WhitePoint, g2.WhitePoint)
&& this.Equals(g1.ChromaticityCoordinates, g2.ChromaticityCoordinates);
}
return this.Equals(x.WhitePoint, y.WhitePoint)
&& this.Equals(x.ChromaticityCoordinates, y.ChromaticityCoordinates);
}
public int GetHashCode(IRgbWorkingSpace obj)
{
throw new NotImplementedException();
}
}
}
Loading…
Cancel
Save