diff --git a/src/ImageSharp/Formats/Webp/AlphaDecoder.cs b/src/ImageSharp/Formats/Webp/AlphaDecoder.cs index 4eb2aef4cf..a9508c2b65 100644 --- a/src/ImageSharp/Formats/Webp/AlphaDecoder.cs +++ b/src/ImageSharp/Formats/Webp/AlphaDecoder.cs @@ -61,7 +61,13 @@ internal class AlphaDecoder : IDisposable var bitReader = new Vp8LBitReader(data); this.LosslessDecoder = new WebpLosslessDecoder(bitReader, memoryAllocator, configuration); this.LosslessDecoder.DecodeImageStream(this.Vp8LDec, width, height, true); - this.Use8BDecode = this.Vp8LDec.Transforms.Count > 0 && Is8BOptimizable(this.Vp8LDec.Metadata); + + // Special case: if alpha data uses only the color indexing transform and + // doesn't use color cache (a frequent case), we will use DecodeAlphaData() + // method that only needs allocation of 1 byte per pixel (alpha channel). + this.Use8BDecode = this.Vp8LDec.Transforms.Count is 1 + && this.Vp8LDec.Transforms[0].TransformType == Vp8LTransformType.ColorIndexingTransform + && Is8BOptimizable(this.Vp8LDec.Metadata); } } diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs index af709c0d86..55c6233654 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs @@ -396,6 +396,17 @@ public class WebpDecoderTests image.CompareToOriginal(provider, ReferenceDecoder); } + // https://github.com/SixLabors/ImageSharp/issues/2257 + [Theory] + [WithFile(Lossy.Issue2257, PixelTypes.Rgba32)] + public void WebpDecoder_CanDecode_Issue2257(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); + } + [Theory] [WithFile(Lossless.LossLessCorruptImage3, PixelTypes.Rgba32)] public void WebpDecoder_ThrowImageFormatException_OnInvalidImages(TestImageProvider provider) diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs index 9796d89833..4eb8b3063d 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs @@ -267,28 +267,51 @@ public class WebpEncoderTests } [Theory] - [WithFile(TestImages.Png.Transparency, PixelTypes.Rgba32, false, 64020)] - [WithFile(TestImages.Png.Transparency, PixelTypes.Rgba32, true, 16200)] - public void Encode_Lossy_WithAlpha_Works(TestImageProvider provider, bool compressed, int expectedFileSize) + [WithFile(TestImages.Png.Transparency, PixelTypes.Rgba32, 64020)] + public void Encode_Lossy_WithAlpha_Works(TestImageProvider provider, int expectedFileSize) where TPixel : unmanaged, IPixel { var encoder = new WebpEncoder() { FileFormat = WebpFileFormatType.Lossy, - UseAlphaCompression = compressed + UseAlphaCompression = false }; using Image image = provider.GetImage(); string encodedFile = image.VerifyEncoder( provider, "webp", - $"with_alpha_compressed_{compressed}", + "with_alpha", encoder, ImageComparer.Tolerant(0.04f), referenceDecoder: new MagickReferenceDecoder()); int encodedBytes = File.ReadAllBytes(encodedFile).Length; - Assert.True(encodedBytes <= expectedFileSize); + Assert.True(encodedBytes <= expectedFileSize, $"encoded bytes are {encodedBytes} and should be smaller then expected file size of {expectedFileSize}"); + } + + [Theory] + [WithFile(TestImages.Png.Transparency, PixelTypes.Rgba32, 16200)] + public void Encode_Lossy_WithAlphaUsingCompression_Works(TestImageProvider provider, int expectedFileSize) + where TPixel : unmanaged, IPixel + { + var encoder = new WebpEncoder() + { + FileFormat = WebpFileFormatType.Lossy, + UseAlphaCompression = true + }; + + using Image image = provider.GetImage(); + string encodedFile = image.VerifyEncoder( + provider, + "webp", + "with_alpha_compressed", + encoder, + ImageComparer.Tolerant(0.04f), + referenceDecoder: new MagickReferenceDecoder()); + + int encodedBytes = File.ReadAllBytes(encodedFile).Length; + Assert.True(encodedBytes <= expectedFileSize, $"encoded bytes are {encodedBytes} and should be smaller then expected file size of {expectedFileSize}"); } [Theory] diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index fa76a2bd31..96b9381517 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -737,6 +737,7 @@ public static class TestImages // Issues public const string Issue1594 = "Webp/issues/Issue1594.webp"; public const string Issue2243 = "Webp/issues/Issue2243.webp"; + public const string Issue2257 = "Webp/issues/Issue2257.webp"; } } diff --git a/tests/Images/Input/Webp/issues/Issue2257.webp b/tests/Images/Input/Webp/issues/Issue2257.webp new file mode 100644 index 0000000000..a5a57a2e1a --- /dev/null +++ b/tests/Images/Input/Webp/issues/Issue2257.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:55f87aee4283615bad9705ac459867facba5b6be114d7e1ece51db7c1ef87916 +size 117810