Browse Source

Implement TrueMotion

pull/1552/head
Brian Popow 6 years ago
parent
commit
37c9a73137
  1. 39
      src/ImageSharp/Formats/WebP/LossyUtils.cs
  2. 8
      src/ImageSharp/Formats/WebP/WebPConstants.cs
  3. 8
      src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs

39
src/ImageSharp/Formats/WebP/LossyUtils.cs

@ -22,15 +22,15 @@ namespace SixLabors.ImageSharp.Formats.WebP
for (int j = 0; j < 16; ++j)
{
// DC += dst[-1 + j * BPS] + dst[j - BPS];
dc += yuv[offset - 1 + (j * WebPConstants.Bps)] + yuv[offset + j - WebPConstants.Bps];
dc += yuv[offset - 1 + (j * WebPConstants.Bps)] + yuv[offset + j - WebPConstants.Bps];
}
Put16(dc >> 5, dst);
}
public static void TM16_C(Span<byte> dst)
public static void TM16_C(Span<byte> dst, byte[] yuv, int offset)
{
TrueMotion(dst, yuv, offset, 16);
}
public static void VE16_C(Span<byte> dst, byte[] yuv, int offset)
@ -101,9 +101,10 @@ namespace SixLabors.ImageSharp.Formats.WebP
Put8x8uv((byte)(dc0 >> 4), dst);
}
public static void TM8uv_C(Span<byte> dst)
public static void TM8uv_C(Span<byte> dst, byte[] yuv, int offset)
{
// TrueMotion
TrueMotion(dst, yuv, offset, 8);
}
public static void VE8uv_C(Span<byte> dst, byte[] yuv, int offset)
@ -179,9 +180,9 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
}
public static void TM4_C(Span<byte> dst)
public static void TM4_C(Span<byte> dst, byte[] yuv, int offset)
{
TrueMotion(dst, yuv, offset, 4);
}
public static void VE4_C(Span<byte> dst, byte[] yuv, int offset)
@ -538,6 +539,27 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
}
private static void TrueMotion(Span<byte> dst, byte[] yuv, int offset, int size)
{
// For information about how true motion works, see rfc6386, page 52. ff and section 20.14.
int topOffset = offset - WebPConstants.Bps;
Span<byte> top = yuv.AsSpan(topOffset);
byte p = yuv[topOffset - 1];
int leftOffset = offset - 1;
byte left = yuv[leftOffset];
for (int y = 0; y < size; ++y)
{
for (int x = 0; x < size; ++x)
{
dst[x] = (byte)Clamp255(left + top[x] - p);
}
leftOffset += WebPConstants.Bps;
left = yuv[leftOffset];
dst = dst.Slice(WebPConstants.Bps);
}
}
// We process u and v together stashed into 32bit(16bit each).
public static uint LoadUv(byte u, byte v)
{
@ -637,5 +659,10 @@ namespace SixLabors.ImageSharp.Formats.WebP
{
dst[x + (y * WebPConstants.Bps)] = v;
}
private static int Clamp255(int x)
{
return x < 0 ? 0 : (x > 255 ? 255 : x);
}
}
}

8
src/ImageSharp/Formats/WebP/WebPConstants.cs

@ -125,10 +125,10 @@ namespace SixLabors.ImageSharp.Formats.WebP
public const int Bps = 32;
// intra prediction modes (TODO: maybe use an enum for this)
public const int DcPred = 0;
public const int TmPred = 1;
public const int VPred = 2;
public const int HPred = 3;
public const int DcPred = 0; // predict DC using row above and column to the left
public const int TmPred = 1; // propagate second differences a la "True Motion"
public const int VPred = 2; // predict rows using row above
public const int HPred = 3; // predict columns using column to the left
/// <summary>
/// How many extra lines are needed on the MB boundary for caching, given a filtering level.

8
src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs

@ -342,7 +342,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
LossyUtils.DC4_C(dst, yuv, offset);
break;
case 1:
LossyUtils.TM4_C(dst);
LossyUtils.TM4_C(dst, yuv, offset);
break;
case 2:
LossyUtils.VE4_C(dst, yuv, offset);
@ -383,7 +383,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
LossyUtils.DC16_C(yDst, yuv, yOff);
break;
case 1:
LossyUtils.TM16_C(yDst);
LossyUtils.TM16_C(yDst, yuv, yOff);
break;
case 2:
LossyUtils.VE16_C(yDst, yuv, yOff);
@ -421,8 +421,8 @@ namespace SixLabors.ImageSharp.Formats.WebP
LossyUtils.DC8uv_C(vDst, yuv, vOff);
break;
case 1:
LossyUtils.TM8uv_C(uDst);
LossyUtils.TM8uv_C(vDst);
LossyUtils.TM8uv_C(uDst, yuv, uOff);
LossyUtils.TM8uv_C(vDst, yuv, vOff);
break;
case 2:
LossyUtils.VE8uv_C(uDst, yuv, uOff);

Loading…
Cancel
Save