Browse Source

Additional tests

pull/1552/head
Brian Popow 5 years ago
parent
commit
dd0242fe49
  1. 9
      src/ImageSharp/Formats/WebP/Lossy/Vp8Histogram.cs
  2. 2
      src/ImageSharp/Formats/WebP/Lossy/YuvConversion.cs
  3. 4
      src/ImageSharp/Formats/WebP/WebpEncoderCore.cs
  4. 79
      tests/ImageSharp.Tests/Formats/WebP/DominantCostRangeTests.cs
  5. 8
      tests/ImageSharp.Tests/Formats/WebP/ImageExtensionsTests.cs
  6. 2
      tests/ImageSharp.Tests/Formats/WebP/LosslessUtilsTests.cs
  7. 10
      tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs
  8. 115
      tests/ImageSharp.Tests/Formats/WebP/Vp8HistogramTests.cs
  9. 94
      tests/ImageSharp.Tests/Formats/WebP/Vp8ModeScoreTests.cs
  10. 83
      tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs
  11. 131
      tests/ImageSharp.Tests/Formats/WebP/YuvConversionTests.cs
  12. 6
      tests/ImageSharp.Tests/TestImages.cs
  13. 3
      tests/Images/Input/WebP/flag_of_germany.png
  14. 3
      tests/Images/Input/WebP/yuv_test.png

9
src/ImageSharp/Formats/WebP/Lossy/Vp8Histogram.cs

@ -18,6 +18,15 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy
private int lastNonZero;
/// <summary>
/// Initializes a new instance of the <see cref="Vp8Histogram" /> class.
/// </summary>
public Vp8Histogram()
{
this.maxValue = 0;
this.lastNonZero = 1;
}
public int GetAlpha()
{
// 'alpha' will later be clipped to [0..MAX_ALPHA] range, clamping outer

2
src/ImageSharp/Formats/WebP/Lossy/YuvConversion.cs

@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
PixelOperations<TPixel>.Instance.ToRgba32(configuration, rowSpan, rgbaRow0);
PixelOperations<TPixel>.Instance.ToRgba32(configuration, nextRowSpan, rgbaRow1);
var rowsHaveAlpha = CheckNonOpaque(rgbaRow0) && CheckNonOpaque(rgbaRow1);
bool rowsHaveAlpha = CheckNonOpaque(rgbaRow0) && CheckNonOpaque(rgbaRow1);
// Downsample U/V planes, two rows at a time.
if (!rowsHaveAlpha)

4
src/ImageSharp/Formats/WebP/WebpEncoderCore.cs

@ -84,12 +84,12 @@ namespace SixLabors.ImageSharp.Formats.Webp
if (this.lossy)
{
var enc = new Vp8Encoder(this.memoryAllocator, this.configuration, image.Width, image.Height, this.quality, this.method, this.entropyPasses);
using var enc = new Vp8Encoder(this.memoryAllocator, this.configuration, image.Width, image.Height, this.quality, this.method, this.entropyPasses);
enc.Encode(image, stream);
}
else
{
var enc = new Vp8LEncoder(this.memoryAllocator, this.configuration, image.Width, image.Height, this.quality, this.method);
using var enc = new Vp8LEncoder(this.memoryAllocator, this.configuration, image.Width, image.Height, this.quality, this.method);
enc.Encode(image, stream);
}
}

79
tests/ImageSharp.Tests/Formats/WebP/DominantCostRangeTests.cs

