From 05f1466a4eb22b26a780032c20e8d7c87128ffe7 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Fri, 23 Oct 2020 18:44:04 +0200 Subject: [PATCH] Fix some mistakes during macro block analysis --- .../Formats/WebP/Lossy/Vp8EncIterator.cs | 61 ++++++++----------- .../Formats/WebP/Lossy/Vp8Encoder.cs | 6 +- 2 files changed, 28 insertions(+), 39 deletions(-) diff --git a/src/ImageSharp/Formats/WebP/Lossy/Vp8EncIterator.cs b/src/ImageSharp/Formats/WebP/Lossy/Vp8EncIterator.cs index fe7d4e095a..a87caa34b0 100644 --- a/src/ImageSharp/Formats/WebP/Lossy/Vp8EncIterator.cs +++ b/src/ImageSharp/Formats/WebP/Lossy/Vp8EncIterator.cs @@ -87,20 +87,18 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy this.YuvOut2 = new byte[WebPConstants.Bps * 16]; this.YuvP = new byte[(32 * WebPConstants.Bps) + (16 * WebPConstants.Bps) + (8 * WebPConstants.Bps)]; // I16+Chroma+I4 preds this.YLeft = new byte[32]; - this.ULeft = new byte[32]; - this.VLeft = new byte[32]; + this.UvLeft = new byte[32]; this.TopNz = new int[9]; this.LeftNz = new int[9]; - // To match the C++ initial values, initialize all with 204. + // To match the C++ initial values of the reference implementation, initialize all with 204. byte defaultInitVal = 204; this.YuvIn.AsSpan().Fill(defaultInitVal); this.YuvOut.AsSpan().Fill(defaultInitVal); this.YuvOut2.AsSpan().Fill(defaultInitVal); this.YuvP.AsSpan().Fill(defaultInitVal); this.YLeft.AsSpan().Fill(defaultInitVal); - this.ULeft.AsSpan().Fill(defaultInitVal); - this.VLeft.AsSpan().Fill(defaultInitVal); + this.UvLeft.AsSpan().Fill(defaultInitVal); for (int i = -255; i <= 255 + 255; ++i) { @@ -146,14 +144,9 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy public byte[] YLeft { get; set; } /// - /// Gets or sets the left u samples. + /// Gets or sets the left uv samples. /// - public byte[] ULeft { get; set; } - - /// - /// Gets or sets the left v samples. - /// - public byte[] VLeft { get; set; } + public byte[] UvLeft { get; set; } /// /// Gets or sets the top luma samples at position 'X'. @@ -228,8 +221,8 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy else { Span yLeft = this.YLeft.AsSpan(); - Span uLeft = this.ULeft.AsSpan(); - Span vLeft = this.VLeft.AsSpan(); + Span uLeft = this.UvLeft.AsSpan(0, 16); + Span vLeft = this.UvLeft.AsSpan(16, 16); if (this.Y == 0) { yLeft[0] = 127; @@ -366,12 +359,11 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy private void SetIntra4Mode(byte[] modes) { int modesIdx = 0; - Span preds = this.Preds.Slice(this.predIdx); + int predIdx = this.predIdx; for (int y = 4; y > 0; --y) { - // TODO: - // memcpy(preds, modes, 4 * sizeof(*modes)); - preds = preds.Slice(this.predsWidth); + modes.AsSpan(modesIdx, 4).CopyTo(this.Preds.Slice(predIdx)); + predIdx += this.predsWidth; modesIdx += 4; } @@ -457,12 +449,12 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy private void MakeChroma8Preds() { - Span left = this.X != 0 ? this.ULeft.AsSpan() : null; + Span left = this.X != 0 ? this.UvLeft.AsSpan() : null; Span top = this.Y != 0 ? this.UvTop.Slice(this.uvTopIdx) : null; this.EncPredChroma8(this.YuvP, left, top); } - // luma 16x16 prediction (paragraph 12.3) + // luma 16x16 prediction (paragraph 12.3). private void EncPredLuma16(Span dst, Span left, Span top) { this.DcMode(dst.Slice(I16DC16), left, top, 16, 16, 5); @@ -471,16 +463,16 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy this.TrueMotion(dst.Slice(I16TM16), left, top, 16); } - // Chroma 8x8 prediction (paragraph 12.2) + // Chroma 8x8 prediction (paragraph 12.2). private void EncPredChroma8(Span dst, Span left, Span top) { - // U block + // U block. this.DcMode(dst.Slice(C8DC8), left, top, 8, 8, 4); this.VerticalPred(dst.Slice(C8VE8), top, 8); this.HorizontalPred(dst.Slice(C8HE8), left, 8); this.TrueMotion(dst.Slice(C8TM8), left, top, 8); - // V block + // V block. dst = dst.Slice(8); if (top != null) { @@ -529,6 +521,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy else if (left != null) { // left but no top. + left = left.Slice(1); // in the reference implementation, left starts at -1. for (j = 0; j < size; ++j) { dc += left[j]; @@ -628,16 +621,17 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy private void ImportBlock(Span src, int srcStride, Span dst, int w, int h, int size) { int dstIdx = 0; + int srcIdx = 0; for (int i = 0; i < h; ++i) { - src.Slice(0, w).CopyTo(dst.Slice(dstIdx)); + src.Slice(srcIdx, w).CopyTo(dst.Slice(dstIdx)); if (w < size) { dst.Slice(dstIdx, size - w).Fill(dst[dstIdx + w - 1]); } dstIdx += WebPConstants.Bps; - src = src.Slice(srcStride); + srcIdx += srcStride; } for (int i = h; i < size; ++i) @@ -650,10 +644,11 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy private void ImportLine(Span src, int srcStride, Span dst, int len, int totalLen) { int i; + int srcIdx = 0; for (i = 0; i < len; ++i) { - dst[i] = src[i]; - src = src.Slice(srcStride); + dst[i] = src[srcIdx]; + srcIdx += srcStride; } for (; i < totalLen; ++i) @@ -686,30 +681,24 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy this.nzIdx = 0; this.yTopIdx = 0; this.uvTopIdx = 0; + this.predIdx = y * 4 * this.predsWidth; this.InitLeft(); - - // TODO: - // it->preds_ = enc->preds_ + y * 4 * enc->preds_w_; } private void InitLeft() { Span yLeft = this.YLeft.AsSpan(); - Span uLeft = this.ULeft.AsSpan(); - Span vLeft = this.VLeft.AsSpan(); + Span uLeft = this.UvLeft.AsSpan(0, 16); + Span vLeft = this.UvLeft.AsSpan(16, 16); byte val = (byte)((this.Y > 0) ? 129 : 127); yLeft[0] = val; uLeft[0] = val; vLeft[0] = val; - uLeft[16] = val; - vLeft[16] = val; yLeft.Slice(1, 16).Fill(129); uLeft.Slice(1, 8).Fill(129); vLeft.Slice(1, 8).Fill(129); - uLeft.Slice(1 + 16, 8).Fill(129); - vLeft.Slice(1 + 16, 8).Fill(129); this.LeftNz[8] = 0; } diff --git a/src/ImageSharp/Formats/WebP/Lossy/Vp8Encoder.cs b/src/ImageSharp/Formats/WebP/Lossy/Vp8Encoder.cs index 7aec1870db..a38b167c07 100644 --- a/src/ImageSharp/Formats/WebP/Lossy/Vp8Encoder.cs +++ b/src/ImageSharp/Formats/WebP/Lossy/Vp8Encoder.cs @@ -167,7 +167,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy alphas[bestAlpha]++; it.CurrentMacroBlockInfo.Alpha = bestAlpha; // For later remapping. - return bestAlpha; // Mixed susceptibility (not just luma) + return bestAlpha; // Mixed susceptibility (not just luma). } private void ConvertRgbToYuv(Image image) @@ -420,8 +420,8 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossy [MethodImpl(InliningOptions.ShortMethod)] private int Interpolate(int v) { - int tabPos = v >> (WebPConstants.GammaTabFix + 2); // integer part - int x = v & ((WebPConstants.GammaTabScale << 2) - 1); // fractional part + int tabPos = v >> (WebPConstants.GammaTabFix + 2); // integer part. + int x = v & ((WebPConstants.GammaTabScale << 2) - 1); // fractional part. int v0 = WebPLookupTables.LinearToGammaTab[tabPos]; int v1 = WebPLookupTables.LinearToGammaTab[tabPos + 1]; int y = (v1 * x) + (v0 * ((WebPConstants.GammaTabScale << 2) - x)); // interpolate