diff --git a/src/ImageSharp/Formats/Jxl/IO/JxlAnsHybridUIntConfiguration.cs b/src/ImageSharp/Formats/Jxl/IO/JxlAnsHybridUIntConfiguration.cs new file mode 100644 index 0000000000..422eb2323f --- /dev/null +++ b/src/ImageSharp/Formats/Jxl/IO/JxlAnsHybridUIntConfiguration.cs @@ -0,0 +1,60 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using System.Diagnostics; +using SixLabors.ImageSharp.Formats.Jxl.Fields; + +namespace SixLabors.ImageSharp.Formats.Jxl.IO; + +internal sealed class JxlAnsHybridUIntConfiguration : IJxlFields +{ + public JxlAnsHybridUIntConfiguration(uint splitExponent = 4, uint msbInToken = 2, uint lsbInToken = 0) + { + this.SplitExponent = splitExponent; + this.SplitToken = 1u << (int)splitExponent; + this.MsbInToken = msbInToken; + this.LsbInToken = lsbInToken; + + Debug.Assert(splitExponent >= msbInToken + lsbInToken, "Split exponent should be < msbInToken + lsbInToken"); + } + + public uint SplitExponent { get; set; } + + public uint SplitToken { get; set; } + + public uint MsbInToken { get; set; } // Most significant bit + + public uint LsbInToken { get; set; } // Least significant bit + + public uint LsbMask => (1u << (int)this.LsbInToken) - 1; + + public void Encode(uint value, ref uint token, ref uint bitCount, ref uint bits) + { + if (value < this.SplitToken) + { + token = value; + bitCount = 0; + bits = 0; + } + else + { + uint n = FloorLog2Nonzero(value); + uint m = value - (1u << (int)n); + + unchecked + { + // The following expression is quite complex. + // See https://github.com/libjxl/libjxl/blob/main/lib/jxl/dec_ans.h#L83C16-L86C47. + token = this.SplitToken + + (uint)(((n - this.SplitExponent) << (int)(this.MsbInToken + this.LsbInToken)) + + ((m >> (int)(n - this.MsbInToken)) << (int)this.LsbInToken) + + (m & ((1 << (int)this.LsbInToken) - 1))); + + bitCount = n - this.MsbInToken - this.LsbInToken; + bits = (value >> (int)this.LsbInToken) & ((1u << (int)bitCount) - 1); + } + } + } + + public bool Visit(JxlVisitor visitor) => throw new NotImplementedException(); +} diff --git a/src/ImageSharp/Formats/Jxl/IO/JxlAnsLz77Parameters.cs b/src/ImageSharp/Formats/Jxl/IO/JxlAnsLz77Parameters.cs new file mode 100644 index 0000000000..ecf5cdc3fa --- /dev/null +++ b/src/ImageSharp/Formats/Jxl/IO/JxlAnsLz77Parameters.cs @@ -0,0 +1,21 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using SixLabors.ImageSharp.Formats.Jxl.Fields; + +namespace SixLabors.ImageSharp.Formats.Jxl.IO; + +internal sealed class JxlAnsLz77Parameters : IJxlFields +{ + public bool Enabled { get; set; } + + public uint MinimumSymbol { get; set; } + + public uint MinimumLength { get; set; } + + public JxlAnsHybridUIntConfiguration LengthUintConfig { get; set; } = new(0, 0, 0); + + public int NonserializedDistanceContext { get; set; } + + public bool Visit(JxlVisitor visitor) => throw new NotImplementedException(); +}