Browse Source

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

pull/1552/head
Brian Popow 7 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 namespace SixLabors.ImageSharp.Formats.WebP
{ {
/// <summary> /// <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> /// </summary>
internal interface IWebPDecoderOptions 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.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> /// <summary>
/// Gets or sets a value indicating whether to do inner filtering. /// Gets or sets a value indicating whether to do inner filtering.
/// TODO: can this be a bool?
/// </summary> /// </summary>
public byte UseInnerFiltering { get; set; } public bool UseInnerFiltering { 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].

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

@ -8,6 +8,9 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// </summary> /// </summary>
internal class Vp8MacroBlockData internal class Vp8MacroBlockData
{ {
/// <summary>
/// Initializes a new instance of the <see cref="Vp8MacroBlockData"/> class.
/// </summary>
public Vp8MacroBlockData() public Vp8MacroBlockData()
{ {
this.Modes = new byte[16]; this.Modes = new byte[16];
@ -15,7 +18,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
} }
/// <summary> /// <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> /// </summary>
public short[] Coeffs { get; set; } public short[] Coeffs { get; set; }
@ -38,7 +41,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
public uint NonZeroUv { get; set; } public uint NonZeroUv { get; set; }
public byte Skip { get; set; } public bool Skip { get; set; }
public byte Segment { 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() static WebPLookupTables()
{ {
// TODO: maybe use hashset here
Abs0 = new Dictionary<int, byte>(); Abs0 = new Dictionary<int, byte>();
for (int i = -255; i <= 255; ++i) 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) 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; block.IsI4x4 = this.bitReader.GetBit(145) is 0;
@ -488,7 +488,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
break; 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); this.DoUVTransform(bitsUv >> 8, coeffs.AsSpan(20 * 16), vDst);
// Stash away top samples for next block. // 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); 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); 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); 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); 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); 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.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); 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); 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.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); 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 left = dec.LeftMacroBlock;
Vp8MacroBlock macroBlock = dec.CurrentMacroBlock; Vp8MacroBlock macroBlock = dec.CurrentMacroBlock;
Vp8MacroBlockData blockData = dec.CurrentBlockData; 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 else
{ {
@ -843,7 +843,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
{ {
Vp8FilterInfo precomputedFilterInfo = dec.FilterStrength[blockData.Segment, blockData.IsI4x4 ? 1 : 0]; Vp8FilterInfo precomputedFilterInfo = dec.FilterStrength[blockData.Segment, blockData.IsI4x4 ? 1 : 0];
dec.FilterInfo[dec.MbX] = (Vp8FilterInfo)precomputedFilterInfo.DeepClone(); 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