Browse Source

Store filter info

pull/1552/head
Brian Popow 6 years ago
parent
commit
38bee8203d
  1. 12
      src/ImageSharp/Formats/WebP/Vp8Decoder.cs
  2. 2
      src/ImageSharp/Formats/WebP/Vp8FilterInfo.cs
  3. 56
      src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs

12
src/ImageSharp/Formats/WebP/Vp8Decoder.cs

@ -19,16 +19,20 @@ namespace SixLabors.ImageSharp.Formats.WebP
this.YuvBuffer = new byte[(WebPConstants.Bps * 17) + (WebPConstants.Bps * 9)];
this.MbWidth = (int)((this.PictureHeader.Width + 15) >> 4);
this.MbHeight = (int)((this.PictureHeader.Height + 15) >> 4);
this.MacroBlockInfo = new Vp8MacroBlock[this.MbWidth];
this.MacroBlockInfo = new Vp8MacroBlock[this.MbWidth + 1];
this.MacroBlockData = new Vp8MacroBlockData[this.MbWidth];
this.YuvTopSamples = new Vp8TopSamples[this.MbWidth];
this.FilterInfo = new Vp8FilterInfo[this.MbWidth];
for (int i = 0; i < this.MbWidth; i++)
{
this.MacroBlockInfo[i] = new Vp8MacroBlock();
this.MacroBlockData[i] = new Vp8MacroBlockData();
this.YuvTopSamples[i] = new Vp8TopSamples();
this.FilterInfo[i] = new Vp8FilterInfo();
}
this.MacroBlockInfo[this.MbWidth] = new Vp8MacroBlock();
this.DeQuantMatrices = new Vp8QuantMatrix[WebPConstants.NumMbSegments];
this.FilterStrength = new Vp8FilterInfo[WebPConstants.NumMbSegments, 2];
for (int i = 0; i < WebPConstants.NumMbSegments; i++)
@ -123,12 +127,10 @@ namespace SixLabors.ImageSharp.Formats.WebP
public Vp8MacroBlockData[] MacroBlockData { get; }
/// <summary>
/// Gets contextual macroblock infos.
/// Gets contextual contextual macroblock info (mbw + 1).
/// </summary>
public Vp8MacroBlock[] MacroBlockInfo { get; }
public int MacroBlockIdx { get; set; }
public LoopFilter Filter { get; set; }
public Vp8FilterInfo[,] FilterStrength { get; }
@ -140,7 +142,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// <summary>
/// Gets or sets filter strength info.
/// </summary>
public Vp8FilterInfo FilterInfo { get; set; }
public Vp8FilterInfo[] FilterInfo { get; set; }
public void Init(Vp8Io io)
{

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

@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// <summary>
/// Gets or sets a value indicating whether to do inner filtering.
/// </summary>
public bool InnerFiltering { get; set; }
public byte InnerFiltering { get; set; }
/// <summary>
/// Gets or sets the high edge variance threshold in [0..2].

56
src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs

@ -78,6 +78,10 @@ namespace SixLabors.ImageSharp.Formats.WebP
{
for (dec.MbY = 0; dec.MbY < dec.BottomRightMbY; ++dec.MbY)
{
// Parse bitstream for this row.
long bitreaderIdx = dec.MbY & dec.NumPartsMinusOne;
Vp8BitReader bitreader = dec.Vp8BitReaders[bitreaderIdx];
// Parse intra mode mode row.
for (int mbX = 0; mbX < dec.MbWidth; ++mbX)
{
@ -86,7 +90,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
for (; dec.MbX < dec.MbWidth; ++dec.MbX)
{
this.DecodeMacroBlock(dec);
this.DecodeMacroBlock(dec, bitreader);
}
// Prepare for next scanline.
@ -168,7 +172,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
private void InitScanline(Vp8Decoder dec)
{
Vp8MacroBlock left = dec.MacroBlockInfo[dec.MacroBlockIdx - 1];
Vp8MacroBlock left = dec.MacroBlockInfo[0];
left.NoneZeroAcDcCoeffs = 0;
left.NoneZeroDcCoeffs = 0;
for (int i = 0; i < dec.IntraL.Length; i++)
@ -324,16 +328,16 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
}
private void DecodeMacroBlock(Vp8Decoder dec)
private void DecodeMacroBlock(Vp8Decoder dec, Vp8BitReader bitreader)
{
Vp8MacroBlock left = dec.MacroBlockInfo[dec.MacroBlockIdx - 1]; // TODO: not sure if this - 1 is correct here
Vp8MacroBlock macroBlock = dec.MacroBlockInfo[dec.MacroBlockIdx + dec.MbX];
Vp8MacroBlockData blockData = dec.MacroBlockData[dec.MacroBlockIdx + dec.MbX];
Vp8MacroBlock left = dec.MacroBlockInfo[0];
Vp8MacroBlock macroBlock = dec.MacroBlockInfo[1 + dec.MbX];
Vp8MacroBlockData blockData = dec.MacroBlockData[dec.MbX];
int skip = dec.UseSkipProbability ? blockData.Skip : 0;
if (skip is 0)
{
this.ParseResiduals(dec, macroBlock);
this.ParseResiduals(dec, bitreader, macroBlock);
}
else
{
@ -348,29 +352,33 @@ namespace SixLabors.ImageSharp.Formats.WebP
blockData.Dither = 0;
}
// TODO: store filter info
// Store filter info.
if (dec.Filter != LoopFilter.None)
{
dec.FilterInfo[dec.MbX] = dec.FilterStrength[blockData.Segment, blockData.IsI4x4 ? 1 : 0];
dec.FilterInfo[dec.MbX].InnerFiltering |= (byte)(skip is 0 ? 1 : 0);
}
}
private bool ParseResiduals(Vp8Decoder decoder, Vp8MacroBlock mb)
private bool ParseResiduals(Vp8Decoder dec, Vp8BitReader br, Vp8MacroBlock mb)
{
byte tnz, lnz;
uint nonZeroY = 0;
uint nonZeroUv = 0;
int first;
var dst = new short[384];
var dstOffset = 0;
Vp8MacroBlockData block = decoder.MacroBlockData[decoder.MbX];
Vp8QuantMatrix q = decoder.DeQuantMatrices[block.Segment];
Vp8BandProbas[,] bands = decoder.Probabilities.BandsPtr;
int dstOffset = 0;
Vp8MacroBlockData block = dec.MacroBlockData[dec.MbX];
Vp8QuantMatrix q = dec.DeQuantMatrices[block.Segment];
Vp8BandProbas[,] bands = dec.Probabilities.BandsPtr;
Vp8BandProbas[] acProba;
Vp8MacroBlock leftMb = null; // TODO: this value needs to be set
Vp8MacroBlock leftMb = dec.MacroBlockInfo[0];
if (!block.IsI4x4)
{
// Parse DC
var dc = new short[16];
int ctx = (int)(mb.NoneZeroDcCoeffs + leftMb.NoneZeroDcCoeffs);
int nz = this.GetCoeffs(GetBandsRow(bands, 1), ctx, q.Y2Mat, 0, dc);
int nz = this.GetCoeffs(br, GetBandsRow(bands, 1), ctx, q.Y2Mat, 0, dc);
mb.NoneZeroDcCoeffs = leftMb.NoneZeroDcCoeffs = (uint)(nz > 0 ? 1 : 0);
if (nz > 0)
{
@ -395,8 +403,8 @@ namespace SixLabors.ImageSharp.Formats.WebP
acProba = GetBandsRow(bands, 3);
}
tnz = (byte)(mb.NoneZeroAcDcCoeffs & 0x0f);
lnz = (byte)(leftMb.NoneZeroAcDcCoeffs & 0x0f);
byte tnz = (byte)(mb.NoneZeroAcDcCoeffs & 0x0f);
byte lnz = (byte)(leftMb.NoneZeroAcDcCoeffs & 0x0f);
for (int y = 0; y < 4; ++y)
{
@ -405,7 +413,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
for (int x = 0; x < 4; ++x)
{
int ctx = l + (tnz & 1);
int nz = this.GetCoeffs(acProba, ctx, q.Y1Mat, first, dst.AsSpan(dstOffset));
int nz = this.GetCoeffs(br, acProba, ctx, q.Y1Mat, first, dst.AsSpan(dstOffset));
l = (nz > first) ? 1 : 0;
tnz = (byte)((tnz >> 1) | (l << 7));
nzCoeffs = NzCodeBits(nzCoeffs, nz, dst[0] != 0 ? 1 : 0);
@ -431,7 +439,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
for (int x = 0; x < 2; ++x)
{
int ctx = l + (tnz & 1);
int nz = this.GetCoeffs(GetBandsRow(bands, 2), ctx, q.UvMat, 0, dst.AsSpan(dstOffset));
int nz = this.GetCoeffs(br, GetBandsRow(bands, 2), ctx, q.UvMat, 0, dst.AsSpan(dstOffset));
l = (nz > 0) ? 1 : 0;
tnz = (byte)((tnz >> 1) | (l << 3));
nzCoeffs = NzCodeBits(nzCoeffs, nz, dst[0] != 0 ? 1 : 0);
@ -462,7 +470,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
return (nonZeroY | nonZeroUv) is 0;
}
private int GetCoeffs(Vp8BandProbas[] prob, int ctx, int[] dq, int n, Span<short> coeffs)
private int GetCoeffs(Vp8BitReader br, Vp8BandProbas[] prob, int ctx, int[] dq, int n, Span<short> coeffs)
{
// Returns the position of the last non - zero coeff plus one.
Vp8ProbaArray p = prob[n].Probabilities[ctx];
@ -475,7 +483,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
// Sequence of zero coeffs.
while (this.bitReader.GetBit((int)p.Probabilities[1]) is 0)
while (br.GetBit((int)p.Probabilities[1]) is 0)
{
p = prob[++n].Probabilities[0];
if (n is 16)
@ -486,7 +494,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
// Non zero coeffs.
int v;
if (this.bitReader.GetBit((int)p.Probabilities[2]) is 0)
if (br.GetBit((int)p.Probabilities[2]) is 0)
{
v = 1;
p = prob[n + 1].Probabilities[1];
@ -498,7 +506,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
int idx = n > 0 ? 1 : 0;
coeffs[WebPConstants.Zigzag[n]] = (short)(this.bitReader.ReadSignedValue(v) * dq[idx]);
coeffs[WebPConstants.Zigzag[n]] = (short)(br.ReadSignedValue(v) * dq[idx]);
}
return 16;

Loading…
Cancel
Save