From 08cbc5ad1163d46c2852ec822f394f71af05ff27 Mon Sep 17 00:00:00 2001 From: Ynse Hoornenborg Date: Fri, 26 Jul 2024 16:56:21 +0200 Subject: [PATCH] Unit test for Partition Type --- .../Formats/Heif/Av1/Av1PartitionType.cs | 90 ++++++++++++++++++- .../Formats/Heif/Av1/Tiling/Av1TileDecoder.cs | 9 +- .../Formats/Heif/Av1/Av1BlockSizeTests.cs | 12 +-- .../Formats/Heif/Av1/Av1PartitionTypeTests.cs | 61 +++++++++++++ 4 files changed, 162 insertions(+), 10 deletions(-) create mode 100644 tests/ImageSharp.Tests/Formats/Heif/Av1/Av1PartitionTypeTests.cs diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1PartitionType.cs b/src/ImageSharp/Formats/Heif/Av1/Av1PartitionType.cs index 0a6092ce8..11f973a06 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Av1PartitionType.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Av1PartitionType.cs @@ -10,51 +10,139 @@ internal enum Av1PartitionType /// /// Not partitioned any further. /// + /// + /// + /// *** + /// * * + /// *** + /// + /// None = 0, /// /// Horizontally split in 2 partitions. /// + /// + /// + /// *** + /// * * + /// *** + /// * * + /// *** + /// + /// Horizontal = 1, /// /// Vertically split in 2 partitions. /// + /// + /// + /// ***** + /// * * * + /// ***** + /// + /// Vertical = 2, /// /// 4 equally sized partitions. /// + /// + /// + /// ***** + /// * * * + /// ***** + /// * * * + /// ***** + /// + /// Split = 3, /// /// Horizontal split and the top partition is split again. /// + /// + /// + /// ***** + /// * * * + /// ***** + /// * * + /// ***** + /// + /// HorizontalA = 4, /// /// Horizontal split and the bottom partition is split again. /// + /// + /// + /// ***** + /// * * + /// ***** + /// * * * + /// ***** + /// + /// HorizontalB = 5, /// /// Vertical split and the left partition is split again. /// + /// + /// + /// ***** + /// * * * + /// *** * + /// * * * + /// ***** + /// + /// VerticalA = 6, /// - /// Vertical split and the right partitino is split again. + /// Vertical split and the right partition is split again. /// + /// + /// + /// ***** + /// * * * + /// * *** + /// * * * + /// ***** + /// + /// VerticalB = 7, /// /// 4:1 horizontal partition. /// + /// + /// + /// *** + /// * * + /// *** + /// * * + /// *** + /// * * + /// *** + /// * * + /// *** + /// + /// Horizontal4 = 8, /// /// 4:1 vertical partition. /// + /// + /// + /// ********* + /// * * * * * + /// ********* + /// + /// Vertical4 = 9, /// diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs index 569f633b1..a66a8ee46 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs @@ -336,13 +336,14 @@ internal class Av1TileDecoder : IAv1TileDecoder int planesCount = this.SequenceHeader.ColorConfig.PlaneCount; for (int i = 0; i < planesCount; i++) { - bool subX = i > 0 && this.SequenceHeader.ColorConfig.SubSamplingX; - bool subY = i > 0 && this.SequenceHeader.ColorConfig.SubSamplingY; + int subX = (i > 0 && this.SequenceHeader.ColorConfig.SubSamplingX) ? 1 : 0; + int subY = (i > 0 && this.SequenceHeader.ColorConfig.SubSamplingY) ? 1 : 0; Av1BlockSize planeBlockSize = partitionInfo.ModeInfo.BlockSize.GetSubsampled(subX, subY); + DebugGuard.IsTrue(planeBlockSize != Av1BlockSize.Invalid, nameof(planeBlockSize)); int txsWide = planeBlockSize.GetWidth() >> 2; int txsHigh = planeBlockSize.GetHeight() >> 2; - int aboveOffset = (partitionInfo.ColumnIndex - this.FrameInfo.TilesInfo.TileColumnStartModeInfo[partitionInfo.ColumnIndex]) >> (subX ? 1 : 0); - int leftOffset = (partitionInfo.RowIndex - this.FrameInfo.TilesInfo.TileRowStartModeInfo[partitionInfo.RowIndex]) >> (subY ? 1 : 0); + int aboveOffset = (partitionInfo.ColumnIndex - this.FrameInfo.TilesInfo.TileColumnStartModeInfo[partitionInfo.ColumnIndex]) >> subX; + int leftOffset = (partitionInfo.RowIndex - this.FrameInfo.TilesInfo.TileRowStartModeInfo[partitionInfo.RowIndex]) >> subY; this.aboveNeighborContext.ClearContext(i, aboveOffset, txsWide); this.leftNeighborContext.ClearContext(i, leftOffset, txsHigh); } diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1BlockSizeTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1BlockSizeTests.cs index 79b32e92a..7e3506aaa 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1BlockSizeTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1BlockSizeTests.cs @@ -71,6 +71,8 @@ public class Av1BlockSizeTests Av1BlockSize blockSize = (Av1BlockSize)s; int originalWidth = blockSize.GetWidth(); int originalHeight = blockSize.GetHeight(); + int halfWidth = originalWidth / 2; + int halfHeight = originalHeight / 2; // Act Av1BlockSize actualNoNo = blockSize.GetSubsampled(false, false); @@ -84,18 +86,18 @@ public class Av1BlockSizeTests if (actualYesNo != Av1BlockSize.Invalid) { - Assert.Equal(originalWidth, actualYesNo.GetWidth() * 2); + Assert.Equal(halfWidth, actualYesNo.GetWidth()); Assert.Equal(originalHeight, actualYesNo.GetHeight()); } if (actualNoYes != Av1BlockSize.Invalid) { Assert.Equal(originalWidth, actualNoYes.GetWidth()); - Assert.Equal(originalHeight, actualNoYes.GetHeight() * 2); + Assert.Equal(halfHeight, actualNoYes.GetHeight()); } - Assert.Equal(originalWidth, actualYesYes.GetWidth() * 2); - Assert.Equal(originalHeight, actualYesYes.GetHeight() * 2); + Assert.Equal(halfWidth, actualYesYes.GetWidth()); + Assert.Equal(halfHeight, actualYesYes.GetHeight()); } public static TheoryData GetAllSizes() @@ -113,7 +115,7 @@ public class Av1BlockSizeTests { int width = blockSize.GetWidth(); int height = blockSize.GetHeight(); - int ratio = width > height ? width / height : height / width; + int ratio = width >= height ? width / height : -height / width; return ratio; } } diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1PartitionTypeTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1PartitionTypeTests.cs new file mode 100644 index 000000000..e7b073264 --- /dev/null +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1PartitionTypeTests.cs @@ -0,0 +1,61 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using SixLabors.ImageSharp.Formats.Heif.Av1; +using SixLabors.ImageSharp.Formats.Heif.Av1.Transform; + +namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; + +[Trait("Format", "Avif")] +public class Av1PartitionTypeTests +{ + [Theory] + [MemberData(nameof(GetAllCombinations))] + internal void GetSubBlockSizeReturnsCorrectRatio(int t, int s) + { + // Assign + Av1PartitionType partitionType = (Av1PartitionType)t; + Av1BlockSize blockSize = (Av1BlockSize)s; + int expectedRatio = partitionType switch + { + Av1PartitionType.None or Av1PartitionType.Split => 1, + Av1PartitionType.HorizontalA or Av1PartitionType.HorizontalB or Av1PartitionType.Horizontal => 2, + Av1PartitionType.VerticalA or Av1PartitionType.VerticalB or Av1PartitionType.Vertical => -2, + Av1PartitionType.Horizontal4 => 4, + Av1PartitionType.Vertical4 => -4, + _ => -1 + }; + + // Act + Av1BlockSize subBlockSize = partitionType.GetBlockSubSize(blockSize); + + // Assert + if (subBlockSize != Av1BlockSize.Invalid) + { + int actualRatio = GetRatio(subBlockSize); + Assert.Equal(expectedRatio, actualRatio); + } + } + + public static TheoryData GetAllCombinations() + { + TheoryData combinations = []; + for (int t = 0; t <= (int)Av1PartitionType.Vertical4; t++) + { + for (int s = 0; s < (int)Av1BlockSize.AllSizes; s++) + { + combinations.Add(t, s); + } + } + + return combinations; + } + + private static int GetRatio(Av1BlockSize blockSize) + { + int width = blockSize.GetWidth(); + int height = blockSize.GetHeight(); + int ratio = width >= height ? width / height : -height / width; + return ratio; + } +}