Browse Source

Parsing the transforms (still WIP)

pull/1552/head
Brian Popow 6 years ago
parent
commit
d4efca8607
  1. 10
      src/ImageSharp/Formats/WebP/Vp8LBitReader.cs
  2. 62
      src/ImageSharp/Formats/WebP/WebPDecoderCore.cs
  3. 37
      src/ImageSharp/Formats/WebP/WebPTransformType.cs

10
src/ImageSharp/Formats/WebP/Vp8LBitReader.cs

@ -8,15 +8,15 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// <summary>
/// A bit reader for VP8 streams.
/// </summary>
public class Vp8LBitreader
public class Vp8LBitReader
{
private readonly Stream stream;
/// <summary>
/// Initializes a new instance of the <see cref="Vp8LBitreader"/> class.
/// Initializes a new instance of the <see cref="Vp8LBitReader"/> class.
/// </summary>
/// <param name="stream">The stream to read from.</param>
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; }
/// <summary>
/// Check if the offset is inside the stream length.
/// Gets a value indicating whether the offset is inside the stream length.
/// </summary>
private bool ValidPosition
{
@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// <returns>True, if the bit is one, otherwise false.</returns>
public bool ReadBit()
{
if (!ValidPosition)
if (!this.ValidPosition)
{
WebPThrowHelper.ThrowImageFormatException("The image stream does not contain enough data");
}

62
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,

37
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
{
/// <summary>
/// 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.
/// </summary>
public enum WebPTransformType : uint
{
/// <summary>
/// The predictor transform can be used to reduce entropy by exploiting the fact that neighboring pixels are often correlated.
/// </summary>
PredictorTransform = 0,
/// <summary>
/// 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.
/// </summary>
ColorTransform = 1,
/// <summary>
/// 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.
/// </summary>
SubtractGreen = 2,
/// <summary>
/// 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.
/// </summary>
ColorIndexingTransform = 3,
}
}
Loading…
Cancel
Save