Browse Source

Change huffman code to a struct

pull/1846/head
Brian Popow 4 years ago
parent
commit
40b6f4e55b
  1. 4
      src/ImageSharp/Formats/Webp/Lossless/HTreeGroup.cs
  2. 2
      src/ImageSharp/Formats/Webp/Lossless/HuffmanCode.cs
  3. 45
      src/ImageSharp/Formats/Webp/Lossless/HuffmanUtils.cs
  4. 14
      src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs
  5. 2
      tests/ImageSharp.Tests/Formats/WebP/ColorSpaceTransformUtilsTests.cs
  6. 2
      tests/ImageSharp.Tests/Formats/WebP/LossyUtilsTests.cs
  7. 2
      tests/ImageSharp.Tests/Formats/WebP/QuantEncTests.cs
  8. 2
      tests/ImageSharp.Tests/Formats/WebP/Vp8EncodingTests.cs

4
src/ImageSharp/Formats/Webp/Lossless/HTreeGroup.cs

@ -19,10 +19,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
{
this.HTrees = new List<HuffmanCode[]>(WebpConstants.HuffmanCodesPerMetaCode);
this.PackedTable = new HuffmanCode[packedTableSize];
for (int i = 0; i < packedTableSize; i++)
{
this.PackedTable[i] = new HuffmanCode();
}
}
/// <summary>

2
src/ImageSharp/Formats/Webp/Lossless/HuffmanCode.cs

