Browse Source

Remove linq usage while getting band probability row, add additional guard checks.

pull/1552/head
Brian Popow 6 years ago
parent
commit
e84301c134
  1. 28
      src/ImageSharp/Formats/WebP/IntraPredictionMode.cs
  2. 3
      src/ImageSharp/Formats/WebP/Readme.md
  3. 12
      src/ImageSharp/Formats/WebP/ReconstructionFilter.cs
  4. 6
      src/ImageSharp/Formats/WebP/VP8BandProbas.cs
  5. 4
      src/ImageSharp/Formats/WebP/Vp8Decoder.cs
  6. 39
      src/ImageSharp/Formats/WebP/Vp8FilterHeader.cs
  7. 38
      src/ImageSharp/Formats/WebP/Vp8FilterInfo.cs
  8. 18
      src/ImageSharp/Formats/WebP/Vp8MacroBlockData.cs
  9. 12
      src/ImageSharp/Formats/WebP/Vp8Proba.cs
  10. 6
      src/ImageSharp/Formats/WebP/Vp8ProbaArray.cs
  11. 35
      src/ImageSharp/Formats/WebP/Vp8Profile.cs
  12. 2
      src/ImageSharp/Formats/WebP/Vp8QuantMatrix.cs
  13. 4
      src/ImageSharp/Formats/WebP/Vp8SegmentHeader.cs
  14. 7
      src/ImageSharp/Formats/WebP/WebPConstants.cs
  15. 1
      src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs
  16. 28
      src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs
  17. 8
      tests/ImageSharp.Tests/TestImages.cs
  18. 3
      tests/Images/Input/WebP/grid.png
  19. 4
      tests/Images/Input/WebP/lossless_with_iccp.webp
  20. 3
      tests/Images/Input/WebP/peak.png

28
src/ImageSharp/Formats/WebP/IntraPredictionMode.cs

@ -0,0 +1,28 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats.WebP
{
internal enum IntraPredictionMode
{
/// <summary>
/// Predict DC using row above and column to the left.
/// </summary>
DcPrediction = 0,
/// <summary>
/// Propagate second differences a la "True Motion".
/// </summary>
TrueMotion = 1,
/// <summary>
/// Predict rows using row above.
/// </summary>
VPrediction = 2,
/// <summary>
/// Predict columns using column to the left.
/// </summary>
HPrediction = 3,
}
}

3
src/ImageSharp/Formats/WebP/Readme.md

@ -4,6 +4,7 @@ Reference implementation, specification and stuff like that:
- [google webp introduction](https://developers.google.com/speed/webp) - [google webp introduction](https://developers.google.com/speed/webp)
- [WebP Spec 1.0.3](https://chromium.googlesource.com/webm/libwebp/+/v1.0.3/doc/webp-container-spec.txt) - [WebP Spec 1.0.3](https://chromium.googlesource.com/webm/libwebp/+/v1.0.3/doc/webp-container-spec.txt)
- [WebP VP8 chunk Spec](http://tools.ietf.org/html/rfc6386) - [WebP VP8 Spec, Lossy](http://tools.ietf.org/html/rfc6386)
- [WebP VP8L Spec, Lossless](https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification)
- [WebP filefront](https://wiki.fileformat.com/image/webp/) - [WebP filefront](https://wiki.fileformat.com/image/webp/)
- [WebP test data](https://github.com/webmproject/libwebp-test-data/) - [WebP test data](https://github.com/webmproject/libwebp-test-data/)

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

@ -1,12 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats.WebP
{
internal enum ReconstructionFilter
{
None,
Bicubic,
Bilinear
}
}

6
src/ImageSharp/Formats/WebP/VP8BandProbas.cs

@ -8,6 +8,9 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// </summary> /// </summary>
internal class Vp8BandProbas internal class Vp8BandProbas
{ {
/// <summary>
/// Initializes a new instance of the <see cref="Vp8BandProbas"/> class.
/// </summary>
public Vp8BandProbas() public Vp8BandProbas()
{ {
this.Probabilities = new Vp8ProbaArray[WebPConstants.NumCtx]; this.Probabilities = new Vp8ProbaArray[WebPConstants.NumCtx];
@ -17,6 +20,9 @@ namespace SixLabors.ImageSharp.Formats.WebP
} }
} }
/// <summary>
/// Gets the Probabilities.
/// </summary>
public Vp8ProbaArray[] Probabilities { get; } public Vp8ProbaArray[] Probabilities { get; }
} }
} }

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

@ -285,12 +285,12 @@ namespace SixLabors.ImageSharp.Formats.WebP
baseLevel = this.SegmentHeader.FilterStrength[s]; baseLevel = this.SegmentHeader.FilterStrength[s];
if (!this.SegmentHeader.Delta) if (!this.SegmentHeader.Delta)
{ {
baseLevel += hdr.Level; baseLevel += hdr.FilterLevel;
} }
} }
else else
{ {
baseLevel = hdr.Level; baseLevel = hdr.FilterLevel;
} }
for (int i4x4 = 0; i4x4 <= 1; ++i4x4) for (int i4x4 = 0; i4x4 <= 1; ++i4x4)

