Browse Source

Implement functions for luma modes

pull/1552/head
Brian Popow 6 years ago
parent
commit
c55334bad6
  1. 309
      src/ImageSharp/Formats/WebP/LossyUtils.cs
  2. 2
      src/ImageSharp/Formats/WebP/Vp8BitReader.cs
  3. 25
      src/ImageSharp/Formats/WebP/Vp8Decoder.cs
  4. 57
      src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs

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

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers.Binary;
namespace SixLabors.ImageSharp.Formats.WebP
{
@ -18,11 +19,10 @@ namespace SixLabors.ImageSharp.Formats.WebP
public static void DC16_C(Span<byte> dst, byte[] yuv, int offset)
{
int dc = 16;
int j;
for (j = 0; j < 16; ++j)
for (int j = 0; j < 16; ++j)
{
// DC += dst[-1 + j * BPS] + dst[j - BPS];
dc += yuv[-1 + (j * WebPConstants.Bps) + offset] + yuv[j - WebPConstants.Bps + offset];
dc += yuv[offset - 1 + (j * WebPConstants.Bps)] + yuv[offset + j - WebPConstants.Bps];
}
Put16(dc >> 5, dst);
@ -106,9 +106,11 @@ namespace SixLabors.ImageSharp.Formats.WebP
// TrueMotion
}
public static void VE8uv_C(Span<byte> dst, Span<byte> src)
public static void VE8uv_C(Span<byte> dst, byte[] yuv, int offset)
{
// vertical
Span<byte> src = yuv.AsSpan(offset - WebPConstants.Bps, 8);
for (int j = 0; j < 8; ++j)
{
// memcpy(dst + j * BPS, dst - BPS, 8);
@ -122,9 +124,11 @@ namespace SixLabors.ImageSharp.Formats.WebP
for (int j = 0; j < 8; ++j)
{
// memset(dst, dst[-1], 8);
// dst += BPS;
byte v = yuv[offset - 1];
Memset(dst, v, 0, 8);
dst = dst.Slice(WebPConstants.Bps);
offset += WebPConstants.Bps;
}
}
@ -160,9 +164,19 @@ namespace SixLabors.ImageSharp.Formats.WebP
Put8x8uv(0x80, dst);
}
public static void DC4_C(Span<byte> dst)
public static void DC4_C(Span<byte> dst, byte[] yuv, int offset)
{
int dc = 4;
for (int i = 0; i < 4; ++i)
{
dc += yuv[offset + i - WebPConstants.Bps] + yuv[offset - 1 + (i * WebPConstants.Bps)];
}
dc >>= 3;
for (int i = 0; i < 4; ++i)
{
Memset(dst, (byte)dc, i * WebPConstants.Bps, 4);
}
}
public static void TM4_C(Span<byte> dst)
@ -170,44 +184,249 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
public static void VE4_C(Span<byte> dst)
{
}
public static void HE4_C(Span<byte> dst)
{
}
public static void RD4_C(Span<byte> dst)
{
}
public static void VR4_C(Span<byte> dst)
public static void VE4_C(Span<byte> dst, byte[] yuv, int offset)
{
// vertical
int topOffset = offset - WebPConstants.Bps;
byte[] vals =
{
Avg3(yuv[topOffset - 1], yuv[topOffset], yuv[topOffset + 1]),
Avg3(yuv[topOffset], yuv[topOffset + 1], yuv[topOffset + 2]),
Avg3(yuv[topOffset + 1], yuv[topOffset + 2], yuv[topOffset + 3]),
Avg3(yuv[topOffset + 2], yuv[topOffset + 3], yuv[topOffset + 4])
};
for (int i = 0; i < 4; ++i)
{
vals.CopyTo(dst.Slice(i * WebPConstants.Bps));
}
}
public static void LD4_C(Span<byte> dst)
{
}
public static void VL4_C(Span<byte> dst)
{
}
public static void HD4_C(Span<byte> dst)
{
}
public static void HU4_C(Span<byte> dst)
public static void HE4_C(Span<byte> dst, byte[] yuv, int offset)
{
// horizontal
byte A = yuv[offset - 1 - WebPConstants.Bps];
byte B = yuv[offset - 1];
byte C = yuv[offset - 1 + WebPConstants.Bps];
byte D = yuv[offset - 1 + (2 * WebPConstants.Bps)];
byte E = yuv[offset - 1 + (3 * WebPConstants.Bps)];
uint val = 0x01010101U * Avg3(A, B, C);
BinaryPrimitives.WriteUInt32BigEndian(dst, val);
val = 0x01010101U * Avg3(B, C, D);
BinaryPrimitives.WriteUInt32BigEndian(dst.Slice(WebPConstants.Bps), val);
val = 0x01010101U * Avg3(C, D, E);
BinaryPrimitives.WriteUInt32BigEndian(dst.Slice(2 * WebPConstants.Bps), val);
val = 0x01010101U * Avg3(D, E, E);
BinaryPrimitives.WriteUInt32BigEndian(dst.Slice(3 * WebPConstants.Bps), val);
}
public static void RD4_C(Span<byte> dst, byte[] yuv, int offset)
{
// Down-right
byte I = yuv[offset - 1];
byte J = yuv[offset - 1 + (1 * WebPConstants.Bps)];
byte K = yuv[offset - 1 + (2 * WebPConstants.Bps)];
byte L = yuv[offset - 1 + (3 * WebPConstants.Bps)];
byte X = yuv[offset - 1 - WebPConstants.Bps];
byte A = yuv[offset - WebPConstants.Bps];
byte B = yuv[offset + 1 - WebPConstants.Bps];
byte C = yuv[offset + 2 - WebPConstants.Bps];
byte D = yuv[offset + 3 - WebPConstants.Bps];
Dst(dst, 0, 3, Avg3(J, K, L));
byte ijk = Avg3(I, J, K);
Dst(dst, 1, 3, ijk);
Dst(dst, 0, 2, ijk);
byte xij = Avg3(X, I, J);
Dst(dst, 2, 3, xij);
Dst(dst, 1, 2, xij);
Dst(dst, 0, 1, xij);
byte axi = Avg3(A, X, I);
Dst(dst, 3, 3, axi);
Dst(dst, 2, 2, axi);
Dst(dst, 1, 1, axi);
Dst(dst, 0, 0, axi);
byte bax = Avg3(B, A, X);
Dst(dst, 3, 2, bax);
Dst(dst, 2, 1, bax);
Dst(dst, 1, 0, bax);
byte cba = Avg3(C, B, A);
Dst(dst, 3, 1, cba);
Dst(dst, 2, 0, cba);
Dst(dst, 3, 0, Avg3(D, C, B));
}
public static void VR4_C(Span<byte> dst, byte[] yuv, int offset)
{
// Vertical-Right
byte I = yuv[offset - 1];
byte J = yuv[offset - 1 + (1 * WebPConstants.Bps)];
byte K = yuv[offset - 1 + (2 * WebPConstants.Bps)];
byte X = yuv[offset - 1 - WebPConstants.Bps];
byte A = yuv[offset - WebPConstants.Bps];
byte B = yuv[offset + 1 - WebPConstants.Bps];
byte C = yuv[offset + 2 - WebPConstants.Bps];
byte D = yuv[offset + 3 - WebPConstants.Bps];
byte xa = Avg2(X, A);
Dst(dst, 0, 0, xa);
Dst(dst, 1, 2, xa);
byte ab = Avg2(A, B);
Dst(dst, 1, 0, ab);
Dst(dst, 2, 2, ab);
byte bc = Avg2(B, C);
Dst(dst, 2, 0, bc);
Dst(dst, 3, 2, bc);
Dst(dst, 3, 0, Avg2(C, D));
Dst(dst, 0, 3, Avg3(K, I, J));
Dst(dst, 0, 2, Avg3(J, I, X));
byte ixa = Avg3(I, X, A);
Dst(dst, 0, 1, ixa);
Dst(dst, 1, 3, ixa);
byte xab = Avg3(X, A, B);
Dst(dst, 1, 1, xab);
Dst(dst, 2, 3, xab);
byte abc = Avg3(A, B, C);
Dst(dst, 2, 1, abc);
Dst(dst, 3, 3, abc);
Dst(dst, 3, 1, Avg3(B, C, D));
}
public static void LD4_C(Span<byte> dst, byte[] yuv, int offset)
{
// Down-Left
byte A = yuv[offset - WebPConstants.Bps];
byte B = yuv[offset + 1 - WebPConstants.Bps];
byte C = yuv[offset + 2 - WebPConstants.Bps];
byte D = yuv[offset + 3 - WebPConstants.Bps];
byte E = yuv[offset + 4 - WebPConstants.Bps];
byte F = yuv[offset + 5 - WebPConstants.Bps];
byte G = yuv[offset + 6 - WebPConstants.Bps];
byte H = yuv[offset + 7 - WebPConstants.Bps];
Dst(dst, 0, 0, Avg3(A, B, C));
byte bcd = Avg3(B, C, D);
Dst(dst, 1, 0, bcd);
Dst(dst, 0, 1, bcd);
byte cde = Avg3(C, D, E);
Dst(dst, 2, 0, cde);
Dst(dst, 1, 1, cde);
Dst(dst, 0, 2, cde);
byte def = Avg3(D, E, F);
Dst(dst, 3, 0, def);
Dst(dst, 2, 1, def);
Dst(dst, 1, 2, def);
Dst(dst, 0, 3, def);
byte efg = Avg3(E, F, G);
Dst(dst, 3, 1, efg);
Dst(dst, 2, 2, efg);
Dst(dst, 1, 3, efg);
byte fgh = Avg3(F, G, H);
Dst(dst, 3, 2, fgh);
Dst(dst, 2, 3, fgh);
Dst(dst, 3, 3, Avg3(G, H, H));
}
public static void VL4_C(Span<byte> dst, byte[] yuv, int offset)
{
// Vertical-Left
byte A = yuv[offset - WebPConstants.Bps];
byte B = yuv[offset + 1 - WebPConstants.Bps];
byte C = yuv[offset + 2 - WebPConstants.Bps];
byte D = yuv[offset + 3 - WebPConstants.Bps];
byte E = yuv[offset + 4 - WebPConstants.Bps];
byte F = yuv[offset + 5 - WebPConstants.Bps];
byte G = yuv[offset + 6 - WebPConstants.Bps];
byte H = yuv[offset + 7 - WebPConstants.Bps];
Dst(dst, 0, 0, Avg2(A, B));
byte bc = Avg2(B, C);
Dst(dst, 1, 0, bc);
Dst(dst, 0, 2, bc);
byte cd = Avg2(C, D);
Dst(dst, 2, 0, cd);
Dst(dst, 1, 2, cd);
byte de = Avg2(D, E);
Dst(dst, 3, 0, de);
Dst(dst, 2, 2, de);
Dst(dst, 0, 1, Avg3(A, B, C));
byte bcd = Avg3(B, C, D);
Dst(dst, 1, 1, bcd);
Dst(dst, 0, 3, bcd);
byte cde = Avg3(C, D, E);
Dst(dst, 2, 1, cde);
Dst(dst, 1, 3, cde);
byte def = Avg3(D, E, F);
Dst(dst, 3, 1, def);
Dst(dst, 2, 3, def);
Dst(dst, 3, 2, Avg3(E, F, G));
Dst(dst, 3, 3, Avg3(F, G, H));
}
public static void HD4_C(Span<byte> dst, byte[] yuv, int offset)
{
// Horizontal-Down
byte I = yuv[offset - 1];
byte J = yuv[offset - 1 + (1 * WebPConstants.Bps)];
byte K = yuv[offset - 1 + (2 * WebPConstants.Bps)];
byte L = yuv[offset - 1 + (3 * WebPConstants.Bps)];
byte X = yuv[offset - 1 - WebPConstants.Bps];
byte A = yuv[offset - WebPConstants.Bps];
byte B = yuv[offset + 1 - WebPConstants.Bps];
byte C = yuv[offset + 2 - WebPConstants.Bps];
byte ix = Avg2(I, X);
Dst(dst, 0, 0, ix);
Dst(dst, 2, 1, ix);
byte ji = Avg2(J, I);
Dst(dst, 0, 1, ji);
Dst(dst, 2, 2, ji);
byte kj = Avg2(K, J);
Dst(dst, 0, 2, kj);
Dst(dst, 2, 3, kj);
Dst(dst, 0, 3, Avg2(L, K));
Dst(dst, 3, 0, Avg3(A, B, C));
Dst(dst, 2, 0, Avg3(X, A, B));
byte ixa = Avg3(I, X, A);
Dst(dst, 1, 0, ixa);
Dst(dst, 3, 1, ixa);
byte jix = Avg3(J, I, X);
Dst(dst, 1, 1, jix);
Dst(dst, 3, 2, jix);
byte kji = Avg3(K, J, I);
Dst(dst, 1, 2, kji);
Dst(dst, 3, 3, kji);
Dst(dst, 1, 3, Avg3(L, K, J));
}
public static void HU4_C(Span<byte> dst, byte[] yuv, int offset)
{
// Horizontal-Up
byte I = yuv[offset - 1];
byte J = yuv[offset - 1 + (1 * WebPConstants.Bps)];
byte K = yuv[offset - 1 + (2 * WebPConstants.Bps)];
byte L = yuv[offset - 1 + (3 * WebPConstants.Bps)];
Dst(dst, 0, 0, Avg2(I, J));
byte jk = Avg2(J, K);
Dst(dst, 2, 0, jk);
Dst(dst, 0, 1, jk);
byte kl = Avg2(K, L);
Dst(dst, 2, 1, kl);
Dst(dst, 0, 2, kl);
Dst(dst, 1, 0, Avg3(I, J, K));
byte jkl = Avg3(J, K, L);
Dst(dst, 3, 0, jkl);
Dst(dst, 1, 1, jkl);
byte kll = Avg3(K, L, L);
Dst(dst, 3, 1, kll);
Dst(dst, 1, 2, kll);
Dst(dst, 3, 2, L);
Dst(dst, 2, 2, L);
Dst(dst, 0, 3, L);
Dst(dst, 1, 3, L);
Dst(dst, 2, 3, L);
Dst(dst, 3, 3, L);
}
public static void Transform(Span<short> src, Span<byte> dst, bool doTwo)
@ -215,7 +434,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
TransformOne(src, dst);
if (doTwo)
{
TransformOne(src, dst);
TransformOne(src.Slice(16), dst.Slice(4));
}
}
@ -229,8 +448,8 @@ namespace SixLabors.ImageSharp.Formats.WebP
// vertical pass
int a = src[srcOffset] + src[srcOffset + 8]; // [-4096, 4094]
int b = src[srcOffset] - src[srcOffset + 8]; // [-4095, 4095]
int c = Mul2(src[4]) - Mul1(src[12]); // [-3783, 3783]
int d = Mul1(src[4]) + Mul2(src[12]); // [-3785, 3781]
int c = Mul2(src[srcOffset + 4]) - Mul1(src[srcOffset + 12]); // [-3783, 3783]
int d = Mul1(src[srcOffset + 4]) + Mul2(src[srcOffset + 12]); // [-3785, 3781]
tmp[tmpOffset] = a + d; // [-7881, 7875]
tmp[tmpOffset + 1] = b + c; // [-7878, 7878]
tmp[tmpOffset + 2] = b - c; // [-7878, 7878]
@ -276,7 +495,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
}
// Simplified transform when only in[0], in[1] and in[4] are non-zero
// Simplified transform when only src[0], src[1] and src[4] are non-zero
public static void TransformAc3(Span<short> src, Span<byte> dst)
{
int a = src[0] + 4;
@ -330,6 +549,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
bgr[0] = (byte)YuvToB(y, u);
bgr[1] = (byte)YuvToG(y, u, v);
bgr[2] = (byte)YuvToR(y, v);
int tmp = 0;
}
public static int YuvToR(int y, int v)
@ -412,5 +632,10 @@ namespace SixLabors.ImageSharp.Formats.WebP
{
return (byte)((a + (2 * b) + c + 2) >> 2);
}
private static void Dst(Span<byte> dst, int x, int y, byte v)
{
dst[x + (y * WebPConstants.Bps)] = v;
}
}
}

