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"/>. /// <paramref name="a"/> implies <paramref name="b"/>.
/// </summary> /// </summary>
internal static bool Implies(bool a, bool b) => !a || b; 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); bool bit = this.ReadEndOfBlockExtra(transformSizeContext, planeType, endOfBlockContext);
if (bit) if (bit)
{ {
endOfBlockExtra += 1 << (endOfBlockShift - 1); Av1Math.SetBit(ref endOfBlockExtra, endOfBlockShift - 1);
} }
else else
{ {
@ -361,7 +361,7 @@ internal ref struct Av1SymbolDecoder
{ {
if (this.ReadLiteral(1) != 0) 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) if (level > Av1Constants.BaseLevelsCount)
{ {
int baseRangeContext = Av1SymbolContextHelper.GetBaseRangeContextEndOfBlock(position, transformClass); 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); int coefficientBaseRange = this.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext);
level += coefficinetBaseRange; level += coefficientBaseRange;
if (coefficinetBaseRange < Av1Constants.BaseRangeSizeMinus1) if (coefficientBaseRange < Av1Constants.BaseRangeSizeMinus1)
{ {
break; break;
} }
@ -405,9 +405,9 @@ internal ref struct Av1SymbolDecoder
int baseRangeContext = Av1SymbolContextHelper.GetBaseRangeContext2d(levels, position); int baseRangeContext = Av1SymbolContextHelper.GetBaseRangeContext2d(levels, position);
for (int idx = 0; idx < Av1Constants.CoefficientBaseRange; idx += Av1Constants.BaseRangeSizeMinus1) for (int idx = 0; idx < Av1Constants.CoefficientBaseRange; idx += Av1Constants.BaseRangeSizeMinus1)
{ {
int k = this.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext); int coefficientBaseRange = this.ReadCoefficientsBaseRange(transformSizeContext, planeType, baseRangeContext);
level += k; level += coefficientBaseRange;
if (k < Av1Constants.BaseRangeSizeMinus1) if (coefficientBaseRange < Av1Constants.BaseRangeSizeMinus1)
{ {
break; break;
} }

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

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