39
src/ImageSharp/Formats/WebP/Vp8FilterHeader.cs

@ -9,6 +9,13 @@ namespace SixLabors.ImageSharp.Formats.WebP
private const int NumModeLfDeltas = 4; private const int NumModeLfDeltas = 4;
private int filterLevel;
private int sharpness;
/// <summary>
/// Initializes a new instance of the <see cref="Vp8FilterHeader"/> class.
/// </summary>
public Vp8FilterHeader() public Vp8FilterHeader()
{ {
this.RefLfDelta = new int[NumRefLfDeltas]; this.RefLfDelta = new int[NumRefLfDeltas];
@ -20,16 +27,36 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// </summary> /// </summary>
public LoopFilter LoopFilter { get; set; } public LoopFilter LoopFilter { get; set; }
// [0..63] /// <summary>
public int Level { get; set; } /// Gets or sets the filter level. Valid values are [0..63].
/// </summary>
public int FilterLevel
{
get => this.filterLevel;
set
{
Guard.MustBeBetweenOrEqualTo(value, 0, 63, nameof(this.FilterLevel));
this.filterLevel = value;
}
}
// [0..7] /// <summary>
public int Sharpness { get; set; } /// Gets or sets the filter sharpness. Valid values are [0..7].
/// </summary>
public int Sharpness
{
get => this.sharpness;
set
{
Guard.MustBeBetweenOrEqualTo(value, 0, 7, nameof(this.Sharpness));
this.sharpness = value;
}
}
public bool UseLfDelta { get; set; } public bool UseLfDelta { get; set; }
public int[] RefLfDelta { get; private set; } public int[] RefLfDelta { get; }
public int[] ModeLfDelta { get; private set; } public int[] ModeLfDelta { get; }
} }
} }

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

