mirror of https://github.com/SixLabors/ImageSharp
4 changed files with 149 additions and 2 deletions
@ -0,0 +1,53 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Diagnostics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
#pragma warning disable SA1405 // Debug.Assert should provide message text
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Ac; |
|||
|
|||
/// <summary>
|
|||
/// AC context
|
|||
/// </summary>
|
|||
internal static class JxlAcContext |
|||
{ |
|||
public const int DctOrderContextStart = 0; |
|||
public const int NonZeroBuckets = 37; |
|||
public const int ZeroDensityContextCount = 458; |
|||
public const int ZeroDensityContextLimit = 474; |
|||
|
|||
public static ReadOnlySpan<int> CoefficientFrequencyContext => |
|||
[ |
|||
0xBAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
|||
15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, |
|||
23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, |
|||
27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, |
|||
]; |
|||
|
|||
public static ReadOnlySpan<int> CoefficientNumNonzeroContext => |
|||
[ |
|||
0xBAD, 0, 31, 62, 62, 93, 93, 93, 93, 123, 123, 123, 123, |
|||
152, 152, 152, 152, 152, 152, 152, 152, 180, 180, 180, 180, 180, |
|||
180, 180, 180, 180, 180, 180, 180, 206, 206, 206, 206, 206, 206, |
|||
206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, |
|||
206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, |
|||
]; |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int ZeroDensityContext(int nonZeroesLeft, int k, int coveredBlocks, int log2CoveredBlocks, int prev) |
|||
{ |
|||
Debug.Assert((1 << log2CoveredBlocks) == coveredBlocks); |
|||
|
|||
nonZeroesLeft = (nonZeroesLeft + coveredBlocks - 1) >> log2CoveredBlocks; |
|||
k >>= log2CoveredBlocks; |
|||
|
|||
Debug.Assert(k > 0); |
|||
Debug.Assert(k < 64); |
|||
Debug.Assert(nonZeroesLeft > 0); |
|||
Debug.Assert(nonZeroesLeft < 64); |
|||
|
|||
return ((CoefficientNumNonzeroContext[nonZeroesLeft] + CoefficientFrequencyContext[k]) * 2) + prev; |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using SixLabors.ImageSharp.Formats.Jxl.Coefficients; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Ac; |
|||
|
|||
internal sealed class JxlBlockContextMap |
|||
{ |
|||
public JxlBlockContextMap() |
|||
{ |
|||
DefaultContextMap.CopyTo(this.ContextMap); |
|||
this.ContextCount = this.ContextMap.Max() + 1; |
|||
this.DcContextCount = 1; |
|||
} |
|||
|
|||
private static ReadOnlySpan<byte> DefaultContextMap => |
|||
[ |
|||
0, 1, 2, 2, 3, 3, 4, 5, 6, 6, 6, 6, 6, |
|||
7, 8, 9, 9, 10, 11, 12, 13, 14, 14, 14, 14, 14, |
|||
7, 8, 9, 9, 10, 11, 12, 13, 14, 14, 14, 14, 14, |
|||
]; |
|||
|
|||
public List<int>[] DcThresholds { get; } = [[], [], []]; |
|||
|
|||
public List<uint> QfThresholds { get; } = []; |
|||
|
|||
public byte[] ContextMap { get; } = new byte[DefaultContextMap.Length]; |
|||
|
|||
public int ContextCount { get; set; } |
|||
|
|||
public int DcContextCount { get; set; } |
|||
|
|||
public int AcContextCount => (this.ContextCount * JxlAcContext.NonZeroBuckets) + JxlAcContext.ZeroDensityContextCount; |
|||
|
|||
public int Context(int dcIndex, uint qf, int ord, int c) |
|||
{ |
|||
int qfIndex = 0; |
|||
for (int i = 0; i < this.QfThresholds.Count; i++) |
|||
{ |
|||
uint t = this.QfThresholds[i]; |
|||
|
|||
if (qf > t) |
|||
{ |
|||
qfIndex++; |
|||
} |
|||
} |
|||
|
|||
int idx = c < 2 ? c ^ 1 : 2; |
|||
idx = (idx * JxlForwardCoefficientOrder.OrderCount) + ord; |
|||
idx = (idx * (this.QfThresholds.Count + 1)) + qfIndex; |
|||
idx = (idx * this.DcContextCount) + dcIndex; |
|||
return this.ContextMap[idx]; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public int ZeroDensityContextOffset(int blockContext) => |
|||
(this.ContextCount * JxlAcContext.NonZeroBuckets) + JxlAcContext.ZeroDensityContextCount + blockContext; |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public int NonZeroContext(int nonZeroes, int blockContext) |
|||
{ |
|||
if (nonZeroes >= 64) |
|||
{ |
|||
nonZeroes = 64; |
|||
} |
|||
|
|||
int ctx = nonZeroes < 8 ? nonZeroes : (4 + (nonZeroes / 2)); |
|||
return (ctx * this.ContextCount) + blockContext; |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Coefficients; |
|||
|
|||
internal static class JxlForwardCoefficientOrder |
|||
{ |
|||
public const byte OrderCount = 13; |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int CoefficientRows(int rows, int columns) => rows < columns ? rows : columns; |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int CoefficientColumns(int rows, int columns) => rows < columns ? columns : rows; |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void CoefficientLayout(ref int rows, ref int columns) |
|||
{ |
|||
rows = CoefficientRows(rows, columns); |
|||
columns = CoefficientColumns(rows, columns); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue