diff --git a/src/ImageSharp/Formats/WebP/AlphaDecoder.cs b/src/ImageSharp/Formats/WebP/AlphaDecoder.cs index fb5663464..d2c8d583f 100644 --- a/src/ImageSharp/Formats/WebP/AlphaDecoder.cs +++ b/src/ImageSharp/Formats/WebP/AlphaDecoder.cs @@ -37,8 +37,10 @@ namespace SixLabors.ImageSharp.Formats.WebP // Taken from vp8l_dec.c AlphaApplyFilter public void AlphaApplyFilter( - int firstRow, int lastRow, - Span output, int outputOffset, + int firstRow, + int lastRow, + Span output, + int outputOffset, int stride) { if (!(this.Filter is WebPFilterNone)) @@ -50,9 +52,12 @@ namespace SixLabors.ImageSharp.Formats.WebP { this.Filter .Unfilter( - prevLine, prevLineOffset, - output, outputOffset, - output, outputOffset, + prevLine, + prevLineOffset, + output, + outputOffset, + output, + outputOffset, stride); prevLineOffset = outputOffset; outputOffset += stride; diff --git a/src/ImageSharp/Formats/WebP/Filters/WebPFilterBase.cs b/src/ImageSharp/Formats/WebP/Filters/WebPFilterBase.cs index 9e1a03125..4ff2ae568 100644 --- a/src/ImageSharp/Formats/WebP/Filters/WebPFilterBase.cs +++ b/src/ImageSharp/Formats/WebP/Filters/WebPFilterBase.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -39,9 +39,13 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters int width); public abstract void Filter( - Span input, int inputOffset, - int width, int height, int stride, - Span output, int outputOffset); + Span input, + int inputOffset, + int width, + int height, + int stride, + Span output, + int outputOffset); protected static void SanityCheck( Span input, Span output, int width, int numRows, int height, int stride, int row) @@ -57,10 +61,14 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters } protected static void PredictLine( - Span src, int srcOffset, - Span pred, int predOffset, - Span dst, int dstOffset, - int length, bool inverse) + Span src, + int srcOffset, + Span pred, + int predOffset, + Span dst, + int dstOffset, + int length, + bool inverse) { if (inverse) { @@ -80,8 +88,10 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters protected void UnfilterHorizontalOrVerticalCore( byte pred, - Span input, int inputOffset, - Span output, int outputOffset, + Span input, + int inputOffset, + Span output, + int outputOffset, int width) { for (int i = 0; i < width; i++) diff --git a/src/ImageSharp/Formats/WebP/Filters/WebPFilterGradient.cs b/src/ImageSharp/Formats/WebP/Filters/WebPFilterGradient.cs index ce751b1f5..27bca5770 100644 --- a/src/ImageSharp/Formats/WebP/Filters/WebPFilterGradient.cs +++ b/src/ImageSharp/Formats/WebP/Filters/WebPFilterGradient.cs @@ -1,10 +1,12 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; namespace SixLabors.ImageSharp.Formats.WebP.Filters { class WebPFilterGradient : WebPFilterBase { - public override void Unfilter( Span prevLine, int? prevLineOffsetNullable, @@ -34,9 +36,13 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters } public override void Filter( - Span input, int inputOffset, - int width, int height, int stride, - Span output, int outputOffset) + Span input, + int inputOffset, + int width, + int height, + int stride, + Span output, + int outputOffset) { // calling (input, width, height, stride, 0, height, 0, output int row = 0; @@ -65,20 +71,27 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters { output[outputOffset] = input[inputOffset]; PredictLine( - input, inputOffset+1, - preds, predsOffset, - output, outputOffset+1, - width-1, + input, + inputOffset + 1, + preds, + predsOffset, + output, + outputOffset + 1, + width - 1, inverse); } while (row < lastRow) { PredictLine( - input, inputOffset, - preds, predsOffset-stride, - output, outputOffset, - 1, inverse); + input, + inputOffset, + preds, + predsOffset - stride, + output, + outputOffset, + 1, + inverse); for (int w = 1; w < width; w++) { @@ -100,4 +113,4 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters return (g & ~0xff) == 0 ? g : (g < 0) ? 0 : 255; } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/WebP/Filters/WebPFilterHorizontal.cs b/src/ImageSharp/Formats/WebP/Filters/WebPFilterHorizontal.cs index 61c384d7d..4328332a5 100644 --- a/src/ImageSharp/Formats/WebP/Filters/WebPFilterHorizontal.cs +++ b/src/ImageSharp/Formats/WebP/Filters/WebPFilterHorizontal.cs @@ -1,13 +1,19 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; namespace SixLabors.ImageSharp.Formats.WebP.Filters { class WebPFilterHorizontal : WebPFilterBase { public override void Unfilter( - Span prevLine, int? prevLineOffsetNullable, - Span input, int inputOffset, - Span output, int outputOffset, + Span prevLine, + int? prevLineOffsetNullable, + Span input, + int inputOffset, + Span output, + int outputOffset, int width) { byte pred = prevLineOffsetNullable is int prevLineOffset @@ -16,15 +22,21 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters this.UnfilterHorizontalOrVerticalCore( pred, - input, inputOffset, - output, outputOffset, + input, + inputOffset, + output, + outputOffset, width); } public override void Filter( - Span input, int inputOffset, - int width, int height, int stride, - Span output, int outputOffset) + Span input, + int inputOffset, + int width, + int height, + int stride, + Span output, + int outputOffset) { int numRows = height; int row = 0; @@ -51,16 +63,19 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters predsOffset = inputOffset; } - if (row == 0) { // leftmost pixel is the same as Input for topmost scanline output[0] = input[0]; PredictLine( - input, inputOffset + 1, - preds, predsOffset, - output, outputOffset + 1, - width - 1, inverse); + input, + inputOffset + 1, + preds, + predsOffset, + output, + outputOffset + 1, + width - 1, + inverse); row = 1; predsOffset += stride; @@ -68,19 +83,27 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters outputOffset += stride; } - // filter line by line + // Filter line by line. while (row < lastRow) { PredictLine( - input, inputOffset, - preds, predsOffset - stride, - output, 0, - 1, inverse); + input, + inputOffset, + preds, + predsOffset - stride, + output, + 0, + 1, + inverse); PredictLine( - input, inputOffset, - preds, predsOffset, - output,outputOffset + 1, - width - 1, inverse); + input, + inputOffset, + preds, + predsOffset, + output, + outputOffset + 1, + width - 1, + inverse); row++; predsOffset += stride; @@ -89,4 +112,4 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/WebP/Filters/WebPFilterNone.cs b/src/ImageSharp/Formats/WebP/Filters/WebPFilterNone.cs index fcecadfb0..04dfafe24 100644 --- a/src/ImageSharp/Formats/WebP/Filters/WebPFilterNone.cs +++ b/src/ImageSharp/Formats/WebP/Filters/WebPFilterNone.cs @@ -1,14 +1,33 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; namespace SixLabors.ImageSharp.Formats.WebP.Filters { // TODO: check if this is a filter or just a placeholder from the C implementation details class WebPFilterNone : WebPFilterBase { - public override void Unfilter(Span prevLine, int? prevLineOffset, Span input, int inputOffset, Span output, int outputOffset, int width) - { } + public override void Unfilter( + Span prevLine, + int? prevLineOffset, + Span input, + int inputOffset, + Span output, + int outputOffset, + int width) + { + } - public override void Filter(Span input, int inputOffset, int width, int height, int stride, Span output, int outputOffset) - { } + public override void Filter( + Span input, + int inputOffset, + int width, + int height, + int stride, + Span output, + int outputOffset) + { + } } } diff --git a/src/ImageSharp/Formats/WebP/Filters/WebPFilterVertical.cs b/src/ImageSharp/Formats/WebP/Filters/WebPFilterVertical.cs index 59ab12caf..04eb2a587 100644 --- a/src/ImageSharp/Formats/WebP/Filters/WebPFilterVertical.cs +++ b/src/ImageSharp/Formats/WebP/Filters/WebPFilterVertical.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; namespace SixLabors.ImageSharp.Formats.WebP.Filters { @@ -20,9 +23,13 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters } public override void Filter( - Span input, int inputOffset, - int width, int height, int stride, - Span output, int outputOffset) + Span input, + int inputOffset, + int width, + int height, + int stride, + Span output, + int outputOffset) { int row = 0; bool inverse = false; @@ -49,14 +56,19 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters if (row == 0) { - // very first top-left pixel is copied. + // Very first top-left pixel is copied. output[0] = input[0]; - // rest of top scan-line is left-predicted: + + // Rest of top scan-line is left-predicted: PredictLine( - input, inputOffset + 1, - preds, predsOffset, - output, outputOffset + 1, - width - 1, inverse); + input, + inputOffset + 1, + preds, + predsOffset, + output, + outputOffset + 1, + width - 1, + inverse); row = 1; inputOffset += stride; outputOffset += stride; @@ -66,14 +78,18 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters predsOffset -= stride; } - // filter line-by-line + // Filter line-by-line. while (row < lastRow) { PredictLine( - input, inputOffset, - preds, predsOffset, - output, outputOffset, - width, inverse); + input, + inputOffset, + preds, + predsOffset, + output, + outputOffset, + width, + inverse); row++; predsOffset += stride; inputOffset += stride; @@ -81,4 +97,4 @@ namespace SixLabors.ImageSharp.Formats.WebP.Filters } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/WebP/LossyUtils.cs b/src/ImageSharp/Formats/WebP/LossyUtils.cs index 68f61a639..a8f6eb98d 100644 --- a/src/ImageSharp/Formats/WebP/LossyUtils.cs +++ b/src/ImageSharp/Formats/WebP/LossyUtils.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Formats.WebP } } - public static void DC16_C(Span dst, byte[] yuv, int offset) + public static void DC16(Span dst, byte[] yuv, int offset) { int dc = 16; for (int j = 0; j < 16; ++j) @@ -28,12 +28,12 @@ namespace SixLabors.ImageSharp.Formats.WebP Put16(dc >> 5, dst); } - public static void TM16_C(Span dst, byte[] yuv, int offset) + public static void TM16(Span dst, byte[] yuv, int offset) { TrueMotion(dst, yuv, offset, 16); } - public static void VE16_C(Span dst, byte[] yuv, int offset) + public static void VE16(Span dst, byte[] yuv, int offset) { // vertical Span src = yuv.AsSpan(offset - WebPConstants.Bps, 16); @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Formats.WebP } } - public static void HE16_C(Span dst, byte[] yuv, int offset) + public static void HE16(Span dst, byte[] yuv, int offset) { // horizontal for (int j = 16; j > 0; --j) @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Formats.WebP } } - public static void DC16NoTop_C(Span dst, byte[] yuv, int offset) + public static void DC16NoTop(Span dst, byte[] yuv, int offset) { // DC with top samples not available. int dc = 8; @@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Formats.WebP Put16(dc >> 4, dst); } - public static void DC16NoLeft_C(Span dst, byte[] yuv, int offset) + public static void DC16NoLeft(Span dst, byte[] yuv, int offset) { // DC with left samples not available. int dc = 8; @@ -83,13 +83,13 @@ namespace SixLabors.ImageSharp.Formats.WebP Put16(dc >> 4, dst); } - public static void DC16NoTopLeft_C(Span dst) + public static void DC16NoTopLeft(Span dst) { // DC with no top and left samples. Put16(0x80, dst); } - public static void DC8uv_C(Span dst, byte[] yuv, int offset) + public static void DC8uv(Span dst, byte[] yuv, int offset) { int dc0 = 8; for (int i = 0; i < 8; ++i) @@ -101,13 +101,13 @@ namespace SixLabors.ImageSharp.Formats.WebP Put8x8uv((byte)(dc0 >> 4), dst); } - public static void TM8uv_C(Span dst, byte[] yuv, int offset) + public static void TM8uv(Span dst, byte[] yuv, int offset) { // TrueMotion TrueMotion(dst, yuv, offset, 8); } - public static void VE8uv_C(Span dst, byte[] yuv, int offset) + public static void VE8uv(Span dst, byte[] yuv, int offset) { // vertical Span src = yuv.AsSpan(offset - WebPConstants.Bps, 8); @@ -119,7 +119,7 @@ namespace SixLabors.ImageSharp.Formats.WebP } } - public static void HE8uv_C(Span dst, byte[] yuv, int offset) + public static void HE8uv(Span dst, byte[] yuv, int offset) { // horizontal for (int j = 0; j < 8; ++j) @@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.Formats.WebP } } - public static void DC8uvNoTop_C(Span dst, byte[] yuv, int offset) + public static void DC8uvNoTop(Span dst, byte[] yuv, int offset) { // DC with no top samples. int dc0 = 4; @@ -146,7 +146,7 @@ namespace SixLabors.ImageSharp.Formats.WebP Put8x8uv((byte)(dc0 >> 3), dst); } - public static void DC8uvNoLeft_C(Span dst, byte[] yuv, int offset) + public static void DC8uvNoLeft(Span dst, byte[] yuv, int offset) { // DC with no left samples. int dc0 = 4; @@ -159,13 +159,13 @@ namespace SixLabors.ImageSharp.Formats.WebP Put8x8uv((byte)(dc0 >> 3), dst); } - public static void DC8uvNoTopLeft_C(Span dst) + public static void DC8uvNoTopLeft(Span dst) { // DC with nothing. Put8x8uv(0x80, dst); } - public static void DC4_C(Span dst, byte[] yuv, int offset) + public static void DC4(Span dst, byte[] yuv, int offset) { int dc = 4; for (int i = 0; i < 4; ++i) @@ -180,12 +180,12 @@ namespace SixLabors.ImageSharp.Formats.WebP } } - public static void TM4_C(Span dst, byte[] yuv, int offset) + public static void TM4(Span dst, byte[] yuv, int offset) { TrueMotion(dst, yuv, offset, 4); } - public static void VE4_C(Span dst, byte[] yuv, int offset) + public static void VE4(Span dst, byte[] yuv, int offset) { // vertical int topOffset = offset - WebPConstants.Bps; @@ -203,231 +203,231 @@ namespace SixLabors.ImageSharp.Formats.WebP } } - public static void HE4_C(Span dst, byte[] yuv, int offset) + public static void HE4(Span 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); + 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); + val = 0x01010101U * Avg3(b, c, d); BinaryPrimitives.WriteUInt32BigEndian(dst.Slice(WebPConstants.Bps), val); - val = 0x01010101U * Avg3(C, D, E); + val = 0x01010101U * Avg3(c, d, e); BinaryPrimitives.WriteUInt32BigEndian(dst.Slice(2 * WebPConstants.Bps), val); - val = 0x01010101U * Avg3(D, E, E); + val = 0x01010101U * Avg3(d, e, e); BinaryPrimitives.WriteUInt32BigEndian(dst.Slice(3 * WebPConstants.Bps), val); } - public static void RD4_C(Span dst, byte[] yuv, int offset) + public static void RD4(Span 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); + 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); + 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); + 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); + 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); + byte cba = Avg3(c, b, a); Dst(dst, 3, 1, cba); Dst(dst, 2, 0, cba); - Dst(dst, 3, 0, Avg3(D, C, B)); + Dst(dst, 3, 0, Avg3(d, c, b)); } - public static void VR4_C(Span dst, byte[] yuv, int offset) + public static void VR4(Span 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); + 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); + byte ab = Avg2(a, b); Dst(dst, 1, 0, ab); Dst(dst, 2, 2, ab); - byte bc = Avg2(B, C); + 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, J, I)); - Dst(dst, 0, 2, Avg3(J, I, X)); - byte ixa = Avg3(I, X, A); + Dst(dst, 3, 0, Avg2(c, d)); + Dst(dst, 0, 3, Avg3(k, j, i)); + 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); + byte xab = Avg3(x, a, b); Dst(dst, 1, 1, xab); Dst(dst, 2, 3, xab); - byte abc = Avg3(A, B, C); + byte abc = Avg3(a, b, c); Dst(dst, 2, 1, abc); Dst(dst, 3, 3, abc); - Dst(dst, 3, 1, Avg3(B, C, D)); + Dst(dst, 3, 1, Avg3(b, c, d)); } - public static void LD4_C(Span dst, byte[] yuv, int offset) + public static void LD4(Span 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); + 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); + 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); + 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); + 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); + byte fgh = Avg3(f, g, h); Dst(dst, 3, 2, fgh); Dst(dst, 2, 3, fgh); - Dst(dst, 3, 3, Avg3(G, H, H)); + Dst(dst, 3, 3, Avg3(g, h, h)); } - public static void VL4_C(Span dst, byte[] yuv, int offset) + public static void VL4(Span 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); + 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); + byte cd = Avg2(c, d); Dst(dst, 2, 0, cd); Dst(dst, 1, 2, cd); - byte de = Avg2(D, E); + 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, 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); + byte cde = Avg3(c, d, e); Dst(dst, 2, 1, cde); Dst(dst, 1, 3, cde); - byte def = Avg3(D, E, F); + 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)); + Dst(dst, 3, 2, Avg3(e, f, g)); + Dst(dst, 3, 3, Avg3(f, g, h)); } - public static void HD4_C(Span dst, byte[] yuv, int offset) + public static void HD4(Span 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); + 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); + byte ji = Avg2(j, i); Dst(dst, 0, 1, ji); Dst(dst, 2, 2, ji); - byte kj = Avg2(K, J); + 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, 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); + byte jix = Avg3(j, i, x); Dst(dst, 1, 1, jix); Dst(dst, 3, 2, jix); - byte kji = Avg3(K, J, I); + byte kji = Avg3(k, j, i); Dst(dst, 1, 2, kji); Dst(dst, 3, 3, kji); - Dst(dst, 1, 3, Avg3(L, K, J)); + Dst(dst, 1, 3, Avg3(l, k, j)); } - public static void HU4_C(Span dst, byte[] yuv, int offset) + public static void HU4(Span 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)]; + 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, 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); + 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, 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); + 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); + 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 src, Span dst, bool doTwo) @@ -743,56 +743,56 @@ namespace SixLabors.ImageSharp.Formats.WebP private static void DoFilter2(byte[] p, int offset, int step) { - // 4 pixels in, 2 pixels out + // 4 pixels in, 2 pixels out. int p1 = p[offset - (2 * step)]; int p0 = p[offset - step]; int q0 = p[offset]; int q1 = p[offset + step]; - int a = (3 * (q0 - p0)) + Vp8LookupTables.Sclip1[p1 - q1]; - int a1 = Vp8LookupTables.Sclip2[(a + 4) >> 3]; - int a2 = Vp8LookupTables.Sclip2[(a + 3) >> 3]; - p[offset - step] = Vp8LookupTables.Clip1[p0 + a2]; - p[offset] = Vp8LookupTables.Clip1[q0 - a1]; + int a = (3 * (q0 - p0)) + WebPLookupTables.Sclip1[p1 - q1]; + int a1 = WebPLookupTables.Sclip2[(a + 4) >> 3]; + int a2 = WebPLookupTables.Sclip2[(a + 3) >> 3]; + p[offset - step] = WebPLookupTables.Clip1[p0 + a2]; + p[offset] = WebPLookupTables.Clip1[q0 - a1]; } private static void DoFilter4(byte[] p, int offset, int step) { - // 4 pixels in, 4 pixels out + // 4 pixels in, 4 pixels out. int p1 = p[offset - (2 * step)]; int p0 = p[offset - step]; int q0 = p[offset]; int q1 = p[offset + step]; int a = 3 * (q0 - p0); - int a1 = Vp8LookupTables.Sclip2[(a + 4) >> 3]; - int a2 = Vp8LookupTables.Sclip2[(a + 3) >> 3]; + int a1 = WebPLookupTables.Sclip2[(a + 4) >> 3]; + int a2 = WebPLookupTables.Sclip2[(a + 3) >> 3]; int a3 = (a1 + 1) >> 1; - p[offset - (2 * step)] = Vp8LookupTables.Clip1[p1 + a3]; - p[offset - step] = Vp8LookupTables.Clip1[p0 + a2]; - p[offset] = Vp8LookupTables.Clip1[q0 - a1]; - p[offset + step] = Vp8LookupTables.Clip1[q1 - a3]; + p[offset - (2 * step)] = WebPLookupTables.Clip1[p1 + a3]; + p[offset - step] = WebPLookupTables.Clip1[p0 + a2]; + p[offset] = WebPLookupTables.Clip1[q0 - a1]; + p[offset + step] = WebPLookupTables.Clip1[q1 - a3]; } private static void DoFilter6(byte[] p, int offset, int step) { - // 6 pixels in, 6 pixels out + // 6 pixels in, 6 pixels out. int p2 = p[offset - (3 * step)]; int p1 = p[offset - (2 * step)]; int p0 = p[offset - step]; int q0 = p[offset]; int q1 = p[offset + step]; int q2 = p[offset + (2 * step)]; - int a = Vp8LookupTables.Sclip1[(3 * (q0 - p0)) + Vp8LookupTables.Sclip1[p1 - q1]]; + int a = WebPLookupTables.Sclip1[(3 * (q0 - p0)) + WebPLookupTables.Sclip1[p1 - q1]]; // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9] int a1 = ((27 * a) + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7 int a2 = ((18 * a) + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7 int a3 = ((9 * a) + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7 - p[offset - (3 * step)] = Vp8LookupTables.Clip1[p2 + a3]; - p[offset - (2 * step)] = Vp8LookupTables.Clip1[p1 + a2]; - p[offset - step] = Vp8LookupTables.Clip1[p0 + a1]; - p[offset] = Vp8LookupTables.Clip1[q0 - a1]; - p[offset + step] = Vp8LookupTables.Clip1[q1 - a2]; - p[offset + (2 * step)] = Vp8LookupTables.Clip1[q2 - a3]; + p[offset - (3 * step)] = WebPLookupTables.Clip1[p2 + a3]; + p[offset - (2 * step)] = WebPLookupTables.Clip1[p1 + a2]; + p[offset - step] = WebPLookupTables.Clip1[p0 + a1]; + p[offset] = WebPLookupTables.Clip1[q0 - a1]; + p[offset + step] = WebPLookupTables.Clip1[q1 - a2]; + p[offset + (2 * step)] = WebPLookupTables.Clip1[q2 - a3]; } private static bool NeedsFilter(byte[] p, int offset, int step, int t) @@ -801,7 +801,7 @@ namespace SixLabors.ImageSharp.Formats.WebP int p0 = p[offset - step]; int q0 = p[offset]; int q1 = p[offset + step]; - return ((4 * Vp8LookupTables.Abs0[p0 - q0]) + Vp8LookupTables.Abs0[p1 - q1]) <= t; + return ((4 * WebPLookupTables.Abs0[p0 - q0]) + WebPLookupTables.Abs0[p1 - q1]) <= t; } private static bool NeedsFilter2(byte[] p, int offset, int step, int t, int it) @@ -814,14 +814,14 @@ namespace SixLabors.ImageSharp.Formats.WebP int q1 = p[offset + step]; int q2 = p[offset + (2 * step)]; int q3 = p[offset + (3 * step)]; - if (((4 * Vp8LookupTables.Abs0[p0 - q0]) + Vp8LookupTables.Abs0[p1 - q1]) > t) + if (((4 * WebPLookupTables.Abs0[p0 - q0]) + WebPLookupTables.Abs0[p1 - q1]) > t) { return false; } - return Vp8LookupTables.Abs0[p3 - p2] <= it && Vp8LookupTables.Abs0[p2 - p1] <= it && - Vp8LookupTables.Abs0[p1 - p0] <= it && Vp8LookupTables.Abs0[q3 - q2] <= it && - Vp8LookupTables.Abs0[q2 - q1] <= it && Vp8LookupTables.Abs0[q1 - q0] <= it; + return WebPLookupTables.Abs0[p3 - p2] <= it && WebPLookupTables.Abs0[p2 - p1] <= it && + WebPLookupTables.Abs0[p1 - p0] <= it && WebPLookupTables.Abs0[q3 - q2] <= it && + WebPLookupTables.Abs0[q2 - q1] <= it && WebPLookupTables.Abs0[q1 - q0] <= it; } private static bool Hev(byte[] p, int offset, int step, int thresh) @@ -830,7 +830,7 @@ namespace SixLabors.ImageSharp.Formats.WebP int p0 = p[offset - step]; int q0 = p[offset]; int q1 = p[offset + step]; - return (Vp8LookupTables.Abs0[p1 - p0] > thresh) || (Vp8LookupTables.Abs0[q1 - q0] > thresh); + return (WebPLookupTables.Abs0[p1 - p0] > thresh) || (WebPLookupTables.Abs0[q1 - q0] > thresh); } private static int MultHi(int v, int coeff) diff --git a/src/ImageSharp/Formats/WebP/Vp8BitReader.cs b/src/ImageSharp/Formats/WebP/Vp8BitReader.cs index 2d3568a2b..21835c3d4 100644 --- a/src/ImageSharp/Formats/WebP/Vp8BitReader.cs +++ b/src/ImageSharp/Formats/WebP/Vp8BitReader.cs @@ -227,7 +227,7 @@ namespace SixLabors.ImageSharp.Formats.WebP n >>= 8; } - return logValue + Vp8LookupTables.LogTable8bit[n]; + return logValue + WebPLookupTables.LogTable8bit[n]; } } } diff --git a/src/ImageSharp/Formats/WebP/Vp8Decoder.cs b/src/ImageSharp/Formats/WebP/Vp8Decoder.cs index 848994d4e..7dab51e33 100644 --- a/src/ImageSharp/Formats/WebP/Vp8Decoder.cs +++ b/src/ImageSharp/Formats/WebP/Vp8Decoder.cs @@ -8,6 +8,8 @@ namespace SixLabors.ImageSharp.Formats.WebP /// internal class Vp8Decoder { + private Vp8MacroBlock leftMacroBlock; + public Vp8Decoder(Vp8FrameHeader frameHeader, Vp8PictureHeader pictureHeader, Vp8SegmentHeader segmentHeader, Vp8Proba probabilities) { this.FilterHeader = new Vp8FilterHeader(); @@ -53,12 +55,12 @@ namespace SixLabors.ImageSharp.Formats.WebP int extraRows = WebPConstants.FilterExtraRows[2]; // TODO: assuming worst case: complex filter int extraY = extraRows * this.CacheYStride; int extraUv = (extraRows / 2) * this.CacheUvStride; - this.CacheY = new byte[width * height + extraY + 256]; // TODO: this is way too much mem, figure out what the min req is. - this.CacheU = new byte[width * height + extraUv + 256]; - this.CacheV = new byte[width * height + extraUv + 256]; - this.TmpYBuffer = new byte[width * height + extraY]; // TODO: figure out min buffer length - this.TmpUBuffer = new byte[width * height + extraUv]; // TODO: figure out min buffer length - this.TmpVBuffer = new byte[width * height + extraUv]; // TODO: figure out min buffer length + this.CacheY = new byte[(width * height) + extraY + 256]; // TODO: this is way too much mem, figure out what the min req is. + this.CacheU = new byte[(width * height) + extraUv + 256]; + this.CacheV = new byte[(width * height) + extraUv + 256]; + this.TmpYBuffer = new byte[(width * height) + extraY]; // TODO: figure out min buffer length + this.TmpUBuffer = new byte[(width * height) + extraUv]; // TODO: figure out min buffer length + this.TmpVBuffer = new byte[(width * height) + extraUv]; // TODO: figure out min buffer length this.Bgr = new byte[width * height * 4]; for (int i = 0; i < this.YuvBuffer.Length; i++) @@ -88,38 +90,47 @@ namespace SixLabors.ImageSharp.Formats.WebP public Vp8SegmentHeader SegmentHeader { get; } - // number of partitions minus one. + /// + /// Gets or sets the number of partitions minus one. + /// public int NumPartsMinusOne { get; set; } - // per-partition boolean decoders. + /// + /// Gets the per-partition boolean decoders. + /// public Vp8BitReader[] Vp8BitReaders { get; } - public bool Dither { get; set; } - /// - /// Gets or sets dequantization matrices (one set of DC/AC dequant factor per segment). + /// Gets the dequantization matrices (one set of DC/AC dequant factor per segment). /// public Vp8QuantMatrix[] DeQuantMatrices { get; } + /// + /// Gets or sets a value indicating whether to use the skip probabilities. + /// public bool UseSkipProbability { get; set; } public byte SkipProbability { get; set; } public Vp8Proba Probabilities { get; set; } - // top intra modes values: 4 * MbWidth + /// + /// Gets or sets the top intra modes values: 4 * MbWidth. + /// public byte[] IntraT { get; set; } - // left intra modes values + /// + /// Gets the left intra modes values. + /// public byte[] IntraL { get; } /// - /// Gets or sets the width in macroblock units. + /// Gets the width in macroblock units. /// public int MbWidth { get; } /// - /// Gets or sets the height in macroblock units. + /// Gets the height in macroblock units. /// public int MbHeight { get; } @@ -198,8 +209,6 @@ namespace SixLabors.ImageSharp.Formats.WebP /// public Vp8FilterInfo[] FilterInfo { get; set; } - private Vp8MacroBlock leftMacroBlock; - public Vp8MacroBlock CurrentMacroBlock { get diff --git a/src/ImageSharp/Formats/WebP/Vp8Io.cs b/src/ImageSharp/Formats/WebP/Vp8Io.cs index 60d97ad2b..82a8cbba8 100644 --- a/src/ImageSharp/Formats/WebP/Vp8Io.cs +++ b/src/ImageSharp/Formats/WebP/Vp8Io.cs @@ -5,59 +5,59 @@ using System; namespace SixLabors.ImageSharp.Formats.WebP { - public ref struct Vp8Io + internal ref struct Vp8Io { /// - /// Picture Width in pixels (invariable). + /// Gets or sets the picture width in pixels (invariable). /// Original, uncropped dimensions. /// The actual area passed to put() is stored in /> field. /// public int Width { get; set; } /// - /// Picture Width in pixels (invariable). + /// Gets or sets the picture height in pixels (invariable). /// Original, uncropped dimensions. /// The actual area passed to put() is stored in /> field. /// public int Height { get; set; } /// - /// Position of the current Rows (in pixels) + /// Gets or sets the y-position of the current macroblock. /// public int MbY { get; set; } /// - /// number of columns in the sample + /// Gets or sets the macroblock width. /// public int MbW { get; set; } /// - /// Number of Rows in the sample + /// Gets or sets the macroblock height. /// public int MbH { get; set; } /// - /// Rows to copy (in YUV format) + /// Rows to copy (in YUV format). /// public Span Y { get; set; } /// - /// Rows to copy (in YUV format) + /// Rows to copy (in YUV format). /// public Span U { get; set; } /// - /// Rows to copy (in YUV format) + /// Rows to copy (in YUV format). /// public Span V { get; set; } /// - /// Row stride for luma + /// Gets or sets the row stride for luma. /// public int YStride { get; set; } /// - /// Row stride for chroma + /// Gets or sets the row stride for chroma. /// public int UvStride { get; set; } diff --git a/src/ImageSharp/Formats/WebP/Vp8LBitReader.cs b/src/ImageSharp/Formats/WebP/Vp8LBitReader.cs index 97a1c242f..9dba6c91d 100644 --- a/src/ImageSharp/Formats/WebP/Vp8LBitReader.cs +++ b/src/ImageSharp/Formats/WebP/Vp8LBitReader.cs @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Formats.WebP /// private const int Vp8LWbits = 32; - private readonly uint[] BitMask = + private readonly uint[] bitMask = { 0, 0x000001, 0x000003, 0x000007, 0x00000f, @@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.Formats.WebP if (!this.eos && nBits <= Vp8LMaxNumBitRead) { - ulong val = this.PrefetchBits() & this.BitMask[nBits]; + ulong val = this.PrefetchBits() & this.bitMask[nBits]; int newBits = this.bitPos + nBits; this.bitPos = newBits; this.ShiftBytes(); diff --git a/src/ImageSharp/Formats/WebP/Vp8LookupTables.cs b/src/ImageSharp/Formats/WebP/Vp8LookupTables.cs deleted file mode 100644 index 4f0a9127e..000000000 --- a/src/ImageSharp/Formats/WebP/Vp8LookupTables.cs +++ /dev/null @@ -1,495 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Collections.Generic; - -namespace SixLabors.ImageSharp.Formats.WebP -{ - internal static class Vp8LookupTables - { - public static readonly Dictionary Abs0; - - public static readonly Dictionary Clip1; - - public static readonly Dictionary Sclip1; - - public static readonly Dictionary Sclip2; - - public static readonly byte[,][] ModesProba = new byte[10, 10][]; - - // 31 ^ clz(i) - public static readonly byte[] LogTable8bit = - { - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - }; - - // Paragraph 14.1 - public static readonly int[] DcTable = - { - 4, 5, 6, 7, 8, 9, 10, 10, - 11, 12, 13, 14, 15, 16, 17, 17, - 18, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 25, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, - 37, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, - 91, 93, 95, 96, 98, 100, 101, 102, - 104, 106, 108, 110, 112, 114, 116, 118, - 122, 124, 126, 128, 130, 132, 134, 136, - 138, 140, 143, 145, 148, 151, 154, 157 - }; - - // Paragraph 14.1 - public static readonly int[] AcTable = - { - 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 60, - 62, 64, 66, 68, 70, 72, 74, 76, - 78, 80, 82, 84, 86, 88, 90, 92, - 94, 96, 98, 100, 102, 104, 106, 108, - 110, 112, 114, 116, 119, 122, 125, 128, - 131, 134, 137, 140, 143, 146, 149, 152, - 155, 158, 161, 164, 167, 170, 173, 177, - 181, 185, 189, 193, 197, 201, 205, 209, - 213, 217, 221, 225, 229, 234, 239, 245, - 249, 254, 259, 264, 269, 274, 279, 284 - }; - - // Paragraph 13 - public static readonly byte[,,,] CoeffsUpdateProba = - { - { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 }, - { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 } - }, - { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 } - }, - { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - }, - { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 }, - { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - }, - { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, - { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } - } - } - }; - - // Paragraph 13.5: Default Token Probability Table. - public static readonly byte[,,,] DefaultCoeffsProba = - { - { - { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 }, - { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 }, - { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 } - }, - { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, - { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 }, - { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 }, - }, - { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, - { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 }, - { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 }, - }, - { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, - { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 }, - { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 } - }, - { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, - { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 }, - { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 } - }, - { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, - { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 }, - { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 } - }, - { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - } - }, - { - { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 }, - { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 }, - { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 } - }, - { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, - { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 }, - { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 } - }, - { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, - { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, - { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 } - }, - { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, - { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 }, - { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 } - }, - { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, - { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, - { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 } - }, - { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, - { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 }, - { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 } - }, - { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, - { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 }, - { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 } - }, - { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, - { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 } - } - }, - { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 }, - { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 }, - { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 } - }, - { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, - { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 }, - { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 } - }, - { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, - { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 }, - { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 } - }, - { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 }, - { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 }, - { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 }, - { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - }, - { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } - } - }, - { - { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 }, - { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 }, - { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 } - }, - { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, - { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 }, - { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 } - }, - { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, - { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 }, - { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 } - }, - { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, - { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 }, - { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 } - }, - { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, - { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 }, - { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 } - }, - { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, - { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 }, - { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 } - }, - { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, - { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 }, - { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 } - }, - { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, - { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } - } - } - }; - - static Vp8LookupTables() - { - // TODO: maybe use hashset here - Abs0 = new Dictionary(); - for (int i = -255; i <= 255; ++i) - { - Abs0[i] = (byte)((i < 0) ? -i : i); - } - - Clip1 = new Dictionary(); - for (int i = -255; i <= 255 + 255; ++i) - { - Clip1[i] = (byte)((i < 0) ? 0 : (i > 255) ? 255 : i); - } - - Sclip1 = new Dictionary(); - for (int i = -1020; i <= 1020; ++i) - { - Sclip1[i] = (sbyte)((i < -128) ? -128 : (i > 127) ? 127 : i); - } - - Sclip2 = new Dictionary(); - for (int i = -112; i <= 112; ++i) - { - Sclip2[i] = (sbyte)((i < -16) ? -16 : (i > 15) ? 15 : i); - } - - InitializeModesProbabilities(); - } - - private static void InitializeModesProbabilities() - { - // Paragraph 11.5 - ModesProba[0, 0] = new byte[] { 231, 120, 48, 89, 115, 113, 120, 152, 112 }; - ModesProba[0, 1] = new byte[] { 152, 179, 64, 126, 170, 118, 46, 70, 95 }; - ModesProba[0, 2] = new byte[] { 175, 69, 143, 80, 85, 82, 72, 155, 103 }; - ModesProba[0, 3] = new byte[] { 56, 58, 10, 171, 218, 189, 17, 13, 152 }; - ModesProba[0, 4] = new byte[] { 114, 26, 17, 163, 44, 195, 21, 10, 173 }; - ModesProba[0, 5] = new byte[] { 121, 24, 80, 195, 26, 62, 44, 64, 85 }; - ModesProba[0, 6] = new byte[] { 144, 71, 10, 38, 171, 213, 144, 34, 26 }; - ModesProba[0, 7] = new byte[] { 170, 46, 55, 19, 136, 160, 33, 206, 71 }; - ModesProba[0, 8] = new byte[] { 63, 20, 8, 114, 114, 208, 12, 9, 226 }; - ModesProba[0, 9] = new byte[] { 81, 40, 11, 96, 182, 84, 29, 16, 36 }; - ModesProba[1, 0] = new byte[] { 134, 183, 89, 137, 98, 101, 106, 165, 148 }; - ModesProba[1, 1] = new byte[] { 72, 187, 100, 130, 157, 111, 32, 75, 80 }; - ModesProba[1, 2] = new byte[] { 66, 102, 167, 99, 74, 62, 40, 234, 128 }; - ModesProba[1, 3] = new byte[] { 41, 53, 9, 178, 241, 141, 26, 8, 107 }; - ModesProba[1, 4] = new byte[] { 74, 43, 26, 146, 73, 166, 49, 23, 157 }; - ModesProba[1, 5] = new byte[] { 65, 38, 105, 160, 51, 52, 31, 115, 128 }; - ModesProba[1, 6] = new byte[] { 104, 79, 12, 27, 217, 255, 87, 17, 7 }; - ModesProba[1, 7] = new byte[] { 87, 68, 71, 44, 114, 51, 15, 186, 23 }; - ModesProba[1, 8] = new byte[] { 47, 41, 14, 110, 182, 183, 21, 17, 194 }; - ModesProba[1, 9] = new byte[] { 66, 45, 25, 102, 197, 189, 23, 18, 22 }; - ModesProba[2, 0] = new byte[] { 88, 88, 147, 150, 42, 46, 45, 196, 205 }; - ModesProba[2, 1] = new byte[] { 43, 97, 183, 117, 85, 38, 35, 179, 61 }; - ModesProba[2, 2] = new byte[] { 39, 53, 200, 87, 26, 21, 43, 232, 171 }; - ModesProba[2, 3] = new byte[] { 56, 34, 51, 104, 114, 102, 29, 93, 77 }; - ModesProba[2, 4] = new byte[] { 39, 28, 85, 171, 58, 165, 90, 98, 64 }; - ModesProba[2, 5] = new byte[] { 34, 22, 116, 206, 23, 34, 43, 166, 73 }; - ModesProba[2, 6] = new byte[] { 107, 54, 32, 26, 51, 1, 81, 43, 31 }; - ModesProba[2, 7] = new byte[] { 68, 25, 106, 22, 64, 171, 36, 225, 114 }; - ModesProba[2, 8] = new byte[] { 34, 19, 21, 102, 132, 188, 16, 76, 124 }; - ModesProba[2, 9] = new byte[] { 62, 18, 78, 95, 85, 57, 50, 48, 51 }; - ModesProba[3, 0] = new byte[] { 193, 101, 35, 159, 215, 111, 89, 46, 111 }; - ModesProba[3, 1] = new byte[] { 60, 148, 31, 172, 219, 228, 21, 18, 111 }; - ModesProba[3, 2] = new byte[] { 112, 113, 77, 85, 179, 255, 38, 120, 114 }; - ModesProba[3, 3] = new byte[] { 40, 42, 1, 196, 245, 209, 10, 25, 109 }; - ModesProba[3, 4] = new byte[] { 88, 43, 29, 140, 166, 213, 37, 43, 154 }; - ModesProba[3, 5] = new byte[] { 61, 63, 30, 155, 67, 45, 68, 1, 209 }; - ModesProba[3, 6] = new byte[] { 100, 80, 8, 43, 154, 1, 51, 26, 71 }; - ModesProba[3, 7] = new byte[] { 142, 78, 78, 16, 255, 128, 34, 197, 171 }; - ModesProba[3, 8] = new byte[] { 41, 40, 5, 102, 211, 183, 4, 1, 221 }; - ModesProba[3, 9] = new byte[] { 51, 50, 17, 168, 209, 192, 23, 25, 82 }; - ModesProba[4, 0] = new byte[] { 138, 31, 36, 171, 27, 166, 38, 44, 229 }; - ModesProba[4, 1] = new byte[] { 67, 87, 58, 169, 82, 115, 26, 59, 179 }; - ModesProba[4, 2] = new byte[] { 63, 59, 90, 180, 59, 166, 93, 73, 154 }; - ModesProba[4, 3] = new byte[] { 40, 40, 21, 116, 143, 209, 34, 39, 175 }; - ModesProba[4, 4] = new byte[] { 47, 15, 16, 183, 34, 223, 49, 45, 183 }; - ModesProba[4, 5] = new byte[] { 46, 17, 33, 183, 6, 98, 15, 32, 183 }; - ModesProba[4, 6] = new byte[] { 57, 46, 22, 24, 128, 1, 54, 17, 37 }; - ModesProba[4, 7] = new byte[] { 65, 32, 73, 115, 28, 128, 23, 128, 205 }; - ModesProba[4, 8] = new byte[] { 40, 3, 9, 115, 51, 192, 18, 6, 223 }; - ModesProba[4, 9] = new byte[] { 87, 37, 9, 115, 59, 77, 64, 21, 47 }; - ModesProba[5, 0] = new byte[] { 104, 55, 44, 218, 9, 54, 53, 130, 226 }; - ModesProba[5, 1] = new byte[] { 64, 90, 70, 205, 40, 41, 23, 26, 57 }; - ModesProba[5, 2] = new byte[] { 54, 57, 112, 184, 5, 41, 38, 166, 213 }; - ModesProba[5, 3] = new byte[] { 30, 34, 26, 133, 152, 116, 10, 32, 134 }; - ModesProba[5, 4] = new byte[] { 39, 19, 53, 221, 26, 114, 32, 73, 255 }; - ModesProba[5, 5] = new byte[] { 31, 9, 65, 234, 2, 15, 1, 118, 73 }; - ModesProba[5, 6] = new byte[] { 75, 32, 12, 51, 192, 255, 160, 43, 51 }; - ModesProba[5, 7] = new byte[] { 88, 31, 35, 67, 102, 85, 55, 186, 85 }; - ModesProba[5, 8] = new byte[] { 56, 21, 23, 111, 59, 205, 45, 37, 192 }; - ModesProba[5, 9] = new byte[] { 55, 38, 70, 124, 73, 102, 1, 34, 98 }; - ModesProba[6, 0] = new byte[] { 125, 98, 42, 88, 104, 85, 117, 175, 82 }; - ModesProba[6, 1] = new byte[] { 95, 84, 53, 89, 128, 100, 113, 101, 45 }; - ModesProba[6, 2] = new byte[] { 75, 79, 123, 47, 51, 128, 81, 171, 1 }; - ModesProba[6, 3] = new byte[] { 57, 17, 5, 71, 102, 57, 53, 41, 49 }; - ModesProba[6, 4] = new byte[] { 38, 33, 13, 121, 57, 73, 26, 1, 85 }; - ModesProba[6, 5] = new byte[] { 41, 10, 67, 138, 77, 110, 90, 47, 114 }; - ModesProba[6, 6] = new byte[] { 115, 21, 2, 10, 102, 255, 166, 23, 6 }; - ModesProba[6, 7] = new byte[] { 101, 29, 16, 10, 85, 128, 101, 196, 26 }; - ModesProba[6, 8] = new byte[] { 57, 18, 10, 102, 102, 213, 34, 20, 43 }; - ModesProba[6, 9] = new byte[] { 117, 20, 15, 36, 163, 128, 68, 1, 26 }; - ModesProba[7, 0] = new byte[] { 102, 61, 71, 37, 34, 53, 31, 243, 192 }; - ModesProba[7, 1] = new byte[] { 69, 60, 71, 38, 73, 119, 28, 222, 37 }; - ModesProba[7, 2] = new byte[] { 68, 45, 128, 34, 1, 47, 11, 245, 171 }; - ModesProba[7, 3] = new byte[] { 62, 17, 19, 70, 146, 85, 55, 62, 70 }; - ModesProba[7, 4] = new byte[] { 37, 43, 37, 154, 100, 163, 85, 160, 1 }; - ModesProba[7, 5] = new byte[] { 63, 9, 92, 136, 28, 64, 32, 201, 85 }; - ModesProba[7, 6] = new byte[] { 75, 15, 9, 9, 64, 255, 184, 119, 16 }; - ModesProba[7, 7] = new byte[] { 86, 6, 28, 5, 64, 255, 25, 248, 1 }; - ModesProba[7, 8] = new byte[] { 56, 8, 17, 132, 137, 255, 55, 116, 128 }; - ModesProba[7, 9] = new byte[] { 58, 15, 20, 82, 135, 57, 26, 121, 40 }; - ModesProba[8, 0] = new byte[] { 164, 50, 31, 137, 154, 133, 25, 35, 218 }; - ModesProba[8, 1] = new byte[] { 51, 103, 44, 131, 131, 123, 31, 6, 158 }; - ModesProba[8, 2] = new byte[] { 86, 40, 64, 135, 148, 224, 45, 183, 128 }; - ModesProba[8, 3] = new byte[] { 22, 26, 17, 131, 240, 154, 14, 1, 209 }; - ModesProba[8, 4] = new byte[] { 45, 16, 21, 91, 64, 222, 7, 1, 197 }; - ModesProba[8, 5] = new byte[] { 56, 21, 39, 155, 60, 138, 23, 102, 213 }; - ModesProba[8, 6] = new byte[] { 83, 12, 13, 54, 192, 255, 68, 47, 28 }; - ModesProba[8, 7] = new byte[] { 85, 26, 85, 85, 128, 128, 32, 146, 171 }; - ModesProba[8, 8] = new byte[] { 18, 11, 7, 63, 144, 171, 4, 4, 246 }; - ModesProba[8, 9] = new byte[] { 35, 27, 10, 146, 174, 171, 12, 26, 128 }; - ModesProba[9, 0] = new byte[] { 190, 80, 35, 99, 180, 80, 126, 54, 45 }; - ModesProba[9, 1] = new byte[] { 85, 126, 47, 87, 176, 51, 41, 20, 32 }; - ModesProba[9, 2] = new byte[] { 101, 75, 128, 139, 118, 146, 116, 128, 85 }; - ModesProba[9, 3] = new byte[] { 56, 41, 15, 176, 236, 85, 37, 9, 62 }; - ModesProba[9, 4] = new byte[] { 71, 30, 17, 119, 118, 255, 17, 18, 138 }; - ModesProba[9, 5] = new byte[] { 101, 38, 60, 138, 55, 70, 43, 26, 142 }; - ModesProba[9, 6] = new byte[] { 146, 36, 19, 30, 171, 255, 97, 27, 20 }; - ModesProba[9, 7] = new byte[] { 138, 45, 61, 62, 219, 1, 81, 188, 64 }; - ModesProba[9, 8] = new byte[] { 32, 41, 20, 117, 151, 142, 20, 21, 163 }; - ModesProba[9, 9] = new byte[] { 112, 19, 12, 61, 195, 128, 48, 4, 24 }; - } - } -} diff --git a/src/ImageSharp/Formats/WebP/Vp8MacroBlockData.cs b/src/ImageSharp/Formats/WebP/Vp8MacroBlockData.cs index f2ab8ff7f..cfac56d3c 100644 --- a/src/ImageSharp/Formats/WebP/Vp8MacroBlockData.cs +++ b/src/ImageSharp/Formats/WebP/Vp8MacroBlockData.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Formats.WebP public bool IsI4x4 { get; set; } /// - /// Gets or sets the modes. One 16x16 mode (#0) or sixteen 4x4 modes. + /// Gets the modes. One 16x16 mode (#0) or sixteen 4x4 modes. /// public byte[] Modes { get; } @@ -38,11 +38,6 @@ namespace SixLabors.ImageSharp.Formats.WebP public uint NonZeroUv { get; set; } - /// - /// Gets or sets the local dithering strength (deduced from NonZero_*). - /// - public byte Dither { get; set; } - public byte Skip { get; set; } public byte Segment { get; set; } diff --git a/src/ImageSharp/Formats/WebP/WebPDecoderBase.cs b/src/ImageSharp/Formats/WebP/WebPDecoderBase.cs deleted file mode 100644 index b9c82c7ec..000000000 --- a/src/ImageSharp/Formats/WebP/WebPDecoderBase.cs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; - -using SixLabors.ImageSharp.Memory; - -namespace SixLabors.ImageSharp.Formats.WebP -{ - abstract class WebPDecoderBase - { - protected HTreeGroup[] GetHTreeGroupForPos(Vp8LMetadata metadata, int x, int y) - { - uint metaIndex = this.GetMetaIndex(metadata.HuffmanImage, metadata.HuffmanXSize, metadata.HuffmanSubSampleBits, x, y); - return metadata.HTreeGroups.AsSpan((int)metaIndex).ToArray(); - } - - private uint GetMetaIndex(IMemoryOwner huffmanImage, int xSize, int bits, int x, int y) - { - if (bits is 0) - { - return 0; - } - - Span huffmanImageSpan = huffmanImage.GetSpan(); - return huffmanImageSpan[(xSize * (y >> bits)) + (x >> bits)]; - } - - /// - /// Decodes the next Huffman code from bit-stream. - /// FillBitWindow(br) needs to be called at minimum every second call - /// to ReadSymbol, in order to pre-fetch enough bits. - /// - protected uint ReadSymbol(Span table, Vp8LBitReader bitReader) - { - // TODO: if the bitReader field is moved to this base class we could omit the parameter. - uint val = (uint)bitReader.PrefetchBits(); - Span tableSpan = table.Slice((int)(val & HuffmanUtils.HuffmanTableMask)); - int nBits = tableSpan[0].BitsUsed - HuffmanUtils.HuffmanTableBits; - if (nBits > 0) - { - bitReader.AdvanceBitPosition(HuffmanUtils.HuffmanTableBits); - val = (uint)bitReader.PrefetchBits(); - tableSpan = tableSpan.Slice((int)tableSpan[0].Value); - tableSpan = tableSpan.Slice((int)val & ((1 << nBits) - 1)); - } - - bitReader.AdvanceBitPosition(tableSpan[0].BitsUsed); - - return tableSpan[0].Value; - } - - protected int GetCopyDistance(int distanceSymbol, Vp8LBitReader bitReader) - { - if (distanceSymbol < 4) - { - return distanceSymbol + 1; - } - - int extraBits = (distanceSymbol - 2) >> 1; - int offset = (2 + (distanceSymbol & 1)) << extraBits; - - return (int)(offset + bitReader.ReadValue(extraBits) + 1); - } - - protected int GetCopyLength(int lengthSymbol, Vp8LBitReader bitReader) - { - // Length and distance prefixes are encoded the same way. - return this.GetCopyDistance(lengthSymbol, bitReader); - } - - // TODO: copied from LosslessDecoder - protected static readonly int[] KCodeToPlane = - { - 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, - 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, - 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, - 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, - 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c, - 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, - 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, - 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, - 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, - 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41, - 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f, - 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70 - }; - - protected static readonly int CodeToPlaneCodes = KCodeToPlane.Length; - - protected int PlaneCodeToDistance(int xSize, int planeCode) - { - if (planeCode > CodeToPlaneCodes) - { - return planeCode - CodeToPlaneCodes; - } - - int distCode = KCodeToPlane[planeCode - 1]; - int yOffset = distCode >> 4; - int xOffset = 8 - (distCode & 0xf); - int dist = (yOffset * xSize) + xOffset; - - // dist < 1 can happen if xSize is very small. - return (dist >= 1) ? dist : 1; - } - } -} diff --git a/src/ImageSharp/Formats/WebP/WebPLookupTables.cs b/src/ImageSharp/Formats/WebP/WebPLookupTables.cs new file mode 100644 index 000000000..26c4be773 --- /dev/null +++ b/src/ImageSharp/Formats/WebP/WebPLookupTables.cs @@ -0,0 +1,580 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Collections.Generic; + +namespace SixLabors.ImageSharp.Formats.WebP +{ + internal static class WebPLookupTables + { + public static readonly Dictionary Abs0; + + public static readonly Dictionary Clip1; + + public static readonly Dictionary Sclip1; + + public static readonly Dictionary Sclip2; + + public static readonly byte[,][] ModesProba = new byte[10, 10][]; + + public static readonly int[] CodeToPlane = + { + 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, + 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, + 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, + 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, + 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c, + 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, + 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, + 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, + 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, + 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41, + 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f, + 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70 + }; + + // 31 ^ clz(i) + public static readonly byte[] LogTable8bit = + { + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + }; + + // Paragraph 14.1 + public static readonly int[] DcTable = + { + 4, 5, 6, 7, 8, 9, 10, 10, + 11, 12, 13, 14, 15, 16, 17, 17, + 18, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 25, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + 37, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, + 91, 93, 95, 96, 98, 100, 101, 102, + 104, 106, 108, 110, 112, 114, 116, 118, + 122, 124, 126, 128, 130, 132, 134, 136, + 138, 140, 143, 145, 148, 151, 154, 157 + }; + + // Paragraph 14.1 + public static readonly int[] AcTable = + { + 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 60, + 62, 64, 66, 68, 70, 72, 74, 76, + 78, 80, 82, 84, 86, 88, 90, 92, + 94, 96, 98, 100, 102, 104, 106, 108, + 110, 112, 114, 116, 119, 122, 125, 128, + 131, 134, 137, 140, 143, 146, 149, 152, + 155, 158, 161, 164, 167, 170, 173, 177, + 181, 185, 189, 193, 197, 201, 205, 209, + 213, 217, 221, 225, 229, 234, 239, 245, + 249, 254, 259, 264, 269, 274, 279, 284 + }; + + // Paragraph 13 + public static readonly byte[,,,] CoeffsUpdateProba = + { + { + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { + { + { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 }, + { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 } + }, + { + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { + { + { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 } + }, + { + { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { + { + { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + } + }; + + // Paragraph 13.5: Default Token Probability Table. + public static readonly byte[,,,] DefaultCoeffsProba = + { + { + { + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { + { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 }, + { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 }, + { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 } + }, + { + { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, + { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 }, + { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 }, + }, + { + { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, + { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 }, + { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 }, + }, + { + { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, + { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 }, + { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 } + }, + { + { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, + { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 }, + { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 } + }, + { + { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, + { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 }, + { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 } + }, + { + { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + } + }, + { + { + { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 }, + { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 }, + { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 } + }, + { + { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, + { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 }, + { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 } + }, + { + { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, + { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, + { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 } + }, + { + { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, + { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 }, + { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 } + }, + { + { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, + { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, + { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 } + }, + { + { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, + { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 }, + { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 } + }, + { + { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, + { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 }, + { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 } + }, + { + { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 } + } + }, + { + { + { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 }, + { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 }, + { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 } + }, + { + { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, + { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 }, + { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 } + }, + { + { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, + { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 }, + { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 } + }, + { + { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 } + }, + { + { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 }, + { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { + { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { + { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + } + }, + { + { + { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 }, + { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 }, + { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 } + }, + { + { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, + { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 }, + { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 } + }, + { + { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, + { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 }, + { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 } + }, + { + { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, + { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 }, + { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 } + }, + { + { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, + { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 }, + { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 } + }, + { + { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, + { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 }, + { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 } + }, + { + { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, + { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 }, + { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 } + }, + { + { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + } + } + }; + + static WebPLookupTables() + { + // TODO: maybe use hashset here + Abs0 = new Dictionary(); + for (int i = -255; i <= 255; ++i) + { + Abs0[i] = (byte)((i < 0) ? -i : i); + } + + Clip1 = new Dictionary(); + for (int i = -255; i <= 255 + 255; ++i) + { + Clip1[i] = (byte)((i < 0) ? 0 : (i > 255) ? 255 : i); + } + + Sclip1 = new Dictionary(); + for (int i = -1020; i <= 1020; ++i) + { + Sclip1[i] = (sbyte)((i < -128) ? -128 : (i > 127) ? 127 : i); + } + + Sclip2 = new Dictionary(); + for (int i = -112; i <= 112; ++i) + { + Sclip2[i] = (sbyte)((i < -16) ? -16 : (i > 15) ? 15 : i); + } + + InitializeModesProbabilities(); + } + + private static void InitializeModesProbabilities() + { + // Paragraph 11.5 + ModesProba[0, 0] = new byte[] { 231, 120, 48, 89, 115, 113, 120, 152, 112 }; + ModesProba[0, 1] = new byte[] { 152, 179, 64, 126, 170, 118, 46, 70, 95 }; + ModesProba[0, 2] = new byte[] { 175, 69, 143, 80, 85, 82, 72, 155, 103 }; + ModesProba[0, 3] = new byte[] { 56, 58, 10, 171, 218, 189, 17, 13, 152 }; + ModesProba[0, 4] = new byte[] { 114, 26, 17, 163, 44, 195, 21, 10, 173 }; + ModesProba[0, 5] = new byte[] { 121, 24, 80, 195, 26, 62, 44, 64, 85 }; + ModesProba[0, 6] = new byte[] { 144, 71, 10, 38, 171, 213, 144, 34, 26 }; + ModesProba[0, 7] = new byte[] { 170, 46, 55, 19, 136, 160, 33, 206, 71 }; + ModesProba[0, 8] = new byte[] { 63, 20, 8, 114, 114, 208, 12, 9, 226 }; + ModesProba[0, 9] = new byte[] { 81, 40, 11, 96, 182, 84, 29, 16, 36 }; + ModesProba[1, 0] = new byte[] { 134, 183, 89, 137, 98, 101, 106, 165, 148 }; + ModesProba[1, 1] = new byte[] { 72, 187, 100, 130, 157, 111, 32, 75, 80 }; + ModesProba[1, 2] = new byte[] { 66, 102, 167, 99, 74, 62, 40, 234, 128 }; + ModesProba[1, 3] = new byte[] { 41, 53, 9, 178, 241, 141, 26, 8, 107 }; + ModesProba[1, 4] = new byte[] { 74, 43, 26, 146, 73, 166, 49, 23, 157 }; + ModesProba[1, 5] = new byte[] { 65, 38, 105, 160, 51, 52, 31, 115, 128 }; + ModesProba[1, 6] = new byte[] { 104, 79, 12, 27, 217, 255, 87, 17, 7 }; + ModesProba[1, 7] = new byte[] { 87, 68, 71, 44, 114, 51, 15, 186, 23 }; + ModesProba[1, 8] = new byte[] { 47, 41, 14, 110, 182, 183, 21, 17, 194 }; + ModesProba[1, 9] = new byte[] { 66, 45, 25, 102, 197, 189, 23, 18, 22 }; + ModesProba[2, 0] = new byte[] { 88, 88, 147, 150, 42, 46, 45, 196, 205 }; + ModesProba[2, 1] = new byte[] { 43, 97, 183, 117, 85, 38, 35, 179, 61 }; + ModesProba[2, 2] = new byte[] { 39, 53, 200, 87, 26, 21, 43, 232, 171 }; + ModesProba[2, 3] = new byte[] { 56, 34, 51, 104, 114, 102, 29, 93, 77 }; + ModesProba[2, 4] = new byte[] { 39, 28, 85, 171, 58, 165, 90, 98, 64 }; + ModesProba[2, 5] = new byte[] { 34, 22, 116, 206, 23, 34, 43, 166, 73 }; + ModesProba[2, 6] = new byte[] { 107, 54, 32, 26, 51, 1, 81, 43, 31 }; + ModesProba[2, 7] = new byte[] { 68, 25, 106, 22, 64, 171, 36, 225, 114 }; + ModesProba[2, 8] = new byte[] { 34, 19, 21, 102, 132, 188, 16, 76, 124 }; + ModesProba[2, 9] = new byte[] { 62, 18, 78, 95, 85, 57, 50, 48, 51 }; + ModesProba[3, 0] = new byte[] { 193, 101, 35, 159, 215, 111, 89, 46, 111 }; + ModesProba[3, 1] = new byte[] { 60, 148, 31, 172, 219, 228, 21, 18, 111 }; + ModesProba[3, 2] = new byte[] { 112, 113, 77, 85, 179, 255, 38, 120, 114 }; + ModesProba[3, 3] = new byte[] { 40, 42, 1, 196, 245, 209, 10, 25, 109 }; + ModesProba[3, 4] = new byte[] { 88, 43, 29, 140, 166, 213, 37, 43, 154 }; + ModesProba[3, 5] = new byte[] { 61, 63, 30, 155, 67, 45, 68, 1, 209 }; + ModesProba[3, 6] = new byte[] { 100, 80, 8, 43, 154, 1, 51, 26, 71 }; + ModesProba[3, 7] = new byte[] { 142, 78, 78, 16, 255, 128, 34, 197, 171 }; + ModesProba[3, 8] = new byte[] { 41, 40, 5, 102, 211, 183, 4, 1, 221 }; + ModesProba[3, 9] = new byte[] { 51, 50, 17, 168, 209, 192, 23, 25, 82 }; + ModesProba[4, 0] = new byte[] { 138, 31, 36, 171, 27, 166, 38, 44, 229 }; + ModesProba[4, 1] = new byte[] { 67, 87, 58, 169, 82, 115, 26, 59, 179 }; + ModesProba[4, 2] = new byte[] { 63, 59, 90, 180, 59, 166, 93, 73, 154 }; + ModesProba[4, 3] = new byte[] { 40, 40, 21, 116, 143, 209, 34, 39, 175 }; + ModesProba[4, 4] = new byte[] { 47, 15, 16, 183, 34, 223, 49, 45, 183 }; + ModesProba[4, 5] = new byte[] { 46, 17, 33, 183, 6, 98, 15, 32, 183 }; + ModesProba[4, 6] = new byte[] { 57, 46, 22, 24, 128, 1, 54, 17, 37 }; + ModesProba[4, 7] = new byte[] { 65, 32, 73, 115, 28, 128, 23, 128, 205 }; + ModesProba[4, 8] = new byte[] { 40, 3, 9, 115, 51, 192, 18, 6, 223 }; + ModesProba[4, 9] = new byte[] { 87, 37, 9, 115, 59, 77, 64, 21, 47 }; + ModesProba[5, 0] = new byte[] { 104, 55, 44, 218, 9, 54, 53, 130, 226 }; + ModesProba[5, 1] = new byte[] { 64, 90, 70, 205, 40, 41, 23, 26, 57 }; + ModesProba[5, 2] = new byte[] { 54, 57, 112, 184, 5, 41, 38, 166, 213 }; + ModesProba[5, 3] = new byte[] { 30, 34, 26, 133, 152, 116, 10, 32, 134 }; + ModesProba[5, 4] = new byte[] { 39, 19, 53, 221, 26, 114, 32, 73, 255 }; + ModesProba[5, 5] = new byte[] { 31, 9, 65, 234, 2, 15, 1, 118, 73 }; + ModesProba[5, 6] = new byte[] { 75, 32, 12, 51, 192, 255, 160, 43, 51 }; + ModesProba[5, 7] = new byte[] { 88, 31, 35, 67, 102, 85, 55, 186, 85 }; + ModesProba[5, 8] = new byte[] { 56, 21, 23, 111, 59, 205, 45, 37, 192 }; + ModesProba[5, 9] = new byte[] { 55, 38, 70, 124, 73, 102, 1, 34, 98 }; + ModesProba[6, 0] = new byte[] { 125, 98, 42, 88, 104, 85, 117, 175, 82 }; + ModesProba[6, 1] = new byte[] { 95, 84, 53, 89, 128, 100, 113, 101, 45 }; + ModesProba[6, 2] = new byte[] { 75, 79, 123, 47, 51, 128, 81, 171, 1 }; + ModesProba[6, 3] = new byte[] { 57, 17, 5, 71, 102, 57, 53, 41, 49 }; + ModesProba[6, 4] = new byte[] { 38, 33, 13, 121, 57, 73, 26, 1, 85 }; + ModesProba[6, 5] = new byte[] { 41, 10, 67, 138, 77, 110, 90, 47, 114 }; + ModesProba[6, 6] = new byte[] { 115, 21, 2, 10, 102, 255, 166, 23, 6 }; + ModesProba[6, 7] = new byte[] { 101, 29, 16, 10, 85, 128, 101, 196, 26 }; + ModesProba[6, 8] = new byte[] { 57, 18, 10, 102, 102, 213, 34, 20, 43 }; + ModesProba[6, 9] = new byte[] { 117, 20, 15, 36, 163, 128, 68, 1, 26 }; + ModesProba[7, 0] = new byte[] { 102, 61, 71, 37, 34, 53, 31, 243, 192 }; + ModesProba[7, 1] = new byte[] { 69, 60, 71, 38, 73, 119, 28, 222, 37 }; + ModesProba[7, 2] = new byte[] { 68, 45, 128, 34, 1, 47, 11, 245, 171 }; + ModesProba[7, 3] = new byte[] { 62, 17, 19, 70, 146, 85, 55, 62, 70 }; + ModesProba[7, 4] = new byte[] { 37, 43, 37, 154, 100, 163, 85, 160, 1 }; + ModesProba[7, 5] = new byte[] { 63, 9, 92, 136, 28, 64, 32, 201, 85 }; + ModesProba[7, 6] = new byte[] { 75, 15, 9, 9, 64, 255, 184, 119, 16 }; + ModesProba[7, 7] = new byte[] { 86, 6, 28, 5, 64, 255, 25, 248, 1 }; + ModesProba[7, 8] = new byte[] { 56, 8, 17, 132, 137, 255, 55, 116, 128 }; + ModesProba[7, 9] = new byte[] { 58, 15, 20, 82, 135, 57, 26, 121, 40 }; + ModesProba[8, 0] = new byte[] { 164, 50, 31, 137, 154, 133, 25, 35, 218 }; + ModesProba[8, 1] = new byte[] { 51, 103, 44, 131, 131, 123, 31, 6, 158 }; + ModesProba[8, 2] = new byte[] { 86, 40, 64, 135, 148, 224, 45, 183, 128 }; + ModesProba[8, 3] = new byte[] { 22, 26, 17, 131, 240, 154, 14, 1, 209 }; + ModesProba[8, 4] = new byte[] { 45, 16, 21, 91, 64, 222, 7, 1, 197 }; + ModesProba[8, 5] = new byte[] { 56, 21, 39, 155, 60, 138, 23, 102, 213 }; + ModesProba[8, 6] = new byte[] { 83, 12, 13, 54, 192, 255, 68, 47, 28 }; + ModesProba[8, 7] = new byte[] { 85, 26, 85, 85, 128, 128, 32, 146, 171 }; + ModesProba[8, 8] = new byte[] { 18, 11, 7, 63, 144, 171, 4, 4, 246 }; + ModesProba[8, 9] = new byte[] { 35, 27, 10, 146, 174, 171, 12, 26, 128 }; + ModesProba[9, 0] = new byte[] { 190, 80, 35, 99, 180, 80, 126, 54, 45 }; + ModesProba[9, 1] = new byte[] { 85, 126, 47, 87, 176, 51, 41, 20, 32 }; + ModesProba[9, 2] = new byte[] { 101, 75, 128, 139, 118, 146, 116, 128, 85 }; + ModesProba[9, 3] = new byte[] { 56, 41, 15, 176, 236, 85, 37, 9, 62 }; + ModesProba[9, 4] = new byte[] { 71, 30, 17, 119, 118, 255, 17, 18, 138 }; + ModesProba[9, 5] = new byte[] { 101, 38, 60, 138, 55, 70, 43, 26, 142 }; + ModesProba[9, 6] = new byte[] { 146, 36, 19, 30, 171, 255, 97, 27, 20 }; + ModesProba[9, 7] = new byte[] { 138, 45, 61, 62, 219, 1, 81, 188, 64 }; + ModesProba[9, 8] = new byte[] { 32, 41, 20, 117, 151, 142, 20, 21, 163 }; + ModesProba[9, 9] = new byte[] { 112, 19, 12, 61, 195, 128, 48, 4, 24 }; + } + } +} diff --git a/src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs b/src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs index 86fd34bae..98fe46cbc 100644 --- a/src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs +++ b/src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Formats.WebP /// The lossless specification can be found here: /// https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification /// - internal sealed class WebPLosslessDecoder : WebPDecoderBase + internal sealed class WebPLosslessDecoder { private readonly Vp8LBitReader bitReader; @@ -27,11 +27,11 @@ namespace SixLabors.ImageSharp.Formats.WebP private static readonly uint PackedNonLiteralCode = 0; - private static readonly int NumArgbCacheRows = 16; + private static readonly int CodeToPlaneCodes = WebPLookupTables.CodeToPlane.Length; private static readonly int FixedTableSize = (630 * 3) + 410; - private static readonly int[] KTableSize = + private static readonly int[] TableSize = { FixedTableSize + 654, FixedTableSize + 656, @@ -47,10 +47,11 @@ namespace SixLabors.ImageSharp.Formats.WebP FixedTableSize + 2704 }; - private static readonly byte[] KCodeLengthCodeOrder = { 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; - private static readonly int NumCodeLengthCodes = KCodeLengthCodeOrder.Length; + private static readonly byte[] CodeLengthCodeOrder = { 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; - private static readonly byte[] KLiteralMap = + private static readonly int NumCodeLengthCodes = CodeLengthCodeOrder.Length; + + private static readonly byte[] LiteralMap = { 0, 1, 1, 1, 0 }; @@ -235,7 +236,7 @@ namespace SixLabors.ImageSharp.Formats.WebP } else { - code = (int)this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Green], this.bitReader); + code = (int)this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Green]); } if (this.bitReader.IsEndOfStream()) @@ -252,10 +253,10 @@ namespace SixLabors.ImageSharp.Formats.WebP } else { - uint red = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Red], this.bitReader); + uint red = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Red]); this.bitReader.FillBitWindow(); - uint blue = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Blue], this.bitReader); - uint alpha = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Alpha], this.bitReader); + uint blue = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Blue]); + uint alpha = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Alpha]); if (this.bitReader.IsEndOfStream()) { break; @@ -271,10 +272,10 @@ namespace SixLabors.ImageSharp.Formats.WebP { // Backward reference is used. int lengthSym = code - WebPConstants.NumLiteralCodes; - int length = this.GetCopyLength(lengthSym, this.bitReader); - uint distSymbol = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Dist], this.bitReader); + int length = this.GetCopyLength(lengthSym); + uint distSymbol = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Dist]); this.bitReader.FillBitWindow(); - int distCode = this.GetCopyDistance((int)distSymbol, this.bitReader); + int distCode = this.GetCopyDistance((int)distSymbol); int dist = this.PlaneCodeToDistance(width, distCode); if (this.bitReader.IsEndOfStream()) { @@ -392,7 +393,7 @@ namespace SixLabors.ImageSharp.Formats.WebP } } - int tableSize = KTableSize[colorCacheBits]; + int tableSize = TableSize[colorCacheBits]; var huffmanTables = new HuffmanCode[numHTreeGroups * tableSize]; var hTreeGroups = new HTreeGroup[numHTreeGroups]; Span huffmanTable = huffmanTables.AsSpan(); @@ -420,7 +421,7 @@ namespace SixLabors.ImageSharp.Formats.WebP hTreeGroup.HTrees.Add(huffmanTable.ToArray()); - if (isTrivialLiteral && KLiteralMap[j] == 1) + if (isTrivialLiteral && LiteralMap[j] == 1) { isTrivialLiteral = huffmanTable[0].BitsUsed == 0; } @@ -515,7 +516,7 @@ namespace SixLabors.ImageSharp.Formats.WebP for (int i = 0; i < numCodes; i++) { - codeLengthCodeLengths[KCodeLengthCodeOrder[i]] = (int)this.bitReader.ReadValue(3); + codeLengthCodeLengths[CodeLengthCodeOrder[i]] = (int)this.bitReader.ReadValue(3); } this.ReadHuffmanCodeLengths(table.ToArray(), codeLengthCodeLengths, alphabetSize, codeLengths); @@ -750,6 +751,81 @@ namespace SixLabors.ImageSharp.Formats.WebP } } + /// + /// Decodes the next Huffman code from bit-stream. + /// FillBitWindow(br) needs to be called at minimum every second call to ReadSymbol, in order to pre-fetch enough bits. + /// + private uint ReadSymbol(Span table) + { + // TODO: if the bitReader field is moved to this base class we could omit the parameter. + uint val = (uint)this.bitReader.PrefetchBits(); + Span tableSpan = table.Slice((int)(val & HuffmanUtils.HuffmanTableMask)); + int nBits = tableSpan[0].BitsUsed - HuffmanUtils.HuffmanTableBits; + if (nBits > 0) + { + this.bitReader.AdvanceBitPosition(HuffmanUtils.HuffmanTableBits); + val = (uint)this.bitReader.PrefetchBits(); + tableSpan = tableSpan.Slice((int)tableSpan[0].Value); + tableSpan = tableSpan.Slice((int)val & ((1 << nBits) - 1)); + } + + this.bitReader.AdvanceBitPosition(tableSpan[0].BitsUsed); + + return tableSpan[0].Value; + } + + private HTreeGroup[] GetHTreeGroupForPos(Vp8LMetadata metadata, int x, int y) + { + uint metaIndex = this.GetMetaIndex(metadata.HuffmanImage, metadata.HuffmanXSize, metadata.HuffmanSubSampleBits, x, y); + return metadata.HTreeGroups.AsSpan((int)metaIndex).ToArray(); + } + + private uint GetMetaIndex(IMemoryOwner huffmanImage, int xSize, int bits, int x, int y) + { + if (bits is 0) + { + return 0; + } + + Span huffmanImageSpan = huffmanImage.GetSpan(); + return huffmanImageSpan[(xSize * (y >> bits)) + (x >> bits)]; + } + + private int PlaneCodeToDistance(int xSize, int planeCode) + { + if (planeCode > CodeToPlaneCodes) + { + return planeCode - CodeToPlaneCodes; + } + + int distCode = WebPLookupTables.CodeToPlane[planeCode - 1]; + int yOffset = distCode >> 4; + int xOffset = 8 - (distCode & 0xf); + int dist = (yOffset * xSize) + xOffset; + + // dist < 1 can happen if xSize is very small. + return (dist >= 1) ? dist : 1; + } + + private int GetCopyDistance(int distanceSymbol) + { + if (distanceSymbol < 4) + { + return distanceSymbol + 1; + } + + int extraBits = (distanceSymbol - 2) >> 1; + int offset = (2 + (distanceSymbol & 1)) << extraBits; + + return (int)(offset + this.bitReader.ReadValue(extraBits) + 1); + } + + private int GetCopyLength(int lengthSymbol) + { + // Length and distance prefixes are encoded the same way. + return this.GetCopyDistance(lengthSymbol); + } + private int AccumulateHCode(HuffmanCode hCode, int shift, HuffmanCode huff) { huff.BitsUsed += hCode.BitsUsed; diff --git a/src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs b/src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs index 82c9b9bd0..42402e025 100644 --- a/src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs +++ b/src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs @@ -12,7 +12,7 @@ using SixLabors.Memory; namespace SixLabors.ImageSharp.Formats.WebP { - internal sealed class WebPLossyDecoder : WebPDecoderBase + internal sealed class WebPLossyDecoder { private readonly Vp8BitReader bitReader; @@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.Formats.WebP int yMode = left[y]; for (int x = 0; x < 4; ++x) { - byte[] prob = Vp8LookupTables.ModesProba[top[x], yMode]; + byte[] prob = WebPLookupTables.ModesProba[top[x], yMode]; int i = WebPConstants.YModesIntra4[this.bitReader.GetBit(prob[0])]; while (i > 0) { @@ -328,34 +328,34 @@ namespace SixLabors.ImageSharp.Formats.WebP switch (lumaMode) { case 0: - LossyUtils.DC4_C(dst, yuv, offset); + LossyUtils.DC4(dst, yuv, offset); break; case 1: - LossyUtils.TM4_C(dst, yuv, offset); + LossyUtils.TM4(dst, yuv, offset); break; case 2: - LossyUtils.VE4_C(dst, yuv, offset); + LossyUtils.VE4(dst, yuv, offset); break; case 3: - LossyUtils.HE4_C(dst, yuv, offset); + LossyUtils.HE4(dst, yuv, offset); break; case 4: - LossyUtils.RD4_C(dst, yuv, offset); + LossyUtils.RD4(dst, yuv, offset); break; case 5: - LossyUtils.VR4_C(dst, yuv, offset); + LossyUtils.VR4(dst, yuv, offset); break; case 6: - LossyUtils.LD4_C(dst, yuv, offset); + LossyUtils.LD4(dst, yuv, offset); break; case 7: - LossyUtils.VL4_C(dst, yuv, offset); + LossyUtils.VL4(dst, yuv, offset); break; case 8: - LossyUtils.HD4_C(dst, yuv, offset); + LossyUtils.HD4(dst, yuv, offset); break; case 9: - LossyUtils.HU4_C(dst, yuv, offset); + LossyUtils.HU4(dst, yuv, offset); break; } @@ -369,25 +369,25 @@ namespace SixLabors.ImageSharp.Formats.WebP switch (mode) { case 0: - LossyUtils.DC16_C(yDst, yuv, yOff); + LossyUtils.DC16(yDst, yuv, yOff); break; case 1: - LossyUtils.TM16_C(yDst, yuv, yOff); + LossyUtils.TM16(yDst, yuv, yOff); break; case 2: - LossyUtils.VE16_C(yDst, yuv, yOff); + LossyUtils.VE16(yDst, yuv, yOff); break; case 3: - LossyUtils.HE16_C(yDst, yuv, yOff); + LossyUtils.HE16(yDst, yuv, yOff); break; case 4: - LossyUtils.DC16NoTop_C(yDst, yuv, yOff); + LossyUtils.DC16NoTop(yDst, yuv, yOff); break; case 5: - LossyUtils.DC16NoLeft_C(yDst, yuv, yOff); + LossyUtils.DC16NoLeft(yDst, yuv, yOff); break; case 6: - LossyUtils.DC16NoTopLeft_C(yDst); + LossyUtils.DC16NoTopLeft(yDst); break; } @@ -406,32 +406,32 @@ namespace SixLabors.ImageSharp.Formats.WebP switch (chromaMode) { case 0: - LossyUtils.DC8uv_C(uDst, yuv, uOff); - LossyUtils.DC8uv_C(vDst, yuv, vOff); + LossyUtils.DC8uv(uDst, yuv, uOff); + LossyUtils.DC8uv(vDst, yuv, vOff); break; case 1: - LossyUtils.TM8uv_C(uDst, yuv, uOff); - LossyUtils.TM8uv_C(vDst, yuv, vOff); + LossyUtils.TM8uv(uDst, yuv, uOff); + LossyUtils.TM8uv(vDst, yuv, vOff); break; case 2: - LossyUtils.VE8uv_C(uDst, yuv, uOff); - LossyUtils.VE8uv_C(vDst, yuv, vOff); + LossyUtils.VE8uv(uDst, yuv, uOff); + LossyUtils.VE8uv(vDst, yuv, vOff); break; case 3: - LossyUtils.HE8uv_C(uDst, yuv, uOff); - LossyUtils.HE8uv_C(vDst, yuv, vOff); + LossyUtils.HE8uv(uDst, yuv, uOff); + LossyUtils.HE8uv(vDst, yuv, vOff); break; case 4: - LossyUtils.DC8uvNoTop_C(uDst, yuv, uOff); - LossyUtils.DC8uvNoTop_C(vDst, yuv, vOff); + LossyUtils.DC8uvNoTop(uDst, yuv, uOff); + LossyUtils.DC8uvNoTop(vDst, yuv, vOff); break; case 5: - LossyUtils.DC8uvNoLeft_C(uDst, yuv, uOff); - LossyUtils.DC8uvNoLeft_C(vDst, yuv, vOff); + LossyUtils.DC8uvNoLeft(uDst, yuv, uOff); + LossyUtils.DC8uvNoLeft(vDst, yuv, vOff); break; case 6: - LossyUtils.DC8uvNoTopLeft_C(uDst); - LossyUtils.DC8uvNoTopLeft_C(vDst); + LossyUtils.DC8uvNoTopLeft(uDst); + LossyUtils.DC8uvNoTopLeft(vDst); break; } @@ -803,7 +803,6 @@ namespace SixLabors.ImageSharp.Formats.WebP blockData.NonZeroY = 0; blockData.NonZeroUv = 0; - blockData.Dither = 0; } // Store filter info. @@ -921,10 +920,6 @@ namespace SixLabors.ImageSharp.Formats.WebP block.NonZeroY = nonZeroY; block.NonZeroUv = nonZeroUv; - // We look at the mode-code of each block and check if some blocks have less - // than three non-zero coeffs (code < 2). This is to avoid dithering flat and empty blocks. - block.Dither = (byte)((nonZeroUv & 0xaaaa) > 0 ? 0 : q.Dither); - return (nonZeroY | nonZeroUv) is 0; } @@ -1227,20 +1222,20 @@ namespace SixLabors.ImageSharp.Formats.WebP } Vp8QuantMatrix m = decoder.DeQuantMatrices[i]; - m.Y1Mat[0] = Vp8LookupTables.DcTable[Clip(q + dqy1Dc, 127)]; - m.Y1Mat[1] = Vp8LookupTables.AcTable[Clip(q + 0, 127)]; - m.Y2Mat[0] = Vp8LookupTables.DcTable[Clip(q + dqy2Dc, 127)] * 2; + m.Y1Mat[0] = WebPLookupTables.DcTable[Clip(q + dqy1Dc, 127)]; + m.Y1Mat[1] = WebPLookupTables.AcTable[Clip(q + 0, 127)]; + m.Y2Mat[0] = WebPLookupTables.DcTable[Clip(q + dqy2Dc, 127)] * 2; // For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16. // The smallest precision for that is '(x*6349) >> 12' but 16 is a good word size. - m.Y2Mat[1] = (Vp8LookupTables.AcTable[Clip(q + dqy2Ac, 127)] * 101581) >> 16; + m.Y2Mat[1] = (WebPLookupTables.AcTable[Clip(q + dqy2Ac, 127)] * 101581) >> 16; if (m.Y2Mat[1] < 8) { m.Y2Mat[1] = 8; } - m.UvMat[0] = Vp8LookupTables.DcTable[Clip(q + dquvDc, 117)]; - m.UvMat[1] = Vp8LookupTables.AcTable[Clip(q + dquvAc, 127)]; + m.UvMat[0] = WebPLookupTables.DcTable[Clip(q + dquvDc, 117)]; + m.UvMat[1] = WebPLookupTables.AcTable[Clip(q + dquvAc, 127)]; // For dithering strength evaluation. m.UvQuant = q + dquvAc; @@ -1259,10 +1254,10 @@ namespace SixLabors.ImageSharp.Formats.WebP { for (int p = 0; p < WebPConstants.NumProbas; ++p) { - byte prob = Vp8LookupTables.CoeffsUpdateProba[t, b, c, p]; + byte prob = WebPLookupTables.CoeffsUpdateProba[t, b, c, p]; int v = this.bitReader.GetBit(prob) != 0 ? (int)this.bitReader.ReadValue(8) - : Vp8LookupTables.DefaultCoeffsProba[t, b, c, p]; + : WebPLookupTables.DefaultCoeffsProba[t, b, c, p]; proba.Bands[t, b].Probabilities[c].Probabilities[p] = (byte)v; } } @@ -1343,9 +1338,8 @@ namespace SixLabors.ImageSharp.Formats.WebP return io; } - static bool Is8bOptimizable(Vp8LMetadata hdr) + private static bool Is8bOptimizable(Vp8LMetadata hdr) { - int i; if (hdr.ColorCacheSize > 0) { return false; @@ -1353,7 +1347,7 @@ namespace SixLabors.ImageSharp.Formats.WebP // When the Huffman tree contains only one symbol, we can skip the // call to ReadSymbol() for red/blue/alpha channels. - for (i = 0; i < hdr.NumHTreeGroups; ++i) + for (int i = 0; i < hdr.NumHTreeGroups; ++i) { List htrees = hdr.HTreeGroups[i].HTrees; if (htrees[HuffIndex.Red][0].Value > 0) diff --git a/tests/ImageSharp.Benchmarks/Codecs/DecodeWebp.cs b/tests/ImageSharp.Benchmarks/Codecs/DecodeWebp.cs index ff9386286..5ec22cbad 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/DecodeWebp.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/DecodeWebp.cs @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs } } - [Benchmark(Baseline = true, Description = "Magick Lossy WebP")] + [Benchmark(Description = "Magick Lossy WebP")] public int WebpLossyMagick() { var settings = new MagickReadSettings { Format = MagickFormat.WebP }; @@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs } } - [Benchmark(Baseline = true, Description = "Magick Lossless WebP")] + [Benchmark(Description = "Magick Lossless WebP")] public int WebpLosslessMagick() { var settings = new MagickReadSettings { Format = MagickFormat.WebP }; diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebPDecoderTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebPDecoderTests.cs index fea51bf73..a6898093a 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/WebPDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/WebPDecoderTests.cs @@ -21,11 +21,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.WebP private static MagickReferenceDecoder ReferenceDecoder => new MagickReferenceDecoder(); [Theory] - [InlineData(Lossless.Lossless1, 1000, 307, 24)] - [InlineData(Lossless.Lossless2, 1000, 307, 24)] + [InlineData(Lossless.GreenTransform1, 1000, 307, 32)] + [InlineData(Lossless.BikeThreeTransforms, 250, 195, 32)] + [InlineData(Lossless.NoTransform2, 128, 128, 32)] [InlineData(Lossy.Alpha1, 1000, 307, 32)] [InlineData(Lossy.Alpha2, 1000, 307, 32)] - public void Identify_DetectsCorrectDimensions( + [InlineData(Lossy.Bike, 250, 195, 24)] + public void Identify_DetectsCorrectDimensionsAndBitDepth( string imagePath, int expectedWidth, int expectedHeight, diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebPMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebPMetaDataTests.cs index 44163da17..485f740a9 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/WebPMetaDataTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/WebPMetaDataTests.cs @@ -12,8 +12,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.WebP { using static SixLabors.ImageSharp.Tests.TestImages.WebP; - using static TestImages.Bmp; - + public class WebPMetaDataTests { [Fact] @@ -27,21 +26,5 @@ namespace SixLabors.ImageSharp.Tests.Formats.WebP Assert.False(meta.BitsPerPixel.Equals(clone.BitsPerPixel));*/ } - - [Theory] - [InlineData(Lossless.Lossless1, BmpInfoHeaderType.WinVersion2)] - public void Identify_DetectsCorrectBitmapInfoHeaderType(string imagePath, BmpInfoHeaderType expectedInfoHeaderType) - { - var testFile = TestFile.Create(imagePath); - using (var stream = new MemoryStream(testFile.Bytes, false)) - { - IImageInfo imageInfo = Image.Identify(stream); - Assert.NotNull(imageInfo); - Assert.Equal(24, imageInfo.PixelType.BitsPerPixel); - //var webpMetaData = imageInfo.Metadata.GetFormatMetadata(WebPFormat.Instance); - //Assert.NotNull(webpMetaData); - //Assert.Equal(expectedInfoHeaderType, webpMetaData.InfoHeaderType); - } - } } } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 66c936ad5..e892d87af 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -378,8 +378,6 @@ namespace SixLabors.ImageSharp.Tests public static class Lossless { - public const string Lossless1 = "WebP/lossless1.webp"; - public const string Lossless2 = "WebP/lossless2.webp"; public const string NoTransform1 = "WebP/lossless_vec_1_0.webp"; public const string NoTransform2 = "WebP/lossless_vec_2_0.webp"; public const string GreenTransform1 = "WebP/lossless1.webp"; @@ -498,11 +496,6 @@ namespace SixLabors.ImageSharp.Tests public const string AlphaNoCompression = "WebP/alpha_no_compression.webp"; } - - public static readonly string[] All = - { - Lossless.Lossless1 - }; } } }