@ -8,6 +8,12 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// </summary> /// </summary>
internal class Vp8FilterInfo : IDeepCloneable internal class Vp8FilterInfo : IDeepCloneable
{ {
private byte limit;
private byte innerLevel;
private byte highEdgeVarianceThreshold;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Vp8FilterInfo"/> class. /// Initializes a new instance of the <see cref="Vp8FilterInfo"/> class.
/// </summary> /// </summary>
@ -30,12 +36,28 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// <summary> /// <summary>
/// Gets or sets the filter limit in [3..189], or 0 if no filtering. /// Gets or sets the filter limit in [3..189], or 0 if no filtering.
/// </summary> /// </summary>
public byte Limit { get; set; } public byte Limit
{
get => this.limit;
set
{
Guard.MustBeBetweenOrEqualTo(value, (byte)0, (byte)189, nameof(this.Limit));
this.limit = value;
}
}
/// <summary> /// <summary>
/// Gets or sets the inner limit in [1..63]. /// Gets or sets the inner limit in [1..63], or 0 if no filtering.
/// </summary> /// </summary>
public byte InnerLevel { get; set; } public byte InnerLevel
{
get => this.innerLevel;
set
{
Guard.MustBeBetweenOrEqualTo(value, (byte)0, (byte)63, nameof(this.InnerLevel));
this.innerLevel = value;
}
}
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to do inner filtering. /// Gets or sets a value indicating whether to do inner filtering.
@ -45,7 +67,15 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// <summary> /// <summary>
/// Gets or sets the high edge variance threshold in [0..2]. /// Gets or sets the high edge variance threshold in [0..2].
/// </summary> /// </summary>
public byte HighEdgeVarianceThreshold { get; set; } public byte HighEdgeVarianceThreshold
{
get => this.highEdgeVarianceThreshold;
set
{
Guard.MustBeBetweenOrEqualTo(value, (byte)0, (byte)2, nameof(this.HighEdgeVarianceThreshold));
this.highEdgeVarianceThreshold = value;
}
}
/// <inheritdoc/> /// <inheritdoc/>
public IDeepCloneable DeepClone() => new Vp8FilterInfo(this); public IDeepCloneable DeepClone() => new Vp8FilterInfo(this);

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

@ -37,8 +37,26 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// </summary> /// </summary>
public byte UvMode { get; set; } public byte UvMode { get; set; }
/// <summary>
/// Gets or sets bit-wise info about the content of each sub-4x4 blocks (in decoding order).
/// Each of the 4x4 blocks for y/u/v is associated with a 2b code according to:
/// code=0 -> no coefficient
/// code=1 -> only DC
/// code=2 -> first three coefficients are non-zero
/// code=3 -> more than three coefficients are non-zero
/// This allows to call specialized transform functions.
/// </summary>
public uint NonZeroY { get; set; } public uint NonZeroY { get; set; }
/// <summary>
/// Gets or sets bit-wise info about the content of each sub-4x4 blocks (in decoding order).
/// Each of the 4x4 blocks for y/u/v is associated with a 2b code according to:
/// code=0 -> no coefficient
/// code=1 -> only DC
/// code=2 -> first three coefficients are non-zero
/// code=3 -> more than three coefficients are non-zero
/// This allows to call specialized transform functions.
/// </summary>
public uint NonZeroUv { get; set; } public uint NonZeroUv { get; set; }
public bool Skip { get; set; } public bool Skip { get; set; }

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

@ -10,11 +10,14 @@ namespace SixLabors.ImageSharp.Formats.WebP
{ {
private const int MbFeatureTreeProbs = 3; private const int MbFeatureTreeProbs = 3;
/// <summary>
/// Initializes a new instance of the <see cref="Vp8Proba"/> class.
/// </summary>
public Vp8Proba() public Vp8Proba()
{ {
this.Segments = new uint[MbFeatureTreeProbs]; this.Segments = new uint[MbFeatureTreeProbs];
this.Bands = new Vp8BandProbas[WebPConstants.NumTypes, WebPConstants.NumBands]; this.Bands = new Vp8BandProbas[WebPConstants.NumTypes, WebPConstants.NumBands];
this.BandsPtr = new Vp8BandProbas[WebPConstants.NumTypes, 16 + 1]; this.BandsPtr = new Vp8BandProbas[WebPConstants.NumTypes][];
for (int i = 0; i < WebPConstants.NumTypes; i++) for (int i = 0; i < WebPConstants.NumTypes; i++)
{ {
@ -26,10 +29,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
for (int i = 0; i < WebPConstants.NumTypes; i++) for (int i = 0; i < WebPConstants.NumTypes; i++)
{ {
for (int j = 0; j < 17; j++) this.BandsPtr[i] = new Vp8BandProbas[16 + 1];
{
this.BandsPtr[i, j] = new Vp8BandProbas();
}
} }
} }
@ -37,6 +37,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
public Vp8BandProbas[,] Bands { get; } public Vp8BandProbas[,] Bands { get; }
public Vp8BandProbas[,] BandsPtr { get; } public Vp8BandProbas[][] BandsPtr { get; }
} }
} }

6
src/ImageSharp/Formats/WebP/Vp8ProbaArray.cs

@ -8,11 +8,17 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// </summary> /// </summary>
internal class Vp8ProbaArray internal class Vp8ProbaArray
{ {
/// <summary>
/// Initializes a new instance of the <see cref="Vp8ProbaArray"/> class.
/// </summary>
public Vp8ProbaArray() public Vp8ProbaArray()
{ {
this.Probabilities = new byte[WebPConstants.NumProbas]; this.Probabilities = new byte[WebPConstants.NumProbas];
} }
/// <summary>
/// Gets the probabilities.
/// </summary>
public byte[] Probabilities { get; } public byte[] Probabilities { get; }
} }
} }

