From 9cb828ec2d2b81559f872191325ab9603645846c Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sun, 4 Jul 2021 13:44:44 +0200 Subject: [PATCH] Store diffusion errors --- src/ImageSharp/Formats/WebP/Lossy/QuantEnc.cs | 17 ++++++++++---- .../Formats/WebP/Lossy/Vp8EncIterator.cs | 23 ++++++++++++++++++- .../Formats/WebP/Lossy/Vp8ModeScore.cs | 6 +++++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/ImageSharp/Formats/WebP/Lossy/QuantEnc.cs b/src/ImageSharp/Formats/WebP/Lossy/QuantEnc.cs index fda44f7e0e..0cc28b423b 100644 --- a/src/ImageSharp/Formats/WebP/Lossy/QuantEnc.cs +++ b/src/ImageSharp/Formats/WebP/Lossy/QuantEnc.cs @@ -240,6 +240,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy rdBest.CopyScore(rdUv); rd.ModeUv = mode; rdUv.UvLevels.CopyTo(rd.UvLevels.AsSpan()); + for (int i = 0; i < 2; i++) + { + rd.Derr[i, 0] = rdUv.Derr[i, 0]; + rd.Derr[i, 1] = rdUv.Derr[i, 1]; + rd.Derr[i, 2] = rdUv.Derr[i, 2]; + } + Span tmp = dst; dst = tmpDst; tmpDst = tmp; @@ -253,6 +260,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // copy 16x8 block if needed. LossyUtils.Vp8Copy16X8(dst, dst0); } + + // Store diffusion errors for next block. + it.StoreDiffusionErrors(rd); } public static int ReconstructIntra16(Vp8EncIterator it, Vp8SegmentInfo dqm, Vp8ModeScore rd, Span yuvOut, int mode) @@ -571,10 +581,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy c[3 * 16] += (short)(((C1 * err1) + (C2 * err2)) >> (DSHIFT - DSCALE)); int err3 = QuantizeSingle(c.Slice(3 * 16), mtx); - // TODO: set errors in rd - // rd->derr[ch][0] = (int8_t)err1; - // rd->derr[ch][1] = (int8_t)err2; - // rd->derr[ch][2] = (int8_t)err3; + rd.Derr[ch, 0] = err1; + rd.Derr[ch, 1] = err2; + rd.Derr[ch, 2] = err3; } } diff --git a/src/ImageSharp/Formats/WebP/Lossy/Vp8EncIterator.cs b/src/ImageSharp/Formats/WebP/Lossy/Vp8EncIterator.cs index 16dba65169..0e1d84243b 100644 --- a/src/ImageSharp/Formats/WebP/Lossy/Vp8EncIterator.cs +++ b/src/ImageSharp/Formats/WebP/Lossy/Vp8EncIterator.cs @@ -167,7 +167,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public uint[] Nz { get; } /// - /// Gets the diffusion error. + /// Gets the top diffusion error. /// public sbyte[] TopDerr { get; } @@ -587,6 +587,27 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public void SetSegment(int segment) => this.CurrentMacroBlockInfo.Segment = segment; + public void StoreDiffusionErrors(Vp8ModeScore rd) + { + for (int ch = 0; ch <= 1; ++ch) + { + Span top = this.TopDerr.AsSpan((this.X * 4) + ch, 2); + Span left = this.LeftDerr.AsSpan(ch, 2); + + // restore err1 + left[0] = (sbyte)rd.Derr[ch, 0]; + + // 3/4th of err3 + left[1] = (sbyte)((3 * rd.Derr[ch, 2]) >> 2); + + // err2 + top[0] = (sbyte)rd.Derr[ch, 1]; + + // 1/4th of err3. + top[1] = (sbyte)(rd.Derr[ch, 2] - left[1]); + } + } + /// /// Returns true if iteration is finished. /// diff --git a/src/ImageSharp/Formats/WebP/Lossy/Vp8ModeScore.cs b/src/ImageSharp/Formats/WebP/Lossy/Vp8ModeScore.cs index e47fa71609..7182f60210 100644 --- a/src/ImageSharp/Formats/WebP/Lossy/Vp8ModeScore.cs +++ b/src/ImageSharp/Formats/WebP/Lossy/Vp8ModeScore.cs @@ -25,6 +25,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.UvLevels = new short[(4 + 4) * 16]; this.ModesI4 = new byte[16]; + this.Derr = new int[2, 3]; } /// @@ -87,6 +88,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy /// public uint Nz { get; set; } + /// + /// Gets the diffusion errors. + /// + public int[,] Derr { get; } + public void InitScore() { this.D = 0;