Browse Source

Bit getting and setting methods

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
ebab7f0e15
  1. 6
      src/ImageSharp/Formats/Heif/Av1/Av1Math.cs
  2. 18
      src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolDecoder.cs
  3. 8
      src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolEncoder.cs
  4. 36
      tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MathTests.cs

6
src/ImageSharp/Formats/Heif/Av1/Av1Math.cs

@ -196,4 +196,10 @@ internal static class Av1Math
/// <paramref name="a"/> implies <paramref name="b"/>.
/// </summary>
internal static bool Implies(bool a, bool b) => !a || b;
internal static int GetBit(int value, int n)
=> (value & (1 << n)) >> n;
internal static void SetBit(ref int endOfBlockExtra, int n)
=> endOfBlockExtra |= 1 << n;
}

18
src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolDecoder.cs

@ -353,7 +353,7 @@ internal ref struct Av1SymbolDecoder
bool bit = this.ReadEndOfBlockExtra(transformSizeContext, planeType, endOfBlockContext);
if (bit)
{
endOfBlockExtra += 1 << (endOfBlockShift - 1);
Av1Math.SetBit(ref endOfBlockExtra, endOfBlockShift - 1);
}
else
{
@ -361,7 +361,7 @@ internal ref struct Av1SymbolDecoder
{
if (this.ReadLiteral(1) != 0)
{
endOfBlockExtra += 1 << (endOfBlockShift - 1 - j);
Av1Math.SetBit(ref endOfBlockExtra, endOfBlockShift - 1 - j);
}
}
}
@ -379,11 +379,11 @@ internal ref struct Av1SymbolDecoder
if (level > Av1Constants.BaseLevelsCount)
{
int baseRangeContext = Av1SymbolContextHelper.GetBaseRangeContextEndOfBlock(position, transformClass);
for (int idx = 0; idx < Av1Constants.CoefficientBaseRange / Av1Constants.BaseRangeSizeMinus1; idx++)
for (int idx = 0; idx < Av1Constants.CoefficientBaseRange; idx += Av1Constants.BaseRangeSizeMinus1)
{
int coefficinetBaseRange = this.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext);
level += coefficinetBaseRange;
if (coefficinetBaseRange < Av1Constants.BaseRangeSizeMinus1)
int coefficientBaseRange = this.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext);
level += coefficientBaseRange;
if (coefficientBaseRange < Av1Constants.BaseRangeSizeMinus1)
{
break;
}
@ -405,9 +405,9 @@ internal ref struct Av1SymbolDecoder
int baseRangeContext = Av1SymbolContextHelper.GetBaseRangeContext2d(levels, position);
for (int idx = 0; idx < Av1Constants.CoefficientBaseRange; idx += Av1Constants.BaseRangeSizeMinus1)
{
int k = this.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext);
level += k;
if (k < Av1Constants.BaseRangeSizeMinus1)
int coefficientBaseRange = this.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext);
level += coefficientBaseRange;
if (coefficientBaseRange < Av1Constants.BaseRangeSizeMinus1)
{
break;
}

8
src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolEncoder.cs

@ -204,13 +204,13 @@ internal class Av1SymbolEncoder : IDisposable
{
ref Av1SymbolWriter w = ref this.writer;
int eobShift = eobOffsetBitCount - 1;
uint bit = (eobExtra & (1 << eobShift)) != 0 ? 1u : 0u;
w.WriteSymbol((int)bit, this.endOfBlockExtra[(int)transformSizeContext][(int)componentType][endOfBlockPosition]);
int bit = Av1Math.GetBit(eobExtra, eobShift);
w.WriteSymbol(bit, this.endOfBlockExtra[(int)transformSizeContext][(int)componentType][endOfBlockPosition]);
for (int i = 1; i < eobOffsetBitCount; i++)
{
eobShift = eobOffsetBitCount - 1 - i;
bit = (eobExtra & (1 << eobShift)) != 0 ? 1u : 0u;
w.WriteLiteral(bit, 1);
bit = Av1Math.GetBit(eobExtra, eobShift);
w.WriteLiteral((uint)bit, 1);
}
}
}

36
tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MathTests.cs

@ -0,0 +1,36 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1;
namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1;
[Trait("Format", "Avif")]
public class Av1MathTests
{
[Theory]
[InlineData(4, 2, 1)]
[InlineData(4, 3, 0)]
[InlineData(5, 3, 0)]
[InlineData(8, 3, 1)]
[InlineData(9, 3, 1)]
[InlineData(9, 0, 1)]
[InlineData(8, 0, 0)]
public void TestGetBitSet(int value, int n, int expected)
{
int actual = Av1Math.GetBit(value, n);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(4, 2, 4)]
[InlineData(0, 2, 4)]
[InlineData(0, 3, 8)]
[InlineData(4, 3, 12)]
public void TestSetBitSet(int value, int n, int expected)
{
int actual = value;
Av1Math.SetBit(ref actual, n);
Assert.Equal(expected, actual);
}
}
Loading…
Cancel
Save