Browse Source

Pass Vp8Matrix as ref

pull/1811/head
Brian Popow 5 years ago
parent
commit
8160a0eeb6
  1. 34
      src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs
  2. 2
      tests/ImageSharp.Tests/Formats/WebP/QuantEncTests.cs

34
src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs

@ -315,14 +315,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
} }
Vp8Encoding.FTransformWht(tmp, dcTmp, scratch); Vp8Encoding.FTransformWht(tmp, dcTmp, scratch);
nz |= QuantizeBlock(dcTmp, rd.YDcLevels, dqm.Y2) << 24; nz |= QuantizeBlock(dcTmp, rd.YDcLevels, ref dqm.Y2) << 24;
for (n = 0; n < 16; n += 2) for (n = 0; n < 16; n += 2)
{ {
// Zero-out the first coeff, so that: a) nz is correct below, and // Zero-out the first coeff, so that: a) nz is correct below, and
// b) finding 'last' non-zero coeffs in SetResidualCoeffs() is simplified. // b) finding 'last' non-zero coeffs in SetResidualCoeffs() is simplified.
tmp[n * 16] = tmp[(n + 1) * 16] = 0; tmp[n * 16] = tmp[(n + 1) * 16] = 0;
nz |= Quantize2Blocks(tmp.Slice(n * 16, 32), rd.YAcLevels.AsSpan(n * 16, 32), dqm.Y1) << n; nz |= Quantize2Blocks(tmp.Slice(n * 16, 32), rd.YAcLevels.AsSpan(n * 16, 32), ref dqm.Y1) << n;
} }
// Transform back. // Transform back.
@ -343,7 +343,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
tmp.Clear(); tmp.Clear();
scratch.Clear(); scratch.Clear();
Vp8Encoding.FTransform(src, reference, tmp, scratch); Vp8Encoding.FTransform(src, reference, tmp, scratch);
int nz = QuantizeBlock(tmp, levels, dqm.Y1); int nz = QuantizeBlock(tmp, levels, ref dqm.Y1);
Vp8Encoding.ITransform(reference, tmp, yuvOut, false, scratch); Vp8Encoding.ITransform(reference, tmp, yuvOut, false, scratch);
return nz; return nz;
@ -370,11 +370,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
scratch); scratch);
} }
CorrectDcValues(it, dqm.Uv, tmp, rd); CorrectDcValues(it, ref dqm.Uv, tmp, rd);
for (n = 0; n < 8; n += 2) for (n = 0; n < 8; n += 2)
{ {
nz |= Quantize2Blocks(tmp.Slice(n * 16, 32), rd.UvLevels.AsSpan(n * 16, 32), dqm.Uv) << n; nz |= Quantize2Blocks(tmp.Slice(n * 16, 32), rd.UvLevels.AsSpan(n * 16, 32), ref dqm.Uv) << n;
} }
for (n = 0; n < 8; n += 2) for (n = 0; n < 8; n += 2)
@ -525,19 +525,18 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
} }
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public static int Quantize2Blocks(Span<short> input, Span<short> output, Vp8Matrix mtx) public static int Quantize2Blocks(Span<short> input, Span<short> output, ref Vp8Matrix mtx)
{ {
int nz = QuantizeBlock(input.Slice(0, 16), output.Slice(0, 16), mtx) << 0; int nz = QuantizeBlock(input.Slice(0, 16), output.Slice(0, 16), ref mtx) << 0;
nz |= QuantizeBlock(input.Slice(1 * 16, 16), output.Slice(1 * 16, 16), mtx) << 1; nz |= QuantizeBlock(input.Slice(1 * 16, 16), output.Slice(1 * 16, 16), ref mtx) << 1;
return nz; return nz;
} }
public static int QuantizeBlock(Span<short> input, Span<short> output, Vp8Matrix mtx) public static int QuantizeBlock(Span<short> input, Span<short> output, ref Vp8Matrix mtx)
{ {
#if SUPPORTS_RUNTIME_INTRINSICS #if SUPPORTS_RUNTIME_INTRINSICS
if (Sse41.IsSupported) if (Sse41.IsSupported)
{ {
#pragma warning disable SA1503 // Braces should not be omitted
// Load all inputs. // Load all inputs.
Vector128<short> input0 = Unsafe.As<short, Vector128<short>>(ref MemoryMarshal.GetReference(input)); Vector128<short> input0 = Unsafe.As<short, Vector128<short>>(ref MemoryMarshal.GetReference(input));
Vector128<short> input8 = Unsafe.As<short, Vector128<short>>(ref MemoryMarshal.GetReference(input.Slice(8, 8))); Vector128<short> input8 = Unsafe.As<short, Vector128<short>>(ref MemoryMarshal.GetReference(input.Slice(8, 8)));
@ -624,10 +623,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
Vector128<sbyte> packedOutput = Sse2.PackSignedSaturate(outZ0.AsInt16(), outZ8.AsInt16()); Vector128<sbyte> packedOutput = Sse2.PackSignedSaturate(outZ0.AsInt16(), outZ8.AsInt16());
// Detect if all 'out' values are zeroes or not. // Detect if all 'out' values are zeros or not.
Vector128<sbyte> cmpeq = Sse2.CompareEqual(packedOutput, Vector128<sbyte>.Zero); Vector128<sbyte> cmpeq = Sse2.CompareEqual(packedOutput, Vector128<sbyte>.Zero);
return Sse2.MoveMask(cmpeq) != 0xffff ? 1 : 0; return Sse2.MoveMask(cmpeq) != 0xffff ? 1 : 0;
#pragma warning restore SA1503 // Braces should not be omitted
} }
else else
#endif #endif
@ -675,7 +673,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
// Quantize as usual, but also compute and return the quantization error. // Quantize as usual, but also compute and return the quantization error.
// Error is already divided by DSHIFT. // Error is already divided by DSHIFT.
public static int QuantizeSingle(Span<short> v, Vp8Matrix mtx) public static int QuantizeSingle(Span<short> v, ref Vp8Matrix mtx)
{ {
int v0 = v[0]; int v0 = v[0];
bool sign = v0 < 0; bool sign = v0 < 0;
@ -696,7 +694,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
return (sign ? -v0 : v0) >> DSCALE; return (sign ? -v0 : v0) >> DSCALE;
} }
public static void CorrectDcValues(Vp8EncIterator it, Vp8Matrix mtx, Span<short> tmp, Vp8ModeScore rd) public static void CorrectDcValues(Vp8EncIterator it, ref Vp8Matrix mtx, Span<short> tmp, Vp8ModeScore rd)
{ {
#pragma warning disable SA1005 // Single line comments should begin with single space #pragma warning disable SA1005 // Single line comments should begin with single space
// | top[0] | top[1] // | top[0] | top[1]
@ -713,13 +711,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
Span<sbyte> left = it.LeftDerr.AsSpan(ch, 2); Span<sbyte> left = it.LeftDerr.AsSpan(ch, 2);
Span<short> c = tmp.Slice(ch * 4 * 16, 4 * 16); Span<short> c = tmp.Slice(ch * 4 * 16, 4 * 16);
c[0] += (short)(((C1 * top[0]) + (C2 * left[0])) >> (DSHIFT - DSCALE)); c[0] += (short)(((C1 * top[0]) + (C2 * left[0])) >> (DSHIFT - DSCALE));
int err0 = QuantizeSingle(c, mtx); int err0 = QuantizeSingle(c, ref mtx);
c[1 * 16] += (short)(((C1 * top[1]) + (C2 * err0)) >> (DSHIFT - DSCALE)); c[1 * 16] += (short)(((C1 * top[1]) + (C2 * err0)) >> (DSHIFT - DSCALE));
int err1 = QuantizeSingle(c.Slice(1 * 16), mtx); int err1 = QuantizeSingle(c.Slice(1 * 16), ref mtx);
c[2 * 16] += (short)(((C1 * err0) + (C2 * left[1])) >> (DSHIFT - DSCALE)); c[2 * 16] += (short)(((C1 * err0) + (C2 * left[1])) >> (DSHIFT - DSCALE));
int err2 = QuantizeSingle(c.Slice(2 * 16), mtx); int err2 = QuantizeSingle(c.Slice(2 * 16), ref mtx);
c[3 * 16] += (short)(((C1 * err1) + (C2 * err2)) >> (DSHIFT - DSCALE)); c[3 * 16] += (short)(((C1 * err1) + (C2 * err2)) >> (DSHIFT - DSCALE));
int err3 = QuantizeSingle(c.Slice(3 * 16), mtx); int err3 = QuantizeSingle(c.Slice(3 * 16), ref mtx);
rd.Derr[ch, 0] = err1; rd.Derr[ch, 0] = err1;
rd.Derr[ch, 1] = err2; rd.Derr[ch, 1] = err2;

2
tests/ImageSharp.Tests/Formats/WebP/QuantEncTests.cs

@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.WebP
} }
// act // act
int actualResult = QuantEnc.QuantizeBlock(input, output, vp8Matrix); int actualResult = QuantEnc.QuantizeBlock(input, output, ref vp8Matrix);
// assert // assert
Assert.True(output.SequenceEqual(expectedOutput)); Assert.True(output.SequenceEqual(expectedOutput));

Loading…
Cancel
Save