Browse Source

better JpegColorConverterTests

af/merge-core
Anton Firszov 9 years ago
parent
commit
98946bdf0c
  1. 321
      tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs

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

@ -1,26 +1,27 @@
using System; namespace SixLabors.ImageSharp.Tests.Formats.Jpg
using System.Numerics; {
using System;
using System.Numerics;
using SixLabors.ImageSharp.ColorSpaces; using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion; using SixLabors.ImageSharp.ColorSpaces.Conversion;
using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder; using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
public class JpegColorConverterTests public class JpegColorConverterTests
{ {
private const float Precision = 0.1f; private const float Precision = 0.01f;
private const int InputBufferLength = 42; public static readonly TheoryData<int, int, int> CommonConversionData =
new TheoryData<int, int, int>
// The result buffer could be shorter {
private const int ResultBufferLength = 40; { 40, 40, 1 },
{ 42, 40, 2 },
private readonly Vector4[] result = new Vector4[ResultBufferLength]; { 42, 39, 3 }
};
private static readonly ColorSpaceConverter ColorSpaceConverter = new ColorSpaceConverter(); private static readonly ColorSpaceConverter ColorSpaceConverter = new ColorSpaceConverter();
@ -31,161 +32,193 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
private ITestOutputHelper Output { get; } private ITestOutputHelper Output { get; }
private static JpegColorConverter.ComponentValues CreateRandomValues(int componentCount, float maxVal = 255f) [Theory]
[MemberData(nameof(CommonConversionData))]
public void ConvertFromYCbCr(int inputBufferLength, int resultBufferLength, int seed)
{ {
var rnd = new Random(42); ValidateConversion(
Buffer2D<float>[] buffers = new Buffer2D<float>[componentCount]; JpegColorSpace.YCbCr,
for (int i = 0; i < componentCount; i++) 3,
{ inputBufferLength,
float[] values = new float[InputBufferLength]; resultBufferLength,
seed,
for (int j = 0; j < InputBufferLength; j++) (values, result, i) =>
{ {
values[j] = (float)rnd.NextDouble() * maxVal; float y = values.Component0[i];
} float cb = values.Component1[i];
float cr = values.Component2[i];
// no need to dispose when buffer is not array owner var ycbcr = new YCbCr(y, cb, cr);
buffers[i] = new Buffer2D<float>(values, values.Length, 1);
} Vector4 rgba = result[i];
return new JpegColorConverter.ComponentValues(buffers, 0); var actual = new Rgb(rgba.X, rgba.Y, rgba.Z);
var expected = ColorSpaceConverter.ToRgb(ycbcr);
Assert.True(actual.AlmostEquals(expected, Precision));
Assert.Equal(1, rgba.W);
});
} }
[Fact] [Theory]
public void ConvertFromYCbCr() [MemberData(nameof(CommonConversionData))]
public void ConvertFromCmyk(int inputBufferLength, int resultBufferLength, int seed)
{ {
var converter = JpegColorConverter.GetConverter(JpegColorSpace.YCbCr);
JpegColorConverter.ComponentValues values = CreateRandomValues(3);
converter.ConvertToRGBA(values, this.result);
for (int i = 0; i < ResultBufferLength; i++)
{
float y = values.Component0[i];
float cb = values.Component1[i];
float cr = values.Component2[i];
var ycbcr = new YCbCr(y, cb, cr);
Vector4 rgba = this.result[i];
var actual = new Rgb(rgba.X, rgba.Y, rgba.Z);
var expected = ColorSpaceConverter.ToRgb(ycbcr);
Assert.True(actual.AlmostEquals(expected, Precision));
Assert.Equal(1, rgba.W);
}
}
[Fact]
public void ConvertFromCmyk()
{
var converter = JpegColorConverter.GetConverter(JpegColorSpace.Cmyk);
JpegColorConverter.ComponentValues values = CreateRandomValues(4);
converter.ConvertToRGBA(values, this.result);
var v = new Vector4(0, 0, 0, 1F); var v = new Vector4(0, 0, 0, 1F);
var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F);
for (int i = 0; i < ResultBufferLength; i++) ValidateConversion(
{ JpegColorSpace.Cmyk,
float c = values.Component0[i]; 4,
float m = values.Component1[i]; inputBufferLength,
float y = values.Component2[i]; resultBufferLength,
float k = values.Component3[i] / 255F; seed,
(values, result, i) =>
v.X = c * k; {
v.Y = m * k; float c = values.Component0[i];
v.Z = y * k; float m = values.Component1[i];
v.W = 1F; float y = values.Component2[i];
float k = values.Component3[i] / 255F;
v *= scale;
v.X = c * k;
Vector4 rgba = this.result[i]; v.Y = m * k;
var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); v.Z = y * k;
var expected = new Rgb(v.X, v.Y, v.Z); v.W = 1F;
Assert.True(actual.AlmostEquals(expected, Precision)); v *= scale;
Assert.Equal(1, rgba.W);
} 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);
});
} }
[Fact] [Theory]
public void ConvertFromYcck() [MemberData(nameof(CommonConversionData))]
public void ConvertFromGrayScale(int inputBufferLength, int resultBufferLength, int seed)
{ {
var converter = JpegColorConverter.GetConverter(JpegColorSpace.Ycck); ValidateConversion(
JpegColorSpace.GrayScale,
JpegColorConverter.ComponentValues values = CreateRandomValues(4); 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);
});
}
converter.ConvertToRGBA(values, this.result); [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);
});
}
[Theory]
[MemberData(nameof(CommonConversionData))]
public void ConvertFromYcck(int inputBufferLength, int resultBufferLength, int seed)
{
var v = new Vector4(0, 0, 0, 1F); var v = new Vector4(0, 0, 0, 1F);
var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F);
for (int i = 0; i < ResultBufferLength; i++) ValidateConversion(
{ JpegColorSpace.Ycck,
float y = values.Component0[i]; 4,
float cb = values.Component1[i] - 128F; inputBufferLength,
float cr = values.Component2[i] - 128F; resultBufferLength,
float k = values.Component3[i] / 255F; seed,
(values, result, i) =>
v.X = (255F - MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; {
v.Y = (255F - MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero)) * k; float y = values.Component0[i];
v.Z = (255F - MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; float cb = values.Component1[i] - 128F;
v.W = 1F; float cr = values.Component2[i] - 128F;
float k = values.Component3[i] / 255F;
v *= scale;
v.X = (255F - MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k;
Vector4 rgba = this.result[i]; v.Y = (255F - MathF.Round(
var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); y - (0.344136F * cb) - (0.714136F * cr),
var expected = new Rgb(v.X, v.Y, v.Z); MidpointRounding.AwayFromZero)) * k;
v.Z = (255F - MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k;
Assert.True(actual.AlmostEquals(expected, Precision)); v.W = 1F;
Assert.Equal(1, rgba.W);
} 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);
});
} }
[Fact] private static JpegColorConverter.ComponentValues CreateRandomValues(
public void ConvertFromGrayScale() int componentCount,
int inputBufferLength,
int seed,
float maxVal = 255f)
{ {
var converter = JpegColorConverter.GetConverter(JpegColorSpace.GrayScale); var rnd = new Random(seed);
Buffer2D<float>[] buffers = new Buffer2D<float>[componentCount];
JpegColorConverter.ComponentValues values = CreateRandomValues(1); for (int i = 0; i < componentCount; i++)
converter.ConvertToRGBA(values, this.result);
for (int i = 0; i < ResultBufferLength; i++)
{ {
float y = values.Component0[i]; float[] values = new float[inputBufferLength];
Vector4 rgba = this.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)); for (int j = 0; j < inputBufferLength; j++)
Assert.Equal(1, rgba.W); {
values[j] = (float)rnd.NextDouble() * maxVal;
}
// no need to dispose when buffer is not array owner
buffers[i] = new Buffer2D<float>(values, values.Length, 1);
} }
return new JpegColorConverter.ComponentValues(buffers, 0);
} }
[Fact] private static void ValidateConversion(
public void ConvertFromRgb() JpegColorSpace colorSpace,
int componentCount,
int inputBufferLength,
int resultBufferLength,
int seed,
Action<JpegColorConverter.ComponentValues, Span<Vector4>, int> doValidate)
{ {
var converter = JpegColorConverter.GetConverter(JpegColorSpace.RGB); var converter = JpegColorConverter.GetConverter(colorSpace);
JpegColorConverter.ComponentValues values = CreateRandomValues(3); JpegColorConverter.ComponentValues values = CreateRandomValues(componentCount, inputBufferLength, seed);
Vector4[] result = new Vector4[resultBufferLength];
converter.ConvertToRGBA(values, this.result); converter.ConvertToRGBA(values, result);
for (int i = 0; i < ResultBufferLength; i++) for (int i = 0; i < resultBufferLength; i++)
{ {
float r = values.Component0[i]; doValidate(values, result, i);
float g = values.Component1[i];
float b = values.Component2[i];
Vector4 rgba = this.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);
} }
} }
} }

Loading…
Cancel
Save