Browse Source

Avoid allocating uvBuffer on each upscale call

pull/1836/head
Brian Popow 4 years ago
parent
commit
1eb1e82a2f
  1. 9
      src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs
  2. 8
      src/ImageSharp/Formats/Webp/Lossy/YuvConversion.cs

9
src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs

@ -692,16 +692,17 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
int mbw = io.MbW;
int uvw = (mbw + 1) / 2;
int y = io.MbY;
byte[] uvBuffer = new byte[(14 * 32) + 15];
if (y == 0)
{
// First line is special cased. We mirror the u/v samples at boundary.
YuvConversion.UpSample(curY, default, curU, curV, curU, curV, dst, default, mbw);
YuvConversion.UpSample(curY, default, curU, curV, curU, curV, dst, default, mbw, uvBuffer);
}
else
{
// We can finish the left-over line from previous call.
YuvConversion.UpSample(tmpYBuffer, curY, topU, topV, curU, curV, buf.Slice(dstStartIdx - bufferStride), dst, mbw);
YuvConversion.UpSample(tmpYBuffer, curY, topU, topV, curU, curV, buf.Slice(dstStartIdx - bufferStride), dst, mbw, uvBuffer);
numLinesOut++;
}
@ -714,7 +715,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
topV = curV;
curU = curU.Slice(io.UvStride);
curV = curV.Slice(io.UvStride);
YuvConversion.UpSample(curY.Slice(io.YStride), curY.Slice(ioStride2), topU, topV, curU, curV, dst.Slice(bufferStride), dst.Slice(bufferStride2), mbw);
YuvConversion.UpSample(curY.Slice(io.YStride), curY.Slice(ioStride2), topU, topV, curU, curV, dst.Slice(bufferStride), dst.Slice(bufferStride2), mbw, uvBuffer);
curY = curY.Slice(ioStride2);
dst = dst.Slice(bufferStride2);
}
@ -736,7 +737,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
// Process the very last row of even-sized picture.
if ((yEnd & 1) == 0)
{
YuvConversion.UpSample(curY, default, curU, curV, curU, curV, dst.Slice(bufferStride), default, mbw);
YuvConversion.UpSample(curY, default, curU, curV, curU, curV, dst.Slice(bufferStride), default, mbw, uvBuffer);
}
}

8
src/ImageSharp/Formats/Webp/Lossy/YuvConversion.cs

@ -73,12 +73,12 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
// we interpolate u/v as:
// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16
// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16
public static void UpSample(Span<byte> topY, Span<byte> bottomY, Span<byte> topU, Span<byte> topV, Span<byte> curU, Span<byte> curV, Span<byte> topDst, Span<byte> bottomDst, int len)
public static void UpSample(Span<byte> topY, Span<byte> bottomY, Span<byte> topU, Span<byte> topV, Span<byte> curU, Span<byte> curV, Span<byte> topDst, Span<byte> bottomDst, int len, byte[] uvBuffer)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Sse41.IsSupported)
{
UpSampleSse41(topY, bottomY, topU, topV, curU, curV, topDst, bottomDst, len);
UpSampleSse41(topY, bottomY, topU, topV, curU, curV, topDst, bottomDst, len, uvBuffer);
}
else
#endif
@ -156,10 +156,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
//
// Then m can be written as
// m = (k + t + 1) / 2 - (((b^c) & (s^t)) | (k^t)) & 1
public static void UpSampleSse41(Span<byte> topY, Span<byte> bottomY, Span<byte> topU, Span<byte> topV, Span<byte> curU, Span<byte> curV, Span<byte> topDst, Span<byte> bottomDst, int len)
public static void UpSampleSse41(Span<byte> topY, Span<byte> bottomY, Span<byte> topU, Span<byte> topV, Span<byte> curU, Span<byte> curV, Span<byte> topDst, Span<byte> bottomDst, int len, byte[] uvBuffer)
{
const int xStep = 3;
byte[] uvBuffer = new byte[(14 * 32) + 15];
Array.Clear(uvBuffer, 0, uvBuffer.Length);
Span<byte> ru = uvBuffer.AsSpan(15);
Span<byte> rv = ru.Slice(32);

Loading…
Cancel
Save