@ -0,0 +1,79 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Formats.Webp.Lossless;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Webp
{
[Trait("Format", "Webp")]
public class DominantCostRangeTests
{
[Fact]
public void DominantCost_Constructor()
{
var dominantCostRange = new DominantCostRange();
Assert.Equal(0, dominantCostRange.LiteralMax);
Assert.Equal(double.MaxValue, dominantCostRange.LiteralMin);
Assert.Equal(0, dominantCostRange.RedMax);
Assert.Equal(double.MaxValue, dominantCostRange.RedMin);
Assert.Equal(0, dominantCostRange.BlueMax);
Assert.Equal(double.MaxValue, dominantCostRange.BlueMin);
}
[Fact]
public void UpdateDominantCostRange_Works()
{
// arrange
var dominantCostRange = new DominantCostRange();
var histogram = new Vp8LHistogram(10)
{
LiteralCost = 1.0d,
RedCost = 2.0d,
BlueCost = 3.0d
};
// act
dominantCostRange.UpdateDominantCostRange(histogram);
// assert
Assert.Equal(1.0d, dominantCostRange.LiteralMax);
Assert.Equal(1.0d, dominantCostRange.LiteralMin);
Assert.Equal(2.0d, dominantCostRange.RedMax);
Assert.Equal(2.0d, dominantCostRange.RedMin);
Assert.Equal(3.0d, dominantCostRange.BlueMax);
Assert.Equal(3.0d, dominantCostRange.BlueMin);
}
[Theory]
[InlineData(3, 19)]
[InlineData(4, 34)]
public void GetHistoBinIndex_Works(int partitions, int expectedIndex)
{
// arrange
var dominantCostRange = new DominantCostRange()
{
BlueMax = 253.4625,
BlueMin = 109.0,
LiteralMax = 285.0,
LiteralMin = 133.0,
RedMax = 191.0,
RedMin = 109.0
};
var histogram = new Vp8LHistogram(6)
{
LiteralCost = 247.0d,
RedCost = 112.0d,
BlueCost = 202.0d,
BitCost = 733.0d
};
dominantCostRange.UpdateDominantCostRange(histogram);
// act
int binIndex = dominantCostRange.GetHistoBinIndex(histogram, partitions);
// assert
Assert.Equal(expectedIndex, binIndex);
}
}
}

8
tests/ImageSharp.Tests/Formats/WebP/ImageExtensionsTest.cs → tests/ImageSharp.Tests/Formats/WebP/ImageExtensionsTests.cs

