diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1BlockSize.cs b/src/ImageSharp/Formats/Heif/Av1/Av1BlockSize.cs index 5a524c261d..92a651d60f 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Av1BlockSize.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Av1BlockSize.cs @@ -3,7 +3,7 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1; -internal enum Av1BlockSize +internal enum Av1BlockSize : byte { // See sction 6.10.4 of the Av1 Specification. diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1LookupTables.cs b/src/ImageSharp/Formats/Heif/Av1/Av1LookupTables.cs new file mode 100644 index 0000000000..a7e9ab7998 --- /dev/null +++ b/src/ImageSharp/Formats/Heif/Av1/Av1LookupTables.cs @@ -0,0 +1,34 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Heif.Av1; + +internal static class Av1LookupTables +{ + // The Subsampled_Size table in the spec (Section 5.11.38. Get plane residual size function). + public static Av1BlockSize[,,] SubSampledSize = + { + { { Av1BlockSize.Block4x4, Av1BlockSize.Block4x4 }, { Av1BlockSize.Block4x4, Av1BlockSize.Block4x4 } }, + { { Av1BlockSize.Block4x8, Av1BlockSize.Block4x4 }, { Av1BlockSize.Invalid, Av1BlockSize.Block4x4 } }, + { { Av1BlockSize.Block8x4, Av1BlockSize.Invalid }, { Av1BlockSize.Block4x4, Av1BlockSize.Block4x4 } }, + { { Av1BlockSize.Block8x8, Av1BlockSize.Block8x4 }, { Av1BlockSize.Block4x8, Av1BlockSize.Block4x4 } }, + { { Av1BlockSize.Block8x16, Av1BlockSize.Block8x8 }, { Av1BlockSize.Invalid, Av1BlockSize.Block4x8 } }, + { { Av1BlockSize.Block16x8, Av1BlockSize.Invalid }, { Av1BlockSize.Block8x8, Av1BlockSize.Block8x4 } }, + { { Av1BlockSize.Block16x16, Av1BlockSize.Block16x8 }, { Av1BlockSize.Block8x16, Av1BlockSize.Block8x8 } }, + { { Av1BlockSize.Block16x32, Av1BlockSize.Block16x16 }, { Av1BlockSize.Invalid, Av1BlockSize.Block8x16 } }, + { { Av1BlockSize.Block32x16, Av1BlockSize.Invalid }, { Av1BlockSize.Block16x16, Av1BlockSize.Block16x8 } }, + { { Av1BlockSize.Block32x32, Av1BlockSize.Block32x16 }, { Av1BlockSize.Block16x32, Av1BlockSize.Block16x16 } }, + { { Av1BlockSize.Block32x64, Av1BlockSize.Block32x32 }, { Av1BlockSize.Invalid, Av1BlockSize.Block16x32 } }, + { { Av1BlockSize.Block64x32, Av1BlockSize.Invalid }, { Av1BlockSize.Block32x32, Av1BlockSize.Block32x16 } }, + { { Av1BlockSize.Block64x64, Av1BlockSize.Block64x32 }, { Av1BlockSize.Block32x64, Av1BlockSize.Block32x32 } }, + { { Av1BlockSize.Block64x128, Av1BlockSize.Block64x64 }, { Av1BlockSize.Invalid, Av1BlockSize.Block32x64 } }, + { { Av1BlockSize.Block128x64, Av1BlockSize.Invalid }, { Av1BlockSize.Block64x64, Av1BlockSize.Block64x32 } }, + { { Av1BlockSize.Block128x128, Av1BlockSize.Block128x64 }, { Av1BlockSize.Block64x128, Av1BlockSize.Block64x64 } }, + { { Av1BlockSize.Block4x16, Av1BlockSize.Block4x8 }, { Av1BlockSize.Invalid, Av1BlockSize.Block4x8 } }, + { { Av1BlockSize.Block16x4, Av1BlockSize.Invalid }, { Av1BlockSize.Block8x4, Av1BlockSize.Block8x4 } }, + { { Av1BlockSize.Block8x32, Av1BlockSize.Block8x16 }, { Av1BlockSize.Invalid, Av1BlockSize.Block4x16 } }, + { { Av1BlockSize.Block32x8, Av1BlockSize.Invalid }, { Av1BlockSize.Block16x8, Av1BlockSize.Block16x4 } }, + { { Av1BlockSize.Block16x64, Av1BlockSize.Block16x32 }, { Av1BlockSize.Invalid, Av1BlockSize.Block8x32 } }, + { { Av1BlockSize.Block64x16, Av1BlockSize.Invalid }, { Av1BlockSize.Block32x16, Av1BlockSize.Block32x8 } }, + }; +} diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs index c286b34b6a..4308ff3326 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileDecoder.cs @@ -451,7 +451,19 @@ internal class Av1TileDecoder : IAv1TileDecoder private Av1TransformSize GetSize(int plane, object transformSize) => throw new NotImplementedException(); - private Av1BlockSize GetPlaneResidualSize(Av1BlockSize sizeChunk, int plane) => throw new NotImplementedException(); + /// + /// 5.11.38. Get plane residual size function. + /// The GetPlaneResidualSize returns the size of a residual block for the specified plane. (The residual block will always + /// have width and height at least equal to 4.) + /// + private Av1BlockSize GetPlaneResidualSize(Av1BlockSize sizeChunk, int plane) + { + int subsamplingX = this.SequenceHeader.ColorConfig.SubSamplingX ? 1 : 0; + int subsamplingY = this.SequenceHeader.ColorConfig.SubSamplingY ? 1 : 0; + int subX = plane > 0 ? subsamplingX : 0; + int subY = plane > 0 ? subsamplingY : 0; + return Av1LookupTables.SubSampledSize[(byte)sizeChunk, subX, subY]; + } /// /// 5.11.35. Transform block syntax.