Browse Source

Skeleton code for pixel pipeline

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
4f4ace4231
  1. 11
      src/ImageSharp/Formats/Heif/Av1/Av1BitDepthExtensions.cs
  2. 10
      src/ImageSharp/Formats/Heif/Av1/Av1Constants.cs
  3. 2
      src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs
  4. 2
      src/ImageSharp/Formats/Heif/Av1/Av1FrameBuffer.cs
  5. 2
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuColorConfig.cs
  6. 8
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuPartitionInfo.cs
  7. 27
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
  8. 6
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs
  9. 155
      src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameDecoder.cs
  10. 8
      src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1LoopFilterContext.cs
  11. 68
      src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1LoopFilterDecoder.cs
  12. 146
      src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantification/Av1InverseQuantizer.cs
  13. 483
      src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantification/Av1QuantizationConstants.cs
  14. 33
      src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantification/DeQuant.cs
  15. 190
      src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantification/QuantizationLookup.cs
  16. 2
      src/ImageSharp/Formats/Heif/Av1/Readme.md
  17. 2
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs
  18. 192
      src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs
  19. 30
      src/ImageSharp/Formats/Heif/Av1/Transform/Av1FrameDecoder.cs
  20. 74
      src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseQuantizer.cs
  21. 2
      src/ImageSharp/Formats/Heif/Av1/Transform/Av1TransformSizeExtensions.cs
  22. 2
      tests/ImageSharp.Tests/Formats/Heif/Av1/ObuFrameHeaderTests.cs

11
src/ImageSharp/Formats/Heif/Av1/Av1BitDepthExtensions.cs

@ -0,0 +1,11 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
namespace SixLabors.ImageSharp.Formats.Heif.Av1;
internal static class Av1BitDepthExtensions
{
public static int GetBitCount(this Av1BitDepth bitDepth) => 8 + ((int)bitDepth << 1);
}

10
src/ImageSharp/Formats/Heif/Av1/Av1Constants.cs

@ -114,11 +114,6 @@ internal static class Av1Constants
/// </summary>
public const int MaxAngleDelta = 3;
/// <summary>
/// Number of segments allowed in segmentation map.
/// </summary>
public const int MaxSegments = 8;
/// <summary>
/// Maximum number of color planes.
/// </summary>
@ -173,4 +168,9 @@ internal static class Av1Constants
/// Log2 of number of values for ChromaFromLuma Alpha U and ChromaFromLuma Alpha V.
/// </summary>
public const int ChromaFromLumaAlphabetSizeLog2 = 4;
/// <summary>
/// Total number of Quantification Matrices sets stored.
/// </summary>
public const int QuantificationMatrixLevelCount = 4;
}

2
src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs

@ -2,8 +2,8 @@
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline;
using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
namespace SixLabors.ImageSharp.Formats.Heif.Av1;

2
src/ImageSharp/Formats/Heif/Av1/Av1FrameBuffer.cs

@ -23,7 +23,7 @@ internal class Av1FrameBuffer : IDisposable
Av1ColorFormat colorFormat = sequenceHeader.ColorConfig.IsMonochrome ? Av1ColorFormat.Yuv400 : maxColorFormat;
this.MaxWidth = sequenceHeader.MaxFrameWidth;
this.MaxHeight = sequenceHeader.MaxFrameHeight;
this.BitDepth = (Av1BitDepth)sequenceHeader.ColorConfig.BitDepth;
this.BitDepth = sequenceHeader.ColorConfig.BitDepth;
int bitsPerPixel = this.BitDepth > Av1BitDepth.EightBit || is16BitPipeline ? 2 : 1;
this.ColorFormat = colorFormat;
this.BufferEnableMask = sequenceHeader.ColorConfig.IsMonochrome ? PictureBufferLumaMask : PictureBufferFullMask;

2
src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuColorConfig.cs

