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