diff --git a/src/ImageSharp/Formats/WebP/Vp8LBitReader.cs b/src/ImageSharp/Formats/WebP/Vp8LBitReader.cs
index bcde6e74c..39ee78cd6 100644
--- a/src/ImageSharp/Formats/WebP/Vp8LBitReader.cs
+++ b/src/ImageSharp/Formats/WebP/Vp8LBitReader.cs
@@ -8,15 +8,15 @@ namespace SixLabors.ImageSharp.Formats.WebP
///
/// A bit reader for VP8 streams.
///
- public class Vp8LBitreader
+ public class Vp8LBitReader
{
private readonly Stream stream;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The stream to read from.
- public Vp8LBitreader(Stream stream)
+ public Vp8LBitReader(Stream stream)
{
this.stream = new MemoryStream();
stream.CopyTo(this.stream);
@@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
private int Bit { get; set; }
///
- /// Check if the offset is inside the stream length.
+ /// Gets a value indicating whether the offset is inside the stream length.
///
private bool ValidPosition
{
@@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// True, if the bit is one, otherwise false.
public bool ReadBit()
{
- if (!ValidPosition)
+ if (!this.ValidPosition)
{
WebPThrowHelper.ThrowImageFormatException("The image stream does not contain enough data");
}
diff --git a/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs b/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs
index 72000b8e9..b8bbf7599 100644
--- a/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs
+++ b/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs
@@ -230,10 +230,70 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
// The first 28 bits of the bitstream specify the width and height of the image.
- var bitReader = new Vp8LBitreader(this.currentStream);
+ var bitReader = new Vp8LBitReader(this.currentStream);
uint width = bitReader.Read(WebPConstants.Vp8LImageSizeBits) + 1;
uint height = bitReader.Read(WebPConstants.Vp8LImageSizeBits) + 1;
+ // The alpha_is_used flag should be set to 0 when all alpha values are 255 in the picture, and 1 otherwise.
+ bool alphaIsUsed = bitReader.ReadBit();
+
+ // The next 3 bytes are the version. The version_number is a 3 bit code that must be set to 0.
+ // Any other value should be treated as an error.
+ uint version = bitReader.Read(3);
+ if (version != 0)
+ {
+ WebPThrowHelper.ThrowImageFormatException($"Unexpected webp version number: {version}");
+ }
+
+ // Next bit indicates, if a transformation is present.
+ bool transformPresent = bitReader.ReadBit();
+ int numberOfTransformsPresent = 0;
+ while (transformPresent)
+ {
+ var transformType = (WebPTransformType)bitReader.Read(2);
+ switch (transformType)
+ {
+ case WebPTransformType.SubtractGreen:
+ // There is no data associated with this transform.
+ break;
+ case WebPTransformType.ColorIndexingTransform:
+ // The transform data contains color table size and the entries in the color table.
+ // 8 bit value for color table size.
+ uint colorTableSize = bitReader.Read(8) + 1;
+ // TODO: color table should follow here?
+ break;
+
+ case WebPTransformType.PredictorTransform:
+ {
+ // The first 3 bits of prediction data define the block width and height in number of bits.
+ // The number of block columns, block_xsize, is used in indexing two-dimensionally.
+ uint sizeBits = bitReader.Read(3) + 2;
+ int blockWidth = 1 << (int)sizeBits;
+ int blockHeight = 1 << (int)sizeBits;
+
+ break;
+ }
+
+ case WebPTransformType.ColorTransform:
+ {
+ // The first 3 bits of the color transform data contain the width and height of the image block in number of bits,
+ // just like the predictor transform:
+ uint sizeBits = bitReader.Read(3) + 2;
+ int blockWidth = 1 << (int)sizeBits;
+ int blockHeight = 1 << (int)sizeBits;
+ break;
+ }
+ }
+
+ numberOfTransformsPresent++;
+ if (numberOfTransformsPresent == 4)
+ {
+ break;
+ }
+
+ transformPresent = bitReader.ReadBit();
+ }
+
return new WebPImageInfo()
{
Width = (int)width,
diff --git a/src/ImageSharp/Formats/WebP/WebPTransformType.cs b/src/ImageSharp/Formats/WebP/WebPTransformType.cs
new file mode 100644
index 000000000..ed6e37e0a
--- /dev/null
+++ b/src/ImageSharp/Formats/WebP/WebPTransformType.cs
@@ -0,0 +1,37 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Formats.WebP
+{
+ ///
+ /// Enum for the different transform types. Transformations are reversible manipulations of the image data
+ /// that can reduce the remaining symbolic entropy by modeling spatial and color correlations.
+ /// Transformations can make the final compression more dense.
+ ///
+ public enum WebPTransformType : uint
+ {
+ ///
+ /// The predictor transform can be used to reduce entropy by exploiting the fact that neighboring pixels are often correlated.
+ ///
+ PredictorTransform = 0,
+
+ ///
+ /// The goal of the color transform is to decorrelate the R, G and B values of each pixel.
+ /// Color transform keeps the green (G) value as it is, transforms red (R) based on green and transforms blue (B) based on green and then based on red.
+ ///
+ ColorTransform = 1,
+
+ ///
+ /// The subtract green transform subtracts green values from red and blue values of each pixel.
+ /// When this transform is present, the decoder needs to add the green value to both red and blue.
+ /// There is no data associated with this transform.
+ ///
+ SubtractGreen = 2,
+
+ ///
+ /// If there are not many unique pixel values, it may be more efficient to create a color index array and replace the pixel values by the array's indices.
+ /// The color indexing transform achieves this.
+ ///
+ ColorIndexingTransform = 3,
+ }
+}