Browse Source

Fix convert to yuv: missed last uv row when height is uneven

pull/1552/head
Brian Popow 5 years ago
parent
commit
5b6d4d82fb
  1. 19
      src/ImageSharp/Formats/WebP/Lossy/YuvConversion.cs
  2. 6
      tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs
  3. 4
      tests/ImageSharp.Tests/TestImages.cs
  4. 3
      tests/Images/Input/WebP/testpattern_opaque.png
  5. 3
      tests/Images/Input/WebP/testpattern_opaque_small.png

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

@ -52,23 +52,23 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
PixelOperations<TPixel>.Instance.ToRgba32(configuration, rowSpan, rgbaRow0);
PixelOperations<TPixel>.Instance.ToRgba32(configuration, nextRowSpan, rgbaRow1);
rowsHaveAlpha = YuvConversion.CheckNonOpaque(rgbaRow0) && YuvConversion.CheckNonOpaque(rgbaRow1);
rowsHaveAlpha = CheckNonOpaque(rgbaRow0) && CheckNonOpaque(rgbaRow1);
// Downsample U/V planes, two rows at a time.
if (!rowsHaveAlpha)
{
YuvConversion.AccumulateRgb(rgbaRow0, rgbaRow1, tmpRgbSpan, width);
AccumulateRgb(rgbaRow0, rgbaRow1, tmpRgbSpan, width);
}
else
{
YuvConversion.AccumulateRgba(rgbaRow0, rgbaRow1, tmpRgbSpan, width);
AccumulateRgba(rgbaRow0, rgbaRow1, tmpRgbSpan, width);
}
YuvConversion.ConvertRgbaToUv(tmpRgbSpan, u.Slice(uvRowIndex * uvWidth), v.Slice(uvRowIndex * uvWidth), uvWidth);
ConvertRgbaToUv(tmpRgbSpan, u.Slice(uvRowIndex * uvWidth), v.Slice(uvRowIndex * uvWidth), uvWidth);
uvRowIndex++;
YuvConversion.ConvertRgbaToY(rgbaRow0, y.Slice(rowIndex * width), width);
YuvConversion.ConvertRgbaToY(rgbaRow1, y.Slice((rowIndex + 1) * width), width);
ConvertRgbaToY(rgbaRow0, y.Slice(rowIndex * width), width);
ConvertRgbaToY(rgbaRow1, y.Slice((rowIndex + 1) * width), width);
}
// Extra last row.
@ -76,14 +76,15 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
{
if (!rowsHaveAlpha)
{
YuvConversion.AccumulateRgb(rgbaRow0, rgbaRow0, tmpRgbSpan, width);
AccumulateRgb(rgbaRow0, rgbaRow0, tmpRgbSpan, width);
}
else
{
YuvConversion.AccumulateRgba(rgbaRow0, rgbaRow0, tmpRgbSpan, width);
AccumulateRgba(rgbaRow0, rgbaRow0, tmpRgbSpan, width);
}
YuvConversion.ConvertRgbaToY(rgbaRow0, y.Slice(rowIndex * width), width);
ConvertRgbaToY(rgbaRow0, y.Slice(rowIndex * width), width);
ConvertRgbaToUv(tmpRgbSpan, u.Slice(uvRowIndex * uvWidth), v.Slice(uvRowIndex * uvWidth), uvWidth);
}
}

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

@ -98,15 +98,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
}
[Theory]
[WithTestPatternImages(187, 221, PixelTypes.Rgba32)]
[WithTestPatternImages(100, 118, PixelTypes.Rgba32)]
[WithFile(TestPatternOpaque, PixelTypes.Rgba32)]
[WithFile(TestPatternOpaqueSmall, PixelTypes.Rgba32)]
public void Encode_Lossy_WorksWithTestPattern<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage();
// Encoding lossy images with transparency is not yet supported, therefor the test image will be made opaque.
image.Mutate(img => img.MakeOpaque());
var encoder = new WebpEncoder() { Lossy = true };
image.VerifyEncoder(provider, "webp", string.Empty, encoder);
}

4
tests/ImageSharp.Tests/TestImages.cs

@ -504,6 +504,10 @@ namespace SixLabors.ImageSharp.Tests
// Reference image as png
public const string Peak = "WebP/peak.png";
// Test pattern images for testing the encoder.
public const string TestPatternOpaque = "WebP/testpattern_opaque.png";
public const string TestPatternOpaqueSmall = "WebP/testpattern_opaque_small.png";
public static class Animated
{
public const string Animated1 = "WebP/animated-webp.webp";

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

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

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

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