Browse Source

Avoid allocating uvBuffer on each upscale call

pull/1836/head
Brian Popow 5 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 mbw = io.MbW;
int uvw = (mbw + 1) / 2; int uvw = (mbw + 1) / 2;
int y = io.MbY; int y = io.MbY;
byte[] uvBuffer = new byte[(14 * 32) + 15];
if (y == 0) if (y == 0)
{ {
// First line is special cased. We mirror the u/v samples at boundary. // 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 else
{ {
// We can finish the left-over line from previous call. // 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++; numLinesOut++;
} }
@ -714,7 +715,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
topV = curV; topV = curV;
curU = curU.Slice(io.UvStride); curU = curU.Slice(io.UvStride);
curV = curV.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); curY = curY.Slice(ioStride2);
dst = dst.Slice(bufferStride2); dst = dst.Slice(bufferStride2);
} }
@ -736,7 +737,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
// Process the very last row of even-sized picture. // Process the very last row of even-sized picture.
if ((yEnd & 1) == 0) 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: // we interpolate u/v as:
// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 // ([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 // ([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 SUPPORTS_RUNTIME_INTRINSICS
if (Sse41.IsSupported) 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 else
#endif #endif
@ -156,10 +156,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
// //
// Then m can be written as // Then m can be written as
// m = (k + t + 1) / 2 - (((b^c) & (s^t)) | (k^t)) & 1 // 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; 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> ru = uvBuffer.AsSpan(15);
Span<byte> rv = ru.Slice(32); Span<byte> rv = ru.Slice(32);

Loading…
Cancel
Save