diff --git a/src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs b/src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs index 7a85889462..d12325f38b 100644 --- a/src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs +++ b/src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs @@ -88,9 +88,22 @@ namespace SixLabors.ImageSharp.Formats.WebP private uint[] DecodeImageStream(Vp8LDecoder decoder, int xSize, int ySize, bool isLevel0) { + int numberOfTransformsPresent = 0; if (isLevel0) { - this.ReadTransformations(xSize, ySize, decoder); + decoder.Transforms = new List(WebPConstants.MaxNumberOfTransforms); + + // Next bit indicates, if a transformation is present. + while (this.bitReader.ReadBit()) + { + if (numberOfTransformsPresent > WebPConstants.MaxNumberOfTransforms) + { + WebPThrowHelper.ThrowImageFormatException($"The maximum number of transforms of {WebPConstants.MaxNumberOfTransforms} was exceeded"); + } + + this.ReadTransformation(xSize, ySize, decoder); + numberOfTransformsPresent++; + } } // Color cache. @@ -571,54 +584,42 @@ namespace SixLabors.ImageSharp.Formats.WebP /// Reads the transformations, if any are present. /// /// Vp8LDecoder where the transformations will be stored. - private void ReadTransformations(int xSize, int ySize, Vp8LDecoder decoder) + private void ReadTransformation(int xSize, int ySize, Vp8LDecoder decoder) { - // Next bit indicates, if a transformation is present. - bool transformPresent = this.bitReader.ReadBit(); - int numberOfTransformsPresent = 0; - decoder.Transforms = new List(WebPConstants.MaxNumberOfTransforms); - while (transformPresent) + var transformType = (Vp8LTransformType)this.bitReader.ReadBits(2); + var transform = new Vp8LTransform(transformType, xSize, ySize); + switch (transformType) { - var transformType = (Vp8LTransformType)this.bitReader.ReadBits(2); - var transform = new Vp8LTransform(transformType, xSize, ySize); - switch (transformType) - { - case Vp8LTransformType.SubtractGreen: - // There is no data associated with this transform. - break; - case Vp8LTransformType.ColorIndexingTransform: - // The transform data contains color table size and the entries in the color table. - // 8 bit value for color table size. - uint numColors = this.bitReader.ReadBits(8) + 1; - int bits = (numColors > 16) ? 0 - : (numColors > 4) ? 1 - : (numColors > 2) ? 2 - : 3; - transform.XSize = LosslessUtils.SubSampleSize(transform.XSize, bits); - break; - - case Vp8LTransformType.PredictorTransform: - case Vp8LTransformType.CrossColorTransform: - { - transform.Bits = (int)this.bitReader.ReadBits(3) + 2; - transform.Data = this.DecodeImageStream( - decoder, - LosslessUtils.SubSampleSize(transform.XSize, transform.Bits), - LosslessUtils.SubSampleSize(transform.YSize, transform.Bits), - false); - break; - } - } - - decoder.Transforms.Add(transform); - numberOfTransformsPresent++; + case Vp8LTransformType.SubtractGreen: + // There is no data associated with this transform. + break; + case Vp8LTransformType.ColorIndexingTransform: + // The transform data contains color table size and the entries in the color table. + // 8 bit value for color table size. + uint numColors = this.bitReader.ReadBits(8) + 1; + int bits = (numColors > 16) ? 0 + : (numColors > 4) ? 1 + : (numColors > 2) ? 2 + : 3; + transform.XSize = LosslessUtils.SubSampleSize(transform.XSize, bits); + transform.Bits = bits; + transform.Data = this.DecodeImageStream(decoder, (int)numColors, 1, false); + break; - transformPresent = this.bitReader.ReadBit(); - if (numberOfTransformsPresent == WebPConstants.MaxNumberOfTransforms && transformPresent) - { - WebPThrowHelper.ThrowImageFormatException($"The maximum number of transforms of {WebPConstants.MaxNumberOfTransforms} was exceeded"); - } + case Vp8LTransformType.PredictorTransform: + case Vp8LTransformType.CrossColorTransform: + { + transform.Bits = (int)this.bitReader.ReadBits(3) + 2; + transform.Data = this.DecodeImageStream( + decoder, + LosslessUtils.SubSampleSize(transform.XSize, transform.Bits), + LosslessUtils.SubSampleSize(transform.YSize, transform.Bits), + false); + break; + } } + + decoder.Transforms.Add(transform); } /// diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebPDecoderTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebPDecoderTests.cs index 87ba6bce45..538cf29dd9 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/WebPDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/WebPDecoderTests.cs @@ -67,9 +67,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.WebP [WithFile(Lossless.GreenTransform2, PixelTypes.Rgba32)] [WithFile(Lossless.GreenTransform3, PixelTypes.Rgba32)] [WithFile(Lossless.GreenTransform4, PixelTypes.Rgba32)] - // TODO: Figure out whats wrong with those two images + // TODO: Reference decoder throws here MagickCorruptImageErrorException //[WithFile(Lossless.GreenTransform5, PixelTypes.Rgba32)] - //[WithFile(Lossless.GreenTransform6, PixelTypes.Rgba32)] public void WebpDecoder_CanDecode_Lossless_WithSubstractGreenTransform(TestImageProvider provider) where TPixel : struct, IPixel { @@ -86,18 +85,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.WebP [WithFile(Lossless.ColorIndexTransform3, PixelTypes.Rgba32)] [WithFile(Lossless.ColorIndexTransform4, PixelTypes.Rgba32)] [WithFile(Lossless.ColorIndexTransform5, PixelTypes.Rgba32)] - [WithFile(Lossless.ColorIndexTransform6, PixelTypes.Rgba32)] - [WithFile(Lossless.ColorIndexTransform7, PixelTypes.Rgba32)] - [WithFile(Lossless.ColorIndexTransform8, PixelTypes.Rgba32)] - [WithFile(Lossless.ColorIndexTransform9, PixelTypes.Rgba32)] - [WithFile(Lossless.ColorIndexTransform10, PixelTypes.Rgba32)] - [WithFile(Lossless.ColorIndexTransform11, PixelTypes.Rgba32)] - [WithFile(Lossless.ColorIndexTransform12, PixelTypes.Rgba32)] - [WithFile(Lossless.ColorIndexTransform13, PixelTypes.Rgba32)] - [WithFile(Lossless.ColorIndexTransform14, PixelTypes.Rgba32)] - [WithFile(Lossless.ColorIndexTransform15, PixelTypes.Rgba32)] - [WithFile(Lossless.ColorIndexTransform16, PixelTypes.Rgba32)] - [WithFile(Lossless.ColorIndexTransform17, PixelTypes.Rgba32)] public void WebpDecoder_CanDecode_Lossless_WithColorIndexTransform(TestImageProvider provider) where TPixel : struct, IPixel { @@ -111,10 +98,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.WebP [Theory] [WithFile(Lossless.PredictorTransform1, PixelTypes.Rgba32)] [WithFile(Lossless.PredictorTransform2, PixelTypes.Rgba32)] - [WithFile(Lossless.PredictorTransform3, PixelTypes.Rgba32)] - [WithFile(Lossless.PredictorTransform4, PixelTypes.Rgba32)] - [WithFile(Lossless.PredictorTransform5, PixelTypes.Rgba32)] - [WithFile(Lossless.PredictorTransform6, PixelTypes.Rgba32)] public void WebpDecoder_CanDecode_Lossless_WithPredictorTransform(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 01dc132458..e030db2f22 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -386,33 +386,16 @@ namespace SixLabors.ImageSharp.Tests public const string GreenTransform2 = "WebP/lossless2.webp"; public const string GreenTransform3 = "WebP/lossless3.webp"; public const string GreenTransform4 = "WebP/lossless_vec_1_4.webp"; - public const string GreenTransform5 = "WebP/lossless_vec_1_7.webp"; - public const string GreenTransform6 = "WebP/lossless_vec_2_4.webp"; + public const string GreenTransform5 = "WebP/lossless_vec_2_4.webp"; public const string CrossColorTransform1 = "WebP/lossless_vec_1_8.webp"; public const string CrossColorTransform2 = "WebP/lossless_vec_2_8.webp"; - public const string PredictorTransform1 = "WebP/lossless_vec_1_10.webp"; - public const string PredictorTransform2 = "WebP/lossless_vec_1_10.webp"; - public const string PredictorTransform3 = "WebP/lossless_vec_1_2.webp"; - public const string PredictorTransform4 = "WebP/lossless_vec_2_10.webp"; - public const string PredictorTransform5 = "WebP/lossless_vec_2_2.webp"; - public const string PredictorTransform6 = "WebP/near_lossless_75.webp"; + public const string PredictorTransform1 = "WebP/lossless_vec_1_2.webp"; + public const string PredictorTransform2 = "WebP/lossless_vec_2_2.webp"; public const string ColorIndexTransform1 = "WebP/lossless4.webp"; public const string ColorIndexTransform2 = "WebP/lossless_vec_1_1.webp"; - public const string ColorIndexTransform3 = "WebP/lossless_vec_1_11.webp"; - public const string ColorIndexTransform4 = "WebP/lossless_vec_1_13.webp"; - public const string ColorIndexTransform5 = "WebP/lossless_vec_1_15.webp"; - public const string ColorIndexTransform6 = "WebP/lossless_vec_1_3.webp"; - public const string ColorIndexTransform7 = "WebP/lossless_vec_1_5.webp"; - public const string ColorIndexTransform8 = "WebP/lossless_vec_1_7.webp"; - public const string ColorIndexTransform9 = "WebP/lossless_vec_1_9.webp"; - public const string ColorIndexTransform10 = "WebP/lossless_vec_2_1.webp"; - public const string ColorIndexTransform11 = "WebP/lossless_vec_2_11.webp"; - public const string ColorIndexTransform12 = "WebP/lossless_vec_2_13.webp"; - public const string ColorIndexTransform13 = "WebP/lossless_vec_2_15.webp"; - public const string ColorIndexTransform14 = "WebP/lossless_vec_2_3.webp"; - public const string ColorIndexTransform15 = "WebP/lossless_vec_2_5.webp"; - public const string ColorIndexTransform16 = "WebP/lossless_vec_2_7.webp"; - public const string ColorIndexTransform17 = "WebP/lossless_vec_2_9.webp"; + public const string ColorIndexTransform3 = "WebP/lossless_vec_1_5.webp"; + public const string ColorIndexTransform4 = "WebP/lossless_vec_2_1.webp"; + public const string ColorIndexTransform5 = "WebP/lossless_vec_2_5.webp"; } public static class Lossy