From c8d580cbe050244a464ce97de6acb6cd4ef858d2 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Fri, 7 Apr 2023 19:29:07 +0200 Subject: [PATCH] Add JsonConstructors --- .../Formats/Webp/Lossy/Vp8BandProbas.cs | 9 +++ .../Formats/Webp/Lossy/Vp8CostArray.cs | 9 +++ src/ImageSharp/Formats/Webp/Lossy/Vp8Costs.cs | 9 +++ .../Formats/Webp/Lossy/Vp8ProbaArray.cs | 9 +++ .../Formats/Webp/Lossy/Vp8Residual.cs | 66 +++++++++++++++++++ src/ImageSharp/Formats/Webp/Lossy/Vp8Stats.cs | 9 +++ .../Formats/Webp/Lossy/Vp8StatsArray.cs | 9 +++ 7 files changed, 120 insertions(+) diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8BandProbas.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8BandProbas.cs index 90506efb8..86304d4bd 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8BandProbas.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8BandProbas.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Text.Json.Serialization; + namespace SixLabors.ImageSharp.Formats.Webp.Lossy; /// @@ -20,6 +22,13 @@ internal class Vp8BandProbas } } + /// + /// Initializes a new instance of the class. + /// Only used for unit tests. + /// + [JsonConstructor] + public Vp8BandProbas(Vp8ProbaArray[] probabilities) => this.Probabilities = probabilities; + /// /// Gets the Probabilities. /// diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8CostArray.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8CostArray.cs index 2c8d723d7..8268e1c02 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8CostArray.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8CostArray.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Text.Json.Serialization; + namespace SixLabors.ImageSharp.Formats.Webp.Lossy; internal class Vp8CostArray @@ -10,5 +12,12 @@ internal class Vp8CostArray /// public Vp8CostArray() => this.Costs = new ushort[67 + 1]; + /// + /// Initializes a new instance of the class. + /// Only used for unit tests. + /// + [JsonConstructor] + public Vp8CostArray(ushort[] costs) => this.Costs = costs; + public ushort[] Costs { get; } } diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Costs.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Costs.cs index eee22159e..2441436fb 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Costs.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Costs.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Text.Json.Serialization; + namespace SixLabors.ImageSharp.Formats.Webp.Lossy; internal class Vp8Costs @@ -17,6 +19,13 @@ internal class Vp8Costs } } + /// + /// Initializes a new instance of the class. + /// Only used for unit tests. + /// + [JsonConstructor] + public Vp8Costs(Vp8CostArray[] costs) => this.Costs = costs; + /// /// Gets the Costs. /// diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8ProbaArray.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8ProbaArray.cs index 337527542..a19f9742f 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8ProbaArray.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8ProbaArray.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Text.Json.Serialization; + namespace SixLabors.ImageSharp.Formats.Webp.Lossy; /// @@ -13,6 +15,13 @@ internal class Vp8ProbaArray /// public Vp8ProbaArray() => this.Probabilities = new byte[WebpConstants.NumProbas]; + /// + /// Initializes a new instance of the class. + /// Only used for unit tests. + /// + [JsonConstructor] + public Vp8ProbaArray(byte[] probabilities) => this.Probabilities = probabilities; + /// /// Gets the probabilities. /// diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs index 68bf09f94..c00d7dbdd 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs @@ -7,6 +7,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; +using System.Text.Json.Serialization; namespace SixLabors.ImageSharp.Formats.Webp.Lossy; @@ -15,6 +16,22 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy; /// internal class Vp8Residual { + public Vp8Residual() + { + } + + [JsonConstructor] + public Vp8Residual(int first, int last, int coeffType, short[] coeffs, Vp8BandProbas[] prob, Vp8Stats[] stats, Vp8Costs[] costs) + { + this.First = first; + this.Last = last; + this.CoeffType = coeffType; + this.Coeffs = coeffs; + this.Prob = prob; + this.Stats = stats; + this.Costs = costs; + } + public int First { get; set; } public int Last { get; set; } @@ -156,6 +173,55 @@ internal class Vp8Residual return LossyUtils.Vp8BitCost(0, (byte)p0); } + if (false) + { + Span scratch = stackalloc byte[32]; + Span ctxs = scratch.Slice(0, 16); + Span levels = scratch.Slice(16); + Span absLevels = stackalloc ushort[16]; + + // Precompute clamped levels and contexts, packed to 8b. + ref short outputRef = ref MemoryMarshal.GetReference(this.Coeffs); + Vector256 c0 = Unsafe.As>(ref outputRef).AsInt16(); + Vector256 d0 = Avx2.Subtract(Vector256.Zero, c0); + Vector256 e0 = Avx2.Max(c0, d0); // abs(v), 16b + Vector256 f = Avx2.PackSignedSaturate(e0, e0); + Vector256 g = Avx2.Min(f.AsByte(), Vector256.Create((byte)2)); + Vector256 h = Avx2.Min(f.AsByte(), Vector256.Create((byte)67)); // clampLevel in [0..67] + + ref byte ctxsRef = ref MemoryMarshal.GetReference(ctxs); + ref byte levelsRef = ref MemoryMarshal.GetReference(levels); + ref ushort absLevelsRef = ref MemoryMarshal.GetReference(absLevels); + Unsafe.As>(ref ctxsRef) = g.GetLower(); + Unsafe.As>(ref levelsRef) = h.GetLower(); + Unsafe.As>(ref absLevelsRef) = e0.AsUInt16(); + + int level; + int flevel; + for (; n < this.Last; ++n) + { + int ctx = ctxs[n]; + level = levels[n]; + flevel = absLevels[n]; + cost += WebpLookupTables.Vp8LevelFixedCosts[flevel] + t.Costs[level]; + t = costs[n + 1].Costs[ctx]; + } + + // Last coefficient is always non-zero. + level = levels[n]; + flevel = absLevels[n]; + cost += WebpLookupTables.Vp8LevelFixedCosts[flevel] + t.Costs[level]; + if (n < 15) + { + int b = WebpConstants.Vp8EncBands[n + 1]; + int ctx = ctxs[n]; + int lastP0 = this.Prob[b].Probabilities[ctx].Probabilities[0]; + cost += LossyUtils.Vp8BitCost(0, (byte)lastP0); + } + + return cost; + } + if (Sse2.IsSupported) { Span scratch = stackalloc byte[32]; diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Stats.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Stats.cs index dda921a7c..b6c05f2d4 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Stats.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Stats.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Text.Json.Serialization; + namespace SixLabors.ImageSharp.Formats.Webp.Lossy; internal class Vp8Stats @@ -17,5 +19,12 @@ internal class Vp8Stats } } + /// + /// Initializes a new instance of the class. + /// Only used for unit tests. + /// + [JsonConstructor] + public Vp8Stats(Vp8StatsArray[] stats) => this.Stats = stats; + public Vp8StatsArray[] Stats { get; } } diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8StatsArray.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8StatsArray.cs index 2fbba6996..864248dd8 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8StatsArray.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8StatsArray.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Text.Json.Serialization; + namespace SixLabors.ImageSharp.Formats.Webp.Lossy; internal class Vp8StatsArray @@ -10,5 +12,12 @@ internal class Vp8StatsArray /// public Vp8StatsArray() => this.Stats = new uint[WebpConstants.NumProbas]; + /// + /// Initializes a new instance of the class. + /// Only used for unit tests. + /// + [JsonConstructor] + public Vp8StatsArray(uint[] stats) => this.Stats = stats; + public uint[] Stats { get; } }