Browse Source

Fix some decoding bugs

pull/1552/head
Brian Popow 6 years ago
parent
commit
d61ce09b02
  1. 10
      src/ImageSharp/Formats/WebP/HuffmanUtils.cs
  2. 2
      src/ImageSharp/Formats/WebP/Vp8LMetadata.cs
  3. 52
      src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs

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

@ -125,18 +125,22 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
Span<HuffmanCode> tableSpan = table;
int tablePos = 0;
for (; count[len] > 0; --count[len])
{
if ((key & mask) != low)
{
tableSpan = tableSpan.Slice(tableSize);
tablePos += tableSize;
tableBits = NextTableBitSize(count, len, rootBits);
tableSize = 1 << tableBits;
totalSize += tableSize;
low = key & mask;
table[low].BitsUsed = tableBits + rootBits;
// TODO: fix this
// table[low].Value = ((table - rootTable) - low);
table[low] = new HuffmanCode
{
BitsUsed = tableBits + rootBits,
Value = (uint)(tablePos - low)
};
}
var huffmanCode = new HuffmanCode

2
src/ImageSharp/Formats/WebP/Vp8LMetadata.cs

@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
public int HuffmanXSize { get; set; }
public int[] HuffmanImage { get; set; }
public uint[] HuffmanImage { get; set; }
public int NumHTreeGroups { get; set; }

52
src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs

@ -108,15 +108,19 @@ namespace SixLabors.ImageSharp.Formats.WebP
private uint[] DecodeImageStream(int xSize, int ySize, bool isLevel0)
{
this.ReadTransformations();
if (isLevel0)
{
this.ReadTransformations();
}
// Read color cache, if present.
bool colorCachePresent = this.bitReader.ReadBit();
int colorCacheBits = 0;
int colorCacheSize = 0;
var colorCache = new ColorCache();
ColorCache colorCache = null;
if (colorCachePresent)
{
colorCache = new ColorCache();
colorCacheBits = (int)this.bitReader.ReadBits(4);
colorCacheSize = 1 << colorCacheBits;
if (!(colorCacheBits >= 1 && colorCacheBits <= WebPConstants.MaxColorCacheBits))
@ -184,7 +188,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
else
{
this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Green]);
code = (int)this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Green]);
}
if (this.bitReader.IsEndOfStream())
@ -301,22 +305,35 @@ namespace SixLabors.ImageSharp.Formats.WebP
private Vp8LMetadata ReadHuffmanCodes(int xSize, int ySize, int colorCacheBits, bool allowRecursion)
{
var metadata = new Vp8LMetadata();
int maxAlphabetSize = 0;
int numHTreeGroups = 1;
int numHTreeGroupsMax = 1;
// If the next bit is zero, there is only one meta Huffman code used everywhere in the image. No more data is stored.
// If this bit is one, the image uses multiple meta Huffman codes. These meta Huffman codes are stored as an entropy image.
bool isEntropyImage = this.bitReader.ReadBit();
if (allowRecursion && isEntropyImage)
if (allowRecursion && this.bitReader.ReadBit())
{
// Use meta Huffman codes.
uint huffmanPrecision = this.bitReader.ReadBits(3) + 2;
int huffmanXSize = this.SubSampleSize(xSize, (int)huffmanPrecision);
int huffmanYSize = this.SubSampleSize(ySize, (int)huffmanPrecision);
int huffmanPixs = huffmanXSize * huffmanYSize;
// TODO: decode entropy image
return new Vp8LMetadata();
uint[] huffmanImage = this.DecodeImageStream(huffmanXSize, huffmanYSize, false);
metadata.HuffmanSubSampleBits = (int)huffmanPrecision;
for (int i = 0; i < huffmanPixs; ++i)
{
// The huffman data is stored in red and green bytes.
uint group = (huffmanImage[i] >> 8) & 0xffff;
huffmanImage[i] = group;
if (group >= numHTreeGroupsMax)
{
numHTreeGroupsMax = (int)group + 1;
}
}
numHTreeGroups = numHTreeGroupsMax;
metadata.HuffmanImage = huffmanImage;
}
// Find maximum alphabet size for the hTree group.
@ -409,13 +426,9 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
}
var metadata = new Vp8LMetadata()
{
// TODO: initialize huffman_image_
NumHTreeGroups = numHTreeGroups,
HTreeGroups = hTreeGroups,
HuffmanTables = huffmanTables,
};
metadata.NumHTreeGroups = numHTreeGroups;
metadata.HTreeGroups = hTreeGroups;
metadata.HuffmanTables = huffmanTables;
return metadata;
}
@ -476,7 +489,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
private void ReadHuffmanCodeLengths(HuffmanCode[] table, int[] codeLengthCodeLengths, int numSymbols, int[] codeLengths)
{
Span<HuffmanCode> tableSpan = table.AsSpan();
int maxSymbol;
int symbol = 0;
int prevCodeLen = WebPConstants.DefaultCodeLength;
@ -498,7 +510,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
while (symbol < numSymbols)
{
if (maxSymbol-- == 0)
if (maxSymbol-- is 0)
{
break;
}
@ -732,9 +744,9 @@ namespace SixLabors.ImageSharp.Formats.WebP
return hCode.BitsUsed;
}
private int GetMetaIndex(int[] image, int xSize, int bits, int x, int y)
private uint GetMetaIndex(uint[] image, int xSize, int bits, int x, int y)
{
if (bits == 0)
if (bits is 0)
{
return 0;
}
@ -744,8 +756,8 @@ namespace SixLabors.ImageSharp.Formats.WebP
private HTreeGroup[] GetHTreeGroupForPos(Vp8LMetadata metadata, int x, int y)
{
int metaIndex = this.GetMetaIndex(metadata.HuffmanImage, metadata.HuffmanXSize, metadata.HuffmanSubSampleBits, x, y);
return metadata.HTreeGroups.AsSpan(metaIndex).ToArray();
uint metaIndex = this.GetMetaIndex(metadata.HuffmanImage, metadata.HuffmanXSize, metadata.HuffmanSubSampleBits, x, y);
return metadata.HTreeGroups.AsSpan((int)metaIndex).ToArray();
}
}
}

Loading…
Cancel
Save