From 53f42bc5af7dfcaa3347cbb2ddb791d5562157dc Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Thu, 19 Mar 2020 12:24:24 +0100 Subject: [PATCH] Review changes for the AlphaDecoder --- .../Formats/WebP/AlphaCompressionMethod.cs | 15 ++++++ src/ImageSharp/Formats/WebP/AlphaDecoder.cs | 52 +++++++------------ .../Formats/WebP/WebPAlphaFilterType.cs | 2 +- 3 files changed, 36 insertions(+), 33 deletions(-) create mode 100644 src/ImageSharp/Formats/WebP/AlphaCompressionMethod.cs diff --git a/src/ImageSharp/Formats/WebP/AlphaCompressionMethod.cs b/src/ImageSharp/Formats/WebP/AlphaCompressionMethod.cs new file mode 100644 index 000000000..52e3e3b61 --- /dev/null +++ b/src/ImageSharp/Formats/WebP/AlphaCompressionMethod.cs @@ -0,0 +1,15 @@ +namespace SixLabors.ImageSharp.Formats.WebP +{ + internal enum AlphaCompressionMethod + { + /// + /// No compression. + /// + NoCompression = 0, + + /// + /// Compressed using the WebP lossless format. + /// + WebPLosslessCompression = 1 + } +} diff --git a/src/ImageSharp/Formats/WebP/AlphaDecoder.cs b/src/ImageSharp/Formats/WebP/AlphaDecoder.cs index 6737c4d09..9d0b68e79 100644 --- a/src/ImageSharp/Formats/WebP/AlphaDecoder.cs +++ b/src/ImageSharp/Formats/WebP/AlphaDecoder.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Formats.WebP /// The width of the image. /// The height of the image. /// The (maybe compressed) alpha data. - /// The first byte of the alpha image stream contains information on ow to decode the stream. + /// The first byte of the alpha image stream contains information on how to decode the stream. /// Used for allocating memory during decoding. /// The configuration. public AlphaDecoder(int width, int height, IMemoryOwner data, byte alphaChunkHeader, MemoryAllocator memoryAllocator, Configuration configuration) @@ -30,32 +30,24 @@ namespace SixLabors.ImageSharp.Formats.WebP this.Data = data; this.LastRow = 0; - // Compression method: Either 0 (no compression) or 1 (Compressed using the WebP lossless format) - int method = alphaChunkHeader & 0x03; - if (method < 0 || method > 1) + var compression = (AlphaCompressionMethod)(alphaChunkHeader & 0x03); + if (compression != AlphaCompressionMethod.NoCompression && compression != AlphaCompressionMethod.WebPLosslessCompression) { - WebPThrowHelper.ThrowImageFormatException($"unexpected alpha compression method {method} found"); + WebPThrowHelper.ThrowImageFormatException($"unexpected alpha compression method {compression} found"); } - this.Compressed = !(method is 0); + this.Compressed = compression is AlphaCompressionMethod.WebPLosslessCompression; - // The filtering method used. Only values between 0 and 3 are valid. + // The filtering method used. Only values between 0 and 3 are valid. int filter = (alphaChunkHeader >> 2) & 0x03; - if (filter < 0 || filter > 3) + if (filter < (int)WebPAlphaFilterType.None || filter > (int)WebPAlphaFilterType.Gradient) { WebPThrowHelper.ThrowImageFormatException($"unexpected alpha filter method {filter} found"); } this.AlphaFilterType = (WebPAlphaFilterType)filter; - - // These INFORMATIVE bits are used to signal the pre-processing that has been performed during compression. - // The decoder can use this information to e.g. dither the values or smooth the gradients prior to display. - // 0: no pre-processing, 1: level reduction - this.PreProcessing = (alphaChunkHeader >> 4) & 0x03; - - this.Vp8LDec = new Vp8LDecoder(width, height, memoryAllocator); - this.Alpha = memoryAllocator.Allocate(width * height); + this.Vp8LDec = new Vp8LDecoder(width, height, memoryAllocator); if (this.Compressed) { @@ -102,12 +94,6 @@ namespace SixLabors.ImageSharp.Formats.WebP public int CropTop { get; } - /// - /// Gets a value indicating whether pre-processing was used during compression. - /// 0: no pre-processing, 1: level reduction. - /// - private int PreProcessing { get; } - /// /// Gets a value indicating whether the alpha channel uses compression. /// @@ -138,15 +124,16 @@ namespace SixLabors.ImageSharp.Formats.WebP if (this.Compressed is false) { Span dataSpan = this.Data.Memory.Span; - if (dataSpan.Length < (this.Width * this.Height)) + var pixelCount = this.Width * this.Height; + if (dataSpan.Length < pixelCount) { WebPThrowHelper.ThrowImageFormatException("not enough data in the ALPH chunk"); } Span alphaSpan = this.Alpha.Memory.Span; - if (this.AlphaFilterType == WebPAlphaFilterType.None) + if (this.AlphaFilterType is WebPAlphaFilterType.None) { - dataSpan.Slice(0, this.Width * this.Height).CopyTo(alphaSpan); + dataSpan.Slice(0, pixelCount).CopyTo(alphaSpan); return; } @@ -194,7 +181,7 @@ namespace SixLabors.ImageSharp.Formats.WebP } Span alphaSpan = this.Alpha.Memory.Span; - Span prev = this.PrevRow == 0 ? null : alphaSpan.Slice(this.Width * this.PrevRow); + Span prev = this.PrevRow is 0 ? null : alphaSpan.Slice(this.Width * this.PrevRow); for (int y = firstRow; y < lastRow; ++y) { switch (this.AlphaFilterType) @@ -223,8 +210,9 @@ namespace SixLabors.ImageSharp.Formats.WebP for (int i = 0; i < width; ++i) { - dst[i] = (byte)(pred + input[i]); - pred = dst[i]; + byte val = (byte)(pred + input[i]); + pred = val; + dst[i] = val; } } @@ -251,12 +239,12 @@ namespace SixLabors.ImageSharp.Formats.WebP } else { - byte top = prev[0]; - byte topLeft = top; - byte left = top; + byte prev0 = prev[0]; + byte topLeft = prev0; + byte left = prev0; for (int i = 0; i < width; ++i) { - top = prev[i]; + byte top = prev[i]; left = (byte)(input[i] + GradientPredictor(left, top, topLeft)); topLeft = top; dst[i] = left; diff --git a/src/ImageSharp/Formats/WebP/WebPAlphaFilterType.cs b/src/ImageSharp/Formats/WebP/WebPAlphaFilterType.cs index dfdc8281c..62e3de07b 100644 --- a/src/ImageSharp/Formats/WebP/WebPAlphaFilterType.cs +++ b/src/ImageSharp/Formats/WebP/WebPAlphaFilterType.cs @@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.WebP /// /// Enum for the different alpha filter types. /// - internal enum WebPAlphaFilterType + internal enum WebPAlphaFilterType : int { /// /// No filtering.