diff --git a/src/ImageSharp/Formats/WebP/Vp8LBitReader.cs b/src/ImageSharp/Formats/WebP/Vp8LBitReader.cs
index 39ee78cd6..036f441d0 100644
--- a/src/ImageSharp/Formats/WebP/Vp8LBitReader.cs
+++ b/src/ImageSharp/Formats/WebP/Vp8LBitReader.cs
@@ -15,11 +15,13 @@ namespace SixLabors.ImageSharp.Formats.WebP
///
/// Initializes a new instance of the class.
///
- /// The stream to read from.
- public Vp8LBitReader(Stream stream)
+ /// The input stream to read from.
+ public Vp8LBitReader(Stream inputStream)
{
this.stream = new MemoryStream();
- stream.CopyTo(this.stream);
+ long inputStreamPos = inputStream.Position;
+ inputStream.CopyTo(this.stream);
+ inputStream.Position = inputStreamPos;
this.Offset = 0;
this.Bit = 0;
}
@@ -29,7 +31,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
private int Bit { get; set; }
///
- /// Gets a value indicating whether the offset is inside the stream length.
+ /// Gets a value indicating whether the offset is inside the inputStream length.
///
private bool ValidPosition
{
@@ -40,7 +42,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
///
- /// Reads a unsigned short value from the stream. The bits of each byte are read in least-significant-bit-first order.
+ /// Reads a unsigned short value from the inputStream. The bits of each byte are read in least-significant-bit-first order.
///
/// The number of bits to read (should not exceed 16).
/// A ushort value.
@@ -67,7 +69,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
{
if (!this.ValidPosition)
{
- WebPThrowHelper.ThrowImageFormatException("The image stream does not contain enough data");
+ WebPThrowHelper.ThrowImageFormatException("The image inputStream does not contain enough data");
}
this.stream.Seek(this.Offset, SeekOrigin.Begin);
@@ -79,7 +81,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
///
- /// Advances the stream by one Bit.
+ /// Advances the inputStream by one Bit.
///
public void AdvanceBit()
{
diff --git a/src/ImageSharp/Formats/WebP/WebPChunkType.cs b/src/ImageSharp/Formats/WebP/WebPChunkType.cs
new file mode 100644
index 000000000..ba7fb9fd6
--- /dev/null
+++ b/src/ImageSharp/Formats/WebP/WebPChunkType.cs
@@ -0,0 +1,56 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Formats.WebP
+{
+ ///
+ /// Contains a list of different webp chunk types.
+ ///
+ internal enum WebPChunkType : uint
+ {
+ ///
+ /// Header signaling the use of VP8 video format.
+ ///
+ Vp8 = 0x56503820U,
+
+ ///
+ /// Header for a extended-VP8 chunk.
+ ///
+ Vp8L = 0x5650384CU,
+
+ ///
+ /// Header for a extended-VP8 chunk.
+ ///
+ Vp8X = 0x56503858U,
+
+ ///
+ /// Chunk contains information about the alpha channel.
+ ///
+ Alpha = 0x414C5048U,
+
+ ///
+ /// Chunk which contains a color profile.
+ ///
+ Iccp = 0x49434350U,
+
+ ///
+ /// Chunk which contains EXIF metadata about the image.
+ ///
+ Exif = 0x45584946U,
+
+ ///
+ /// Chunk contains XMP metadata about the image.
+ ///
+ Xmp = 0x584D5020U,
+
+ ///
+ /// For an animated image, this chunk contains the global parameters of the animation.
+ ///
+ AnimationParameter = 0x414E494D,
+
+ ///
+ /// For animated images, this chunk contains information about a single frame. If the Animation flag is not set, then this chunk SHOULD NOT be present.
+ ///
+ Animation = 0x414E4D46,
+ }
+}
diff --git a/src/ImageSharp/Formats/WebP/WebPConstants.cs b/src/ImageSharp/Formats/WebP/WebPConstants.cs
index f07a79814..d1c451799 100644
--- a/src/ImageSharp/Formats/WebP/WebPConstants.cs
+++ b/src/ImageSharp/Formats/WebP/WebPConstants.cs
@@ -58,106 +58,5 @@ namespace SixLabors.ImageSharp.Formats.WebP
0x42, // B
0x50 // P
};
-
- ///
- /// Header signaling the use of VP8 video format.
- ///
- public static readonly byte[] Vp8Header =
- {
- 0x56, // V
- 0x50, // P
- 0x38, // 8
- 0x20, // Space
- };
-
- ///
- /// Header for a extended-VP8 chunk.
- ///
- public static readonly byte[] Vp8XHeader =
- {
- 0x56, // V
- 0x50, // P
- 0x38, // 8
- 0x58, // X
- };
-
- public static readonly byte LossLessFlag = 0x4C; // L
-
- ///
- /// VP8 header, signaling the use of VP8L lossless format.
- ///
- public static readonly byte[] Vp8LHeader =
- {
- 0x56, // V
- 0x50, // P
- 0x38, // 8
- LossLessFlag // L
- };
-
- ///
- /// Chunk contains information about the alpha channel.
- ///
- public static readonly byte[] AlphaHeader =
- {
- 0x41, // A
- 0x4C, // L
- 0x50, // P
- 0x48, // H
- };
-
- ///
- /// Chunk which contains a color profile.
- ///
- public static readonly byte[] IccpHeader =
- {
- 0x49, // I
- 0x43, // C
- 0x43, // C
- 0x50, // P
- };
-
- ///
- /// Chunk which contains EXIF metadata about the image.
- ///
- public static readonly byte[] ExifHeader =
- {
- 0x45, // E
- 0x58, // X
- 0x49, // I
- 0x46, // F
- };
-
- ///
- /// Chunk contains XMP metadata about the image.
- ///
- public static readonly byte[] XmpHeader =
- {
- 0x58, // X
- 0x4D, // M
- 0x50, // P
- 0x20, // Space
- };
-
- ///
- /// For an animated image, this chunk contains the global parameters of the animation.
- ///
- public static readonly byte[] AnimationParameterHeader =
- {
- 0x41, // A
- 0x4E, // N
- 0x49, // I
- 0x4D, // M
- };
-
- ///
- /// For animated images, this chunk contains information about a single frame. If the Animation flag is not set, then this chunk SHOULD NOT be present.
- ///
- public static readonly byte[] AnimationHeader =
- {
- 0x41, // A
- 0x4E, // N
- 0x4D, // M
- 0x46, // F
- };
}
}
diff --git a/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs b/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs
index 4f574e7d7..f3b70aaec 100644
--- a/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs
+++ b/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs
@@ -4,7 +4,6 @@
using System;
using System.Buffers.Binary;
using System.IO;
-using System.Linq;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
@@ -74,14 +73,15 @@ namespace SixLabors.ImageSharp.Formats.WebP
Buffer2D pixels = image.GetRootFramePixelBuffer();
if (imageInfo.IsLossLess)
{
- ReadSimpleLossless(pixels, image.Width, image.Height);
+ ReadSimpleLossless(pixels, image.Width, image.Height, (int)imageInfo.DataSize);
}
else
{
- ReadSimpleLossy(pixels, image.Width, image.Height);
+ ReadSimpleLossy(pixels, image.Width, image.Height, (int)imageInfo.DataSize);
}
// TODO: there can be optional chunks after the image data, like EXIF, XMP etc.
+ this.ParseOptionalChunks();
return image;
}
@@ -123,22 +123,16 @@ namespace SixLabors.ImageSharp.Formats.WebP
private WebPImageInfo ReadVp8Info(int vpxWidth = 0, int vpxHeight = 0)
{
- // Read VP8 chunk header.
- this.currentStream.Read(this.buffer, 0, 4);
-
- if (this.buffer.AsSpan().SequenceEqual(WebPConstants.Vp8Header))
- {
- return this.ReadVp8Header(vpxWidth, vpxHeight);
- }
+ WebPChunkType type = this.ReadChunkType();
- if (this.buffer.AsSpan().SequenceEqual(WebPConstants.Vp8LHeader))
+ switch (type)
{
- return this.ReadVp8LHeader(vpxWidth, vpxHeight);
- }
-
- if (this.buffer.SequenceEqual(WebPConstants.Vp8XHeader))
- {
- return this.ReadVp8XHeader();
+ case WebPChunkType.Vp8:
+ return this.ReadVp8Header(vpxWidth, vpxHeight);
+ case WebPChunkType.Vp8L:
+ return this.ReadVp8LHeader(vpxWidth, vpxHeight);
+ case WebPChunkType.Vp8X:
+ return this.ReadVp8XHeader();
}
WebPThrowHelper.ThrowImageFormatException("Unrecognized VP8 header");
@@ -185,6 +179,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
int height = BinaryPrimitives.ReadInt32LittleEndian(this.buffer) + 1;
// TODO: optional chunks ICCP and ANIM can follow here. Ignoring them for now.
+ this.ParseOptionalChunks();
// A VP8 or VP8L chunk will follow here.
return this.ReadVp8Info(width, height);
@@ -324,16 +319,24 @@ namespace SixLabors.ImageSharp.Formats.WebP
};
}
- private void ReadSimpleLossy(Buffer2D pixels, int width, int height)
+ private void ParseOptionalChunks()
+ {
+ // Read VP8 chunk header.
+ this.currentStream.Read(this.buffer, 0, 4);
+ }
+
+ private void ReadSimpleLossy(Buffer2D pixels, int width, int height, int chunkSize)
where TPixel : struct, IPixel
{
- // TODO: implement decoding
+ // TODO: implement decoding, for simulating the decoding, skipping the chunk size bytes.
+ this.currentStream.Skip(chunkSize);
}
- private void ReadSimpleLossless(Buffer2D pixels, int width, int height)
+ private void ReadSimpleLossless(Buffer2D pixels, int width, int height, int chunkSize)
where TPixel : struct, IPixel
{
- // TODO: implement decoding
+ // TODO: implement decoding, for simulating the decoding, skipping the chunk size bytes.
+ this.currentStream.Skip(chunkSize);
}
private void ReadExtended(Buffer2D pixels, int width, int height)
@@ -341,5 +344,18 @@ namespace SixLabors.ImageSharp.Formats.WebP
{
// TODO: implement decoding
}
+
+ ///
+ /// Identifies the chunk type from the chunk.
+ ///
+ ///
+ /// Thrown if the input stream is not valid.
+ ///
+ private WebPChunkType ReadChunkType()
+ {
+ return this.currentStream.Read(this.buffer, 0, 4) == 4
+ ? (WebPChunkType)BinaryPrimitives.ReadUInt32BigEndian(this.buffer)
+ : throw new ImageFormatException("Invalid WebP data.");
+ }
}
}