@ -44,7 +44,7 @@ internal class ObuColorConfig
public ObuChromoSamplePosition ChromaSamplePosition { get; set; }
public int BitDepth { get; set; }
public Av1BitDepth BitDepth { get; set; }
public Av1ColorFormat GetColorFormat()
{

8
src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuPartitionInfo.cs

@ -1,8 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
internal class ObuPartitionInfo
{
}

27
src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline.Quantification;
using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
@ -78,7 +79,7 @@ internal class ObuReader
case ObuType.SequenceHeader:
this.SequenceHeader = new();
ReadSequenceHeader(ref reader, this.SequenceHeader);
if (this.SequenceHeader.ColorConfig.BitDepth == 12)
if (this.SequenceHeader.ColorConfig.BitDepth == Av1BitDepth.TwelveBit)
{
// TODO: Initialize 12 bit predictors
}
@ -503,7 +504,7 @@ internal class ObuReader
break;
case ObuSequenceProfile.Professional:
default:
if (colorConfig.BitDepth == 12)
if (colorConfig.BitDepth == Av1BitDepth.TwelveBit)
{
colorConfig.SubSamplingX = reader.ReadBoolean();
if (colorConfig.SubSamplingX)
@ -564,15 +565,15 @@ internal class ObuReader
bool hasHighBitDepth = reader.ReadBoolean();
if (sequenceHeader.SequenceProfile == ObuSequenceProfile.Professional && hasHighBitDepth)
{
colorConfig.BitDepth = reader.ReadBoolean() ? 12 : 10;
colorConfig.BitDepth = reader.ReadBoolean() ? Av1BitDepth.TwelveBit : Av1BitDepth.TenBit;
}
else if (sequenceHeader.SequenceProfile <= ObuSequenceProfile.Professional)
{
colorConfig.BitDepth = hasHighBitDepth ? 10 : 8;
colorConfig.BitDepth = hasHighBitDepth ? Av1BitDepth.TenBit : Av1BitDepth.EightBit;
}
else
{
colorConfig.BitDepth = 8;
colorConfig.BitDepth = Av1BitDepth.EightBit;
}
}
@ -1091,7 +1092,7 @@ internal class ObuReader
frameHeader.SegmentationParameters.QMLevel[2] = new int[Av1Constants.MaxSegmentCount];
for (int segmentId = 0; segmentId < Av1Constants.MaxSegmentCount; segmentId++)
{
int qIndex = GetQIndex(frameHeader.SegmentationParameters, segmentId, frameHeader.QuantizationParameters.BaseQIndex);
int qIndex = QuantizationLookup.GetQIndex(frameHeader.SegmentationParameters, segmentId, frameHeader.QuantizationParameters.BaseQIndex);
frameHeader.QuantizationParameters.QIndex[segmentId] = qIndex;
frameHeader.LosslessArray[segmentId] = qIndex == 0 &&
frameHeader.QuantizationParameters.DeltaQDc[(int)Av1Plane.Y] == 0 &&
@ -1151,20 +1152,6 @@ internal class ObuReader
private static bool IsSegmentationFeatureActive(ObuSegmentationParameters segmentationParameters, int segmentId, ObuSegmentationLevelFeature feature)
=> segmentationParameters.Enabled && segmentationParameters.IsFeatureActive(segmentId, feature);
private static int GetQIndex(ObuSegmentationParameters segmentationParameters, int segmentId, int baseQIndex)
{
if (IsSegmentationFeatureActive(segmentationParameters, segmentId, ObuSegmentationLevelFeature.AlternativeQuantizer))
{
int data = segmentationParameters.FeatureData[segmentId, (int)ObuSegmentationLevelFeature.AlternativeQuantizer];
int qIndex = baseQIndex + data;
return Av1Math.Clamp(qIndex, 0, Av1Constants.MaxQ);
}
else
{
return baseQIndex;
}
}
/// <summary>
/// 5.9.1. General frame header OBU syntax.
/// </summary>

6
src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs

@ -164,7 +164,7 @@ internal class ObuWriter
else
{
writer.WriteBoolean(colorConfig.ColorRange);
if (sequenceHeader.SequenceProfile == ObuSequenceProfile.Professional && colorConfig.BitDepth == 12)
if (sequenceHeader.SequenceProfile == ObuSequenceProfile.Professional && colorConfig.BitDepth == Av1BitDepth.TwelveBit)
{
writer.WriteBoolean(colorConfig.SubSamplingX);
if (colorConfig.SubSamplingX)
@ -184,11 +184,11 @@ internal class ObuWriter
private static void WriteBitDepth(ref Av1BitStreamWriter writer, ObuColorConfig colorConfig, ObuSequenceHeader sequenceHeader)
{
bool hasHighBitDepth = colorConfig.BitDepth > 8;
bool hasHighBitDepth = colorConfig.BitDepth > Av1BitDepth.EightBit;
writer.WriteBoolean(hasHighBitDepth);
if (sequenceHeader.SequenceProfile == ObuSequenceProfile.Professional && hasHighBitDepth)
{
writer.WriteBoolean(colorConfig.BitDepth == 12);
writer.WriteBoolean(colorConfig.BitDepth == Av1BitDepth.TwelveBit);
}
}

155
src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameDecoder.cs

@ -0,0 +1,155 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline.Quantification;
using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline;
internal class Av1FrameDecoder
{
private readonly ObuSequenceHeader sequenceHeader;
private readonly ObuFrameHeader frameHeader;
private readonly Av1FrameInfo frameInfo;
private readonly Av1InverseQuantizer inverseQuantizer;
private readonly DeQuant deQuants;
public Av1FrameDecoder(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, Av1FrameInfo frameInfo)
{
this.sequenceHeader = sequenceHeader;
this.frameHeader = frameHeader;
this.frameInfo = frameInfo;
this.inverseQuantizer = new(sequenceHeader, frameHeader);
this.deQuants = new();
}
public void DecodeFrame()
{
for (int column = 0; column < this.frameHeader.TilesInfo.TileColumnCount; column++)
{
this.DecodeFrameTiles(column);
}
bool doLoopFilterFlag = false;
bool doLoopRestoration = false;
bool doUpscale = false;
this.DecodeLoopFilterForFrame(doLoopFilterFlag);
if (doLoopRestoration)
{
// LoopRestorationSaveBoundaryLines(false);
}
// DecodeCdef();
// SuperResolutionUpscaling(doUpscale);
if (doLoopRestoration && doUpscale)
{
// LoopRestorationSaveBoundaryLines(true);
}
// DecodeLoopRestoration(doLoopRestoration);
// PadPicture();
}
private void DecodeFrameTiles(int tileColumn)
{
int tileRowCount = this.frameHeader.TilesInfo.TileRowCount;
int tileCount = tileRowCount * this.frameHeader.TilesInfo.TileColumnCount;
for (int row = 0; row < tileRowCount; row++)
{
int superblockRowTileStart = this.frameHeader.TilesInfo.TileRowStartModeInfo[row] << Av1Constants.ModeInfoSizeLog2 >>
this.sequenceHeader.SuperblockSizeLog2;
int superblockRow = row + superblockRowTileStart;
int modeInfoRow = superblockRow << this.sequenceHeader.SuperblockSizeLog2 >> Av1Constants.ModeInfoSizeLog2;
// EbColorConfig* color_config = &dec_mod_ctxt->seq_header->color_config;
// svt_cfl_init(&dec_mod_ctxt->cfl_ctx, color_config);
this.DecodeTileRow(row, tileColumn, modeInfoRow, superblockRow);
}
}
private void DecodeTileRow(int tileRow, int tileColumn, int modeInfoRow, int superblockRow)
{
int superblockModeInfoSizeLog2 = this.sequenceHeader.SuperblockSizeLog2 - Av1Constants.ModeInfoSizeLog2;
int superblockRowTileStart = this.frameHeader.TilesInfo.TileRowStartModeInfo[tileRow] << Av1Constants.ModeInfoSizeLog2 >>
this.sequenceHeader.SuperblockSizeLog2;
int superblockRowInTile = superblockRow - superblockRowTileStart;
ObuTileGroupHeader tileInfo = this.frameHeader.TilesInfo;
for (int modeInfoColumn = tileInfo.TileColumnStartModeInfo[tileColumn]; modeInfoColumn < tileInfo.TileColumnStartModeInfo[tileColumn + 1];
modeInfoColumn += this.sequenceHeader.SuperblockModeInfoSize)
{
int superblockColumn = modeInfoColumn << Av1Constants.ModeInfoSizeLog2 >> this.sequenceHeader.SuperblockSizeLog2;
Av1SuperblockInfo superblockInfo = this.frameInfo.GetSuperblock(new Point(superblockColumn, superblockRow));
Point modeInfoPosition = new Point(modeInfoColumn, modeInfoRow);
this.DecodeSuperblock(modeInfoPosition, superblockInfo);
}
}
private void DecodeSuperblock(Point modeInfoPosition, Av1SuperblockInfo superblockInfo)
{
this.inverseQuantizer.UpdateDequant(this.deQuants, superblockInfo);
DecodePartition(modeInfoPosition, superblockInfo);
}
private static void DecodePartition(Point modeInfoPosition, Av1SuperblockInfo superblockInfo)
{
Av1BlockModeInfo modeInfo = superblockInfo.GetModeInfo(modeInfoPosition);
for (int i = 0; i < superblockInfo.BlockCount; i++)
{
Point subPosition = modeInfo.PositionInSuperblock;
Av1BlockSize subSize = modeInfo.BlockSize;
Point globalPosition = new(modeInfoPosition.X, modeInfoPosition.Y);
globalPosition.Offset(subPosition);
Av1BlockDecoder.DecodeBlock(modeInfo, globalPosition, subSize, superblockInfo);
}
}
private void DecodeLoopFilterForFrame(bool doLoopFilterFlag)
{
if (!doLoopFilterFlag)
{
return;
}
int superblockSizeLog2 = this.sequenceHeader.SuperblockSizeLog2;
int pictureWidthInSuperblocks = Av1Math.DivideLog2Ceiling(this.frameHeader.FrameSize.FrameWidth, this.sequenceHeader.SuperblockSizeLog2);
int pictureHeightInSuperblocks = Av1Math.DivideLog2Ceiling(this.frameHeader.FrameSize.FrameHeight, this.sequenceHeader.SuperblockSizeLog2);
// Loop over a frame : tregger dec_loop_filter_sb for each SB
for (int superblockIndexY = 0; superblockIndexY < pictureHeightInSuperblocks; ++superblockIndexY)
{
for (int superblockIndexX = 0; superblockIndexX < pictureWidthInSuperblocks; ++superblockIndexX)
{
int superblockOriginX = superblockIndexX << superblockSizeLog2;
int superblockOriginY = superblockIndexY << superblockSizeLog2;
bool endOfRowFlag = superblockIndexX == pictureWidthInSuperblocks - 1;
Point superblockPoint = new(superblockOriginX, superblockOriginY);
Av1SuperblockInfo superblockInfo = this.frameInfo.GetSuperblock(superblockPoint);
// LF function for a SB
/*
DecodeLoopFilterForSuperblock(
superblockInfo,
this.frameHeader,
this.sequenceHeader,
reconstructionFrameBuffer,
loopFilterContext,
superblockOriginY >> 2,
superblockOriginX >> 2,
Av1Plane.Y,
3,
endOfRowFlag,
superblockInfo.SuperblockDeltaLoopFilter);
*/
}
}
}
}

8
src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1LoopFilterContext.cs

@ -0,0 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline.LoopFilter;
internal class Av1LoopFilterContext
{
}

68
src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1LoopFilterDecoder.cs

@ -0,0 +1,68 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline.LoopFilter;
internal class Av1LoopFilterDecoder
{
private readonly ObuSequenceHeader sequenceHeader;
private readonly ObuFrameHeader frameHeader;
private readonly Av1FrameInfo frameInfo;
private readonly Av1FrameBuffer frameBuffer;
private readonly Av1LoopFilterContext loopFilterContext;
public Av1LoopFilterDecoder(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, Av1FrameInfo frameInfo, Av1FrameBuffer frameBuffer)
{
this.sequenceHeader = sequenceHeader;
this.frameHeader = frameHeader;
this.frameInfo = frameInfo;
this.frameBuffer = frameBuffer;
this.loopFilterContext = new();
}
public void DecodeFrame(bool doLoopFilterFlag)
{
Guard.NotNull(this.sequenceHeader);
Guard.NotNull(this.frameHeader);
Guard.NotNull(this.frameInfo);
if (!doLoopFilterFlag)
{
return;
}
int superblockSizeLog2 = this.sequenceHeader.SuperblockSizeLog2;
int frameWidthInSuperblocks = Av1Math.DivideLog2Ceiling(this.frameHeader.FrameSize.FrameWidth, this.sequenceHeader.SuperblockSizeLog2);
int frameHeightInSuperblocks = Av1Math.DivideLog2Ceiling(this.frameHeader.FrameSize.FrameHeight, this.sequenceHeader.SuperblockSizeLog2);
// Loop over a frame : tregger dec_loop_filter_sb for each SB
for (int superblockIndexY = 0; superblockIndexY < frameHeightInSuperblocks; ++superblockIndexY)
{
for (int superblockIndexX = 0; superblockIndexX < frameWidthInSuperblocks; ++superblockIndexX)
{
int superblockOriginX = superblockIndexX << superblockSizeLog2;
int superblockOriginY = superblockIndexY << superblockSizeLog2;
bool endOfRowFlag = superblockIndexX == frameWidthInSuperblocks - 1;
Point superblockPoint = new(superblockOriginX, superblockOriginY);
Av1SuperblockInfo superblockInfo = this.frameInfo.GetSuperblock(superblockPoint);
Point superblockOriginInModeInfo = new(superblockOriginX >> 2, superblockOriginY >> 2);
// LF function for a SB
this.DecodeForSuperblock(
superblockInfo,
superblockOriginInModeInfo,
Av1Plane.Y,
3,
endOfRowFlag,
superblockInfo.SuperblockDeltaLoopFilter);
}
}
}
private void DecodeForSuperblock(Av1SuperblockInfo superblockInfo, Point modeInfoLocation, Av1Plane startPlane, int endPlane, bool endOfRowFlag, Span<int> superblockDeltaLoopFilter)
=> throw new NotImplementedException();
}

146
src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantification/Av1InverseQuantizer.cs

@ -0,0 +1,146 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline.Quantification;
internal class Av1InverseQuantizer
{
private const int QuatizationMatrixTotalSize = 3344;
private readonly ObuSequenceHeader sequenceHeader;
private readonly ObuFrameHeader frameHeader;
private readonly int[][][] inverseQuantizationMatrix;
private DeQuant? deQuantsDeltaQ;
public Av1InverseQuantizer(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{
this.sequenceHeader = sequenceHeader;
this.frameHeader = frameHeader;
this.inverseQuantizationMatrix = new int[Av1Constants.QuantificationMatrixLevelCount][][];
for (int q = 0; q < Av1Constants.QuantificationMatrixLevelCount; ++q)
{
this.inverseQuantizationMatrix[q] = new int[Av1Constants.MaxPlanes][];
for (int c = 0; c < Av1Constants.MaxPlanes; c++)
{
int lumaOrChroma = Math.Min(1, c);
int current = 0;
this.inverseQuantizationMatrix[q][c] = new int[(int)Av1TransformSize.AllSizes];
for (Av1TransformSize t = 0; t < Av1TransformSize.AllSizes; ++t)
{
int size = t.GetSize2d();
Av1TransformSize qmTransformSize = t.GetAdjusted();
if (q == Av1Constants.QuantificationMatrixLevelCount - 1)
{
this.inverseQuantizationMatrix[q][c][(int)t] = -1;
}
else if (t != qmTransformSize)
{
// Reuse matrices for 'qm_tx_size'
this.inverseQuantizationMatrix[q][c][(int)t] = this.inverseQuantizationMatrix[q][c][(int)qmTransformSize];
}
else
{
Guard.MustBeLessThanOrEqualTo(current + size, QuatizationMatrixTotalSize, nameof(current));
this.inverseQuantizationMatrix[q][c][(int)t] = Av1QuantizationConstants.InverseWT[q][lumaOrChroma][current];
current += size;
}
}
}
}
}
public void UpdateDequant(DeQuant deQuants, Av1SuperblockInfo superblockInfo)
{
Av1BitDepth bitDepth = this.sequenceHeader.ColorConfig.BitDepth;
Guard.NotNull(deQuants, nameof(deQuants));
this.deQuantsDeltaQ = deQuants;
if (this.frameHeader.DeltaQParameters.IsPresent)
{
for (int i = 0; i < Av1Constants.MaxSegmentCount; i++)
{
int currentQIndex = QuantizationLookup.GetQIndex(this.frameHeader.SegmentationParameters, i, superblockInfo.SuperblockDeltaQ);
for (Av1Plane plane = 0; (int)plane < Av1Constants.MaxPlanes; plane++)
{
int dcDeltaQ = this.frameHeader.QuantizationParameters.DeltaQDc[(int)plane];
int acDeltaQ = this.frameHeader.QuantizationParameters.DeltaQAc[(int)plane];
this.deQuantsDeltaQ.SetDc(i, plane, QuantizationLookup.GetDcQuant(currentQIndex, dcDeltaQ, bitDepth));
this.deQuantsDeltaQ.SetAc(i, plane, QuantizationLookup.GetAcQuant(currentQIndex, acDeltaQ, bitDepth));
}
}
}
}
public int InverseQuantize(Av1BlockModeInfo mode, Span<int> level, Span<int> qCoefficients, Av1TransformType transformType, Av1TransformSize transformSize, Av1Plane plane)
{
Guard.NotNull(this.deQuantsDeltaQ);
Av1ScanOrder scanOrder = Av1ScanOrderConstants.GetScanOrder(transformSize, transformType);
short[] scanIndices = scanOrder.Scan;
int maxValue = (1 << (7 + this.sequenceHeader.ColorConfig.BitDepth.GetBitCount())) - 1;
int minValue = -(1 << (7 + this.sequenceHeader.ColorConfig.BitDepth.GetBitCount()));
Av1TransformSize qmTransformSize = transformSize.GetAdjusted();
bool usingQuantizationMatrix = this.frameHeader.QuantizationParameters.IsUsingQMatrix;
bool lossless = this.frameHeader.LosslessArray[mode.SegmentId];
short dequantDc = this.deQuantsDeltaQ.GetDc(mode.SegmentId, plane);
short dequantAc = this.deQuantsDeltaQ.GetAc(mode.SegmentId, plane);
int qmLevel = lossless || !usingQuantizationMatrix ? Av1ScanOrderConstants.QuantizationMatrixLevelCount - 1 : this.frameHeader.QuantizationParameters.QMatrix[(int)plane];
ref int iqMatrix = ref (transformType.ToClass() == Av1TransformClass.Class2D) ?
ref this.inverseQuantizationMatrix[qmLevel][(int)plane][(int)qmTransformSize]
: ref this.inverseQuantizationMatrix[Av1Constants.QuantificationMatrixLevelCount - 1][0][(int)qmTransformSize];
int shift = transformSize.GetScale();
int coefficientCount = level[0];
level = level[1..];
int lev = level[0];
int qCoefficient;
if (lev != 0)
{
int pos = scanIndices[0];
qCoefficient = (int)(((long)Math.Abs(lev) * GetDeQuantizedValue(dequantDc, pos, ref iqMatrix)) & 0xffffff);
qCoefficient >>= shift;
if (lev < 0)
{
qCoefficient = -qCoefficient;
}
qCoefficients[0] = Av1Math.Clamp(qCoefficient, minValue, maxValue);
}
for (int i = 1; i < coefficientCount; i++)
{
lev = level[i];
if (lev != 0)
{
int pos = scanIndices[i];
qCoefficient = (int)(((long)Math.Abs(lev) * GetDeQuantizedValue(dequantAc, pos, ref iqMatrix)) & 0xffffff);
qCoefficient >>= shift;
if (lev < 0)
{
qCoefficient = -qCoefficient;
}
qCoefficients[pos] = Av1Math.Clamp(qCoefficient, minValue, maxValue);
}
}
return coefficientCount;
}
private static int GetDeQuantizedValue(short dequant, int coefficientIndex, ref int iqMatrix)
{
int deQuantifiedValue = dequant;
// TODO: Check order of operators
deQuantifiedValue = ((Unsafe.Add(ref iqMatrix, coefficientIndex) * deQuantifiedValue) + (1 << (Av1ScanOrderConstants.QuantizationMatrixLevelBitCount - 1))) >> Av1ScanOrderConstants.QuantizationMatrixLevelBitCount;
return deQuantifiedValue;
}
}

483
src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantification/Av1QuantizationConstants.cs

@ -0,0 +1,483 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline.Quantification;
internal class Av1QuantizationConstants
{
public static int[][][] InverseWT =>
[
[
// Luma
[
// Size 4x4
32, 43, 73, 97, 43, 67, 94, 110, 73, 94, 137, 150, 97, 110, 150, 200,
// Size 8x8
32, 32, 38, 51, 68, 84, 95, 109, 32, 35, 40, 49, 63, 76, 89, 102, 38,
40, 54, 65, 78, 91, 98, 106, 51, 49, 65, 82, 97, 111, 113, 121, 68, 63,
78, 97, 117, 134, 138, 142, 84, 76, 91, 111, 134, 152, 159, 168, 95, 89,
98, 113, 138, 159, 183, 199, 109, 102, 106, 121, 142, 168, 199, 220,
// Size 16x16
32, 31, 31, 34, 36, 44, 48, 59, 65, 80, 83, 91, 97, 104, 111, 119, 31,
32, 32, 33, 34, 41, 44, 54, 59, 72, 75, 83, 90, 97, 104, 112, 31, 32,
33, 35, 36, 42, 45, 54, 59, 71, 74, 81, 86, 93, 100, 107, 34, 33, 35,
39, 42, 47, 51, 58, 63, 74, 76, 81, 84, 90, 97, 105, 36, 34, 36, 42, 48,
54, 57, 64, 68, 79, 81, 88, 91, 96, 102, 105, 44, 41, 42, 47, 54, 63,
67, 75, 79, 90, 92, 95, 100, 102, 109, 112, 48, 44, 45, 51, 57, 67, 71,
80, 85, 96, 99, 107, 108, 111, 117, 120, 59, 54, 54, 58, 64, 75, 80, 92,
98, 110, 113, 115, 116, 122, 125, 130, 65, 59, 59, 63, 68, 79, 85, 98,
105, 118, 121, 127, 130, 134, 135, 140, 80, 72, 71, 74, 79, 90, 96, 110,
118, 134, 137, 140, 143, 144, 146, 152, 83, 75, 74, 76, 81, 92, 99, 113,
121, 137, 140, 151, 152, 155, 158, 165, 91, 83, 81, 81, 88, 95, 107,
115, 127, 140, 151, 159, 166, 169, 173, 179, 97, 90, 86, 84, 91, 100,
108, 116, 130, 143, 152, 166, 174, 182, 189, 193, 104, 97, 93, 90, 96,
102, 111, 122, 134, 144, 155, 169, 182, 191, 200, 210, 111, 104, 100,
97, 102, 109, 117, 125, 135, 146, 158, 173, 189, 200, 210, 220, 119,
112, 107, 105, 105, 112, 120, 130, 140, 152, 165, 179, 193, 210, 220,
231,
// Size 32x32
32, 31, 31, 31, 31, 32, 34, 35, 36, 39, 44, 46, 48, 54, 59, 62, 65, 71,
80, 81, 83, 88, 91, 94, 97, 101, 104, 107, 111, 115, 119, 123, 31, 32,
32, 32, 32, 32, 34, 34, 35, 38, 42, 44, 46, 51, 56, 59, 62, 68, 76, 77,
78, 84, 86, 89, 92, 95, 99, 102, 105, 109, 113, 116, 31, 32, 32, 32, 32,
32, 33, 34, 34, 37, 41, 42, 44, 49, 54, 56, 59, 65, 72, 73, 75, 80, 83,
86, 90, 93, 97, 101, 104, 108, 112, 116, 31, 32, 32, 32, 33, 33, 34, 35,
35, 38, 41, 43, 45, 49, 54, 56, 59, 64, 72, 73, 74, 79, 82, 85, 88, 91,
94, 97, 101, 104, 107, 111, 31, 32, 32, 33, 33, 34, 35, 36, 36, 39, 42,
44, 45, 50, 54, 56, 59, 64, 71, 72, 74, 78, 81, 84, 86, 89, 93, 96, 100,
104, 107, 111, 32, 32, 32, 33, 34, 35, 37, 37, 38, 40, 42, 44, 46, 49,
53, 55, 58, 63, 69, 70, 72, 76, 79, 82, 85, 89, 93, 96, 99, 102, 106,
109, 34, 34, 33, 34, 35, 37, 39, 41, 42, 45, 47, 49, 51, 54, 58, 60, 63,
68, 74, 75, 76, 80, 81, 82, 84, 87, 90, 93, 97, 101, 105, 110, 35, 34,
34, 35, 36, 37, 41, 43, 45, 47, 50, 52, 53, 57, 61, 63, 65, 70, 76, 77,
79, 82, 84, 86, 89, 91, 92, 93, 96, 100, 103, 107, 36, 35, 34, 35, 36,
38, 42, 45, 48, 50, 54, 55, 57, 60, 64, 66, 68, 73, 79, 80, 81, 85, 88,
90, 91, 93, 96, 99, 102, 103, 105, 107, 39, 38, 37, 38, 39, 40, 45, 47,
50, 54, 58, 59, 61, 65, 69, 71, 73, 78, 84, 85, 86, 91, 92, 92, 95, 98,
100, 101, 103, 106, 110, 114, 44, 42, 41, 41, 42, 42, 47, 50, 54, 58,
63, 65, 67, 71, 75, 77, 79, 84, 90, 91, 92, 95, 95, 97, 100, 101, 102,
105, 109, 111, 112, 114, 46, 44, 42, 43, 44, 44, 49, 52, 55, 59, 65, 67,
69, 74, 78, 80, 82, 87, 93, 94, 95, 98, 100, 103, 102, 105, 108, 110,
111, 113, 117, 121, 48, 46, 44, 45, 45, 46, 51, 53, 57, 61, 67, 69, 71,
76, 80, 83, 85, 90, 96, 97, 99, 103, 107, 105, 108, 111, 111, 113, 117,
119, 120, 122, 54, 51, 49, 49, 50, 49, 54, 57, 60, 65, 71, 74, 76, 82,
87, 89, 92, 97, 104, 105, 106, 111, 110, 111, 114, 113, 116, 120, 120,
121, 125, 130, 59, 56, 54, 54, 54, 53, 58, 61, 64, 69, 75, 78, 80, 87,
92, 95, 98, 103, 110, 111, 113, 115, 115, 119, 116, 120, 122, 122, 125,
129, 130, 130, 62, 59, 56, 56, 56, 55, 60, 63, 66, 71, 77, 80, 83, 89,
95, 98, 101, 107, 114, 115, 117, 119, 123, 121, 125, 126, 125, 129, 131,
131, 135, 140, 65, 62, 59, 59, 59, 58, 63, 65, 68, 73, 79, 82, 85, 92,
98, 101, 105, 111, 118, 119, 121, 126, 127, 128, 130, 130, 134, 133,
135, 140, 140, 140, 71, 68, 65, 64, 64, 63, 68, 70, 73, 78, 84, 87, 90,
97, 103, 107, 111, 117, 125, 126, 128, 134, 132, 136, 133, 138, 137,
140, 143, 142, 145, 150, 80, 76, 72, 72, 71, 69, 74, 76, 79, 84, 90, 93,
96, 104, 110, 114, 118, 125, 134, 135, 137, 139, 140, 139, 143, 142,
144, 146, 146, 151, 152, 151, 81, 77, 73, 73, 72, 70, 75, 77, 80, 85,
91, 94, 97, 105, 111, 115, 119, 126, 135, 137, 138, 144, 147, 146, 148,
149, 151, 150, 156, 155, 157, 163, 83, 78, 75, 74, 74, 72, 76, 79, 81,
86, 92, 95, 99, 106, 113, 117, 121, 128, 137, 138, 140, 147, 151, 156,
152, 157, 155, 161, 158, 162, 165, 164, 88, 84, 80, 79, 78, 76, 80, 82,
85, 91, 95, 98, 103, 111, 115, 119, 126, 134, 139, 144, 147, 152, 154,
158, 163, 159, 165, 163, 168, 168, 169, 176, 91, 86, 83, 82, 81, 79, 81,
84, 88, 92, 95, 100, 107, 110, 115, 123, 127, 132, 140, 147, 151, 154,
159, 161, 166, 171, 169, 173, 173, 176, 179, 177, 94, 89, 86, 85, 84,
82, 82, 86, 90, 92, 97, 103, 105, 111, 119, 121, 128, 136, 139, 146,
156, 158, 161, 166, 168, 174, 179, 178, 180, 183, 183, 190, 97, 92, 90,
88, 86, 85, 84, 89, 91, 95, 100, 102, 108, 114, 116, 125, 130, 133, 143,
148, 152, 163, 166, 168, 174, 176, 182, 187, 189, 188, 193, 191, 101,
95, 93, 91, 89, 89, 87, 91, 93, 98, 101, 105, 111, 113, 120, 126, 130,
138, 142, 149, 157, 159, 171, 174, 176, 183, 184, 191, 195, 199, 197,
204, 104, 99, 97, 94, 93, 93, 90, 92, 96, 100, 102, 108, 111, 116, 122,
125, 134, 137, 144, 151, 155, 165, 169, 179, 182, 184, 191, 193, 200,
204, 210, 206, 107, 102, 101, 97, 96, 96, 93, 93, 99, 101, 105, 110,
113, 120, 122, 129, 133, 140, 146, 150, 161, 163, 173, 178, 187, 191,
193, 200, 202, 210, 214, 222, 111, 105, 104, 101, 100, 99, 97, 96, 102,
103, 109, 111, 117, 120, 125, 131, 135, 143, 146, 156, 158, 168, 173,
180, 189, 195, 200, 202, 210, 212, 220, 224, 115, 109, 108, 104, 104,
102, 101, 100, 103, 106, 111, 113, 119, 121, 129, 131, 140, 142, 151,
155, 162, 168, 176, 183, 188, 199, 204, 210, 212, 220, 222, 230, 119,
113, 112, 107, 107, 106, 105, 103, 105, 110, 112, 117, 120, 125, 130,
135, 140, 145, 152, 157, 165, 169, 179, 183, 193, 197, 210, 214, 220,
222, 231, 232, 123, 116, 116, 111, 111, 109, 110, 107, 107, 114, 114,
121, 122, 130, 130, 140, 140, 150, 151, 163, 164, 176, 177, 190, 191,
204, 206, 222, 224, 230, 232, 242,
// Size 4x8
32, 42, 75, 91, 33, 42, 69, 86, 37, 58, 84, 91, 49, 71, 103, 110, 65,
84, 125, 128, 80, 97, 142, 152, 91, 100, 145, 178, 104, 112, 146, 190,
// Size 8x4
32, 33, 37, 49, 65, 80, 91, 104, 42, 42, 58, 71, 84, 97, 100, 112, 75,
69, 84, 103, 125, 142, 145, 146, 91, 86, 91, 110, 128, 152, 178, 190,
// Size 8x16
32, 32, 36, 53, 65, 87, 93, 99, 31, 33, 34, 49, 59, 78, 86, 93, 32, 34,
36, 50, 59, 77, 82, 89, 34, 37, 42, 54, 63, 79, 80, 88, 36, 38, 48, 60,
68, 84, 86, 90, 44, 43, 53, 71, 79, 95, 94, 97, 48, 46, 56, 76, 85, 102,
105, 105, 58, 54, 63, 87, 98, 116, 112, 115, 65, 58, 68, 92, 105, 124,
122, 124, 79, 70, 79, 104, 118, 141, 135, 135, 82, 72, 81, 106, 121,
144, 149, 146, 91, 80, 88, 106, 130, 148, 162, 159, 97, 86, 94, 107,
128, 157, 167, 171, 103, 93, 98, 114, 131, 150, 174, 186, 110, 100, 101,
117, 138, 161, 183, 193, 118, 107, 105, 118, 136, 157, 182, 203,
// Size 16x8
32, 31, 32, 34, 36, 44, 48, 58, 65, 79, 82, 91, 97, 103, 110, 118, 32,
33, 34, 37, 38, 43, 46, 54, 58, 70, 72, 80, 86, 93, 100, 107, 36, 34,
36, 42, 48, 53, 56, 63, 68, 79, 81, 88, 94, 98, 101, 105, 53, 49, 50,
54, 60, 71, 76, 87, 92, 104, 106, 106, 107, 114, 117, 118, 65, 59, 59,
63, 68, 79, 85, 98, 105, 118, 121, 130, 128, 131, 138, 136, 87, 78, 77,
79, 84, 95, 102, 116, 124, 141, 144, 148, 157, 150, 161, 157, 93, 86,
82, 80, 86, 94, 105, 112, 122, 135, 149, 162, 167, 174, 183, 182, 99,
93, 89, 88, 90, 97, 105, 115, 124, 135, 146, 159, 171, 186, 193, 203,
// Size 16x32
32, 31, 32, 34, 36, 44, 53, 59, 65, 79, 87, 90, 93, 96, 99, 102, 31, 32,
32, 34, 35, 42, 51, 56, 62, 75, 82, 85, 88, 91, 94, 97, 31, 32, 33, 33,
34, 41, 49, 54, 59, 72, 78, 82, 86, 90, 93, 97, 31, 32, 33, 34, 35, 41,
49, 54, 59, 71, 78, 81, 84, 87, 90, 93, 32, 32, 34, 35, 36, 42, 50, 54,
59, 71, 77, 80, 82, 86, 89, 93, 32, 33, 35, 37, 38, 42, 49, 53, 58, 69,
75, 78, 82, 86, 89, 92, 34, 34, 37, 39, 42, 48, 54, 58, 63, 73, 79, 78,
80, 83, 88, 92, 35, 34, 37, 41, 45, 50, 57, 61, 65, 76, 82, 83, 84, 84,
87, 90, 36, 34, 38, 43, 48, 54, 60, 64, 68, 78, 84, 87, 86, 89, 90, 90,
39, 37, 40, 45, 50, 58, 65, 69, 73, 84, 89, 89, 91, 91, 93, 96, 44, 41,
43, 48, 53, 63, 71, 75, 79, 90, 95, 93, 94, 95, 97, 97, 46, 43, 44, 49,
55, 65, 73, 78, 82, 93, 98, 100, 98, 100, 99, 103, 48, 45, 46, 51, 56,
67, 76, 80, 85, 96, 102, 102, 105, 102, 105, 104, 53, 49, 50, 54, 60,
71, 82, 87, 92, 103, 109, 107, 107, 110, 107, 111, 58, 54, 54, 58, 63,
75, 87, 92, 98, 110, 116, 115, 112, 111, 115, 112, 61, 57, 56, 60, 66,
77, 89, 95, 101, 114, 120, 118, 119, 118, 116, 120, 65, 60, 58, 63, 68,
79, 92, 98, 105, 118, 124, 123, 122, 123, 124, 121, 71, 65, 63, 68, 73,
84, 97, 103, 111, 125, 132, 132, 130, 128, 127, 130, 79, 72, 70, 74, 79,
90, 104, 110, 118, 133, 141, 136, 135, 135, 135, 131, 81, 74, 71, 75,
80, 91, 105, 112, 119, 135, 142, 140, 140, 138, 139, 142, 82, 75, 72,
76, 81, 92, 106, 113, 121, 136, 144, 151, 149, 149, 146, 143, 88, 80,
77, 80, 85, 97, 108, 115, 126, 142, 149, 153, 153, 152, 152, 154, 91,
83, 80, 81, 88, 100, 106, 114, 130, 142, 148, 155, 162, 160, 159, 155,
94, 85, 83, 82, 91, 100, 105, 118, 131, 137, 153, 160, 165, 167, 166,
168, 97, 88, 86, 85, 94, 100, 107, 123, 128, 140, 157, 161, 167, 173,
171, 169, 100, 91, 89, 87, 97, 100, 111, 121, 127, 145, 152, 164, 173,
178, 182, 181, 103, 94, 93, 90, 98, 101, 114, 120, 131, 144, 150, 170,
174, 180, 186, 183, 107, 97, 96, 93, 100, 104, 117, 119, 136, 142, 155,
168, 177, 187, 191, 198, 110, 101, 100, 97, 101, 108, 117, 123, 138,
141, 161, 165, 183, 188, 193, 200, 114, 104, 104, 100, 103, 112, 117,
127, 137, 146, 159, 167, 185, 190, 201, 206, 118, 108, 107, 103, 105,
115, 118, 131, 136, 151, 157, 172, 182, 197, 203, 208, 122, 111, 111,
107, 107, 119, 119, 136, 136, 156, 156, 178, 179, 203, 204, 217,
// Size 32x16
32, 31, 31, 31, 32, 32, 34, 35, 36, 39, 44, 46, 48, 53, 58, 61, 65, 71,
79, 81, 82, 88, 91, 94, 97, 100, 103, 107, 110, 114, 118, 122, 31, 32,
32, 32, 32, 33, 34, 34, 34, 37, 41, 43, 45, 49, 54, 57, 60, 65, 72, 74,
75, 80, 83, 85, 88, 91, 94, 97, 101, 104, 108, 111, 32, 32, 33, 33, 34,
35, 37, 37, 38, 40, 43, 44, 46, 50, 54, 56, 58, 63, 70, 71, 72, 77, 80,
83, 86, 89, 93, 96, 100, 104, 107, 111, 34, 34, 33, 34, 35, 37, 39, 41,
43, 45, 48, 49, 51, 54, 58, 60, 63, 68, 74, 75, 76, 80, 81, 82, 85, 87,
90, 93, 97, 100, 103, 107, 36, 35, 34, 35, 36, 38, 42, 45, 48, 50, 53,
55, 56, 60, 63, 66, 68, 73, 79, 80, 81, 85, 88, 91, 94, 97, 98, 100,
101, 103, 105, 107, 44, 42, 41, 41, 42, 42, 48, 50, 54, 58, 63, 65, 67,
71, 75, 77, 79, 84, 90, 91, 92, 97, 100, 100, 100, 100, 101, 104, 108,
112, 115, 119, 53, 51, 49, 49, 50, 49, 54, 57, 60, 65, 71, 73, 76, 82,
87, 89, 92, 97, 104, 105, 106, 108, 106, 105, 107, 111, 114, 117, 117,
117, 118, 119, 59, 56, 54, 54, 54, 53, 58, 61, 64, 69, 75, 78, 80, 87,
92, 95, 98, 103, 110, 112, 113, 115, 114, 118, 123, 121, 120, 119, 123,
127, 131, 136, 65, 62, 59, 59, 59, 58, 63, 65, 68, 73, 79, 82, 85, 92,
98, 101, 105, 111, 118, 119, 121, 126, 130, 131, 128, 127, 131, 136,
138, 137, 136, 136, 79, 75, 72, 71, 71, 69, 73, 76, 78, 84, 90, 93, 96,
103, 110, 114, 118, 125, 133, 135, 136, 142, 142, 137, 140, 145, 144,
142, 141, 146, 151, 156, 87, 82, 78, 78, 77, 75, 79, 82, 84, 89, 95, 98,
102, 109, 116, 120, 124, 132, 141, 142, 144, 149, 148, 153, 157, 152,
150, 155, 161, 159, 157, 156, 90, 85, 82, 81, 80, 78, 78, 83, 87, 89,
93, 100, 102, 107, 115, 118, 123, 132, 136, 140, 151, 153, 155, 160,
161, 164, 170, 168, 165, 167, 172, 178, 93, 88, 86, 84, 82, 82, 80, 84,
86, 91, 94, 98, 105, 107, 112, 119, 122, 130, 135, 140, 149, 153, 162,
165, 167, 173, 174, 177, 183, 185, 182, 179, 96, 91, 90, 87, 86, 86, 83,
84, 89, 91, 95, 100, 102, 110, 111, 118, 123, 128, 135, 138, 149, 152,
160, 167, 173, 178, 180, 187, 188, 190, 197, 203, 99, 94, 93, 90, 89,
89, 88, 87, 90, 93, 97, 99, 105, 107, 115, 116, 124, 127, 135, 139, 146,
152, 159, 166, 171, 182, 186, 191, 193, 201, 203, 204, 102, 97, 97, 93,
93, 92, 92, 90, 90, 96, 97, 103, 104, 111, 112, 120, 121, 130, 131, 142,
143, 154, 155, 168, 169, 181, 183, 198, 200, 206, 208, 217,
// Size 4x16
31, 44, 79, 96, 32, 41, 72, 90, 32, 42, 71, 86, 34, 48, 73, 83, 34, 54,
78, 89, 41, 63, 90, 95, 45, 67, 96, 102, 54, 75, 110, 111, 60, 79, 118,
123, 72, 90, 133, 135, 75, 92, 136, 149, 83, 100, 142, 160, 88, 100,
140, 173, 94, 101, 144, 180, 101, 108, 141, 188, 108, 115, 151, 197,
// Size 16x4
31, 32, 32, 34, 34, 41, 45, 54, 60, 72, 75, 83, 88, 94, 101, 108, 44,
41, 42, 48, 54, 63, 67, 75, 79, 90, 92, 100, 100, 101, 108, 115, 79, 72,
71, 73, 78, 90, 96, 110, 118, 133, 136, 142, 140, 144, 141, 151, 96, 90,
86, 83, 89, 95, 102, 111, 123, 135, 149, 160, 173, 180, 188, 197,
// Size 8x32
32, 32, 36, 53, 65, 87, 93, 99, 31, 32, 35, 51, 62, 82, 88, 94, 31, 33,
34, 49, 59, 78, 86, 93, 31, 33, 35, 49, 59, 78, 84, 90, 32, 34, 36, 50,
59, 77, 82, 89, 32, 35, 38, 49, 58, 75, 82, 89, 34, 37, 42, 54, 63, 79,
80, 88, 35, 37, 45, 57, 65, 82, 84, 87, 36, 38, 48, 60, 68, 84, 86, 90,
39, 40, 50, 65, 73, 89, 91, 93, 44, 43, 53, 71, 79, 95, 94, 97, 46, 44,
55, 73, 82, 98, 98, 99, 48, 46, 56, 76, 85, 102, 105, 105, 53, 50, 60,
82, 92, 109, 107, 107, 58, 54, 63, 87, 98, 116, 112, 115, 61, 56, 66,
89, 101, 120, 119, 116, 65, 58, 68, 92, 105, 124, 122, 124, 71, 63, 73,
97, 111, 132, 130, 127, 79, 70, 79, 104, 118, 141, 135, 135, 81, 71, 80,
105, 119, 142, 140, 139, 82, 72, 81, 106, 121, 144, 149, 146, 88, 77,
85, 108, 126, 149, 153, 152, 91, 80, 88, 106, 130, 148, 162, 159, 94,
83, 91, 105, 131, 153, 165, 166, 97, 86, 94, 107, 128, 157, 167, 171,
100, 89, 97, 111, 127, 152, 173, 182, 103, 93, 98, 114, 131, 150, 174,
186, 107, 96, 100, 117, 136, 155, 177, 191, 110, 100, 101, 117, 138,
161, 183, 193, 114, 104, 103, 117, 137, 159, 185, 201, 118, 107, 105,
118, 136, 157, 182, 203, 122, 111, 107, 119, 136, 156, 179, 204,
// Size 32x8
32, 31, 31, 31, 32, 32, 34, 35, 36, 39, 44, 46, 48, 53, 58, 61, 65, 71,
79, 81, 82, 88, 91, 94, 97, 100, 103, 107, 110, 114, 118, 122, 32, 32,
33, 33, 34, 35, 37, 37, 38, 40, 43, 44, 46, 50, 54, 56, 58, 63, 70, 71,
72, 77, 80, 83, 86, 89, 93, 96, 100, 104, 107, 111, 36, 35, 34, 35, 36,
38, 42, 45, 48, 50, 53, 55, 56, 60, 63, 66, 68, 73, 79, 80, 81, 85, 88,
91, 94, 97, 98, 100, 101, 103, 105, 107, 53, 51, 49, 49, 50, 49, 54, 57,
60, 65, 71, 73, 76, 82, 87, 89, 92, 97, 104, 105, 106, 108, 106, 105,
107, 111, 114, 117, 117, 117, 118, 119, 65, 62, 59, 59, 59, 58, 63, 65,
68, 73, 79, 82, 85, 92, 98, 101, 105, 111, 118, 119, 121, 126, 130, 131,
128, 127, 131, 136, 138, 137, 136, 136, 87, 82, 78, 78, 77, 75, 79, 82,
84, 89, 95, 98, 102, 109, 116, 120, 124, 132, 141, 142, 144, 149, 148,
153, 157, 152, 150, 155, 161, 159, 157, 156, 93, 88, 86, 84, 82, 82, 80,
84, 86, 91, 94, 98, 105, 107, 112, 119, 122, 130, 135, 140, 149, 153,
162, 165, 167, 173, 174, 177, 183, 185, 182, 179, 99, 94, 93, 90, 89,
89, 88, 87, 90, 93, 97, 99, 105, 107, 115, 116, 124, 127, 135, 139, 146,
152, 159, 166, 171, 182, 186, 191, 193, 201, 203, 204
],
// Chroma
[
// Size 4x4
35, 46, 57, 66, 46, 60, 69, 71, 57, 69, 90, 90, 66, 71, 90, 109,
// Size 8x8
31, 38, 47, 50, 57, 63, 67, 71, 38, 47, 46, 47, 52, 57, 62, 67, 47, 46,
54, 57, 61, 66, 67, 68, 50, 47, 57, 66, 72, 77, 75, 75, 57, 52, 61, 72,
82, 88, 86, 84, 63, 57, 66, 77, 88, 96, 95, 95, 67, 62, 67, 75, 86, 95,
104, 107, 71, 67, 68, 75, 84, 95, 107, 113,
// Size 16x16
32, 30, 33, 41, 49, 49, 50, 54, 57, 63, 65, 68, 70, 72, 74, 76, 30, 32,
35, 42, 46, 45, 46, 49, 52, 57, 58, 62, 64, 67, 70, 72, 33, 35, 39, 45,
47, 45, 46, 49, 51, 56, 57, 60, 62, 64, 66, 69, 41, 42, 45, 48, 50, 49,
50, 52, 53, 57, 58, 59, 60, 61, 64, 67, 49, 46, 47, 50, 53, 53, 54, 55,
56, 60, 61, 64, 64, 65, 66, 66, 49, 45, 45, 49, 53, 58, 60, 62, 63, 67,
68, 67, 69, 68, 70, 70, 50, 46, 46, 50, 54, 60, 61, 65, 67, 71, 71, 74,
73, 73, 74, 74, 54, 49, 49, 52, 55, 62, 65, 71, 73, 78, 79, 78, 77, 78,
78, 78, 57, 52, 51, 53, 56, 63, 67, 73, 76, 82, 83, 84, 84, 84, 82, 83,
63, 57, 56, 57, 60, 67, 71, 78, 82, 89, 90, 90, 89, 88, 87, 88, 65, 58,
57, 58, 61, 68, 71, 79, 83, 90, 91, 94, 93, 93, 92, 93, 68, 62, 60, 59,
64, 67, 74, 78, 84, 90, 94, 98, 99, 98, 98, 98, 70, 64, 62, 60, 64, 69,
73, 77, 84, 89, 93, 99, 102, 103, 104, 104, 72, 67, 64, 61, 65, 68, 73,
78, 84, 88, 93, 98, 103, 106, 108, 109, 74, 70, 66, 64, 66, 70, 74, 78,
82, 87, 92, 98, 104, 108, 111, 112, 76, 72, 69, 67, 66, 70, 74, 78, 83,
88, 93, 98, 104, 109, 112, 116,
// Size 32x32
32, 31, 30, 32, 33, 36, 41, 45, 49, 48, 49, 50, 50, 52, 54, 56, 57, 60,
63, 64, 65, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 31, 31, 31, 33,
34, 38, 42, 45, 47, 47, 47, 47, 48, 50, 52, 53, 54, 57, 60, 61, 61, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 30, 31, 32, 33, 35, 40, 42, 44,
46, 45, 45, 45, 46, 47, 49, 51, 52, 54, 57, 58, 58, 61, 62, 63, 64, 66,
67, 68, 70, 71, 72, 74, 32, 33, 33, 35, 37, 41, 43, 45, 47, 46, 45, 46,
46, 47, 49, 50, 51, 54, 57, 57, 58, 60, 61, 62, 63, 64, 65, 66, 67, 68,
69, 70, 33, 34, 35, 37, 39, 43, 45, 46, 47, 46, 45, 46, 46, 47, 49, 50,
51, 53, 56, 57, 57, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 36, 38,
40, 41, 43, 47, 47, 47, 48, 46, 45, 46, 46, 47, 48, 49, 50, 52, 54, 55,
55, 57, 58, 59, 61, 62, 64, 65, 66, 67, 68, 69, 41, 42, 42, 43, 45, 47,
48, 49, 50, 49, 49, 49, 50, 50, 52, 52, 53, 55, 57, 58, 58, 60, 59, 59,
60, 61, 61, 63, 64, 66, 67, 69, 45, 45, 44, 45, 46, 47, 49, 50, 51, 51,
51, 51, 52, 52, 53, 54, 55, 57, 59, 59, 60, 61, 61, 62, 63, 63, 63, 63,
63, 64, 65, 66, 49, 47, 46, 47, 47, 48, 50, 51, 53, 53, 53, 54, 54, 54,
55, 56, 56, 58, 60, 61, 61, 63, 64, 64, 64, 64, 65, 66, 66, 66, 66, 66,
48, 47, 45, 46, 46, 46, 49, 51, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61,
63, 64, 64, 66, 66, 65, 66, 67, 67, 67, 67, 68, 69, 70, 49, 47, 45, 45,
45, 45, 49, 51, 53, 55, 58, 59, 60, 61, 62, 63, 63, 65, 67, 67, 68, 69,
67, 68, 69, 68, 68, 69, 70, 70, 70, 70, 50, 47, 45, 46, 46, 46, 49, 51,
54, 56, 59, 60, 60, 62, 64, 64, 65, 67, 69, 69, 70, 70, 71, 71, 70, 70,
71, 71, 71, 71, 72, 74, 50, 48, 46, 46, 46, 46, 50, 52, 54, 56, 60, 60,
61, 63, 65, 66, 67, 68, 71, 71, 71, 73, 74, 72, 73, 74, 73, 73, 74, 74,
74, 74, 52, 50, 47, 47, 47, 47, 50, 52, 54, 57, 61, 62, 63, 66, 68, 69,
70, 72, 75, 75, 75, 77, 75, 75, 76, 75, 75, 76, 75, 75, 76, 77, 54, 52,
49, 49, 49, 48, 52, 53, 55, 58, 62, 64, 65, 68, 71, 72, 73, 75, 78, 78,
79, 79, 78, 79, 77, 78, 78, 77, 78, 79, 78, 78, 56, 53, 51, 50, 50, 49,
52, 54, 56, 59, 63, 64, 66, 69, 72, 73, 75, 77, 80, 80, 81, 81, 82, 80,
81, 81, 79, 81, 80, 79, 81, 82, 57, 54, 52, 51, 51, 50, 53, 55, 56, 60,
63, 65, 67, 70, 73, 75, 76, 79, 82, 82, 83, 85, 84, 83, 84, 83, 84, 82,
82, 84, 83, 82, 60, 57, 54, 54, 53, 52, 55, 57, 58, 61, 65, 67, 68, 72,
75, 77, 79, 82, 85, 85, 86, 88, 86, 87, 85, 86, 85, 85, 86, 84, 85, 86,
63, 60, 57, 57, 56, 54, 57, 59, 60, 63, 67, 69, 71, 75, 78, 80, 82, 85,
89, 89, 90, 90, 90, 89, 89, 88, 88, 88, 87, 88, 88, 87, 64, 61, 58, 57,
57, 55, 58, 59, 61, 64, 67, 69, 71, 75, 78, 80, 82, 85, 89, 90, 91, 92,
93, 92, 92, 91, 91, 90, 91, 90, 90, 92, 65, 61, 58, 58, 57, 55, 58, 60,
61, 64, 68, 70, 71, 75, 79, 81, 83, 86, 90, 91, 91, 94, 94, 96, 93, 94,
93, 94, 92, 93, 93, 92, 67, 63, 61, 60, 59, 57, 60, 61, 63, 66, 69, 70,
73, 77, 79, 81, 85, 88, 90, 92, 94, 96, 96, 97, 98, 95, 97, 95, 96, 95,
95, 96, 68, 64, 62, 61, 60, 58, 59, 61, 64, 66, 67, 71, 74, 75, 78, 82,
84, 86, 90, 93, 94, 96, 98, 98, 99, 100, 98, 99, 98, 98, 98, 97, 69, 65,
63, 62, 61, 59, 59, 62, 64, 65, 68, 71, 72, 75, 79, 80, 83, 87, 89, 92,
96, 97, 98, 100, 100, 101, 102, 101, 101, 101, 100, 102, 70, 66, 64, 63,
62, 61, 60, 63, 64, 66, 69, 70, 73, 76, 77, 81, 84, 85, 89, 92, 93, 98,
99, 100, 102, 102, 103, 104, 104, 103, 104, 102, 71, 67, 66, 64, 63, 62,
61, 63, 64, 67, 68, 70, 74, 75, 78, 81, 83, 86, 88, 91, 94, 95, 100,
101, 102, 104, 104, 105, 106, 107, 105, 107, 72, 68, 67, 65, 64, 64, 61,
63, 65, 67, 68, 71, 73, 75, 78, 79, 84, 85, 88, 91, 93, 97, 98, 102,
103, 104, 106, 106, 108, 108, 109, 107, 73, 69, 68, 66, 65, 65, 63, 63,
66, 67, 69, 71, 73, 76, 77, 81, 82, 85, 88, 90, 94, 95, 99, 101, 104,
105, 106, 109, 108, 110, 111, 112, 74, 70, 70, 67, 66, 66, 64, 63, 66,
67, 70, 71, 74, 75, 78, 80, 82, 86, 87, 91, 92, 96, 98, 101, 104, 106,
108, 108, 111, 111, 112, 113, 75, 71, 71, 68, 68, 67, 66, 64, 66, 68,
70, 71, 74, 75, 79, 79, 84, 84, 88, 90, 93, 95, 98, 101, 103, 107, 108,
110, 111, 113, 113, 115, 76, 72, 72, 69, 69, 68, 67, 65, 66, 69, 70, 72,
74, 76, 78, 81, 83, 85, 88, 90, 93, 95, 98, 100, 104, 105, 109, 111,
112, 113, 116, 115, 78, 74, 74, 70, 70, 69, 69, 66, 66, 70, 70, 74, 74,
77, 78, 82, 82, 86, 87, 92, 92, 96, 97, 102, 102, 107, 107, 112, 113,
115, 115, 118,
// Size 4x8
31, 47, 60, 66, 40, 45, 54, 61, 46, 56, 64, 64, 48, 61, 75, 73, 54, 65,
85, 82, 61, 69, 92, 92, 64, 68, 90, 102, 68, 71, 87, 105,
// Size 8x4
31, 40, 46, 48, 54, 61, 64, 68, 47, 45, 56, 61, 65, 69, 68, 71, 60, 54,
64, 75, 85, 92, 90, 87, 66, 61, 64, 73, 82, 92, 102, 105,
// Size 8x16
32, 37, 48, 52, 57, 66, 68, 71, 30, 40, 46, 48, 52, 60, 63, 66, 33, 43,
47, 47, 51, 59, 60, 63, 42, 47, 50, 50, 53, 60, 59, 62, 49, 48, 53, 54,
57, 62, 62, 62, 49, 46, 53, 61, 64, 69, 66, 66, 50, 46, 54, 64, 67, 73,
72, 70, 54, 49, 55, 68, 73, 80, 76, 75, 57, 50, 56, 70, 76, 84, 80, 79,
63, 55, 60, 75, 82, 92, 87, 84, 64, 56, 61, 75, 83, 93, 93, 89, 68, 59,
64, 74, 86, 94, 98, 94, 70, 62, 66, 73, 83, 96, 99, 98, 72, 64, 66, 75,
83, 92, 101, 104, 74, 67, 66, 74, 84, 94, 103, 106, 76, 69, 67, 73, 82,
91, 101, 109,
// Size 16x8
32, 30, 33, 42, 49, 49, 50, 54, 57, 63, 64, 68, 70, 72, 74, 76, 37, 40,
43, 47, 48, 46, 46, 49, 50, 55, 56, 59, 62, 64, 67, 69, 48, 46, 47, 50,
53, 53, 54, 55, 56, 60, 61, 64, 66, 66, 66, 67, 52, 48, 47, 50, 54, 61,
64, 68, 70, 75, 75, 74, 73, 75, 74, 73, 57, 52, 51, 53, 57, 64, 67, 73,
76, 82, 83, 86, 83, 83, 84, 82, 66, 60, 59, 60, 62, 69, 73, 80, 84, 92,
93, 94, 96, 92, 94, 91, 68, 63, 60, 59, 62, 66, 72, 76, 80, 87, 93, 98,
99, 101, 103, 101, 71, 66, 63, 62, 62, 66, 70, 75, 79, 84, 89, 94, 98,
104, 106, 109,
// Size 16x32
32, 31, 37, 42, 48, 49, 52, 54, 57, 63, 66, 67, 68, 69, 71, 72, 31, 31,
38, 42, 47, 47, 50, 52, 54, 60, 63, 64, 65, 66, 67, 68, 30, 32, 40, 42,
46, 45, 48, 50, 52, 57, 60, 62, 63, 65, 66, 68, 32, 34, 41, 44, 46, 45,
48, 49, 51, 57, 59, 61, 62, 63, 64, 65, 33, 36, 43, 45, 47, 46, 47, 49,
51, 56, 59, 60, 60, 62, 63, 65, 37, 40, 47, 47, 47, 45, 47, 48, 50, 54,
57, 58, 60, 61, 62, 63, 42, 43, 47, 48, 50, 49, 50, 52, 53, 57, 60, 58,
59, 60, 62, 63, 45, 44, 47, 49, 51, 51, 52, 54, 55, 59, 61, 61, 61, 60,
61, 61, 49, 46, 48, 50, 53, 53, 54, 55, 57, 60, 62, 63, 62, 63, 62, 62,
48, 46, 47, 50, 53, 56, 57, 59, 60, 64, 66, 65, 65, 64, 64, 65, 49, 45,
46, 49, 53, 58, 61, 62, 64, 67, 69, 67, 66, 66, 66, 65, 49, 46, 46, 49,
53, 59, 62, 64, 65, 69, 71, 70, 68, 68, 67, 68, 50, 46, 46, 50, 54, 59,
64, 65, 67, 71, 73, 72, 72, 70, 70, 69, 52, 48, 47, 50, 54, 61, 66, 68,
71, 75, 77, 74, 73, 73, 71, 72, 54, 50, 49, 52, 55, 62, 68, 71, 73, 78,
80, 78, 76, 74, 75, 73, 55, 51, 49, 52, 56, 63, 69, 72, 75, 80, 82, 80,
79, 78, 76, 77, 57, 52, 50, 53, 56, 64, 70, 73, 76, 82, 84, 82, 80, 80,
79, 77, 60, 54, 52, 55, 58, 65, 72, 75, 79, 85, 88, 86, 84, 82, 81, 81,
63, 57, 55, 58, 60, 67, 75, 78, 82, 89, 92, 88, 87, 85, 84, 81, 64, 58,
55, 58, 61, 68, 75, 78, 82, 89, 92, 90, 89, 87, 86, 86, 64, 59, 56, 58,
61, 68, 75, 79, 83, 90, 93, 95, 93, 91, 89, 87, 67, 61, 58, 60, 63, 69,
76, 79, 85, 92, 95, 96, 94, 92, 91, 91, 68, 62, 59, 60, 64, 71, 74, 78,
86, 91, 94, 96, 98, 96, 94, 91, 69, 62, 60, 60, 65, 70, 72, 79, 85, 88,
95, 98, 99, 98, 97, 96, 70, 63, 62, 60, 66, 69, 73, 81, 83, 89, 96, 97,
99, 101, 98, 97, 71, 64, 63, 61, 67, 68, 74, 79, 82, 90, 93, 98, 102,
102, 102, 101, 72, 65, 64, 62, 66, 68, 75, 78, 83, 89, 92, 100, 101,
103, 104, 102, 73, 66, 65, 63, 66, 69, 75, 76, 84, 87, 93, 98, 102, 105,
106, 107, 74, 67, 67, 64, 66, 70, 74, 77, 84, 86, 94, 96, 103, 105, 106,
107, 75, 68, 68, 65, 66, 71, 74, 78, 83, 87, 93, 96, 103, 105, 109, 109,
76, 69, 69, 66, 67, 72, 73, 80, 82, 88, 91, 97, 101, 107, 109, 110, 77,
70, 70, 67, 67, 73, 73, 81, 81, 90, 90, 99, 99, 108, 108, 113,
// Size 32x16
32, 31, 30, 32, 33, 37, 42, 45, 49, 48, 49, 49, 50, 52, 54, 55, 57, 60,
63, 64, 64, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 31, 31, 32, 34,
36, 40, 43, 44, 46, 46, 45, 46, 46, 48, 50, 51, 52, 54, 57, 58, 59, 61,
62, 62, 63, 64, 65, 66, 67, 68, 69, 70, 37, 38, 40, 41, 43, 47, 47, 47,
48, 47, 46, 46, 46, 47, 49, 49, 50, 52, 55, 55, 56, 58, 59, 60, 62, 63,
64, 65, 67, 68, 69, 70, 42, 42, 42, 44, 45, 47, 48, 49, 50, 50, 49, 49,
50, 50, 52, 52, 53, 55, 58, 58, 58, 60, 60, 60, 60, 61, 62, 63, 64, 65,
66, 67, 48, 47, 46, 46, 47, 47, 50, 51, 53, 53, 53, 53, 54, 54, 55, 56,
56, 58, 60, 61, 61, 63, 64, 65, 66, 67, 66, 66, 66, 66, 67, 67, 49, 47,
45, 45, 46, 45, 49, 51, 53, 56, 58, 59, 59, 61, 62, 63, 64, 65, 67, 68,
68, 69, 71, 70, 69, 68, 68, 69, 70, 71, 72, 73, 52, 50, 48, 48, 47, 47,
50, 52, 54, 57, 61, 62, 64, 66, 68, 69, 70, 72, 75, 75, 75, 76, 74, 72,
73, 74, 75, 75, 74, 74, 73, 73, 54, 52, 50, 49, 49, 48, 52, 54, 55, 59,
62, 64, 65, 68, 71, 72, 73, 75, 78, 78, 79, 79, 78, 79, 81, 79, 78, 76,
77, 78, 80, 81, 57, 54, 52, 51, 51, 50, 53, 55, 57, 60, 64, 65, 67, 71,
73, 75, 76, 79, 82, 82, 83, 85, 86, 85, 83, 82, 83, 84, 84, 83, 82, 81,
63, 60, 57, 57, 56, 54, 57, 59, 60, 64, 67, 69, 71, 75, 78, 80, 82, 85,
89, 89, 90, 92, 91, 88, 89, 90, 89, 87, 86, 87, 88, 90, 66, 63, 60, 59,
59, 57, 60, 61, 62, 66, 69, 71, 73, 77, 80, 82, 84, 88, 92, 92, 93, 95,
94, 95, 96, 93, 92, 93, 94, 93, 91, 90, 67, 64, 62, 61, 60, 58, 58, 61,
63, 65, 67, 70, 72, 74, 78, 80, 82, 86, 88, 90, 95, 96, 96, 98, 97, 98,
100, 98, 96, 96, 97, 99, 68, 65, 63, 62, 60, 60, 59, 61, 62, 65, 66, 68,
72, 73, 76, 79, 80, 84, 87, 89, 93, 94, 98, 99, 99, 102, 101, 102, 103,
103, 101, 99, 69, 66, 65, 63, 62, 61, 60, 60, 63, 64, 66, 68, 70, 73,
74, 78, 80, 82, 85, 87, 91, 92, 96, 98, 101, 102, 103, 105, 105, 105,
107, 108, 71, 67, 66, 64, 63, 62, 62, 61, 62, 64, 66, 67, 70, 71, 75,
76, 79, 81, 84, 86, 89, 91, 94, 97, 98, 102, 104, 106, 106, 109, 109,
108, 72, 68, 68, 65, 65, 63, 63, 61, 62, 65, 65, 68, 69, 72, 73, 77, 77,
81, 81, 86, 87, 91, 91, 96, 97, 101, 102, 107, 107, 109, 110, 113,
// Size 4x16
31, 49, 63, 69, 32, 45, 57, 65, 36, 46, 56, 62, 43, 49, 57, 60, 46, 53,
60, 63, 45, 58, 67, 66, 46, 59, 71, 70, 50, 62, 78, 74, 52, 64, 82, 80,
57, 67, 89, 85, 59, 68, 90, 91, 62, 71, 91, 96, 63, 69, 89, 101, 65, 68,
89, 103, 67, 70, 86, 105, 69, 72, 88, 107,
// Size 16x4
31, 32, 36, 43, 46, 45, 46, 50, 52, 57, 59, 62, 63, 65, 67, 69, 49, 45,
46, 49, 53, 58, 59, 62, 64, 67, 68, 71, 69, 68, 70, 72, 63, 57, 56, 57,
60, 67, 71, 78, 82, 89, 90, 91, 89, 89, 86, 88, 69, 65, 62, 60, 63, 66,
70, 74, 80, 85, 91, 96, 101, 103, 105, 107,
// Size 8x32
32, 37, 48, 52, 57, 66, 68, 71, 31, 38, 47, 50, 54, 63, 65, 67, 30, 40,
46, 48, 52, 60, 63, 66, 32, 41, 46, 48, 51, 59, 62, 64, 33, 43, 47, 47,
51, 59, 60, 63, 37, 47, 47, 47, 50, 57, 60, 62, 42, 47, 50, 50, 53, 60,
59, 62, 45, 47, 51, 52, 55, 61, 61, 61, 49, 48, 53, 54, 57, 62, 62, 62,
48, 47, 53, 57, 60, 66, 65, 64, 49, 46, 53, 61, 64, 69, 66, 66, 49, 46,
53, 62, 65, 71, 68, 67, 50, 46, 54, 64, 67, 73, 72, 70, 52, 47, 54, 66,
71, 77, 73, 71, 54, 49, 55, 68, 73, 80, 76, 75, 55, 49, 56, 69, 75, 82,
79, 76, 57, 50, 56, 70, 76, 84, 80, 79, 60, 52, 58, 72, 79, 88, 84, 81,
63, 55, 60, 75, 82, 92, 87, 84, 64, 55, 61, 75, 82, 92, 89, 86, 64, 56,
61, 75, 83, 93, 93, 89, 67, 58, 63, 76, 85, 95, 94, 91, 68, 59, 64, 74,
86, 94, 98, 94, 69, 60, 65, 72, 85, 95, 99, 97, 70, 62, 66, 73, 83, 96,
99, 98, 71, 63, 67, 74, 82, 93, 102, 102, 72, 64, 66, 75, 83, 92, 101,
104, 73, 65, 66, 75, 84, 93, 102, 106, 74, 67, 66, 74, 84, 94, 103, 106,
75, 68, 66, 74, 83, 93, 103, 109, 76, 69, 67, 73, 82, 91, 101, 109, 77,
70, 67, 73, 81, 90, 99, 108,
// Size 32x8
32, 31, 30, 32, 33, 37, 42, 45, 49, 48, 49, 49, 50, 52, 54, 55, 57, 60,
63, 64, 64, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 37, 38, 40, 41,
43, 47, 47, 47, 48, 47, 46, 46, 46, 47, 49, 49, 50, 52, 55, 55, 56, 58,
59, 60, 62, 63, 64, 65, 67, 68, 69, 70, 48, 47, 46, 46, 47, 47, 50, 51,
53, 53, 53, 53, 54, 54, 55, 56, 56, 58, 60, 61, 61, 63, 64, 65, 66, 67,
66, 66, 66, 66, 67, 67, 52, 50, 48, 48, 47, 47, 50, 52, 54, 57, 61, 62,
64, 66, 68, 69, 70, 72, 75, 75, 75, 76, 74, 72, 73, 74, 75, 75, 74, 74,
73, 73, 57, 54, 52, 51, 51, 50, 53, 55, 57, 60, 64, 65, 67, 71, 73, 75,
76, 79, 82, 82, 83, 85, 86, 85, 83, 82, 83, 84, 84, 83, 82, 81, 66, 63,
60, 59, 59, 57, 60, 61, 62, 66, 69, 71, 73, 77, 80, 82, 84, 88, 92, 92,
93, 95, 94, 95, 96, 93, 92, 93, 94, 93, 91, 90, 68, 65, 63, 62, 60, 60,
59, 61, 62, 65, 66, 68, 72, 73, 76, 79, 80, 84, 87, 89, 93, 94, 98, 99,
99, 102, 101, 102, 103, 103, 101, 99, 71, 67, 66, 64, 63, 62, 62, 61,
62, 64, 66, 67, 70, 71, 75, 76, 79, 81, 84, 86, 89, 91, 94, 97, 98, 102,
104, 106, 106, 109, 109, 108
]
]
];
}

33
src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantification/DeQuant.cs

@ -0,0 +1,33 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline.Quantification;
internal class DeQuant
{
private readonly short[][] dcContent;
private readonly short[][] acContent;
public DeQuant()
{
this.dcContent = new short[Av1Constants.MaxSegmentCount][];
this.acContent = new short[Av1Constants.MaxSegmentCount][];
for (int segmentId = 0; segmentId < Av1Constants.MaxSegmentCount; segmentId++)
{
this.dcContent[segmentId] = new short[Av1Constants.MaxPlanes];
this.acContent[segmentId] = new short[Av1Constants.MaxPlanes];
}
}
public short GetDc(int segmentId, Av1Plane plane)
=> this.dcContent[segmentId][(int)plane];
public short GetAc(int segmentId, Av1Plane plane)
=> this.acContent[segmentId][(int)plane];
public void SetAc(int segmentId, Av1Plane plane, short value)
=> this.dcContent[segmentId][(int)plane] = value;
public void SetDc(int segmentId, Av1Plane plane, short value)
=> this.dcContent[segmentId][(int)plane] = value;
}

190
src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantification/QuantizationLookup.cs

@ -0,0 +1,190 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline.Quantification;
internal class QuantizationLookup
{
// Coefficient scaling and quantization with AV1 TX are tailored to
// the AV1 TX transforms. Regardless of the bit-depth of the input,
// the transform stages scale the coefficient values up by a factor of
// 8 (3 bits) over the scale of the pixel values. Thus, for 8-bit
// input, the coefficients have effectively 11 bits of scale depth
// (8+3), 10-bit input pixels result in 13-bit coefficient depth
// (10+3) and 12-bit pixels yield 15-bit (12+3) coefficient depth.
// All quantizers are built using this invariant of x8, 3-bit scaling,
// thus the Q3 suffix.
// A partial exception to this rule is large transforms; to avoid
// overflow, TX blocks with > 256 pels (>16x16) are scaled only
// 4-times unity (2 bits) over the pixel depth, and TX blocks with
// over 1024 pixels (>32x32) are scaled up only 2x unity (1 bit).
// This descaling is found via av1_tx_get_scale(). Thus, 16x32, 32x16
// and 32x32 transforms actually return Q2 coefficients, and 32x64,
// 64x32 and 64x64 transforms return Q1 coefficients. However, the
// quantizers are de-scaled down on-the-fly by the same amount
// (av1_tx_get_scale()) during quantization, and as such the
// dequantized/decoded coefficients, even for large TX blocks, are always
// effectively Q3. Meanwhile, quantized/coded coefficients are Q0
// because Qn quantizers are applied to Qn tx coefficients.
// Note that encoder decision making (which uses the quantizer to
// generate several bespoke lamdas for RDO and other heuristics)
// expects quantizers to be larger for higher-bitdepth input. In
// addition, the minimum allowable quantizer is 4; smaller values will
// underflow to 0 in the actual quantization routines.
private static readonly short[] AcQlookup8 = [
4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138,
140, 142, 144, 146, 148, 150, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, 182, 185, 188,
191, 194, 197, 200, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255, 260,
265, 270, 275, 280, 285, 290, 295, 300, 305, 311, 317, 323, 329, 335, 341, 347, 353, 359, 366,
373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448, 456, 465, 474, 483, 492, 501, 510, 520,
530, 540, 550, 560, 571, 582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715, 729, 743,
757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933, 951, 969, 988, 1007, 1026, 1046, 1066,
1087, 1108, 1129, 1151, 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451, 1479, 1508, 1537,
1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
];
private static readonly short[] AcQlookup10 = [
4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40, 44, 48, 51, 55, 59, 63,
67, 71, 75, 79, 83, 88, 92, 96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145,
149, 154, 158, 163, 168, 172, 177, 181, 186, 190, 195, 199, 204, 208, 213, 217, 222, 226, 231,
235, 240, 244, 249, 253, 258, 262, 267, 271, 275, 280, 284, 289, 293, 297, 302, 306, 311, 315,
319, 324, 328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371, 375, 379, 384, 388, 392, 396,
401, 409, 417, 425, 433, 441, 449, 458, 466, 474, 482, 490, 498, 506, 514, 523, 531, 539, 547,
555, 563, 571, 579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713, 725, 737, 749,
761, 773, 785, 797, 809, 825, 841, 857, 873, 889, 905, 922, 938, 954, 970, 986, 1002, 1018, 1038,
1058, 1078, 1098, 1118, 1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386, 1411, 1435, 1463,
1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791, 1823, 1859, 1895, 1931, 1967, 2003, 2039, 2079,
2119, 2159, 2199, 2239, 2283, 2327, 2371, 2415, 2459, 2507, 2555, 2603, 2651, 2703, 2755, 2807, 2859, 2915, 2971,
3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591, 3659, 3731, 3803, 3876, 3952, 4028, 4104, 4184, 4264,
4348, 4432, 4516, 4604, 4692, 4784, 4876, 4972, 5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148,
6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312,
];
private static readonly short[] AcQlookup12 = [
4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99, 112, 126, 139, 154, 168,
183, 199, 214, 230, 247, 263, 280, 297, 314, 331, 349, 366, 384, 402, 420, 438,
456, 475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660, 679, 698, 716, 735,
753, 772, 791, 809, 828, 846, 865, 884, 902, 920, 939, 957, 976, 994, 1012, 1030,
1049, 1067, 1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264, 1282, 1299, 1317,
1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457, 1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595,
1627, 1660, 1693, 1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052, 2085, 2118,
2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378, 2411, 2459, 2508, 2556, 2605, 2653, 2701, 2750,
2798, 2847, 2895, 2943, 2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555, 3619,
3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149, 4230, 4310, 4390, 4470, 4550, 4631, 4711, 4791,
4871, 4967, 5064, 5160, 5256, 5352, 5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410,
6522, 6650, 6778, 6906, 7034, 7162, 7290, 7435, 7579, 7723, 7867, 8011, 8155, 8315, 8475, 8635,
8795, 8956, 9132, 9308, 9484, 9660, 9836, 10028, 10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661,
11885, 12109, 12333, 12573, 12813, 13053, 13309, 13565, 13821, 14093, 14365, 14637, 14925, 15213, 15502, 15806,
16110, 16414, 16734, 17054, 17390, 17726, 18062, 18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486,
21902, 22334, 22766, 23214, 23662, 24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599, 28143, 28687, 29247,
];
private static readonly short[] DcQlookup8 = [
4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23,
24, 25, 26, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40,
41, 42, 43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51, 52, 53, 53, 54, 55, 56, 57,
57, 58, 59, 60, 61, 62, 62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 70, 71, 72, 73,
74, 74, 75, 76, 77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88, 90, 92,
93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 108, 110, 111, 113, 114, 116, 117, 118, 120, 121,
123, 125, 127, 129, 131, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164,
166, 169, 172, 174, 177, 180, 182, 185, 187, 190, 192, 195, 199, 202, 205, 208, 211, 214, 217, 220,
223, 226, 230, 233, 237, 240, 243, 247, 250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292,
296, 300, 304, 309, 313, 317, 322, 326, 330, 335, 340, 344, 349, 354, 359, 364, 369, 374, 379, 384,
389, 395, 400, 406, 411, 417, 423, 429, 435, 441, 447, 454, 461, 467, 475, 482, 489, 497, 505, 513,
522, 530, 539, 549, 559, 569, 579, 590, 602, 614, 626, 640, 654, 668, 684, 700, 717, 736, 755, 775,
796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098, 1139, 1184, 1232, 1282, 1336,
];
private static readonly short[] DcQlookup10 = [
4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37, 40, 43, 47, 50, 53, 57,
60, 64, 68, 71, 75, 78, 82, 86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128,
132, 136, 140, 143, 147, 151, 155, 159, 163, 166, 170, 174, 178, 182, 185, 189, 193, 197, 200,
204, 208, 212, 215, 219, 223, 226, 230, 233, 237, 241, 244, 248, 251, 255, 259, 262, 266, 269,
273, 276, 280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314, 317, 321, 324, 327, 331, 334,
337, 343, 350, 356, 362, 369, 375, 381, 387, 394, 400, 406, 412, 418, 424, 430, 436, 442, 448,
454, 460, 466, 472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567, 576, 584, 592,
601, 609, 617, 625, 634, 644, 655, 666, 676, 687, 698, 708, 718, 729, 739, 749, 759, 770, 782,
795, 807, 819, 831, 844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001, 1015, 1030,
1045, 1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202, 1218, 1236, 1253, 1271, 1288, 1306, 1323, 1342,
1361, 1379, 1398, 1416, 1436, 1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670, 1692, 1717, 1741,
1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088, 2123, 2159, 2197, 2236, 2276, 2319, 2363,
2410, 2458, 2508, 2561, 2616, 2675, 2737, 2802, 2871, 2944, 3020, 3102, 3188, 3280, 3375, 3478, 3586, 3702, 3823,
3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347,
];
private static readonly short[] DcQlookup12 = [
4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91, 103, 115, 127, 140, 153,
166, 180, 194, 208, 222, 237, 251, 266, 281, 296, 312, 327, 343, 358, 374, 390,
405, 421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580, 596, 611, 627, 643,
659, 674, 690, 706, 721, 737, 752, 768, 783, 798, 814, 829, 844, 859, 874, 889,
904, 919, 934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080, 1094, 1108, 1122,
1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234, 1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342,
1368, 1393, 1419, 1444, 1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692, 1717, 1741,
1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933, 1957, 1992, 2027, 2061, 2096, 2130, 2165, 2199,
2233, 2267, 2300, 2334, 2367, 2400, 2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746, 2788,
2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127, 3177, 3226, 3275, 3324, 3373, 3421, 3469, 3517,
3565, 3621, 3677, 3733, 3788, 3843, 3897, 3951, 4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420,
4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013, 5083, 5153, 5222, 5291, 5367, 5442, 5517,
5591, 5665, 5745, 5825, 5905, 5984, 6063, 6149, 6234, 6319, 6404, 6495, 6587, 6678, 6769, 6867,
6966, 7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085, 8214, 8352, 8492, 8635, 8788,
8945, 9104, 9275, 9450, 9639, 9832, 10031, 10245, 10465, 10702, 10946, 11210, 11482, 11776, 12081, 12409,
12750, 13118, 13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943, 17575, 18237, 18949, 19718, 20521, 21387,
];
public static short GetDcQuant(int qIndex, int dcDeltaQ, Av1BitDepth bitDepth)
{
int qClamped = Av1Math.Clamp(qIndex + dcDeltaQ, 0, Av1Constants.MaxQ);
switch (bitDepth)
{
case Av1BitDepth.EightBit:
return DcQlookup8[qClamped];
case Av1BitDepth.TenBit:
return DcQlookup10[qClamped];
case Av1BitDepth.TwelveBit:
return DcQlookup12[qClamped];
default:
Guard.IsFalse(true, nameof(bitDepth), "bit_depth should be EB_EIGHT_BIT, EB_TEN_BIT or EB_TWELVE_BIT");
return -1;
}
}
public static short GetAcQuant(int qIndex, int dcDeltaQ, Av1BitDepth bitDepth)
{
int qClamped = Av1Math.Clamp(qIndex + dcDeltaQ, 0, Av1Constants.MaxQ);
switch (bitDepth)
{
case Av1BitDepth.EightBit:
return AcQlookup8[qClamped];
case Av1BitDepth.TenBit:
return AcQlookup10[qClamped];
case Av1BitDepth.TwelveBit:
return AcQlookup12[qClamped];
default:
Guard.IsFalse(true, nameof(bitDepth), "bit_depth should be EB_EIGHT_BIT, EB_TEN_BIT or EB_TWELVE_BIT");
return -1;
}
}
public static int GetQIndex(ObuSegmentationParameters segmentationParameters, int segmentId, int baseQIndex)
{
if (segmentationParameters.IsFeatureActive(segmentId, ObuSegmentationLevelFeature.AlternativeQuantizer))
{
int data = segmentationParameters.FeatureData[segmentId, (int)ObuSegmentationLevelFeature.AlternativeQuantizer];
int qIndex = baseQIndex + data;
return Av1Math.Clamp(qIndex, 0, Av1Constants.MaxQ);
}
else
{
return baseQIndex;
}
}
}

2
src/ImageSharp/Formats/Heif/Av1/Readme.md

@ -63,6 +63,8 @@ The smallest unit in the frame. It determines the parameters for an area of 4 by
[AOM's original development implementation](https://github.com/AOMediaCodec/libavif)
[Paper describing the techniques used in AV1](https://arxiv.org/pdf/2008.06091)
# Test images
[Netflix image repository](http://download.opencontent.netflix.com/?prefix=AV1/)

2
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs

@ -1655,7 +1655,7 @@ internal class Av1TileReader : IAv1TileReader
int bh4 = partitionInfo.ModeInfo.BlockSize.Get4x4HighCount();
int xMin = Math.Min(this.FrameHeader.ModeInfoColumnCount - columnIndex, bw4);
int yMin = Math.Min(this.FrameHeader.ModeInfoRowCount - rowIndex, bh4);
int segmentId = Av1Constants.MaxSegments - 1;
int segmentId = Av1Constants.MaxSegmentCount - 1;
for (int y = 0; y < yMin; y++)
{
for (int x = 0; x < xMin; x++)

192
src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs

@ -0,0 +1,192 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
internal class Av1BlockDecoder
{
private readonly ObuSequenceHeader sequenceHeader;
private readonly ObuFrameHeader frameHeader;
private readonly Av1FrameInfo frameInfo;
private readonly Av1FrameBuffer frameBuffer;
public Av1BlockDecoder(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, Av1FrameInfo frameInfo, Av1FrameBuffer frameBuffer)
{
this.sequenceHeader = sequenceHeader;
this.frameHeader = frameHeader;
this.frameInfo = frameInfo;
this.frameBuffer = frameBuffer;
}
public static void DecodeBlock(Av1BlockModeInfo modeInfo, Point modeInfoPosition, Av1BlockSize blockSize, Av1SuperblockInfo superblockInfo)
{
/*
ObuColorConfig colorConfig = this.sequenceHeader.ColorConfig;
Av1TransformType transformType;
Span<int> coefficients;
Av1TransformSize transformSize;
int transformUnitCount;
bool hasChroma = Av1TileReader.HasChroma(this.sequenceHeader, modeInfoPosition, blockSize);
Av1PartitionInfo partitionInfo = new(modeInfo, superblockInfo, hasChroma, Av1PartitionType.None);
int maxBlocksWide = partitionInfo.GetMaxBlockWide(blockSize, false);
int maxBlocksHigh = partitionInfo.GetMaxBlockHigh(blockSize, false);
bool isLossless = this.frameHeader.LosslessArray[modeInfo.SegmentId];
bool isLosslessBlock = isLossless && ((blockSize >= Av1BlockSize.Block64x64) && (blockSize <= Av1BlockSize.Block128x128));
int chromaTransformUnitCount = isLosslessBlock
? (maxBlocksWide * maxBlocksHigh) >> ((colorConfig.SubSamplingX ? 1 : 0) + (colorConfig.SubSamplingY ? 1 : 0))
: modeInfo.TransformUnitsCount[(int)Av1Plane.U];
bool highBitDepth = false;
bool is16BitsPipeline = false;
int loopFilterStride = this.frameHeader.ModeInfoStride;
for (int plane = 0; plane < colorConfig.PlaneCount; plane++)
{
int subX = (plane > 0) ? colorConfig.SubSamplingX ? 1 : 0 : 0;
int subY = (plane > 0) ? colorConfig.SubSamplingY ? 1 : 0 : 0;
if (plane != 0 && !partitionInfo.IsChroma)
{
continue;
}
int transformInfoIndex = plane switch
{
2 => superblockInfo.TransformInfoIndexUv + modeInfo.FirstTransformLocation[plane - 1] + chromaTransformUnitCount,
1 => superblockInfo.TransformInfoIndexY + modeInfo.FirstTransformLocation[plane],
0 => superblockInfo.TransformInfoIndexY + modeInfo.FirstTransformLocation[plane],
_ => throw new InvalidImageContentException("Maximum of 3 color planes")
};
ref Av1TransformInfo transformInfo = ref Unsafe.Add(ref this.frameInfo.GetSuperblockTransform(plane, superblockInfo.Position), transformInfoIndex);
if (isLosslessBlock)
{
Guard.IsTrue(transformInfo.Size == Av1TransformSize.Size4x4, nameof(transformInfo.Size), "Lossless may only have 4x4 blocks.");
transformUnitCount = (maxBlocksWide * maxBlocksHigh) >> (subX + subY);
}
else
{
transformUnitCount = modeInfo.TransformUnitsCount[Math.Min(1, plane)];
}
Guard.IsFalse(transformUnitCount == 0, nameof(transformUnitCount), "Must have at least a single transform unit to decode.");
this.DeriveBlockPointers(
this.reconstructionFrameBuffer,
plane,
(modeInfoPosition.X >> subX) << Av1Constants.ModeInfoSizeLog2,
(modeInfoPosition.Y >> subY) << Av1Constants.ModeInfoSizeLog2,
out Span<byte> blockReconstructionBuffer,
out int reconstructionStride,
subX,
subY);
for (int tu = 0; tu < transformUnitCount; tu++)
{
Span<byte> transformBlockReconstructionBuffer;
int transformBlockOffset;
transformSize = transformInfo.Size;
coefficients = this.currentCoefficients[plane];
transformBlockOffset = ((transformInfo.OffsetY * reconstructionStride) + transformInfo.OffsetX) << Av1Constants.ModeInfoSizeLog2;
transformBlockReconstructionBuffer = blockReconstructionBuffer.Slice(transformBlockOffset << (highBitDepth ? 1 : 0));
if (this.isLoopFilterEnabled)
{
if (plane != 2)
{
Fill4x4LoopFilterParameters(
this.loopFilterContext,
(modeInfoPosition.X & (~subX)) + (transformInfo.OffsetX << subX),
(modeInfoPosition.Y & (~subY)) + (transformInfo.OffsetY << subY),
loopFilterStride,
transformSize,
subX,
subY,
plane);
}
}
// if (!inter_block)
if (true)
{
PredictIntra(
partitionInfo,
plane,
transformSize,
tile,
transformBlockReconstructionBuffer,
reconstructionStride,
this.reconstructionFrameBuffer.BitDepth,
transformInfo.OffsetX,
transformInfo.OffsetY);
}
int numberOfCoefficients = 0;
if (!modeInfo.Skip && transformInfo.CodeBlockFlag)
{
Span<int> quantizationCoefficients = this.CurrentInverseQuantizationCoefficients;
int inverseQuantizationSize = transformSize.GetWidth() * transformSize.GetHeight();
quantizationCoefficients[..inverseQuantizationSize].Clear();
this.CurrentInverseQuantizationCoefficients = quantizationCoefficients[inverseQuantizationSize..];
transformType = transformInfo.Type;
numberOfCoefficients = InverseQuantize(
partitionInfo, modeInfo, coefficients, quantizationCoefficients, transformType, transformSize, plane);
if (numberOfCoefficients != 0)
{
this.CurrentCoefficients[plane] += numberOfCoefficients + 1;
if (this.reconstructionFrameBuffer.BitDepth == Av1BitDepth.EightBit && !is16BitsPipeline)
{
InverseTransformReconstruction8Bit(
quantizationCoefficients,
(Span<byte>)transformBlockReconstructionBuffer,
reconstructionStride,
(Span<byte>)transformBlockReconstructionBuffer,
reconstructionStride,
transformSize,
transformType,
plane,
numberOfCoefficients,
isLossless);
}
else
{
throw new NotImplementedException("No support for 16 bit pipeline yet.");
}
}
}
// Store Luma for CFL if required!
if (plane == (int)Av1Plane.Y && StoreChromeFromLumeRequired(colorConfig, partitionInfo, this.frameHeader.IsChroma))
{
ChromaFromLumaStoreTransform(
partitionInfo,
this.chromaFromLumaContext,
transformInfo.OffsetY,
transformInfo.OffsetX,
transformSize,
blockSize,
colorConfig,
transformBlockReconstructionBuffer,
reconstructionStride,
is16BitsPipeline);
}
// increment transform pointer
transformInfo = ref Unsafe.Add(ref transformInfo, 1);
}
}*/
}
}

30
src/ImageSharp/Formats/Heif/Av1/Transform/Av1FrameDecoder.cs

@ -1,30 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
internal class Av1FrameDecoder
{
private readonly ObuSequenceHeader sequenceHeader;
private readonly ObuFrameHeader frameHeader;
private readonly Av1FrameInfo frameInfo;
public Av1FrameDecoder(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, Av1FrameInfo frameInfo)
{
this.sequenceHeader = sequenceHeader;
this.frameHeader = frameHeader;
this.frameInfo = frameInfo;
}
public void DecodeFrame()
{
Guard.NotNull(this.sequenceHeader);
Guard.NotNull(this.frameHeader);
Guard.NotNull(this.frameInfo);
// TODO: Implement.
}
}

74
src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseQuantizer.cs

@ -1,74 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Quantization;
internal class Av1InverseQuantizer
{
public static int InverseQuantize(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, ObuPartitionInfo part, Av1BlockModeInfo mode, int[] level, int[] qCoefficients, Av1TransformType txType, Av1TransformSize txSize, Av1Plane plane)
{
Av1ScanOrder scanOrder = Av1ScanOrderConstants.GetScanOrder(txSize, txType);
short[] scanIndices = scanOrder.Scan;
int maxValue = (1 << (7 + sequenceHeader.ColorConfig.BitDepth)) - 1;
int minValue = -(1 << (7 + sequenceHeader.ColorConfig.BitDepth));
bool usingQuantizationMatrix = frameHeader.QuantizationParameters.IsUsingQMatrix;
bool lossless = frameHeader.LosslessArray[mode.SegmentId];
short[] dequant = []; // Get from DecModCtx
int qmLevel = (lossless || !usingQuantizationMatrix) ? Av1ScanOrderConstants.QuantizationMatrixLevelCount - 1 : frameHeader.QuantizationParameters.QMatrix[(int)plane];
byte[] iqMatrix = []; // txType.Is2dTransform() ? Get from DecModCtx
int shift = txSize.GetScale();
int coefficientCount = level[0];
Span<int> levelSpan = level.AsSpan(1);
int lev = levelSpan[0];
int qCoefficient;
if (lev != 0)
{
int pos = scanIndices[0];
qCoefficient = (int)(((long)Math.Abs(lev) * GetDequantizationValue(dequant[0], pos, iqMatrix)) & 0xffffff);
qCoefficient >>= shift;
if (lev < 0)
{
qCoefficient = -qCoefficient;
}
qCoefficients[0] = Av1Math.Clamp(qCoefficient, minValue, maxValue);
}
for (int i = 1; i < coefficientCount; i++)
{
lev = levelSpan[i];
if (lev != 0)
{
int pos = scanIndices[i];
qCoefficient = (int)(((long)Math.Abs(lev) * GetDequantizationValue(dequant[1], pos, iqMatrix)) & 0xffffff);
qCoefficient >>= shift;
if (lev < 0)
{
qCoefficient = -qCoefficient;
}
qCoefficients[pos] = Av1Math.Clamp(qCoefficient, minValue, maxValue);
}
}
return coefficientCount;
}
private static int GetDequantizationValue(short dequant, int coefficientIndex, byte[] iqMatrix)
{
int dqv = dequant;
if (iqMatrix != null)
{
dqv = ((iqMatrix[coefficientIndex] * dqv) + (1 << (Av1ScanOrderConstants.QuantizationMatrixLevelBitCount - 1))) >> Av1ScanOrderConstants.QuantizationMatrixLevelBitCount;
}
return dqv;
}
}

2
src/ImageSharp/Formats/Heif/Av1/Transform/Av1TransformSizeExtensions.cs

@ -135,6 +135,8 @@ internal static class Av1TransformSizeExtensions
2, 3, 4, 5, 6, 3, 2, 4, 3, 5, 4, 6, 5, 4, 2, 5, 3, 6, 4,
];
public static int GetSize2d(this Av1TransformSize size) => Size2d[(int)size];
public static int GetScale(this Av1TransformSize size)
{
int pels = Size2d[(int)size];

2
tests/ImageSharp.Tests/Formats/Heif/Av1/ObuFrameHeaderTests.cs

@ -283,7 +283,7 @@ public class ObuFrameHeaderTests
MatrixCoefficients = ObuMatrixCoefficients.Unspecified,
SubSamplingX = false,
SubSamplingY = false,
BitDepth = 8,
BitDepth = Av1BitDepth.EightBit,
HasSeparateUvDelta = true,
ColorRange = true,
},

Loading…
Cancel
Save