diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs index 718497703b..f071eb21d3 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs @@ -113,28 +113,28 @@ internal partial class Av1FrameInfo return this.modeInfos[index]; } - public ref Av1TransformInfo GetSuperblockTransform(int plane, Point index) + public Span GetSuperblockTransform(int plane, Point index) { if (plane == 0) { - return ref this.GetSuperblockTransformY(index); + return this.GetSuperblockTransformY(index); } - return ref this.GetSuperblockTransformUv(index); + return this.GetSuperblockTransformUv(index); } - public ref Av1TransformInfo GetSuperblockTransformY(Point index) + public Span GetSuperblockTransformY(Point index) { Span span = this.transformInfosY; int offset = ((index.Y * this.superblockColumnCount) + index.X) * this.modeInfoCountPerSuperblock; - return ref span[offset]; + return span.Slice(offset, this.modeInfoCountPerSuperblock); } - public ref Av1TransformInfo GetSuperblockTransformUv(Point index) + public Span GetSuperblockTransformUv(Point index) { Span span = this.transformInfosUv; int offset = (((index.Y * this.superblockColumnCount) + index.X) * this.modeInfoCountPerSuperblock) << 1; - return ref span[offset]; + return span.Slice(offset, this.modeInfoCountPerSuperblock); } public Span GetCoefficients(int plane) => diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockInfo.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockInfo.cs index e35658d9e2..4f84d21a76 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockInfo.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockInfo.cs @@ -43,9 +43,9 @@ internal class Av1SuperblockInfo public int BlockCount { get; internal set; } - public ref Av1TransformInfo GetTransformInfoY() => ref this.frameInfo.GetSuperblockTransformY(this.Position); + public Span GetTransformInfoY() => this.frameInfo.GetSuperblockTransformY(this.Position); - public ref Av1TransformInfo GetTransformInfoUv() => ref this.frameInfo.GetSuperblockTransformUv(this.Position); + public Span GetTransformInfoUv() => this.frameInfo.GetSuperblockTransformUv(this.Position); public Av1BlockModeInfo GetModeInfo(Point index) => this.frameInfo.GetModeInfo(this.Position, index); diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs index d75df3f93f..c6acbb6505 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs @@ -413,13 +413,13 @@ internal class Av1TileReader : IAv1TileReader continue; } - ref Av1TransformInfo transformInfoRef = ref (plane == 0) ? ref superblockInfo.GetTransformInfoY() : ref superblockInfo.GetTransformInfoUv(); + Span transformInfoSpan = (plane == 0) ? superblockInfo.GetTransformInfoY() : superblockInfo.GetTransformInfoUv(); if (isLosslessBlock) { // TODO: Implement. int unitHeight = Av1Math.RoundPowerOf2(Math.Min(modeUnitBlocksHigh + row, maxBlocksHigh), 0); int unitWidth = Av1Math.RoundPowerOf2(Math.Min(modeUnitBlocksWide + column, maxBlocksWide), 0); - DebugGuard.IsTrue(Unsafe.Add(ref transformInfoRef, transformInfoIndices[plane]).Size == Av1TransformSize.Size4x4, "Lossless frame shall have transform units of size 4x4."); + DebugGuard.IsTrue(transformInfoSpan[transformInfoIndices[plane]].Size == Av1TransformSize.Size4x4, "Lossless frame shall have transform units of size 4x4."); transformUnitCount = ((unitWidth - column) * (unitHeight - row)) >> (subX + subY); } else @@ -439,7 +439,7 @@ internal class Av1TileReader : IAv1TileReader DebugGuard.IsFalse(transformUnitCount == 0, nameof(transformUnitCount), string.Empty); for (int tu = 0; tu < transformUnitCount; tu++) { - Av1TransformInfo transformInfo = Unsafe.Add(ref transformInfoRef, transformInfoIndices[plane]); + Av1TransformInfo transformInfo = transformInfoSpan[transformInfoIndices[plane]]; DebugGuard.MustBeLessThanOrEqualTo(transformInfo.OffsetX, maxBlocksWide, nameof(transformInfo)); DebugGuard.MustBeLessThanOrEqualTo(transformInfo.OffsetY, maxBlocksHigh, nameof(transformInfo)); @@ -830,8 +830,8 @@ internal class Av1TileReader : IAv1TileReader { int transformInfoYIndex = partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Y]; int transformInfoUvIndex = partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Uv]; - ref Av1TransformInfo lumaTransformInfo = ref superblockInfo.GetTransformInfoY(); - ref Av1TransformInfo chromaTransformInfo = ref superblockInfo.GetTransformInfoUv(); + Span lumaTransformInfo = superblockInfo.GetTransformInfoY(); + Span chromaTransformInfo = superblockInfo.GetTransformInfoUv(); int totalLumaTransformUnitCount = 0; int totalChromaTransformUnitCount = 0; int forceSplitCount = 0; @@ -864,7 +864,7 @@ internal class Av1TileReader : IAv1TileReader { for (int blockColumn = idx; blockColumn < unitWidth; blockColumn += stepColumn) { - Unsafe.Add(ref lumaTransformInfo, transformInfoYIndex) = new Av1TransformInfo( + lumaTransformInfo[transformInfoYIndex] = new Av1TransformInfo( transformSize, blockColumn, blockRow); transformInfoYIndex++; lumaTransformUnitCount++; @@ -889,7 +889,7 @@ internal class Av1TileReader : IAv1TileReader { for (int blockColumn = idx; blockColumn < unitWidth; blockColumn += stepColumn) { - Unsafe.Add(ref chromaTransformInfo, transformInfoUvIndex) = new Av1TransformInfo( + chromaTransformInfo[transformInfoUvIndex] = new Av1TransformInfo( transformSizeUv, blockColumn, blockRow); transformInfoUvIndex++; chromaTransformUnitCount++; @@ -910,8 +910,8 @@ internal class Av1TileReader : IAv1TileReader partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Uv], nameof(totalChromaTransformUnitCount)); int originalIndex = transformInfoUvIndex - totalChromaTransformUnitCount; - ref Av1TransformInfo originalInfo = ref Unsafe.Add(ref chromaTransformInfo, originalIndex); - ref Av1TransformInfo infoV = ref Unsafe.Add(ref chromaTransformInfo, transformInfoUvIndex); + ref Av1TransformInfo originalInfo = ref chromaTransformInfo[originalIndex]; + ref Av1TransformInfo infoV = ref chromaTransformInfo[transformInfoUvIndex]; for (int i = 0; i < totalChromaTransformUnitCount; i++) { infoV = originalInfo; diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs index cfe3fa093c..fc90726a33 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs @@ -75,8 +75,8 @@ internal class Av1BlockDecoder 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; + int subX = (plane > 0) && colorConfig.SubSamplingX ? 1 : 0; + int subY = (plane > 0) && colorConfig.SubSamplingY ? 1 : 0; if (plane != 0 && !partitionInfo.IsChroma) { @@ -90,11 +90,12 @@ internal class Av1BlockDecoder 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); + Span transformInfo = this.frameInfo.GetSuperblockTransform(plane, superblockInfo.Position)[transformInfoIndex..]; + Guard.NotNull(transformInfo[0]); if (isLosslessBlock) { - Guard.IsTrue(transformInfo.Size == Av1TransformSize.Size4x4, nameof(transformInfo.Size), "Lossless may only have 4x4 blocks."); + Guard.IsTrue(transformInfo[0].Size == Av1TransformSize.Size4x4, nameof(transformInfo), "Lossless may only have 4x4 blocks."); transformUnitCount = (maxBlocksWide * maxBlocksHigh) >> (subX + subY); } else @@ -120,10 +121,10 @@ internal class Av1BlockDecoder Span transformBlockReconstructionBuffer; int transformBlockOffset; - transformSize = transformInfo.Size; + transformSize = transformInfo[0].Size; Span coefficients = superblockInfo.GetCoefficients((Av1Plane)plane)[this.currentCoefficientIndex[plane]..]; - transformBlockOffset = ((transformInfo.OffsetY * reconstructionStride) + transformInfo.OffsetX) << Av1Constants.ModeInfoSizeLog2; + transformBlockOffset = ((transformInfo[0].OffsetY * reconstructionStride) + transformInfo[0].OffsetX) << Av1Constants.ModeInfoSizeLog2; transformBlockReconstructionBuffer = blockReconstructionBuffer.Slice(transformBlockOffset << (highBitDepth ? 1 : 0)); if (this.isLoopFilterEnabled) @@ -156,18 +157,18 @@ internal class Av1BlockDecoder transformBlockReconstructionBuffer, reconstructionStride, this.frameBuffer.BitDepth, - transformInfo.OffsetX, - transformInfo.OffsetY); + transformInfo[0].OffsetX, + transformInfo[0].OffsetY); } int numberOfCoefficients = 0; - if (!modeInfo.Skip && transformInfo.CodeBlockFlag) + if (!modeInfo.Skip && transformInfo[0].CodeBlockFlag) { Span quantizationCoefficients = this.CurrentInverseQuantizationCoefficients; int inverseQuantizationSize = transformSize.GetWidth() * transformSize.GetHeight(); quantizationCoefficients[..inverseQuantizationSize].Clear(); - transformType = transformInfo.Type; + transformType = transformInfo[0].Type; // SVT: svt_aom_inverse_quantize numberOfCoefficients = inverseQuantizer.InverseQuantize( @@ -216,7 +217,7 @@ internal class Av1BlockDecoder } // increment transform pointer - transformInfo = ref Unsafe.Add(ref transformInfo, 1); + transformInfo = transformInfo[1..]; } } }