diff --git a/src/ImageSharp/Formats/Jxl/Cms/TransferFunctions/JxlHybridLogGammaTransferFunctionBase.cs b/src/ImageSharp/Formats/Jxl/Cms/TransferFunctions/JxlHlgTransferFunction.cs similarity index 52% rename from src/ImageSharp/Formats/Jxl/Cms/TransferFunctions/JxlHybridLogGammaTransferFunctionBase.cs rename to src/ImageSharp/Formats/Jxl/Cms/TransferFunctions/JxlHlgTransferFunction.cs index 795db106c3..053a2a5cfb 100644 --- a/src/ImageSharp/Formats/Jxl/Cms/TransferFunctions/JxlHybridLogGammaTransferFunctionBase.cs +++ b/src/ImageSharp/Formats/Jxl/Cms/TransferFunctions/JxlHlgTransferFunction.cs @@ -1,33 +1,78 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Numerics; +using SixLabors.ImageSharp.Formats.Jxl.Processing; + namespace SixLabors.ImageSharp.Formats.Jxl.Cms.TransferFunctions; /// -/// Base class for HLG transfer function. +/// Hybrid Log Gamma transfer function. /// -internal abstract class JxlHybridLogGammaTransferFunctionBase +internal sealed class JxlHlgTransferFunction { // Shared constants used by transfer functions - protected const float A = 0.17883277f; - protected const float RA = 1.0f / A; - protected const float B = 1 - (4 * A); - protected const float C = 0.5599107295f; - protected const float Inverse12 = 1.0f / 12.0f; + private const float A = 0.17883277f; + private const float RA = 1.0f / A; + private const float B = 1 - (4 * A); + private const float C = 0.5599107295f; + private const float Inverse12 = 1.0f / 12.0f; + private const float HiAdd = B * Inverse12; + private const float HiMul = 0.003639807079052639f; // MathF.Exp(-C * RA) * Inverse12 + private const float HiPow = 8.067285659607931f; // RA * JxlMath.InverseLog2E + + /// + /// Initializes a new instance of the class. + /// + /// + /// Use static methods. Don't instantiate this class. + /// + private JxlHlgTransferFunction() + { + } + + public static Vector EncodedFromDisplay(Vector x) + { + Vector sign = Vector.Create(0x80000000u).As(); + Vector originalSign = x & sign; + x = Vector.AndNot(sign, x); + Vector belowInverse12 = Vector.LessThan(x, Vector.Create(Inverse12)); + + Vector lo = Vector.SquareRoot(Vector.Create(3.0f) * x); + Vector hi = (Vector.Create(A * JxlMath.InverseLog2E) * Vector.Log2((Vector.Create(12f) * x) + Vector.Create(-B))) + Vector.Create(C); + Vector magnitude = Vector.ConditionalSelect(belowInverse12, lo, hi); + return Vector.AndNot(sign, magnitude) | originalSign; + } + + public static Vector DisplayFromEncoded(Vector x) + { + Vector sign = Vector.Create(0x80000000u).As(); + Vector originalSign = x & sign; + x = Vector.AndNot(sign, x); + Vector below05 = Vector.LessThan(x, Vector.Create(0.5f)); + + Vector lo = x * (x * Vector.Create(1f / 3f)); + Vector hi = (Pow2(x * Vector.Create(HiPow)) * Vector.Create(HiMul)) + Vector.Create(HiAdd); + Vector magnitude = Vector.ConditionalSelect(below05, lo, hi); + + return Vector.AndNot(sign, magnitude) | originalSign; + } + + private static Vector Pow2(Vector x) => JxlSimdUtils.FastPow2f(x); /// /// Converts encoded signal to display signal. /// /// The encoded signal /// The display signal - protected static double DisplayFromEncoded(double encoded) => Ootf(InverseOotf(encoded)); + public static double DisplayFromEncoded(double encoded) => Ootf(InverseOotf(encoded)); /// /// Converts display signal to encoded signal. /// /// The display signal /// The encoded signal - protected static double EncodedFromDisplay(double display) => Oetf(InverseOetf(display)); + public static double EncodedFromDisplay(double display) => Oetf(InverseOetf(display)); /// /// Opto-Electronic Transfer Function - converts @@ -39,7 +84,7 @@ internal abstract class JxlHybridLogGammaTransferFunctionBase /// /// Scene light /// Digital video signal - private static double Oetf(double s) + public static double Oetf(double s) { if (s == 0) { @@ -70,7 +115,7 @@ internal abstract class JxlHybridLogGammaTransferFunctionBase /// /// Digital video signal /// Scene light - private static double InverseOetf(double e) + public static double InverseOetf(double e) { if (e == 0) { @@ -100,7 +145,7 @@ internal abstract class JxlHybridLogGammaTransferFunctionBase /// /// Input signal /// Digital video signal - private static double Ootf(double s) => s; + public static double Ootf(double s) => s; /// /// Inverse Opto-Optical Transfer Function - as-is. @@ -110,5 +155,5 @@ internal abstract class JxlHybridLogGammaTransferFunctionBase /// /// Digital video signal /// Scene light - private static double InverseOotf(double s) => s; + public static double InverseOotf(double s) => s; } diff --git a/src/ImageSharp/Formats/Jxl/Cms/TransferFunctions/JxlHybridLogGammaTransferFunction.cs b/src/ImageSharp/Formats/Jxl/Cms/TransferFunctions/JxlHybridLogGammaTransferFunction.cs deleted file mode 100644 index 3957c3ac7b..0000000000 --- a/src/ImageSharp/Formats/Jxl/Cms/TransferFunctions/JxlHybridLogGammaTransferFunction.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Six Labors Split License. - -using System.Numerics; -using SixLabors.ImageSharp.Formats.Jxl.Processing; - -namespace SixLabors.ImageSharp.Formats.Jxl.Cms.TransferFunctions; - -internal sealed class JxlHybridLogGammaTransferFunction : JxlHybridLogGammaTransferFunctionBase -{ - private const float HiAdd = B * Inverse12; - private const float HiMul = 0.003639807079052639f; // MathF.Exp(-C * RA) * Inverse12 - private const float HiPow = 8.067285659607931f; // RA * JxlMath.InverseLog2E - - /// - /// Initializes a new instance of the class. - /// - /// - /// Use static methods. Don't instantiate this class. - /// - private JxlHybridLogGammaTransferFunction() - { - } - - public static Vector EncodedFromDisplay(Vector x) - { - Vector sign = Vector.Create(0x80000000u).As(); - Vector originalSign = x & sign; - x = Vector.AndNot(sign, x); - Vector belowInverse12 = Vector.LessThan(x, Vector.Create(Inverse12)); - - Vector lo = Vector.SquareRoot(Vector.Create(3.0f) * x); - Vector hi = (Vector.Create(A * JxlMath.InverseLog2E) * Vector.Log2((Vector.Create(12f) * x) + Vector.Create(-B))) + Vector.Create(C); - Vector magnitude = Vector.ConditionalSelect(belowInverse12, lo, hi); - return Vector.AndNot(sign, magnitude) | originalSign; - } - - public static Vector DisplayFromEncoded(Vector x) - { - Vector sign = Vector.Create(0x80000000u).As(); - Vector originalSign = x & sign; - x = Vector.AndNot(sign, x); - Vector below05 = Vector.LessThan(x, Vector.Create(0.5f)); - - Vector lo = x * (x * Vector.Create(1f / 3f)); - Vector hi = (Pow2(x * Vector.Create(HiPow)) * Vector.Create(HiMul)) + Vector.Create(HiAdd); - Vector magnitude = Vector.ConditionalSelect(below05, lo, hi); - - return Vector.AndNot(sign, magnitude) | originalSign; - } - - private static Vector Pow2(Vector x) => x * x; -}