35
src/ImageSharp/Formats/WebP/Vp8Profile.cs

@ -1,35 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats.WebP
{
/// <summary>
/// The version number of the frame header enables or disables certain features in the bitstream.
/// +---------+-------------------------+-------------+
/// | Version | Reconstruction Filter | Loop Filter |
/// +---------+-------------------------+-------------+
/// | 0 | Bicubic | Normal |
/// | | | |
/// | 1 | Bilinear | Simple |
/// | | | |
/// | 2 | Bilinear | None |
/// | | | |
/// | 3 | None | None |
/// | | | |
/// | Other | Reserved for future use | |
/// +---------+-------------------------+-------------+
/// See paragraph 9, https://tools.ietf.org/html/rfc6386.
/// </summary>
internal class Vp8Profile
{
/// <summary>
/// Gets or sets the reconstruction filter.
/// </summary>
public ReconstructionFilter ReconstructionFilter { get; set; }
/// <summary>
/// Gets or sets the loop filter.
/// </summary>
public LoopFilter LoopFilter { get; set; }
}
}

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

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
get => this.dither; get => this.dither;
set set
{ {
Guard.MustBeBetweenOrEqualTo(value, 0, 255, nameof(this.dither)); Guard.MustBeBetweenOrEqualTo(value, 0, 255, nameof(this.Dither));
this.dither = value; this.dither = value;
} }
} }

4
src/ImageSharp/Formats/WebP/Vp8SegmentHeader.cs

@ -32,11 +32,11 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// <summary> /// <summary>
/// Gets quantization changes. /// Gets quantization changes.
/// </summary> /// </summary>
public byte[] Quantizer { get; private set; } public byte[] Quantizer { get; }
/// <summary> /// <summary>
/// Gets the filter strength for segments. /// Gets the filter strength for segments.
/// </summary> /// </summary>
public byte[] FilterStrength { get; private set; } public byte[] FilterStrength { get; }
} }
} }

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

@ -110,7 +110,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
NumDistanceCodes NumDistanceCodes
}; };
// VP8 constants from here on:
public const int NumMbSegments = 4; public const int NumMbSegments = 4;
public const int MaxNumPartitions = 8; public const int MaxNumPartitions = 8;
@ -126,12 +125,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
// this is the common stride for enc/dec // this is the common stride for enc/dec
public const int Bps = 32; public const int Bps = 32;
// intra prediction modes (TODO: maybe use an enum for this)
public const int DcPred = 0; // predict DC using row above and column to the left
public const int TmPred = 1; // propagate second differences a la "True Motion"
public const int VPred = 2; // predict rows using row above
public const int HPred = 3; // predict columns using column to the left
/// <summary> /// <summary>
/// How many extra lines are needed on the MB boundary for caching, given a filtering level. /// How many extra lines are needed on the MB boundary for caching, given a filtering level.
/// Simple filter(1): up to 2 luma samples are read and 1 is written. /// Simple filter(1): up to 2 luma samples are read and 1 is written.

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

