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

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

@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to do inner filtering. /// Gets or sets a value indicating whether to do inner filtering.
/// </summary> /// </summary>
public bool InnerFiltering { get; set; } public byte InnerFiltering { get; set; }
/// <summary> /// <summary>
/// Gets or sets the high edge variance threshold in [0..2]. /// 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) 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. // Parse intra mode mode row.
for (int mbX = 0; mbX < dec.MbWidth; ++mbX) for (int mbX = 0; mbX < dec.MbWidth; ++mbX)
{ {
@ -86,7 +90,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
for (; dec.MbX < dec.MbWidth; ++dec.MbX) for (; dec.MbX < dec.MbWidth; ++dec.MbX)
{ {
this.DecodeMacroBlock(dec); this.DecodeMacroBlock(dec, bitreader);
} }
// Prepare for next scanline. // Prepare for next scanline.
@ -168,7 +172,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
private void InitScanline(Vp8Decoder dec) private void InitScanline(Vp8Decoder dec)
{ {
Vp8MacroBlock left = dec.MacroBlockInfo[dec.MacroBlockIdx - 1]; Vp8MacroBlock left = dec.MacroBlockInfo[0];
left.NoneZeroAcDcCoeffs = 0; left.NoneZeroAcDcCoeffs = 0;
left.NoneZeroDcCoeffs = 0; left.NoneZeroDcCoeffs = 0;
for (int i = 0; i < dec.IntraL.Length; i++) 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 left = dec.MacroBlockInfo[0];
Vp8MacroBlock macroBlock = dec.MacroBlockInfo[dec.MacroBlockIdx + dec.MbX]; Vp8MacroBlock macroBlock = dec.MacroBlockInfo[1 + dec.MbX];
Vp8MacroBlockData blockData = dec.MacroBlockData[dec.MacroBlockIdx + dec.MbX]; Vp8MacroBlockData blockData = dec.MacroBlockData[dec.MbX];
int skip = dec.UseSkipProbability ? blockData.Skip : 0; int skip = dec.UseSkipProbability ? blockData.Skip : 0;
if (skip is 0) if (skip is 0)
{ {
this.ParseResiduals(dec, macroBlock); this.ParseResiduals(dec, bitreader, macroBlock);
} }
else else
{ {
@ -348,29 +352,33 @@ namespace SixLabors.ImageSharp.Formats.WebP
blockData.Dither = 0; 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 nonZeroY = 0;
uint nonZeroUv = 0; uint nonZeroUv = 0;
int first; int first;
var dst = new short[384]; var dst = new short[384];
var dstOffset = 0; int dstOffset = 0;
Vp8MacroBlockData block = decoder.MacroBlockData[decoder.MbX]; Vp8MacroBlockData block = dec.MacroBlockData[dec.MbX];
Vp8QuantMatrix q = decoder.DeQuantMatrices[block.Segment]; Vp8QuantMatrix q = dec.DeQuantMatrices[block.Segment];
Vp8BandProbas[,] bands = decoder.Probabilities.BandsPtr; Vp8BandProbas[,] bands = dec.Probabilities.BandsPtr;
Vp8BandProbas[] acProba; Vp8BandProbas[] acProba;
Vp8MacroBlock leftMb = null; // TODO: this value needs to be set Vp8MacroBlock leftMb = dec.MacroBlockInfo[0];
if (!block.IsI4x4) if (!block.IsI4x4)
{ {
// Parse DC // Parse DC
var dc = new short[16]; var dc = new short[16];
int ctx = (int)(mb.NoneZeroDcCoeffs + leftMb.NoneZeroDcCoeffs); 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); mb.NoneZeroDcCoeffs = leftMb.NoneZeroDcCoeffs = (uint)(nz > 0 ? 1 : 0);
if (nz > 0) if (nz > 0)
{ {
@ -395,8 +403,8 @@ namespace SixLabors.ImageSharp.Formats.WebP
acProba = GetBandsRow(bands, 3); acProba = GetBandsRow(bands, 3);
} }
tnz = (byte)(mb.NoneZeroAcDcCoeffs & 0x0f); byte tnz = (byte)(mb.NoneZeroAcDcCoeffs & 0x0f);
lnz = (byte)(leftMb.NoneZeroAcDcCoeffs & 0x0f); byte lnz = (byte)(leftMb.NoneZeroAcDcCoeffs & 0x0f);
for (int y = 0; y < 4; ++y) for (int y = 0; y < 4; ++y)
{ {
@ -405,7 +413,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
for (int x = 0; x < 4; ++x) for (int x = 0; x < 4; ++x)
{ {
int ctx = l + (tnz & 1); 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; l = (nz > first) ? 1 : 0;
tnz = (byte)((tnz >> 1) | (l << 7)); tnz = (byte)((tnz >> 1) | (l << 7));
nzCoeffs = NzCodeBits(nzCoeffs, nz, dst[0] != 0 ? 1 : 0); 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) for (int x = 0; x < 2; ++x)
{ {
int ctx = l + (tnz & 1); 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; l = (nz > 0) ? 1 : 0;
tnz = (byte)((tnz >> 1) | (l << 3)); tnz = (byte)((tnz >> 1) | (l << 3));
nzCoeffs = NzCodeBits(nzCoeffs, nz, dst[0] != 0 ? 1 : 0); nzCoeffs = NzCodeBits(nzCoeffs, nz, dst[0] != 0 ? 1 : 0);
@ -462,7 +470,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
return (nonZeroY | nonZeroUv) is 0; 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. // Returns the position of the last non - zero coeff plus one.
Vp8ProbaArray p = prob[n].Probabilities[ctx]; Vp8ProbaArray p = prob[n].Probabilities[ctx];
@ -475,7 +483,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
} }
// Sequence of zero coeffs. // 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]; p = prob[++n].Probabilities[0];
if (n is 16) if (n is 16)
@ -486,7 +494,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
// Non zero coeffs. // Non zero coeffs.
int v; int v;
if (this.bitReader.GetBit((int)p.Probabilities[2]) is 0) if (br.GetBit((int)p.Probabilities[2]) is 0)
{ {
v = 1; v = 1;
p = prob[n + 1].Probabilities[1]; p = prob[n + 1].Probabilities[1];
@ -498,7 +506,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
} }
int idx = n > 0 ? 1 : 0; 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; return 16;

Loading…
Cancel
Save