diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuColorConfig.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuColorConfig.cs
index 83dddd2fe..3c7349b19 100644
--- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuColorConfig.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuColorConfig.cs
@@ -7,8 +7,15 @@ internal class ObuColorConfig
{
public bool IsColorDescriptionPresent { get; set; }
- public int ChannelCount { get; set; }
-
+ ///
+ /// Gets or sets the number of color channels in this image.
+ ///
+ public int PlaneCount { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the image has a single greyscale plane, will have
+ /// color planes otherwise.
+ ///
public bool IsMonochrome { get; set; }
public ObuColorPrimaries ColorPrimaries { get; set; }
diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
index d5e4ae4cc..fc3b19d31 100644
--- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
@@ -465,7 +465,7 @@ internal class ObuReader
colorConfig.IsMonochrome = reader.ReadBoolean();
}
- colorConfig.ChannelCount = colorConfig.IsMonochrome ? 1 : 3;
+ colorConfig.PlaneCount = colorConfig.IsMonochrome ? 1 : Av1Constants.MaxPlanes;
colorConfig.IsColorDescriptionPresent = reader.ReadBoolean();
colorConfig.ColorPrimaries = ObuColorPrimaries.Unspecified;
colorConfig.TransferCharacteristics = ObuTransferCharacteristics.Unspecified;
@@ -1191,7 +1191,7 @@ internal class ObuReader
///
private void ReadFrameHeader(ref Av1BitStreamReader reader, ObuHeader header, bool trailingBit)
{
- int planeCount = this.SequenceHeader!.ColorConfig.IsMonochrome ? 1 : 3;
+ int planeCount = this.SequenceHeader!.ColorConfig.PlaneCount;
int startBitPosition = reader.BitPosition;
this.ReadUncompressedFrameHeader(ref reader, header, planeCount);
if (trailingBit)
diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs
index 4a154da0e..1b704309d 100644
--- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs
@@ -112,6 +112,7 @@ internal class ObuWriter
writer.WriteBoolean(colorConfig.IsMonochrome);
}
+ colorConfig.PlaneCount = colorConfig.IsMonochrome ? 1 : Av1Constants.MaxPlanes;
writer.WriteBoolean(false); // colorConfig.IsColorDescriptionPresent
if (colorConfig.IsMonochrome)
{
diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveNeighbor4x4Context.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveNeighbor4x4Context.cs
index ee82adced..111deae1f 100644
--- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveNeighbor4x4Context.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseAboveNeighbor4x4Context.cs
@@ -50,7 +50,7 @@ internal class Av1ParseAboveNeighbor4x4Context
public void Clear(ObuSequenceHeader sequenceHeader, int modeInfoColumnStart, int modeInfoColumnEnd)
{
- int planeCount = sequenceHeader.ColorConfig.ChannelCount;
+ int planeCount = sequenceHeader.ColorConfig.PlaneCount;
int width = modeInfoColumnEnd - modeInfoColumnStart;
Array.Fill(this.AboveTransformWidth, Av1TransformSize.Size64x64.GetWidth(), 0, width);
Array.Fill(this.AbovePartitionWidth, 0, 0, width);
diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftNeighbor4x4Context.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftNeighbor4x4Context.cs
index 7ce7beb62..8e034f6e9 100644
--- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftNeighbor4x4Context.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1ParseLeftNeighbor4x4Context.cs
@@ -50,7 +50,7 @@ internal class Av1ParseLeftNeighbor4x4Context
public void Clear(ObuSequenceHeader sequenceHeader)
{
int blockCount = sequenceHeader.SuperblockModeInfoSize;
- int planeCount = sequenceHeader.ColorConfig.ChannelCount;
+ int planeCount = sequenceHeader.ColorConfig.PlaneCount;
int neighbor4x4Count = sequenceHeader.SuperblockModeInfoSize;
Array.Fill(this.LeftTransformHeight, Av1TransformSize.Size64x64.GetHeight(), 0, blockCount);
Array.Fill(this.LeftPartitionHeight, 0, 0, blockCount);
diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs
index 66484a06a..5cb054682 100644
--- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs
@@ -52,7 +52,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
// reallocate_parse_context_memory
// Hard code number of threads to 1 for now.
- int planesCount = sequenceHeader.ColorConfig.IsMonochrome ? 1 : Av1Constants.MaxPlanes;
+ int planesCount = sequenceHeader.ColorConfig.PlaneCount;
int superblockColumnCount =
Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameWidth, sequenceHeader.SuperblockSizeLog2) >> sequenceHeader.SuperblockSizeLog2;
int modeInfoWideColumnCount = superblockColumnCount * sequenceHeader.SuperblockModeInfoSize;
@@ -84,7 +84,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
int modeInfoRowEnd = this.FrameInfo.TilesInfo.TileRowStartModeInfo[tileRowIndex + 1];
this.aboveNeighborContext.Clear(this.SequenceHeader, modeInfoColumnStart, modeInfoColumnEnd);
this.ClearLoopFilterDelta();
- int planesCount = this.SequenceHeader.ColorConfig.ChannelCount;
+ int planesCount = this.SequenceHeader.ColorConfig.PlaneCount;
// Default initialization of Wiener and SGR Filter.
this.referenceSgrXqd = new int[planesCount][];
@@ -138,7 +138,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
private void ReadLoopRestoration(Point modeInfoLocation, Av1BlockSize superBlockSize)
{
- int planesCount = this.SequenceHeader.ColorConfig.ChannelCount;
+ int planesCount = this.SequenceHeader.ColorConfig.PlaneCount;
for (int plane = 0; plane < planesCount; plane++)
{
if (this.FrameInfo.LoopRestorationParameters[plane].Type != ObuRestorationType.None)
@@ -290,7 +290,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
int columnIndex = modeInfoLocation.X;
int block4x4Width = blockSize.Get4x4WideCount();
int block4x4Height = blockSize.Get4x4HighCount();
- int planesCount = this.SequenceHeader.ColorConfig.ChannelCount;
+ int planesCount = this.SequenceHeader.ColorConfig.PlaneCount;
Point superblockLocation = superblockInfo.Position * this.SequenceHeader.SuperblockModeInfoSize;
Point locationInSuperblock = new Point(modeInfoLocation.X - superblockLocation.X, modeInfoLocation.Y - superblockLocation.Y);
Av1BlockModeInfo blockModeInfo = new(planesCount, blockSize, locationInSuperblock);
@@ -341,7 +341,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
private void ResetSkipContext(Av1PartitionInfo partitionInfo)
{
- int planesCount = this.SequenceHeader.ColorConfig.IsMonochrome ? 1 : 3;
+ int planesCount = this.SequenceHeader.ColorConfig.PlaneCount;
for (int i = 0; i < planesCount; i++)
{
bool subX = i > 0 && this.SequenceHeader.ColorConfig.SubSamplingX;
@@ -368,7 +368,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
int modeUnitBlocksHigh = maxUnitSize.GetHeight() >> 2;
modeUnitBlocksWide = Math.Min(maxBlocksWide, modeUnitBlocksWide);
modeUnitBlocksHigh = Math.Min(maxBlocksHigh, modeUnitBlocksHigh);
- int planeCount = this.SequenceHeader.ColorConfig.ChannelCount;
+ int planeCount = this.SequenceHeader.ColorConfig.PlaneCount;
bool isLossless = this.FrameInfo.LosslessArray[partitionInfo.ModeInfo.SegmentId];
bool isLosslessBlock = isLossless && (blockSize >= Av1BlockSize.Block64x64) && (blockSize <= Av1BlockSize.Block128x128);
int subSampling = (this.SequenceHeader.ColorConfig.SubSamplingX ? 1 : 0) + (this.SequenceHeader.ColorConfig.SubSamplingY ? 1 : 0);
@@ -1734,7 +1734,7 @@ internal class Av1TileDecoder : IAv1TileDecoder
int frameLoopFilterCount = 1;
if (this.FrameInfo.DeltaLoopFilterParameters.IsMulti)
{
- frameLoopFilterCount = this.SequenceHeader.ColorConfig.ChannelCount > 1 ? Av1Constants.FrameLoopFilterCount : Av1Constants.FrameLoopFilterCount - 2;
+ frameLoopFilterCount = this.SequenceHeader.ColorConfig.PlaneCount > 1 ? Av1Constants.FrameLoopFilterCount : Av1Constants.FrameLoopFilterCount - 2;
}
Span currentDeltaLoopFilter = partitionInfo.SuperblockInfo.SuperblockDeltaLoopFilter;