Browse Source

WebP: Move ReadSymbol to WebPDecoderBase

it's used in Lossy decoder for alpha decoding as well.
pull/1147/head
Peter Amrehn 6 years ago
parent
commit
723a0a7766
  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)];
}
/// <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)
{
if (distanceSymbol < 4)

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

@ -235,7 +235,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
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())
@ -252,10 +252,10 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
else
{
uint red = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Red]);
uint red = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Red], this.bitReader);
this.bitReader.FillBitWindow();
uint blue = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Blue]);
uint alpha = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Alpha]);
uint blue = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Blue], this.bitReader);
uint alpha = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Alpha], this.bitReader);
if (this.bitReader.IsEndOfStream())
{
break;
@ -272,7 +272,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
// Backward reference is used.
int lengthSym = code - WebPConstants.NumLiteralCodes;
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();
int distCode = this.GetCopyDistance((int)distSymbol, this.bitReader);
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;
}
/// <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)
{
uint val = (uint)(this.bitReader.PrefetchBits() & (HuffmanUtils.HuffmanPackedTableSize - 1));

Loading…
Cancel
Save