@ -602,7 +602,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
int repeat = (int)(this.bitReader.ReadValue(extraBits) + repeatOffset); int repeat = (int)(this.bitReader.ReadValue(extraBits) + repeatOffset);
if (symbol + repeat > numSymbols) if (symbol + repeat > numSymbols)
{ {
// TODO: not sure, if this should be treated as an error here
return; return;
} }

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

@ -3,7 +3,6 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -207,8 +206,8 @@ namespace SixLabors.ImageSharp.Formats.WebP
{ {
// Hardcoded 16x16 intra-mode decision tree. // Hardcoded 16x16 intra-mode decision tree.
int yMode = this.bitReader.GetBit(156) != 0 ? int yMode = this.bitReader.GetBit(156) != 0 ?
this.bitReader.GetBit(128) != 0 ? WebPConstants.TmPred : WebPConstants.HPred : this.bitReader.GetBit(128) != 0 ? (int)IntraPredictionMode.TrueMotion : (int)IntraPredictionMode.HPrediction :
this.bitReader.GetBit(163) != 0 ? WebPConstants.VPred : WebPConstants.DcPred; this.bitReader.GetBit(163) != 0 ? (int)IntraPredictionMode.VPrediction : (int)IntraPredictionMode.DcPrediction;
block.Modes[0] = (byte)yMode; block.Modes[0] = (byte)yMode;
for (int i = 0; i < left.Length; i++) for (int i = 0; i < left.Length; i++)
{ {
@ -864,7 +863,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
int dstOffset = 0; int dstOffset = 0;
Vp8MacroBlockData block = dec.CurrentBlockData; Vp8MacroBlockData block = dec.CurrentBlockData;
Vp8QuantMatrix q = dec.DeQuantMatrices[block.Segment]; Vp8QuantMatrix q = dec.DeQuantMatrices[block.Segment];
Vp8BandProbas[,] bands = dec.Probabilities.BandsPtr; Vp8BandProbas[][] bands = dec.Probabilities.BandsPtr;
Vp8BandProbas[] acProba; Vp8BandProbas[] acProba;
Vp8MacroBlock leftMb = dec.LeftMacroBlock; Vp8MacroBlock leftMb = dec.LeftMacroBlock;
short[] dst = block.Coeffs; short[] dst = block.Coeffs;
@ -876,14 +875,14 @@ namespace SixLabors.ImageSharp.Formats.WebP
if (block.IsI4x4) if (block.IsI4x4)
{ {
first = 0; first = 0;
acProba = GetBandsRow(bands, 3); acProba = bands[3];
} }
else else
{ {
// 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(br, GetBandsRow(bands, 1), ctx, q.Y2Mat, 0, dc); int nz = this.GetCoeffs(br, 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 > 1) if (nz > 1)
{ {
@ -901,7 +900,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
} }
first = 1; first = 1;
acProba = GetBandsRow(bands, 0); acProba = bands[0];
} }
byte tnz = (byte)(mb.NoneZeroAcDcCoeffs & 0x0f); byte tnz = (byte)(mb.NoneZeroAcDcCoeffs & 0x0f);
@ -941,7 +940,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(br, GetBandsRow(bands, 2), ctx, q.UvMat, 0, dst.AsSpan(dstOffset)); int nz = this.GetCoeffs(br, 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[dstOffset] != 0 ? 1 : 0); nzCoeffs = NzCodeBits(nzCoeffs, nz, dst[dstOffset] != 0 ? 1 : 0);
@ -1164,11 +1163,11 @@ namespace SixLabors.ImageSharp.Formats.WebP
{ {
Vp8FilterHeader vp8FilterHeader = dec.FilterHeader; Vp8FilterHeader vp8FilterHeader = dec.FilterHeader;
vp8FilterHeader.LoopFilter = this.bitReader.ReadBool() ? LoopFilter.Simple : LoopFilter.Complex; vp8FilterHeader.LoopFilter = this.bitReader.ReadBool() ? LoopFilter.Simple : LoopFilter.Complex;
vp8FilterHeader.Level = (int)this.bitReader.ReadValue(6); vp8FilterHeader.FilterLevel = (int)this.bitReader.ReadValue(6);
vp8FilterHeader.Sharpness = (int)this.bitReader.ReadValue(3); vp8FilterHeader.Sharpness = (int)this.bitReader.ReadValue(3);
vp8FilterHeader.UseLfDelta = this.bitReader.ReadBool(); vp8FilterHeader.UseLfDelta = this.bitReader.ReadBool();
dec.Filter = (vp8FilterHeader.Level == 0) ? LoopFilter.None : vp8FilterHeader.LoopFilter; dec.Filter = (vp8FilterHeader.FilterLevel == 0) ? LoopFilter.None : vp8FilterHeader.LoopFilter;
if (vp8FilterHeader.UseLfDelta) if (vp8FilterHeader.UseLfDelta)
{ {
// Update lf-delta? // Update lf-delta?
@ -1314,7 +1313,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
for (int b = 0; b < 16 + 1; ++b) for (int b = 0; b < 16 + 1; ++b)
{ {
proba.BandsPtr[t, b] = proba.Bands[t, WebPConstants.Bands[b]]; proba.BandsPtr[t][b] = proba.Bands[t, WebPConstants.Bands[b]];
} }
} }
@ -1391,13 +1390,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
return nzCoeffs; return nzCoeffs;
} }
[MethodImpl(InliningOptions.ShortMethod)]
private static Vp8BandProbas[] GetBandsRow(Vp8BandProbas[,] bands, int rowIdx)
{
Vp8BandProbas[] bandsRow = Enumerable.Range(0, bands.GetLength(1)).Select(x => bands[rowIdx, x]).ToArray();
return bandsRow;
}
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
private static int CheckMode(int mbx, int mby, int mode) private static int CheckMode(int mbx, int mby, int mode)
{ {

8
tests/ImageSharp.Tests/TestImages.cs

@ -506,10 +506,10 @@ namespace SixLabors.ImageSharp.Tests
// Invalid / corrupted images // Invalid / corrupted images
// Below images have errors according to webpinfo. The error message webpinfo gives is "Truncated data detected when parsing RIFF payload." // Below images have errors according to webpinfo. The error message webpinfo gives is "Truncated data detected when parsing RIFF payload."
public const string LossLessCorruptImage1 = "Webp/lossless_big_random_alpha.webp"; // substract_green, predictor, cross_color. public const string LossLessCorruptImage1 = "WebP/lossless_big_random_alpha.webp"; // substract_green, predictor, cross_color.
public const string LossLessCorruptImage2 = "Webp/lossless_vec_2_7.webp"; // color_indexing, predictor. public const string LossLessCorruptImage2 = "WebP/lossless_vec_2_7.webp"; // color_indexing, predictor.
public const string LossLessCorruptImage3 = "Webp/lossless_color_transform.webp"; // cross_color, predictor public const string LossLessCorruptImage3 = "WebP/lossless_color_transform.webp"; // cross_color, predictor
public const string LossLessCorruptImage4 = "Webp/near_lossless_75.webp"; // predictor, cross_color. public const string LossLessCorruptImage4 = "WebP/near_lossless_75.webp"; // predictor, cross_color.
} }
public static class Lossy public static class Lossy

3
tests/Images/Input/WebP/grid.png

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5c53fb4527509058a8a4caf72e03ee8634f4704ab5369a8e5d194e62359d6ad0
size 117

4
tests/Images/Input/WebP/lossless_with_iccp.webp

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:312aea5ac9557bdfa78ec95bab5c3446a97c980317f46c96a20a4b7837d0ae37 oid sha256:3cdb75584ac3db92d78c2c1ec828cb813d280540e5f1bb262ba0b2c352900f81
size 68355 size 69076

3
tests/Images/Input/WebP/peak.png

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b9b56ed5c1278664222c77f9a452b824b4f9215c819502b3f6b0e0d44270e7e7
size 26456
Loading…
Cancel
Save