@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
/// A classic way to do entropy coding where a smaller number of bits are used for more frequent codes.
/// </summary>
[DebuggerDisplay("BitsUsed: {BitsUsed}, Value: {Value}")]
internal class HuffmanCode
internal struct HuffmanCode
{
/// <summary>
/// Gets or sets the number of bits used for this symbol.

45
src/ImageSharp/Formats/Webp/Lossless/HuffmanUtils.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Webp.Lossless
{
@ -307,9 +308,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
public static int BuildHuffmanTable(Span<HuffmanCode> table, int rootBits, int[] codeLengths, int codeLengthsSize)
{
Guard.MustBeGreaterThan(rootBits, 0, nameof(rootBits));
Guard.NotNull(codeLengths, nameof(codeLengths));
Guard.MustBeGreaterThan(codeLengthsSize, 0, nameof(codeLengthsSize));
DebugGuard.MustBeGreaterThan(rootBits, 0, nameof(rootBits));
DebugGuard.NotNull(codeLengths, nameof(codeLengths));
DebugGuard.MustBeGreaterThan(codeLengthsSize, 0, nameof(codeLengthsSize));
// sorted[codeLengthsSize] is a pre-allocated array for sorting symbols by code length.
int[] sorted = new int[codeLengthsSize];
@ -467,27 +468,27 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
break;
}
else if (repetitions < 11)
if (repetitions < 11)
{
tokens[pos].Code = 17;
tokens[pos].ExtraBits = (byte)(repetitions - 3);
pos++;
break;
}
else if (repetitions < 139)
if (repetitions < 139)
{
tokens[pos].Code = 18;
tokens[pos].ExtraBits = (byte)(repetitions - 11);
pos++;
break;
}
else
{
tokens[pos].Code = 18;
tokens[pos].ExtraBits = 0x7f; // 138 repeated 0s
pos++;
repetitions -= 138;
}
tokens[pos].Code = 18;
tokens[pos].ExtraBits = 0x7f; // 138 repeated 0s
pos++;
repetitions -= 138;
}
return pos;
@ -519,20 +520,19 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
break;
}
else if (repetitions < 7)
if (repetitions < 7)
{
tokens[pos].Code = 16;
tokens[pos].ExtraBits = (byte)(repetitions - 3);
pos++;
break;
}
else
{
tokens[pos].Code = 16;
tokens[pos].ExtraBits = 3;
pos++;
repetitions -= 6;
}
tokens[pos].Code = 16;
tokens[pos].ExtraBits = 3;
pos++;
repetitions -= 6;
}
return pos;
@ -541,7 +541,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
/// <summary>
/// Get the actual bit values for a tree of bit depths.
/// </summary>
/// <param name="tree">The hiffman tree.</param>
/// <param name="tree">The huffman tree.</param>
private static void ConvertBitDepthsToSymbols(HuffmanTreeCode tree)
{
// 0 bit-depth means that the symbol does not exist.
@ -628,7 +628,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
/// </summary>
private static void ReplicateValue(Span<HuffmanCode> table, int step, int end, HuffmanCode code)
{
Guard.IsTrue(end % step == 0, nameof(end), "end must be a multiple of step");
DebugGuard.IsTrue(end % step == 0, nameof(end), "end must be a multiple of step");
do
{
@ -656,6 +656,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
/// <summary>
/// Heuristics for selecting the stride ranges to collapse.
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
private static bool ValuesShouldBeCollapsedToStrideAverage(int a, int b) => Math.Abs(a - b) < 4;
}
}

14
src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs

@ -834,10 +834,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
private void BuildPackedTable(HTreeGroup hTreeGroup)
{
for (uint code = 0; code < HuffmanUtils.HuffmanPackedTableSize; ++code)
for (uint code = 0; code < HuffmanUtils.HuffmanPackedTableSize; code++)
{
uint bits = code;
HuffmanCode huff = hTreeGroup.PackedTable[bits];
ref HuffmanCode huff = ref hTreeGroup.PackedTable[bits];
HuffmanCode hCode = hTreeGroup.HTrees[HuffIndex.Green][bits];
if (hCode.Value >= WebpConstants.NumLiteralCodes)
{
@ -848,10 +848,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
{
huff.BitsUsed = 0;
huff.Value = 0;
bits >>= AccumulateHCode(hCode, 8, huff);
bits >>= AccumulateHCode(hTreeGroup.HTrees[HuffIndex.Red][bits], 16, huff);
bits >>= AccumulateHCode(hTreeGroup.HTrees[HuffIndex.Blue][bits], 0, huff);
bits >>= AccumulateHCode(hTreeGroup.HTrees[HuffIndex.Alpha][bits], 24, huff);
bits >>= AccumulateHCode(hCode, 8, ref huff);
bits >>= AccumulateHCode(hTreeGroup.HTrees[HuffIndex.Red][bits], 16, ref huff);
bits >>= AccumulateHCode(hTreeGroup.HTrees[HuffIndex.Blue][bits], 0, ref huff);
bits >>= AccumulateHCode(hTreeGroup.HTrees[HuffIndex.Alpha][bits], 24, ref huff);
}
}
}
@ -992,7 +992,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
}
[MethodImpl(InliningOptions.ShortMethod)]
private static int AccumulateHCode(HuffmanCode hCode, int shift, HuffmanCode huff)
private static int AccumulateHCode(HuffmanCode hCode, int shift, ref HuffmanCode huff)
{
huff.BitsUsed += hCode.BitsUsed;
huff.Value |= hCode.Value << shift;

2
tests/ImageSharp.Tests/Formats/WebP/ColorSpaceTransformUtilsTests.cs

@ -5,7 +5,7 @@ using SixLabors.ImageSharp.Formats.Webp.Lossless;
using SixLabors.ImageSharp.Tests.TestUtilities;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.WebP
namespace SixLabors.ImageSharp.Tests.Formats.Webp
{
[Trait("Format", "Webp")]
public class ColorSpaceTransformUtilsTests

2
tests/ImageSharp.Tests/Formats/WebP/LossyUtilsTests.cs

@ -6,7 +6,7 @@ using SixLabors.ImageSharp.Formats.Webp.Lossy;
using SixLabors.ImageSharp.Tests.TestUtilities;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.WebP
namespace SixLabors.ImageSharp.Tests.Formats.Webp
{
[Trait("Format", "Webp")]
public class LossyUtilsTests

2
tests/ImageSharp.Tests/Formats/WebP/QuantEncTests.cs

@ -6,7 +6,7 @@ using SixLabors.ImageSharp.Formats.Webp.Lossy;
using SixLabors.ImageSharp.Tests.TestUtilities;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.WebP
namespace SixLabors.ImageSharp.Tests.Formats.Webp
{
[Trait("Format", "Webp")]
public class QuantEncTests

2
tests/ImageSharp.Tests/Formats/WebP/Vp8EncodingTests.cs

@ -6,7 +6,7 @@ using SixLabors.ImageSharp.Formats.Webp.Lossy;
using SixLabors.ImageSharp.Tests.TestUtilities;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.WebP
namespace SixLabors.ImageSharp.Tests.Formats.Webp
{
[Trait("Format", "Webp")]
public class Vp8EncodingTests

Loading…
Cancel
Save