mirror of https://github.com/SixLabors/ImageSharp
8 changed files with 244 additions and 14 deletions
@ -1,11 +1,168 @@ |
|||||
// Copyright (c) Six Labors.
|
// Copyright (c) Six Labors.
|
||||
// Licensed under the Six Labors Split License.
|
// Licensed under the Six Labors Split License.
|
||||
|
|
||||
|
using System.Numerics; |
||||
|
using System.Runtime.CompilerServices; |
||||
|
|
||||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; |
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; |
||||
|
|
||||
internal partial class Av1TileWriter |
internal class Av1NeighborArrayUnit<T> |
||||
|
where T : struct, IMinMaxValue<T> |
||||
{ |
{ |
||||
internal class Av1NeighborArrayUnit |
public static readonly T InvalidNeighborData = T.MaxValue; |
||||
|
|
||||
|
[Flags] |
||||
|
public enum UnitMask |
||||
|
{ |
||||
|
Left = 1, |
||||
|
Top = 2, |
||||
|
TopLeft = 4, |
||||
|
} |
||||
|
|
||||
|
private readonly T[] left; |
||||
|
private readonly T[] top; |
||||
|
private readonly T[] topLeft; |
||||
|
|
||||
|
public Av1NeighborArrayUnit(int leftSize, int topSize, int topLeftSize) |
||||
|
{ |
||||
|
this.left = new T[leftSize]; |
||||
|
this.top = new T[topSize]; |
||||
|
this.topLeft = new T[topLeftSize]; |
||||
|
} |
||||
|
|
||||
|
public Span<T> Left => this.left; |
||||
|
|
||||
|
public Span<T> Top => this.top; |
||||
|
|
||||
|
public Span<T> TopLeft => this.topLeft; |
||||
|
|
||||
|
public required int GranularityNormalLog2 { get; set; } |
||||
|
|
||||
|
public required int GranularityTopLeftLog2 { get; set; } |
||||
|
|
||||
|
public int UnitSize { get; private set; } |
||||
|
|
||||
|
public int GetLeftIndex(Point loc) => loc.Y >> this.GranularityNormalLog2; |
||||
|
|
||||
|
public int GetTopIndex(Point loc) => loc.X >> this.GranularityNormalLog2; |
||||
|
|
||||
|
public int GetTopLeftIndex(Point loc) |
||||
|
=> this.left.Length + (loc.X >> this.GranularityTopLeftLog2) - (loc.Y >> this.GranularityTopLeftLog2); |
||||
|
|
||||
|
public void UnitModeWrite(Span<T> value, Point origin, Size blockSize, UnitMask mask) |
||||
{ |
{ |
||||
|
int idx, j; |
||||
|
|
||||
|
int count; |
||||
|
int na_offset; |
||||
|
int na_unit_size; |
||||
|
|
||||
|
na_unit_size = this.UnitSize; |
||||
|
|
||||
|
if ((mask & UnitMask.Top) == UnitMask.Top) |
||||
|
{ |
||||
|
// Top Neighbor Array
|
||||
|
// ----------12345678---------------------
|
||||
|
// ^ ^
|
||||
|
// | |
|
||||
|
// | |
|
||||
|
// xxxxxxxx
|
||||
|
// x x
|
||||
|
// x x
|
||||
|
// 12345678
|
||||
|
//
|
||||
|
// The top neighbor array is updated with the samples from the
|
||||
|
// bottom row of the source block
|
||||
|
//
|
||||
|
// Index = org_x
|
||||
|
na_offset = this.GetTopIndex(origin); |
||||
|
|
||||
|
ref T dst_ptr = ref this.Top[na_offset * na_unit_size]; |
||||
|
|
||||
|
count = blockSize.Width >> this.GranularityNormalLog2; |
||||
|
|
||||
|
for (idx = 0; idx < count; ++idx) |
||||
|
{ |
||||
|
/* svt_memcpy less that 10 bytes*/ |
||||
|
for (j = 0; j < na_unit_size; ++j) |
||||
|
{ |
||||
|
dst_ptr = value[j]; |
||||
|
dst_ptr = Unsafe.Add(ref dst_ptr, 1); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if ((mask & UnitMask.Left) == UnitMask.Left) |
||||
|
{ |
||||
|
// Left Neighbor Array
|
||||
|
//
|
||||
|
// |
|
||||
|
// |
|
||||
|
// 1 xxxxxxx1
|
||||
|
// 2 <---- x 2
|
||||
|
// 3 <---- x 3
|
||||
|
// 4 xxxxxxx4
|
||||
|
// |
|
||||
|
// |
|
||||
|
//
|
||||
|
// The left neighbor array is updated with the samples from the
|
||||
|
// right column of the source block
|
||||
|
//
|
||||
|
// Index = org_y
|
||||
|
na_offset = this.GetLeftIndex(origin); |
||||
|
|
||||
|
ref T dst_ptr = ref this.Left[na_offset * na_unit_size]; |
||||
|
|
||||
|
count = blockSize.Height >> this.GranularityNormalLog2; |
||||
|
|
||||
|
for (idx = 0; idx < count; ++idx) |
||||
|
{ |
||||
|
/* svt_memcpy less that 10 bytes*/ |
||||
|
for (j = 0; j < na_unit_size; ++j) |
||||
|
{ |
||||
|
dst_ptr = value[j]; |
||||
|
dst_ptr = Unsafe.Add(ref dst_ptr, 1); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if ((mask & UnitMask.TopLeft) == UnitMask.TopLeft) |
||||
|
{ |
||||
|
// Top-left Neighbor Array
|
||||
|
//
|
||||
|
// 4-5--6--7------------
|
||||
|
// 3 \ \
|
||||
|
// 2 \ \
|
||||
|
// 1 \ \
|
||||
|
// |\ xxxxxx7
|
||||
|
// | \ x 6
|
||||
|
// | \ x 5
|
||||
|
// | \1x2x3x4
|
||||
|
// |
|
||||
|
//
|
||||
|
// The top-left neighbor array is updated with the reversed samples
|
||||
|
// from the right column and bottom row of the source block
|
||||
|
//
|
||||
|
// Index = org_x - org_y
|
||||
|
Point topLeft = origin; |
||||
|
topLeft.Offset(0, blockSize.Height - 1); |
||||
|
na_offset = this.GetTopLeftIndex(topLeft); |
||||
|
|
||||
|
// Copy bottom-row + right-column
|
||||
|
// *Note - start from the bottom-left corner
|
||||
|
ref T dst_ptr = ref this.TopLeft[na_offset * na_unit_size]; |
||||
|
|
||||
|
count = ((blockSize.Width + blockSize.Height) >> this.GranularityTopLeftLog2) - 1; |
||||
|
|
||||
|
for (idx = 0; idx < count; ++idx) |
||||
|
{ |
||||
|
/* svt_memcpy less that 10 bytes*/ |
||||
|
for (j = 0; j < na_unit_size; ++j) |
||||
|
{ |
||||
|
dst_ptr = value[j]; |
||||
|
dst_ptr = Unsafe.Add(ref dst_ptr, 1); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,13 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Six Labors Split License.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.Formats.Heif.Av1.Transform; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; |
||||
|
|
||||
|
internal class Av1TransformUnit |
||||
|
{ |
||||
|
public ushort[] NzCoefficientCount { get; } = new ushort[3]; |
||||
|
|
||||
|
public Av1TransformType[] TransformType { get; } = new Av1TransformType[Av1Constants.PlaneTypeCount]; |
||||
|
} |
||||
Loading…
Reference in new issue