From 996e93dba2f3c6810b166c98b1e5e4faea0afaaf Mon Sep 17 00:00:00 2001
From: winscripter <142818255+winscripter@users.noreply.github.com>
Date: Tue, 14 Jul 2026 23:26:11 +0400
Subject: [PATCH] Implement ac_context.h
---
src/ImageSharp/Formats/Jxl/Ac/JxlAcContext.cs | 53 ++++++++++++++
.../Formats/Jxl/Ac/JxlBlockContextMap.cs | 72 +++++++++++++++++++
.../JxlForwardCoefficientOrder.cs | 24 +++++++
src/ImageSharp/Formats/Jxl/JxlFormat.cs | 2 -
4 files changed, 149 insertions(+), 2 deletions(-)
create mode 100644 src/ImageSharp/Formats/Jxl/Ac/JxlAcContext.cs
create mode 100644 src/ImageSharp/Formats/Jxl/Ac/JxlBlockContextMap.cs
create mode 100644 src/ImageSharp/Formats/Jxl/Coefficients/JxlForwardCoefficientOrder.cs
diff --git a/src/ImageSharp/Formats/Jxl/Ac/JxlAcContext.cs b/src/ImageSharp/Formats/Jxl/Ac/JxlAcContext.cs
new file mode 100644
index 0000000000..98f86534b2
--- /dev/null
+++ b/src/ImageSharp/Formats/Jxl/Ac/JxlAcContext.cs
@@ -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;
+
+///
+/// AC context
+///
+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 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 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;
+ }
+}
diff --git a/src/ImageSharp/Formats/Jxl/Ac/JxlBlockContextMap.cs b/src/ImageSharp/Formats/Jxl/Ac/JxlBlockContextMap.cs
new file mode 100644
index 0000000000..3b7e75605f
--- /dev/null
+++ b/src/ImageSharp/Formats/Jxl/Ac/JxlBlockContextMap.cs
@@ -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 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[] DcThresholds { get; } = [[], [], []];
+
+ public List 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;
+ }
+}
diff --git a/src/ImageSharp/Formats/Jxl/Coefficients/JxlForwardCoefficientOrder.cs b/src/ImageSharp/Formats/Jxl/Coefficients/JxlForwardCoefficientOrder.cs
new file mode 100644
index 0000000000..04cacb176a
--- /dev/null
+++ b/src/ImageSharp/Formats/Jxl/Coefficients/JxlForwardCoefficientOrder.cs
@@ -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);
+ }
+}
diff --git a/src/ImageSharp/Formats/Jxl/JxlFormat.cs b/src/ImageSharp/Formats/Jxl/JxlFormat.cs
index d5dfa802b1..00e7b66eb5 100644
--- a/src/ImageSharp/Formats/Jxl/JxlFormat.cs
+++ b/src/ImageSharp/Formats/Jxl/JxlFormat.cs
@@ -1,8 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-using System.Collections.Generic;
-
namespace SixLabors.ImageSharp.Formats.Jxl;
internal class JxlFormat : IImageFormat