@ -11,11 +11,11 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Webp
{
[Trait("Format", "Webp")]
public class ImageExtensionsTest
public class ImageExtensionsTests
{
private readonly Configuration configuration;
public ImageExtensionsTest()
public ImageExtensionsTests()
{
this.configuration = new Configuration();
this.configuration.AddWebp();
@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
[Fact]
public void SaveAsWebp_Path()
{
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTests));
string file = Path.Combine(dir, "SaveAsWebp_Path.webp");
using (var image = new Image<Rgba32>(this.configuration, 10, 10))
@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
[Fact]
public async Task SaveAsWebpAsync_Path()
{
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTests));
string file = Path.Combine(dir, "SaveAsWebpAsync_Path.webp");
using (var image = new Image<Rgba32>(this.configuration, 10, 10))

2
tests/ImageSharp.Tests/Formats/WebP/LosslessUtilsTests.cs

@ -5,7 +5,7 @@ using SixLabors.ImageSharp.Formats.Webp.Lossless;
using SixLabors.ImageSharp.Tests.TestUtilities;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.WebP
namespace SixLabors.ImageSharp.Tests.Formats.Webp
{
[Trait("Format", "Webp")]
public class LosslessUtilsTests

10
tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs

@ -11,7 +11,7 @@ using SixLabors.ImageSharp.Tests.TestUtilities;
#endif
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.WebP
namespace SixLabors.ImageSharp.Tests.Formats.Webp
{
[Trait("Format", "Webp")]
public class PredictorEncoderTests
@ -82,14 +82,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.WebP
};
// Convert image pixels to bgra array.
var imgBytes = File.ReadAllBytes(TestImageFullPath(TestImages.WebP.Peak));
byte[] imgBytes = File.ReadAllBytes(TestImageFullPath(TestImages.WebP.Peak));
using var image = Image.Load<Rgba32>(imgBytes);
uint[] bgra = ToBgra(image);
int colorTransformBits = 3;
int transformWidth = LosslessUtils.SubSampleSize(image.Width, colorTransformBits);
int transformHeight = LosslessUtils.SubSampleSize(image.Height, colorTransformBits);
var transformData = new uint[transformWidth * transformHeight];
uint[] transformData = new uint[transformWidth * transformHeight];
// act
PredictorEncoder.ColorSpaceTransform(image.Width, image.Height, colorTransformBits, 75, bgra, transformData);
@ -111,14 +111,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.WebP
};
// Convert image pixels to bgra array.
var imgBytes = File.ReadAllBytes(TestImageFullPath(TestImages.WebP.Lossless.BikeSmall));
byte[] imgBytes = File.ReadAllBytes(TestImageFullPath(TestImages.WebP.Lossless.BikeSmall));
using var image = Image.Load<Rgba32>(imgBytes, new WebpDecoder());
uint[] bgra = ToBgra(image);
int colorTransformBits = 4;
int transformWidth = LosslessUtils.SubSampleSize(image.Width, colorTransformBits);
int transformHeight = LosslessUtils.SubSampleSize(image.Height, colorTransformBits);
var transformData = new uint[transformWidth * transformHeight];
uint[] transformData = new uint[transformWidth * transformHeight];
// act
PredictorEncoder.ColorSpaceTransform(image.Width, image.Height, colorTransformBits, 75, bgra, transformData);

115
tests/ImageSharp.Tests/Formats/WebP/Vp8HistogramTests.cs

@ -0,0 +1,115 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using SixLabors.ImageSharp.Formats.WebP.Lossy;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Webp
{
[Trait("Format", "Webp")]
public class Vp8HistogramTests
{
public static IEnumerable<object[]> Data
{
get
{
var result = new List<object[]>();
result.Add(new object[]
{
new byte[]
{
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 19, 16, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 19, 16, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 19, 16, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 19, 16, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 19, 16, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 19, 16, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 19, 16, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 19, 16, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 19, 16, 204, 204, 204,
204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 19, 16, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
204, 204, 204, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 19, 16, 204, 204, 204,
204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 19, 16, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
204, 204, 204, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 19, 16, 204, 204, 204,
204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 19, 16, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
204, 204, 204, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 24, 16, 204, 204, 204,
204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
204, 204, 204
},
new byte[]
{
128, 128, 128, 128, 129, 129, 129, 129, 127, 127, 127, 127, 129, 129, 129, 129, 128, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 128, 128, 128, 128, 129, 129,
129, 129, 127, 127, 127, 127, 129, 129, 129, 129, 129, 128, 127, 127, 128, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 128, 128, 128, 128, 129, 129, 129, 129, 127, 127, 127, 127,
129, 129, 129, 129, 129, 129, 128, 127, 129, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 128, 128, 128, 128, 129, 129, 129, 129, 127, 127, 127, 127, 129, 129, 129, 129, 129, 129,
129, 128, 129, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 128, 128, 127, 127, 129,
129, 129, 129, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
204, 204, 204, 204, 204, 204, 204, 204, 129, 129, 128, 128, 129, 129, 129, 129, 204, 204, 204,
204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
204, 204, 129, 129, 129, 129, 129, 129, 129, 129, 204, 204, 204, 204, 204, 204, 204, 204, 204,
204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 129, 129, 129, 129,
129, 129, 129, 129, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
204, 204, 204, 204, 204, 204, 204, 204, 204
}
});
return result;
}
}
[Fact]
public void GetAlpha_WithEmptyHistogram_Works()
{
// arrange
var histogram = new Vp8Histogram();
// act
int alpha = histogram.GetAlpha();
// assert
Assert.Equal(0, alpha);
}
[Theory]
[MemberData(nameof(Data))]
public void GetAlpha_Works(byte[] reference, byte[] pred)
{
// arrange
var histogram = new Vp8Histogram();
histogram.CollectHistogram(reference, pred, 0, 1);
// act
int alpha = histogram.GetAlpha();
// assert
Assert.Equal(1054, alpha);
}
[Theory]
[MemberData(nameof(Data))]
public void Merge_Works(byte[] reference, byte[] pred)
{
// arrange
var histogram1 = new Vp8Histogram();
histogram1.CollectHistogram(reference, pred, 0, 1);
var histogram2 = new Vp8Histogram();
histogram1.Merge(histogram2);
// act
int alpha = histogram2.GetAlpha();
// assert
Assert.Equal(1054, alpha);
}
}
}

94
tests/ImageSharp.Tests/Formats/WebP/Vp8ModeScoreTests.cs

@ -0,0 +1,94 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Formats.Webp.Lossy;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Webp
{
[Trait("Format", "Webp")]
public class Vp8ModeScoreTests
{
[Fact]
public void InitScore_Works()
{
var score = new Vp8ModeScore();
score.InitScore();
Assert.Equal(0, score.D);
Assert.Equal(0, score.SD);
Assert.Equal(0, score.R);
Assert.Equal(0, score.H);
Assert.Equal(0u, score.Nz);
Assert.Equal(Vp8ModeScore.MaxCost, score.Score);
}
[Fact]
public void CopyScore_Works()
{
// arrange
var score1 = new Vp8ModeScore
{
Score = 123,
Nz = 1,
D = 2,
H = 3,
ModeI16 = 4,
ModeUv = 5,
R = 6,
SD = 7
};
var score2 = new Vp8ModeScore();
score2.InitScore();
// act
score2.CopyScore(score1);
// assert
Assert.Equal(score1.D, score2.D);
Assert.Equal(score1.SD, score2.SD);
Assert.Equal(score1.R, score2.R);
Assert.Equal(score1.H, score2.H);
Assert.Equal(score1.Nz, score2.Nz);
Assert.Equal(score1.Score, score2.Score);
}
[Fact]
public void AddScore_Works()
{
// arrange
var score1 = new Vp8ModeScore
{
Score = 123,
Nz = 1,
D = 2,
H = 3,
ModeI16 = 4,
ModeUv = 5,
R = 6,
SD = 7
};
var score2 = new Vp8ModeScore
{
Score = 123,
Nz = 1,
D = 2,
H = 3,
ModeI16 = 4,
ModeUv = 5,
R = 6,
SD = 7
};
// act
score2.AddScore(score1);
// assert
Assert.Equal(4, score2.D);
Assert.Equal(14, score2.SD);
Assert.Equal(12, score2.R);
Assert.Equal(6, score2.H);
Assert.Equal(1u, score2.Nz);
Assert.Equal(246, score2.Score);
}
}
}

83
tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs

@ -13,6 +13,24 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
[Trait("Format", "Webp")]
public class WebpEncoderTests
{
[Theory]
[WithFile(Flag, PixelTypes.Rgba32)]
[WithFile(TestImages.Png.PalettedTwoColor, PixelTypes.Rgba32)]
[WithFile(TestImages.Png.Paletted256Colors, PixelTypes.Rgba32)]
public void Encode_Lossless_WithPalette_Works<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
var encoder = new WebpEncoder()
{
Lossy = false,
Quality = 100,
Method = 6
};
using Image<TPixel> image = provider.GetImage();
image.VerifyEncoder(provider, "webp", string.Empty, encoder);
}
[Theory]
[WithFile(TestImages.Bmp.Car, PixelTypes.Rgba32, 100)]
[WithFile(TestImages.Bmp.Car, PixelTypes.Rgba32, 80)]
@ -32,25 +50,32 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
}
[Theory]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 0)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 1)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 2)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 3)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 4)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 5)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 6)]
public void Encode_Lossless_WithDifferentMethods_Works<TPixel>(TestImageProvider<TPixel> provider, int method)
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 0, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 1, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 2, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 3, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 4, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 5, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 6, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 0, 100)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 1, 100)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 2, 100)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 3, 100)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 4, 100)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 5, 100)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 6, 100)]
public void Encode_Lossless_WithDifferentMethodAndQuality_Works<TPixel>(TestImageProvider<TPixel> provider, int method, int quality)
where TPixel : unmanaged, IPixel<TPixel>
{
var encoder = new WebpEncoder()
{
Lossy = false,
Method = method,
Quality = 75
Quality = quality
};
using Image<TPixel> image = provider.GetImage();
string testOutputDetails = string.Concat("lossless", "_m", method);
string testOutputDetails = string.Concat("lossless", "_m", method, "_q", quality);
image.VerifyEncoder(provider, "webp", testOutputDetails, encoder);
}
@ -73,17 +98,23 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
}
[Theory]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 0)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 1)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 2)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 3)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 4)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 5)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 6)]
public void Encode_Lossy_WithDifferentMethods_Works<TPixel>(TestImageProvider<TPixel> provider, int method)
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 0, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 1, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 2, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 3, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 4, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 5, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 6, 75)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 0, 100)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 1, 100)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 2, 100)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 3, 100)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 4, 100)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 5, 100)]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 6, 100)]
public void Encode_Lossy_WithDifferentMethodsAndQuality_Works<TPixel>(TestImageProvider<TPixel> provider, int method, int quality)
where TPixel : unmanaged, IPixel<TPixel>
{
int quality = 75;
var encoder = new WebpEncoder()
{
Lossy = true,
@ -92,7 +123,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
};
using Image<TPixel> image = provider.GetImage();
string testOutputDetails = string.Concat("lossy", "_m", method);
string testOutputDetails = string.Concat("lossy", "_m", method, "_q", quality);
image.VerifyEncoder(provider, "webp", testOutputDetails, encoder, customComparer: GetComparer(quality));
}
@ -108,6 +139,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
image.VerifyEncoder(provider, "webp", string.Empty, encoder, ImageComparer.Tolerant(0.04f));
}
[Theory]
[WithFile(TestPatternOpaque, PixelTypes.Rgba32)]
[WithFile(TestPatternOpaqueSmall, PixelTypes.Rgba32)]
public void Encode_Lossless_WorksWithTestPattern<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage();
var encoder = new WebpEncoder() { Lossy = false };
image.VerifyEncoder(provider, "webp", string.Empty, encoder);
}
[Fact]
public void Encode_Lossless_OneByOnePixel_Works()
{

131
tests/ImageSharp.Tests/Formats/WebP/YuvConversionTests.cs

@ -0,0 +1,131 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats.Webp.Lossy;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Webp
{
[Trait("Format", "Webp")]
public class YuvConversionTests
{
[Theory]
[WithFile(TestImages.WebP.Yuv, PixelTypes.Rgba32)]
public void ConvertRgbToYuv_Works<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
// arrange
using Image<TPixel> image = provider.GetImage();
Configuration config = image.GetConfiguration();
MemoryAllocator memoryAllocator = config.MemoryAllocator;
int pixels = image.Width * image.Height;
using System.Buffers.IMemoryOwner<byte> yBuffer = memoryAllocator.Allocate<byte>(pixels);
using System.Buffers.IMemoryOwner<byte> uBuffer = memoryAllocator.Allocate<byte>(pixels / 2);
using System.Buffers.IMemoryOwner<byte> vBuffer = memoryAllocator.Allocate<byte>(pixels / 2);
Span<byte> y = yBuffer.GetSpan();
Span<byte> u = uBuffer.GetSpan();
Span<byte> v = vBuffer.GetSpan();
byte[] expectedY =
{
82, 82, 82, 82, 128, 135, 134, 129, 167, 179, 176, 172, 192, 201, 200, 204, 188, 172, 175, 177, 168,
151, 154, 154, 153, 152, 151, 151, 152, 160, 160, 160, 160, 82, 82, 82, 82, 140, 137, 135, 116, 174,
183, 176, 162, 196, 199, 199, 210, 188, 166, 176, 181, 170, 145, 155, 154, 153, 154, 151, 151, 150,
162, 159, 160, 160, 82, 82, 83, 82, 142, 139, 137, 117, 176, 184, 177, 164, 195, 199, 198, 210, 188,
165, 175, 180, 169, 145, 155, 154, 153, 154, 152, 151, 150, 163, 160, 160, 160, 82, 82, 82, 82, 124,
122, 120, 101, 161, 171, 165, 151, 197, 209, 208, 210, 197, 174, 183, 189, 175, 148, 158, 158, 155,
151, 148, 148, 147, 159, 156, 156, 159, 128, 140, 142, 124, 189, 185, 183, 167, 201, 199, 198, 209,
179, 165, 171, 179, 160, 145, 151, 152, 151, 154, 152, 151, 153, 164, 160, 160, 160, 170, 170, 170,
169, 135, 137, 139, 122, 185, 182, 180, 165, 201, 200, 199, 210, 180, 166, 173, 180, 162, 145, 153,
153, 151, 154, 151, 150, 152, 164, 160, 159, 159, 170, 170, 170, 170, 134, 135, 137, 120, 184, 180,
177, 164, 200, 198, 196, 210, 181, 167, 174, 181, 163, 146, 155, 155, 153, 154, 152, 150, 152, 163,
160, 159, 159, 167, 167, 167, 168, 129, 116, 117, 101, 167, 166, 164, 149, 205, 210, 209, 210, 191,
177, 184, 191, 170, 149, 158, 159, 153, 151, 148, 146, 148, 159, 155, 155, 155, 170, 169, 170, 170,
167, 174, 175, 161, 201, 201, 200, 204, 178, 173, 174, 185, 159, 148, 155, 158, 152, 152, 151, 150,
153, 162, 159, 158, 160, 170, 169, 169, 168, 109, 122, 120, 129, 179, 183, 184, 171, 199, 200, 198,
210, 172, 166, 170, 179, 155, 145, 150, 152, 149, 155, 152, 150, 155, 164, 161, 159, 162, 170, 170,
170, 170, 92, 111, 109, 115, 176, 176, 177, 165, 198, 198, 196, 209, 174, 170, 173, 183, 159, 148,
155, 156, 152, 154, 152, 150, 154, 163, 160, 158, 159, 166, 166, 168, 169, 98, 117, 116, 117, 172,
162, 164, 152, 209, 210, 210, 210, 184, 179, 183, 192, 164, 151, 157, 159, 150, 150, 148, 146, 150,
159, 155, 154, 157, 170, 169, 170, 170, 117, 136, 134, 123, 192, 196, 196, 197, 179, 180, 180, 191,
159, 155, 159, 164, 153, 151, 152, 150, 154, 160, 157, 155, 160, 170, 166, 167, 165, 120, 134, 135,
139, 69, 87, 86, 90, 201, 199, 199, 208, 165, 166, 167, 177, 148, 145, 148, 151, 150, 155, 153, 150,
157, 165, 162, 159, 165, 170, 169, 170, 166, 84, 107, 108, 111, 49, 66, 64, 71, 200, 199, 198, 208,
171, 173, 174, 184, 155, 150, 155, 157, 152, 153, 153, 149, 156, 163, 160, 157, 162, 167, 165, 169,
167, 97, 121, 121, 125, 60, 77, 75, 76, 204, 210, 210, 210, 179, 180, 181, 191, 158, 152, 156, 159,
150, 150, 149, 146, 152, 159, 156, 153, 160, 170, 169, 170, 170, 112, 135, 136, 138, 71, 88, 86, 79,
188, 188, 188, 197, 160, 162, 163, 170, 152, 150, 152, 151, 154, 157, 156, 152, 160, 167, 164, 164,
161, 135, 146, 150, 143, 77, 98, 99, 103, 51, 62, 60, 62, 172, 166, 165, 174, 145, 145, 145, 150,
152, 155, 154, 150, 160, 165, 163, 159, 168, 170, 168, 170, 151, 80, 104, 109, 101, 44, 63, 63, 66,
55, 52, 53, 51, 175, 176, 175, 183, 151, 153, 155, 158, 151, 152, 152, 148, 157, 161, 160, 156, 164,
168, 165, 169, 156, 100, 122, 126, 118, 60, 79, 79, 81, 54, 52, 52, 51, 177, 181, 180, 188, 153,
153, 155, 159, 149, 150, 150, 146, 155, 159, 157, 153, 164, 170, 169, 170, 170, 109, 131, 136, 127,
66, 86, 86, 87, 46, 43, 43, 47, 168, 170, 169, 175, 151, 151, 152, 153, 153, 155, 154, 150, 160,
164, 162, 160, 161, 151, 157, 165, 144, 88, 109, 114, 105, 55, 69, 68, 67, 62, 56, 56, 59, 151, 145,
145, 148, 154, 154, 154, 150, 162, 164, 163, 159, 170, 170, 167, 170, 135, 80, 100, 110, 89, 41, 61,
64, 59, 56, 53, 50, 50, 94, 85, 86, 79, 154, 155, 155, 158, 152, 152, 152, 148, 159, 161, 160, 155,
166, 169, 165, 169, 146, 104, 122, 131, 110, 61, 80, 83, 75, 53, 53, 48, 47, 84, 74, 75, 75, 154,
154, 154, 158, 151, 150, 150, 146, 158, 159, 158, 154, 167, 170, 169, 170, 153, 108, 127, 136, 113,
63, 83, 87, 78, 48, 46, 43, 41, 81, 71, 72, 74, 153, 153, 153, 155, 153, 152, 152, 148, 160, 161,
159, 157, 165, 165, 166, 170, 143, 101, 118, 127, 104, 60, 75, 78, 70, 56, 51, 48, 46, 85, 76, 77,
81, 152, 154, 154, 151, 164, 164, 163, 159, 170, 170, 167, 170, 121, 84, 98, 114, 78, 44, 60, 68,
52, 56, 53, 48, 56, 96, 85, 85, 83, 107, 105, 106, 100, 151, 151, 152, 148, 160, 160, 160, 155, 169,
170, 166, 169, 134, 108, 121, 135, 98, 63, 79, 87, 69, 53, 53, 46, 50, 85, 73, 73, 71, 104, 95, 96,
97, 151, 151, 151, 148, 160, 159, 159, 155, 169, 170, 170, 170, 137, 108, 121, 136, 99, 63, 78, 87,
67, 51, 48, 43, 48, 85, 73, 72, 71, 105, 96, 97, 98, 152, 150, 150, 147, 160, 159, 159, 155, 169,
170, 169, 170, 140, 111, 125, 139, 102, 67, 81, 87, 67, 50, 47, 41, 46, 83, 71, 71, 70, 103, 96, 96,
98, 160, 162, 163, 159, 170, 170, 167, 170, 109, 91, 98, 117, 70, 49, 60, 72, 49, 55, 54, 46, 62,
95, 84, 81, 85, 107, 104, 105, 103, 96, 98, 97, 100, 160, 159, 160, 156, 170, 170, 167, 169, 122,
111, 118, 136, 87, 66, 77, 88, 62, 52, 53, 43, 56, 85, 74, 71, 76, 105, 95, 96, 96, 98, 100, 100,
100, 160, 160, 160, 156, 170, 170, 167, 170, 120, 109, 116, 134, 86, 64, 75, 86, 60, 53, 51, 43, 56,
86, 75, 72, 77, 106, 96, 97, 96, 97, 100, 100, 100, 160, 160, 160, 159, 169, 170, 168, 170, 129,
115, 117, 123, 90, 71, 76, 79, 62, 51, 51, 47, 59, 79, 75, 74, 81, 100, 97, 98, 98, 100, 100, 100,
100
};
byte[] expectedU =
{
90, 90, 59, 63, 36, 38, 23, 20, 34, 35, 47, 48, 70, 82, 104, 121, 121, 90, 90, 61, 69, 37, 42, 22,
18, 33, 32, 47, 47, 67, 75, 97, 113, 120, 59, 61, 30, 37, 22, 20, 38, 36, 50, 50, 78, 83, 113, 122,
142, 166, 164, 63, 69, 37, 43, 20, 18, 34, 32, 48, 47, 70, 73, 102, 110, 136, 166, 166, 36, 37, 22,
20, 38, 35, 50, 49, 80, 80, 116, 119, 145, 165, 185, 197, 193, 38, 42, 20, 18, 35, 32, 48, 47, 72,
72, 106, 108, 142, 165, 184, 191, 194, 23, 22, 38, 34, 50, 48, 81, 77, 117, 115, 150, 160, 184, 194,
212, 220, 217, 20, 18, 36, 32, 49, 47, 76, 71, 111, 108, 148, 164, 185, 190, 208, 217, 219, 34, 33,
50, 48, 80, 73, 116, 111, 150, 154, 184, 190, 213, 217, 226, 232, 232, 35, 32, 49, 47, 80, 72, 115,
107, 154, 164, 187, 189, 211, 216, 228, 237, 235, 47, 46, 77, 70, 115, 106, 149, 148, 184, 187, 213,
214, 226, 230, 227, 223, 224, 48, 47, 83, 73, 119, 108, 159, 164, 190, 189, 214, 216, 229, 236, 229,
222, 220, 70, 67, 113, 101, 145, 142, 184, 185, 213, 211, 226, 229, 226, 226, 218, 211, 212, 82, 75,
122, 110, 165, 165, 193, 190, 217, 216, 231, 236, 226, 222, 214, 208, 207, 104, 97, 142, 136, 186,
184, 212, 208, 227, 228, 227, 229, 218, 214, 196, 185, 188, 121, 113, 166, 166, 197, 191, 220, 217,
232, 237, 223, 222, 211, 208, 185, 173, 172, 121, 120, 164, 166, 193, 194, 217, 219, 232, 235, 224,
220, 212, 207, 188, 172, 172
};
byte[] expectedV =
{
240, 240, 201, 206, 172, 174, 136, 136, 92, 90, 55, 50, 37, 30, 26, 23, 23, 240, 240, 204, 213, 173,
179, 141, 141, 96, 98, 56, 54, 38, 31, 27, 25, 23, 201, 204, 164, 172, 129, 135, 82, 87, 46, 47, 33,
29, 25, 23, 20, 16, 16, 206, 213, 172, 180, 137, 141, 93, 99, 54, 54, 36, 31, 26, 25, 21, 17, 16,
172, 173, 129, 138, 81, 89, 45, 49, 32, 30, 24, 24, 19, 16, 42, 55, 51, 174, 179, 136, 141, 89, 99,
51, 55, 35, 31, 26, 25, 21, 17, 39, 48, 52, 136, 141, 82, 92, 45, 51, 31, 32, 24, 24, 19, 17, 43,
51, 74, 85, 81, 136, 141, 87, 99, 49, 55, 32, 32, 25, 25, 20, 17, 41, 46, 69, 81, 83, 92, 96, 46,
53, 32, 34, 24, 25, 18, 18, 44, 47, 76, 81, 103, 117, 116, 90, 97, 48, 54, 30, 31, 24, 25, 18, 17,
43, 46, 74, 80, 103, 118, 122, 55, 57, 33, 36, 24, 26, 19, 20, 44, 43, 76, 77, 102, 111, 138, 159,
157, 50, 54, 30, 31, 24, 25, 17, 17, 47, 46, 77, 79, 106, 118, 143, 164, 168, 37, 38, 25, 26, 19,
21, 43, 41, 75, 73, 103, 106, 138, 152, 174, 195, 194, 30, 31, 23, 25, 16, 17, 51, 46, 81, 79, 111,
118, 151, 164, 188, 205, 206, 26, 27, 20, 21, 43, 39, 74, 69, 103, 102, 138, 143, 174, 188, 204,
216, 218, 23, 25, 16, 17, 55, 48, 85, 81, 117, 118, 159, 164, 195, 205, 216, 227, 227, 23, 23, 16,
16, 51, 52, 81, 83, 116, 122, 157, 168, 194, 206, 218, 227, 227
};
// act
YuvConversion.ConvertRgbToYuv(image, config, memoryAllocator, y, u, v);
// assert
Assert.True(expectedY.AsSpan().SequenceEqual(y));
Assert.True(expectedU.AsSpan().SequenceEqual(u.Slice(0, expectedU.Length)));
Assert.True(expectedV.AsSpan().SequenceEqual(v.Slice(0, expectedV.Length)));
}
}
}

6
tests/ImageSharp.Tests/TestImages.cs

@ -508,6 +508,12 @@ namespace SixLabors.ImageSharp.Tests
public const string TestPatternOpaque = "WebP/testpattern_opaque.png";
public const string TestPatternOpaqueSmall = "WebP/testpattern_opaque_small.png";
// Test image for encoding image with a palette.
public const string Flag = "WebP/flag_of_germany.png";
// Test images for converting rgb data to yuv.
public const string Yuv = "WebP/yuv_test.png";
public static class Animated
{
public const string Animated1 = "WebP/animated-webp.webp";

3
tests/Images/Input/WebP/flag_of_germany.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:26bf39cea75210c9132eec4567f1f63c870b1eec3b541cfc25da7b5095902f41
size 72315

3
tests/Images/Input/WebP/yuv_test.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:96b86c39cad831c97c6ef9633d4d2d04ea0382547514dda5b1f639e10d7207fa
size 3389
Loading…
Cancel
Save