Browse Source

Add CFL

See chroma_from_luma.cc and chroma_from_luma.h
pull/3153/head
winscripter 1 month ago
parent
commit
abafaf8c03
  1. 2
      src/ImageSharp/Formats/Jxl/Processing/JxlAcStrategy.cs
  2. 46
      src/ImageSharp/Formats/Jxl/Processing/JxlChromaFromLuma.cs
  3. 113
      src/ImageSharp/Formats/Jxl/Processing/JxlColorCorrelation.cs
  4. 42
      src/ImageSharp/Formats/Jxl/Processing/JxlColorCorrelationMap.cs

2
src/ImageSharp/Formats/Jxl/Processing/JxlAcStrategy.cs

@ -4,7 +4,7 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static SixLabors.ImageSharp.Formats.Jxl.JxlFrameDimensions;
using static SixLabors.ImageSharp.Formats.Jxl.Processing.JxlFrameDimensions;
#pragma warning disable SA1405 // Debug.Assert should provide message text

46
src/ImageSharp/Formats/Jxl/Processing/JxlChromaFromLuma.cs

@ -0,0 +1,46 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Jxl.Fields;
using static SixLabors.ImageSharp.Formats.Jxl.Processing.JxlFrameDimensions;
namespace SixLabors.ImageSharp.Formats.Jxl.Processing;
/// <summary>
/// Shared constants for CFL (Chroma From Luma) functions.
/// </summary>
internal static class JxlChromaFromLuma
{
/// <summary>
/// Tiles are 64x64.
/// </summary>
public const int ColorTileDimension = 64;
/// <summary>
/// Division of the color tile dimension by the block dimension. Therefore,
/// this is 8x8.
/// </summary>
public const int ColorTileDimensionInBlocks = ColorTileDimension / BlockDimensions;
public const int DefaultColorFactor = 84;
/// <summary>
/// Chroma From Luma fixed point precision, which is
/// 11 bits.
/// </summary>
public const int CflFixedPointPrecision = 11;
/// <summary>
/// 524287
/// </summary>
public const int CflFixedPointRatioMax = (256 << CflFixedPointPrecision) - 1;
/// <summary>
/// Shared variable U32 distributions for the color factor.
/// </summary>
public static readonly JxlU32Enc ColorFactorDistribution = new(
JxlFieldExpressions.Value(DefaultColorFactor),
JxlFieldExpressions.Value(256),
JxlFieldExpressions.BitsOffset(8, 2),
JxlFieldExpressions.BitsOffset(16, 258));
}

113
src/ImageSharp/Formats/Jxl/Processing/JxlColorCorrelation.cs

@ -0,0 +1,113 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Jxl.Fields;
using SixLabors.ImageSharp.Formats.Jxl.Processing.Decoder;
namespace SixLabors.ImageSharp.Formats.Jxl.Processing;
internal sealed class JxlColorCorrelation
{
private float baseCorrelationX;
private float baseCorrelationB = DefaultYToBRatio;
private readonly float[] dcFactors = new float[4];
private uint colorFactor = JxlChromaFromLuma.DefaultColorFactor;
private float colorScale = 1.0f / JxlChromaFromLuma.DefaultColorFactor;
public int YToXDc { get; private set; }
public int YToBDc { get; private set; }
public float ColorFactor => this.colorFactor;
public float BaseCorrelationX
{
get => this.baseCorrelationX;
set => this.baseCorrelationX = value;
}
public float BaseCorrelationB
{
get => this.baseCorrelationB;
set => this.baseCorrelationB = value;
}
public bool IsJpegCompatible =>
this.BaseCorrelationX == 0 &&
this.BaseCorrelationB == 0 &&
this.YToBDc == 0 &&
this.YToXDc == 0 &&
this.ColorFactor == JxlChromaFromLuma.DefaultColorFactor;
public ReadOnlySpan<float> DcFactors => this.dcFactors;
public float YToXRatio(int xFactor) => this.BaseCorrelationX + (xFactor * this.colorScale);
public float YToBRatio(int bFactor) => this.BaseCorrelationB + (bFactor * this.colorScale);
public void SetColorFactor(uint factor)
{
this.colorFactor = factor;
this.colorScale = 1f / factor;
this.RecomputeDcFactors();
}
public void SetYToBDc(int yToBDc)
{
this.YToBDc = yToBDc;
this.RecomputeDcFactors();
}
public void SetYToXDc(int yToXDc)
{
this.YToXDc = yToXDc;
this.RecomputeDcFactors();
}
public void RecomputeDcFactors()
{
this.dcFactors[0] = this.YToXRatio(this.YToXDc);
this.dcFactors[2] = this.YToBRatio(this.YToBDc);
}
public bool DecodeDc(JxlBitReader reader)
{
bool allDefault = reader.ReadBoolean();
if (allDefault)
{
return true;
}
this.SetColorFactor(JxlU32Coder.Read(JxlChromaFromLuma.ColorFactorDistribution, reader));
if (!JxlF16Coder.Read(reader, ref this.baseCorrelationX))
{
return false;
}
if (MathF.Abs(this.baseCorrelationX) > 4f)
{
throw new InvalidOperationException("Base X correlation is out of range");
}
if (!JxlF16Coder.Read(reader, ref this.baseCorrelationB))
{
return false;
}
if (MathF.Abs(this.baseCorrelationB) > 4f)
{
throw new InvalidOperationException("Base B correlation is out of range");
}
this.YToXDc = (int)reader.ReadBits32(8) + sbyte.MinValue;
this.YToBDc = (int)reader.ReadBits32(8) + sbyte.MinValue;
this.RecomputeDcFactors();
return true;
}
public static int RatioJpeg(int factor) => factor * (1 << JxlChromaFromLuma.CflFixedPointPrecision) / JxlChromaFromLuma.DefaultColorFactor;
}

42
src/ImageSharp/Formats/Jxl/Processing/JxlColorCorrelationMap.cs

@ -0,0 +1,42 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Jxl.Memory.ImageTypes;
using SixLabors.ImageSharp.Formats.Jxl.Processing.Decoder;
namespace SixLabors.ImageSharp.Formats.Jxl.Processing;
/// <summary>
/// JPEG XL Color correlation map.
/// </summary>
internal sealed class JxlColorCorrelationMap
{
public JxlColorCorrelation Base { get; set; } = new();
public JxlImageSB? YToXMap { get; set; }
public JxlImageSB? YToBMap { get; set; }
public bool DecodeDc(JxlBitReader reader) => this.Base.DecodeDc(reader);
public static JxlColorCorrelationMap Create(Configuration configuration, int width, int height, bool xyb)
{
JxlColorCorrelationMap map = new();
(int xBlocks, int yBlocks) = (DivCeil(width, JxlChromaFromLuma.ColorTileDimension), DivCeil(height, JxlChromaFromLuma.ColorTileDimension));
map.YToXMap = new JxlImageSB(configuration, xBlocks, yBlocks);
map.YToBMap = new JxlImageSB(configuration, xBlocks, yBlocks);
ZeroFillImage(map.YToXMap);
ZeroFillImage(map.YToBMap);
if (!xyb)
{
map.Base.BaseCorrelationB = 0;
}
map.Base.RecomputeDcFactors();
return map;
}
}
Loading…
Cancel
Save