mirror of https://github.com/SixLabors/ImageSharp
3 changed files with 134 additions and 0 deletions
@ -0,0 +1,72 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Six Labors Split License.
|
||||
|
|
||||
|
using System.Numerics; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Entropy; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts AV1 symbol probabilities into fixed-point encoder rate costs.
|
||||
|
/// </summary>
|
||||
|
internal static class Av1ProbabilityCost |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The number of fractional bits in an encoder rate cost.
|
||||
|
/// </summary>
|
||||
|
public const int CostShift = 9; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the probability costs for normalized eight-bit probabilities from 128 through 255.
|
||||
|
/// </summary>
|
||||
|
private static ReadOnlySpan<ushort> ProbabilityCosts => |
||||
|
[ |
||||
|
512, 506, 501, 495, 489, 484, 478, 473, 467, 462, 456, 451, 446, 441, 435, |
||||
|
430, 425, 420, 415, 410, 405, 400, 395, 390, 385, 380, 375, 371, 366, 361, |
||||
|
356, 352, 347, 343, 338, 333, 329, 324, 320, 316, 311, 307, 302, 298, 294, |
||||
|
289, 285, 281, 277, 273, 268, 264, 260, 256, 252, 248, 244, 240, 236, 232, |
||||
|
228, 224, 220, 216, 212, 209, 205, 201, 197, 194, 190, 186, 182, 179, 175, |
||||
|
171, 168, 164, 161, 157, 153, 150, 146, 143, 139, 136, 132, 129, 125, 122, |
||||
|
119, 115, 112, 109, 105, 102, 99, 95, 92, 89, 86, 82, 79, 76, 73, 70, |
||||
|
66, 63, 60, 57, 54, 51, 48, 45, 42, 38, 35, 32, 29, 26, 23, 20, 18, 15, |
||||
|
12, 9, 6, 3 |
||||
|
]; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the fixed-point cost of writing the requested number of equiprobable bits.
|
||||
|
/// </summary>
|
||||
|
/// <param name="bitCount">The number of bits.</param>
|
||||
|
/// <returns>The rate cost in 1/512-bit units.</returns>
|
||||
|
public static int GetLiteralCost(int bitCount) => bitCount << CostShift; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the fixed-point cost of coding one symbol from an inverse cumulative distribution.
|
||||
|
/// </summary>
|
||||
|
/// <param name="distribution">The distribution used by the entropy writer.</param>
|
||||
|
/// <param name="symbol">The zero-based symbol.</param>
|
||||
|
/// <returns>The rate cost in 1/512-bit units.</returns>
|
||||
|
public static int GetSymbolCost(Av1Distribution distribution, int symbol) |
||||
|
{ |
||||
|
int inverseLower = symbol == 0 ? Av1Distribution.ProbabilityTop : (int)distribution[symbol - 1]; |
||||
|
int inverseUpper = (int)distribution[symbol]; |
||||
|
return GetProbabilityCost(inverseLower - inverseUpper); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the fixed-point cost of a Q15 probability.
|
||||
|
/// </summary>
|
||||
|
/// <param name="probability">The Q15 probability numerator.</param>
|
||||
|
/// <returns>The rate cost in 1/512-bit units.</returns>
|
||||
|
public static int GetProbabilityCost(int probability) |
||||
|
{ |
||||
|
probability = Math.Clamp(probability, 1, Av1Distribution.ProbabilityTop - 1); |
||||
|
int shift = 14 - BitOperations.Log2((uint)probability); |
||||
|
|
||||
|
// Normalization puts every probability in the upper half of an eight-bit range. The lookup therefore
|
||||
|
// covers one binary order of magnitude, while the shift contributes the exact number of whole bits.
|
||||
|
int normalizedProbability = (((probability << shift) * 256) + (Av1Distribution.ProbabilityTop >> 1)) |
||||
|
/ Av1Distribution.ProbabilityTop; |
||||
|
normalizedProbability = Math.Min(normalizedProbability, 255); |
||||
|
|
||||
|
return ProbabilityCosts[normalizedProbability - 128] + (shift << CostShift); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue