Browse Source

WebP: Move ReadSymbol to WebPDecoderBase

it's used in Lossy decoder for alpha decoding as well.
pull/1552/head
Peter Amrehn 6 years ago
parent
commit
f14f2a5925
  1. 24
      src/ImageSharp/Formats/WebP/WebPDecoderBase.cs
  2. 33
      src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs

24
src/ImageSharp/Formats/WebP/WebPDecoderBase.cs

@ -27,6 +27,30 @@ namespace SixLabors.ImageSharp.Formats.WebP
return huffmanImageSpan[(xSize * (y >> bits)) + (x >> bits)]; return huffmanImageSpan[(xSize * (y >> bits)) + (x >> bits)];
} }
/// <summary>
/// Decodes the next Huffman code from bit-stream.
/// FillBitWindow(br) needs to be called at minimum every second call
/// to ReadSymbol, in order to pre-fetch enough bits.
/// </summary>
protected uint ReadSymbol(Span<HuffmanCode> table, Vp8LBitReader bitReader)
{
// TODO: if the bitReader field is moved to this base class we could omit the parameter.
uint val = (uint)bitReader.PrefetchBits();
Span<HuffmanCode> tableSpan = table.Slice((int)(val & HuffmanUtils.HuffmanTableMask));
int nBits = tableSpan[0].BitsUsed - HuffmanUtils.HuffmanTableBits;
if (nBits > 0)
{
bitReader.AdvanceBitPosition(HuffmanUtils.HuffmanTableBits);
val = (uint)bitReader.PrefetchBits();
tableSpan = tableSpan.Slice((int)tableSpan[0].Value);
tableSpan = tableSpan.Slice((int)val & ((1 << nBits) - 1));
}
bitReader.AdvanceBitPosition(tableSpan[0].BitsUsed);
return tableSpan[0].Value;
}
protected int GetCopyDistance(int distanceSymbol, Vp8LBitReader bitReader) protected int GetCopyDistance(int distanceSymbol, Vp8LBitReader bitReader)
{ {
if (distanceSymbol < 4) if (distanceSymbol < 4)

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

@ -235,7 +235,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
} }
else else
{ {
code = (int)this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Green]); code = (int)this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Green], this.bitReader);
} }
if (this.bitReader.IsEndOfStream()) if (this.bitReader.IsEndOfStream())
@ -252,10 +252,10 @@ namespace SixLabors.ImageSharp.Formats.WebP
} }
else else
{ {
uint red = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Red]); uint red = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Red], this.bitReader);
this.bitReader.FillBitWindow(); this.bitReader.FillBitWindow();
uint blue = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Blue]); uint blue = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Blue], this.bitReader);
uint alpha = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Alpha]); uint alpha = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Alpha], this.bitReader);
if (this.bitReader.IsEndOfStream()) if (this.bitReader.IsEndOfStream())
{ {
break; break;
@ -272,7 +272,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
// Backward reference is used. // Backward reference is used.
int lengthSym = code - WebPConstants.NumLiteralCodes; int lengthSym = code - WebPConstants.NumLiteralCodes;
int length = this.GetCopyLength(lengthSym, this.bitReader); int length = this.GetCopyLength(lengthSym, this.bitReader);
uint distSymbol = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Dist]); uint distSymbol = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Dist], this.bitReader);
this.bitReader.FillBitWindow(); this.bitReader.FillBitWindow();
int distCode = this.GetCopyDistance((int)distSymbol, this.bitReader); int distCode = this.GetCopyDistance((int)distSymbol, this.bitReader);
int dist = this.PlaneCodeToDistance(width, distCode); int dist = this.PlaneCodeToDistance(width, distCode);
@ -691,29 +691,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
decoder.Metadata.HuffmanMask = (numBits is 0) ? ~0 : (1 << numBits) - 1; decoder.Metadata.HuffmanMask = (numBits is 0) ? ~0 : (1 << numBits) - 1;
} }
/// <summary>
/// Decodes the next Huffman code from bit-stream.
/// FillBitWindow(br) needs to be called at minimum every second call
/// to ReadSymbol, in order to pre-fetch enough bits.
/// </summary>
private uint ReadSymbol(Span<HuffmanCode> table)
{
uint val = (uint)this.bitReader.PrefetchBits();
Span<HuffmanCode> tableSpan = table.Slice((int)(val & HuffmanUtils.HuffmanTableMask));
int nBits = tableSpan[0].BitsUsed - HuffmanUtils.HuffmanTableBits;
if (nBits > 0)
{
this.bitReader.AdvanceBitPosition(HuffmanUtils.HuffmanTableBits);
val = (uint)this.bitReader.PrefetchBits();
tableSpan = tableSpan.Slice((int)tableSpan[0].Value);
tableSpan = tableSpan.Slice((int)val & ((1 << nBits) - 1));
}
this.bitReader.AdvanceBitPosition(tableSpan[0].BitsUsed);
return tableSpan[0].Value;
}
private uint ReadPackedSymbols(HTreeGroup[] group, Span<uint> pixelData, int decodedPixels) private uint ReadPackedSymbols(HTreeGroup[] group, Span<uint> pixelData, int decodedPixels)
{ {
uint val = (uint)(this.bitReader.PrefetchBits() & (HuffmanUtils.HuffmanPackedTableSize - 1)); uint val = (uint)(this.bitReader.PrefetchBits() & (HuffmanUtils.HuffmanPackedTableSize - 1));

Loading…
Cancel
Save