From e0305d78c5dc0986a860034e3c5d859c1a406528 Mon Sep 17 00:00:00 2001 From: winscripter <142818255+winscripter@users.noreply.github.com> Date: Wed, 2 Sep 2026 21:58:14 +0400 Subject: [PATCH] Partial adaptive quantizer encoder --- .../Encoder/JxlAdaptiveQuantization.cs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/ImageSharp/Formats/Jxl/Processing/Encoder/JxlAdaptiveQuantization.cs diff --git a/src/ImageSharp/Formats/Jxl/Processing/Encoder/JxlAdaptiveQuantization.cs b/src/ImageSharp/Formats/Jxl/Processing/Encoder/JxlAdaptiveQuantization.cs new file mode 100644 index 0000000000..00150b3dd3 --- /dev/null +++ b/src/ImageSharp/Formats/Jxl/Processing/Encoder/JxlAdaptiveQuantization.cs @@ -0,0 +1,44 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.Formats.Jxl.Processing.Encoder; + +/// +/// Adaptive quantization encoder +/// +internal static class JxlAdaptiveQuantization +{ + // Scaling differences between JPEG XL and Butteraugli + private const float SGMul = 226.77216153508914f; + private const float SGMul2 = 1f / 73.377132366608819f; + + // Includes correlation factor for std::log -> log2 + private const float SGRetMul = SGMul2 * 18.6580932135f * JxlMath.InverseLog2E; + private const float SGVOffset = 7.7825991679894591f; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float ComputeMaskForAcStrategyUse(float outputValue) + { + const float multiplier = 1f; + const float offset = 0.001f; + + return multiplier / (outputValue + offset); + } + + public static float RatioOfDerivativesOfCubicRootToSimpleGamma(float v, bool invert = false) + { + float epsilon = 1e-2f; + v = Math.Max(0, v); // cannot be < 0 + const float numMul = SGRetMul * 3 * SGMul; + float voffset = (SGVOffset * JxlMath.InverseLog2E) + epsilon; + const float denMul = JxlMath.InverseLog2E * SGMul; + + float v2 = v * v; + float num = (numMul * v2) + epsilon; + float den = ((denMul * v) * v2) + voffset; + + return invert ? num / den : den / num; + } +}