Browse Source

Fix lossy decoding issue: return value of ParseResiduals was not used

pull/1552/head
Brian Popow 6 years ago
parent
commit
e31f8d53cb
  1. 2
      src/ImageSharp/Formats/WebP/IWebPDecoderOptions.cs
  2. 2
      src/ImageSharp/Formats/WebP/Vp8Decoder.cs
  3. 3
      src/ImageSharp/Formats/WebP/Vp8FilterInfo.cs
  4. 7
      src/ImageSharp/Formats/WebP/Vp8MacroBlockData.cs
  5. 1
      src/ImageSharp/Formats/WebP/WebPLookupTables.cs
  6. 20
      src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs

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

@ -4,7 +4,7 @@
namespace SixLabors.ImageSharp.Formats.WebP
{
/// <summary>
/// Image decoder for generating an image out of a webp stream.
/// Image decoder options for generating an image out of a webp stream.
/// </summary>
internal interface IWebPDecoderOptions
{

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

@ -340,7 +340,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
info.Limit = 0; // no filtering.
}
info.UseInnerFiltering = (byte)i4x4;
info.UseInnerFiltering = i4x4 is 1;
}
}
}

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

@ -39,9 +39,8 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// <summary>
/// Gets or sets a value indicating whether to do inner filtering.
/// TODO: can this be a bool?
/// </summary>
public byte UseInnerFiltering { get; set; }
public bool UseInnerFiltering { get; set; }
/// <summary>
/// Gets or sets the high edge variance threshold in [0..2].

7
src/ImageSharp/Formats/WebP/Vp8MacroBlockData.cs

@ -8,6 +8,9 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// </summary>
internal class Vp8MacroBlockData
{
/// <summary>
/// Initializes a new instance of the <see cref="Vp8MacroBlockData"/> class.
/// </summary>
public Vp8MacroBlockData()
{
this.Modes = new byte[16];
@ -15,7 +18,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
/// <summary>
/// Gets or sets the coefficient. 384 coeffs = (16+4+4) * 4*4.
/// Gets or sets the coefficients. 384 coeffs = (16+4+4) * 4*4.
/// </summary>
public short[] Coeffs { get; set; }
@ -38,7 +41,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
public uint NonZeroUv { get; set; }
public byte Skip { get; set; }
public bool Skip { get; set; }
public byte Segment { get; set; }
}

1
src/ImageSharp/Formats/WebP/WebPLookupTables.cs

@ -444,7 +444,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
static WebPLookupTables()
{
// TODO: maybe use hashset here
Abs0 = new Dictionary<int, byte>();
for (int i = -255; i <= 255; ++i)
{

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

@ -191,7 +191,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
if (dec.UseSkipProbability)
{
block.Skip = (byte)this.bitReader.GetBit(dec.SkipProbability);
block.Skip = this.bitReader.GetBit(dec.SkipProbability) is 1;
}
block.IsI4x4 = this.bitReader.GetBit(145) is 0;
@ -488,7 +488,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
break;
}
this.DoUVTransform(bitsUv >> 0, coeffs.AsSpan(16 * 16), uDst);
this.DoUVTransform(bitsUv, coeffs.AsSpan(16 * 16), uDst);
this.DoUVTransform(bitsUv >> 8, coeffs.AsSpan(20 * 16), vDst);
// Stash away top samples for next block.
@ -545,7 +545,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
LossyUtils.SimpleHFilter16(dec.CacheY.Memory.Span, offset, yBps, limit + 4);
}
if (filterInfo.UseInnerFiltering > 0)
if (filterInfo.UseInnerFiltering)
{
LossyUtils.SimpleHFilter16i(dec.CacheY.Memory.Span, offset, yBps, limit);
}
@ -555,7 +555,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
LossyUtils.SimpleVFilter16(dec.CacheY.Memory.Span, offset, yBps, limit + 4);
}
if (filterInfo.UseInnerFiltering > 0)
if (filterInfo.UseInnerFiltering)
{
LossyUtils.SimpleVFilter16i(dec.CacheY.Memory.Span, offset, yBps, limit);
}
@ -572,7 +572,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
LossyUtils.HFilter8(dec.CacheU.Memory.Span, dec.CacheV.Memory.Span, uvOffset, uvBps, limit + 4, iLevel, hevThresh);
}
if (filterInfo.UseInnerFiltering > 0)
if (filterInfo.UseInnerFiltering)
{
LossyUtils.HFilter16i(dec.CacheY.Memory.Span, yOffset, yBps, limit, iLevel, hevThresh);
LossyUtils.HFilter8i(dec.CacheU.Memory.Span, dec.CacheV.Memory.Span, uvOffset, uvBps, limit, iLevel, hevThresh);
@ -584,7 +584,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
LossyUtils.VFilter8(dec.CacheU.Memory.Span, dec.CacheV.Memory.Span, uvOffset, uvBps, limit + 4, iLevel, hevThresh);
}
if (filterInfo.UseInnerFiltering > 0)
if (filterInfo.UseInnerFiltering)
{
LossyUtils.VFilter16i(dec.CacheY.Memory.Span, yOffset, yBps, limit, iLevel, hevThresh);
LossyUtils.VFilter8i(dec.CacheU.Memory.Span, dec.CacheV.Memory.Span, uvOffset, uvBps, limit, iLevel, hevThresh);
@ -820,11 +820,11 @@ namespace SixLabors.ImageSharp.Formats.WebP
Vp8MacroBlock left = dec.LeftMacroBlock;
Vp8MacroBlock macroBlock = dec.CurrentMacroBlock;
Vp8MacroBlockData blockData = dec.CurrentBlockData;
int skip = dec.UseSkipProbability ? blockData.Skip : 0;
bool skip = dec.UseSkipProbability ? blockData.Skip : false;
if (skip is 0)
if (!skip)
{
this.ParseResiduals(dec, bitreader, macroBlock);
skip = this.ParseResiduals(dec, bitreader, macroBlock);
}
else
{
@ -843,7 +843,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
{
Vp8FilterInfo precomputedFilterInfo = dec.FilterStrength[blockData.Segment, blockData.IsI4x4 ? 1 : 0];
dec.FilterInfo[dec.MbX] = (Vp8FilterInfo)precomputedFilterInfo.DeepClone();
dec.FilterInfo[dec.MbX].UseInnerFiltering |= (byte)(skip is 0 ? 1 : 0);
dec.FilterInfo[dec.MbX].UseInnerFiltering |= !skip;
}
}

Loading…
Cancel
Save