2
src/ImageSharp/Formats/WebP/Vp8BitReader.cs

@ -84,8 +84,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
public int GetBit(int prob)
{
Guard.MustBeGreaterThan(prob, 0, nameof(prob));
uint range = this.range;
if (this.bits < 0)
{

25
src/ImageSharp/Formats/WebP/Vp8Decoder.cs

@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
this.SegmentHeader = segmentHeader;
this.Probabilities = probabilities;
this.IntraL = new byte[4];
this.YuvBuffer = new byte[(WebPConstants.Bps * 17) + (WebPConstants.Bps * 9)];
this.YuvBuffer = new byte[2000]; // new byte[(WebPConstants.Bps * 17) + (WebPConstants.Bps * 9)];
this.MbWidth = (int)((this.PictureHeader.Width + 15) >> 4);
this.MbHeight = (int)((this.PictureHeader.Height + 15) >> 4);
this.CacheYStride = 16 * this.MbWidth;
@ -58,6 +58,18 @@ namespace SixLabors.ImageSharp.Formats.WebP
this.TmpVBuffer = new byte[width * height]; // TODO: figure out min buffer length
this.Bgr = new byte[width * height * 4];
for (int i = 0; i < this.YuvBuffer.Length; i++)
{
this.YuvBuffer[i] = 205;
}
for (int i = 0; i < this.CacheY.Length; i++)
{
this.CacheY[i] = 205;
this.CacheU[i] = 205;
this.CacheV[i] = 205;
}
this.Vp8BitReaders = new Vp8BitReader[WebPConstants.MaxNumPartitions];
this.Init(io);
}
@ -176,11 +188,13 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// </summary>
public Vp8FilterInfo[] FilterInfo { get; set; }
private Vp8MacroBlock leftMacroBlock;
public Vp8MacroBlock CurrentMacroBlock
{
get
{
return this.MacroBlockInfo[this.MbX + 1];
return this.MacroBlockInfo[this.MbX];
}
}
@ -188,7 +202,12 @@ namespace SixLabors.ImageSharp.Formats.WebP
{
get
{
return this.MacroBlockInfo[this.MbX];
if (this.leftMacroBlock is null)
{
this.leftMacroBlock = new Vp8MacroBlock();
}
return this.leftMacroBlock;
}
}

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

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
@ -129,15 +130,15 @@ namespace SixLabors.ImageSharp.Formats.WebP
private void ParseIntraMode(Vp8Decoder dec, int mbX)
{
Vp8MacroBlockData block = dec.MacroBlockData[mbX];
Span<byte> top = dec.IntraT.AsSpan(4 * mbX, 4);
byte[] left = dec.IntraL;
byte[] top = dec.IntraT;
if (dec.SegmentHeader.UpdateMap)
{
// Hardcoded tree parsing.
block.Segment = this.bitReader.GetBit((int)dec.Probabilities.Segments[0]) != 0
block.Segment = this.bitReader.GetBit((int)dec.Probabilities.Segments[0]) is 0
? (byte)this.bitReader.GetBit((int)dec.Probabilities.Segments[1])
: (byte)this.bitReader.GetBit((int)dec.Probabilities.Segments[2]);
: (byte)(this.bitReader.GetBit((int)dec.Probabilities.Segments[2]) + 2);
}
else
{
@ -154,9 +155,9 @@ namespace SixLabors.ImageSharp.Formats.WebP
if (!block.IsI4x4)
{
// Hardcoded 16x16 intra-mode decision tree.
int yMode = this.bitReader.GetBit(156) > 0 ?
this.bitReader.GetBit(128) > 0 ? WebPConstants.TmPred : WebPConstants.HPred :
this.bitReader.GetBit(163) > 0 ? WebPConstants.VPred : WebPConstants.DcPred;
int yMode = this.bitReader.GetBit(156) != 0 ?
this.bitReader.GetBit(128) != 0 ? WebPConstants.TmPred : WebPConstants.HPred :
this.bitReader.GetBit(163) != 0 ? WebPConstants.VPred : WebPConstants.DcPred;
block.Modes[0] = (byte)yMode;
for (int i = 0; i < left.Length; i++)
{
@ -192,12 +193,12 @@ namespace SixLabors.ImageSharp.Formats.WebP
// Hardcoded UVMode decision tree.
block.UvMode = (byte)(this.bitReader.GetBit(142) is 0 ? 0 :
this.bitReader.GetBit(114) is 0 ? 2 :
this.bitReader.GetBit(183) > 0 ? 1 : 3);
this.bitReader.GetBit(183) != 0 ? 1 : 3);
}
private void InitScanline(Vp8Decoder dec)
{
Vp8MacroBlock left = dec.MacroBlockInfo[0];
Vp8MacroBlock left = dec.LeftMacroBlock;
left.NoneZeroAcDcCoeffs = 0;
left.NoneZeroDcCoeffs = 0;
for (int i = 0; i < dec.IntraL.Length; i++)
@ -312,6 +313,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
if (block.IsI4x4)
{
// uint32_t* const top_right = (uint32_t*)(y_dst - BPS + 16);
Span<uint> topRight = MemoryMarshal.Cast<byte, uint>(yuv.AsSpan(yOff - WebPConstants.Bps + 16));
if (mby > 0)
{
if (mbx >= dec.MbWidth - 1)
@ -326,45 +328,45 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
// Replicate the top-right pixels below.
// top_right[BPS] = top_right[2 * BPS] = top_right[3 * BPS] = top_right[0];
//topRight[WebPConstants.Bps] = topRight[2 * WebPConstants.Bps] = topRight[3 * WebPConstants.Bps] = topRight[0];
// Predict and add residuals for all 4x4 blocks in turn.
for (int n = 0; n < 16; ++n, bits <<= 2)
{
// uint8_t * const dst = y_dst + kScan[n];
Span<byte> dst = yDst.Slice(WebPConstants.Scan[n]);
int offset = yOff + WebPConstants.Scan[n];
Span<byte> dst = yuv.AsSpan(offset);
byte lumaMode = block.Modes[n];
switch (lumaMode)
{
case 0:
LossyUtils.DC4_C(dst);
LossyUtils.DC4_C(dst, yuv, offset);
break;
case 1:
LossyUtils.TM4_C(dst);
break;
case 2:
LossyUtils.VE4_C(dst);
LossyUtils.VE4_C(dst, yuv, offset);
break;
case 3:
LossyUtils.HE4_C(dst);
LossyUtils.HE4_C(dst, yuv, offset);
break;
case 4:
LossyUtils.RD4_C(dst);
LossyUtils.RD4_C(dst, yuv, offset);
break;
case 5:
LossyUtils.VR4_C(dst);
LossyUtils.VR4_C(dst, yuv, offset);
break;
case 6:
LossyUtils.LD4_C(dst);
LossyUtils.LD4_C(dst, yuv, offset);
break;
case 7:
LossyUtils.VL4_C(dst);
LossyUtils.VL4_C(dst, yuv, offset);
break;
case 8:
LossyUtils.HD4_C(dst);
LossyUtils.HD4_C(dst, yuv, offset);
break;
case 9:
LossyUtils.HU4_C(dst);
LossyUtils.HU4_C(dst, yuv, offset);
break;
}
@ -423,8 +425,8 @@ namespace SixLabors.ImageSharp.Formats.WebP
LossyUtils.TM8uv_C(vDst);
break;
case 2:
LossyUtils.VE8uv_C(uDst, yuv.AsSpan(uOff - WebPConstants.Bps, 8));
LossyUtils.VE8uv_C(vDst, yuv.AsSpan(vOff - WebPConstants.Bps, 8));
LossyUtils.VE8uv_C(uDst, yuv, uOff);
LossyUtils.VE8uv_C(vDst, yuv, vOff);
break;
case 3:
LossyUtils.HE8uv_C(uDst, yuv, uOff);
@ -647,7 +649,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
luv = uv;
}
/*if ((len & 1) is 0)
if ((len & 1) is 0)
{
uv0 = ((3 * tluv) + luv + 0x00020002u) >> 2;
LossyUtils.YuvToBgr(topY[len - 1], (int)(uv0 & 0xff), (int)(uv0 >> 16), topDst.Slice((len - 1) * xStep));
@ -656,7 +658,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
uv0 = ((3 * luv) + tluv + 0x00020002u) >> 2;
LossyUtils.YuvToBgr(bottomY[len - 1], (int)(uv0 & 0xff), (int)(uv0 >> 16), bottomDst.Slice((len - 1) * xStep));
}
}*/
}
}
private void DoTransform(uint bits, Span<short> src, Span<byte> dst)
@ -773,6 +775,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
else
{
// Only DC is non-zero -> inlined simplified transform.
int dc0 = (dc[0] + 3) >> 3;
for (int i = 0; i < 16 * 16; i += 16)
{
@ -930,7 +933,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
else
{
int bit1 = br.GetBit(p[8]);
int bit0 = br.GetBit(p[9] + bit1);
int bit0 = br.GetBit(p[9 + bit1]);
int cat = (2 * bit1) + bit0;
v = 0;
byte[] tab = null;
@ -1016,14 +1019,14 @@ namespace SixLabors.ImageSharp.Formats.WebP
for (int i = 0; i < vp8SegmentHeader.Quantizer.Length; i++)
{
hasValue = this.bitReader.ReadBool();
uint quantizeValue = hasValue ? this.bitReader.ReadValue(7) : 0;
int quantizeValue = hasValue ? this.bitReader.ReadSignedValue(7) : 0;
vp8SegmentHeader.Quantizer[i] = (byte)quantizeValue;
}
for (int i = 0; i < vp8SegmentHeader.FilterStrength.Length; i++)
{
hasValue = this.bitReader.ReadBool();
uint filterStrengthValue = hasValue ? this.bitReader.ReadValue(6) : 0;
int filterStrengthValue = hasValue ? this.bitReader.ReadSignedValue(6) : 0;
vp8SegmentHeader.FilterStrength[i] = (byte)filterStrengthValue;
}

Loading…
Cancel
Save