mirror of https://github.com/SixLabors/ImageSharp
3 changed files with 140 additions and 1 deletions
@ -0,0 +1,119 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Six Labors Split License.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.Memory; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Formats.Heif.Hevc; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Owns the native-precision luma and chroma sample planes for one reconstructed HEVC still picture.
|
||||
|
/// </summary>
|
||||
|
internal sealed class HevcPictureBuffer : IDisposable |
||||
|
{ |
||||
|
/// <summary>The horizontal chroma subsampling shift.</summary>
|
||||
|
private readonly int chromaSubsamplingX; |
||||
|
|
||||
|
/// <summary>The vertical chroma subsampling shift.</summary>
|
||||
|
private readonly int chromaSubsamplingY; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="HevcPictureBuffer"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="configuration">The configuration providing the image memory allocator.</param>
|
||||
|
/// <param name="sequenceParameterSet">The coded dimensions, precision, and chroma layout.</param>
|
||||
|
public HevcPictureBuffer(Configuration configuration, HevcSequenceParameterSet sequenceParameterSet) |
||||
|
{ |
||||
|
this.Width = sequenceParameterSet.Width; |
||||
|
this.Height = sequenceParameterSet.Height; |
||||
|
this.BitDepthLuma = sequenceParameterSet.BitDepthLuma; |
||||
|
this.BitDepthChroma = sequenceParameterSet.BitDepthChroma; |
||||
|
this.ChromaFormat = sequenceParameterSet.ChromaFormat; |
||||
|
this.SeparateColorPlane = sequenceParameterSet.SeparateColorPlaneFlag; |
||||
|
|
||||
|
// Separate color planes are independently coded at full resolution even though chroma_format_idc is 4:4:4.
|
||||
|
this.chromaSubsamplingX = !this.SeparateColorPlane && this.ChromaFormat is 1 or 2 ? 1 : 0; |
||||
|
this.chromaSubsamplingY = !this.SeparateColorPlane && this.ChromaFormat == 1 ? 1 : 0; |
||||
|
this.Luma = configuration.MemoryAllocator.Allocate2D<ushort>(this.Width, this.Height); |
||||
|
if (this.ChromaFormat != 0) |
||||
|
{ |
||||
|
int chromaWidth = DivideCeilingByPowerOfTwo(this.Width, this.chromaSubsamplingX); |
||||
|
int chromaHeight = DivideCeilingByPowerOfTwo(this.Height, this.chromaSubsamplingY); |
||||
|
|
||||
|
this.ChromaBlue = configuration.MemoryAllocator.Allocate2D<ushort>(chromaWidth, chromaHeight); |
||||
|
this.ChromaRed = configuration.MemoryAllocator.Allocate2D<ushort>(chromaWidth, chromaHeight); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>Gets the coded luma width in samples.</summary>
|
||||
|
public int Width { get; } |
||||
|
|
||||
|
/// <summary>Gets the coded luma height in samples.</summary>
|
||||
|
public int Height { get; } |
||||
|
|
||||
|
/// <summary>Gets the luma sample precision in bits.</summary>
|
||||
|
public int BitDepthLuma { get; } |
||||
|
|
||||
|
/// <summary>Gets the chroma sample precision in bits.</summary>
|
||||
|
public int BitDepthChroma { get; } |
||||
|
|
||||
|
/// <summary>Gets the HEVC chroma-format identifier.</summary>
|
||||
|
public byte ChromaFormat { get; } |
||||
|
|
||||
|
/// <summary>Gets a value indicating whether the three planes are coded as independent full-resolution color planes.</summary>
|
||||
|
public bool SeparateColorPlane { get; } |
||||
|
|
||||
|
/// <summary>Gets the luma or first separate-color-plane allocation.</summary>
|
||||
|
public Buffer2D<ushort> Luma { get; } |
||||
|
|
||||
|
/// <summary>Gets the blue-difference chroma or second separate-color-plane allocation.</summary>
|
||||
|
public Buffer2D<ushort>? ChromaBlue { get; } |
||||
|
|
||||
|
/// <summary>Gets the red-difference chroma or third separate-color-plane allocation.</summary>
|
||||
|
public Buffer2D<ushort>? ChromaRed { get; } |
||||
|
|
||||
|
/// <summary>Gets the horizontal chroma subsampling shift for the selected plane.</summary>
|
||||
|
/// <param name="plane">The reconstruction plane.</param>
|
||||
|
/// <returns>Zero for luma and full-resolution planes; otherwise, the chroma shift.</returns>
|
||||
|
public int GetSubsamplingX(HevcPlane plane) => plane == HevcPlane.Y ? 0 : this.chromaSubsamplingX; |
||||
|
|
||||
|
/// <summary>Gets the vertical chroma subsampling shift for the selected plane.</summary>
|
||||
|
/// <param name="plane">The reconstruction plane.</param>
|
||||
|
/// <returns>Zero for luma and full-resolution planes; otherwise, the chroma shift.</returns>
|
||||
|
public int GetSubsamplingY(HevcPlane plane) => plane == HevcPlane.Y ? 0 : this.chromaSubsamplingY; |
||||
|
|
||||
|
/// <summary>Gets the selected plane width in samples.</summary>
|
||||
|
/// <param name="plane">The reconstruction plane.</param>
|
||||
|
/// <returns>The coded plane width.</returns>
|
||||
|
public int GetWidth(HevcPlane plane) => DivideCeilingByPowerOfTwo(this.Width, this.GetSubsamplingX(plane)); |
||||
|
|
||||
|
/// <summary>Gets the selected plane height in samples.</summary>
|
||||
|
/// <param name="plane">The reconstruction plane.</param>
|
||||
|
/// <returns>The coded plane height.</returns>
|
||||
|
public int GetHeight(HevcPlane plane) => DivideCeilingByPowerOfTwo(this.Height, this.GetSubsamplingY(plane)); |
||||
|
|
||||
|
/// <summary>Gets one coded row from the selected reconstruction plane.</summary>
|
||||
|
/// <param name="plane">The reconstruction plane.</param>
|
||||
|
/// <param name="row">The zero-based row index in plane samples.</param>
|
||||
|
/// <returns>The complete coded plane row.</returns>
|
||||
|
public Span<ushort> GetRowSpan(HevcPlane plane, int row) |
||||
|
=> plane switch |
||||
|
{ |
||||
|
HevcPlane.Y => this.Luma.DangerousGetRowSpan(row), |
||||
|
HevcPlane.Cb => this.ChromaBlue!.DangerousGetRowSpan(row), |
||||
|
_ => this.ChromaRed!.DangerousGetRowSpan(row), |
||||
|
}; |
||||
|
|
||||
|
/// <summary>Releases the owned luma and chroma plane allocations.</summary>
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
this.Luma.Dispose(); |
||||
|
this.ChromaBlue?.Dispose(); |
||||
|
this.ChromaRed?.Dispose(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>Divides a nonnegative sample count by a power of two with upward rounding.</summary>
|
||||
|
/// <param name="value">The sample count.</param>
|
||||
|
/// <param name="shift">The base-two divisor logarithm.</param>
|
||||
|
/// <returns>The upward-rounded quotient.</returns>
|
||||
|
private static int DivideCeilingByPowerOfTwo(int value, int shift) => (value + (1 << shift) - 1) >> shift; |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Six Labors Split License.
|
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Formats.Heif.Hevc; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Identifies an HEVC luma or chroma reconstruction plane.
|
||||
|
/// </summary>
|
||||
|
internal enum HevcPlane |
||||
|
{ |
||||
|
/// <summary>The luma or first separate-color plane.</summary>
|
||||
|
Y = 0, |
||||
|
|
||||
|
/// <summary>The blue-difference chroma or second separate-color plane.</summary>
|
||||
|
Cb = 1, |
||||
|
|
||||
|
/// <summary>The red-difference chroma or third separate-color plane.</summary>
|
||||
|
Cr = 2, |
||||
|
} |
||||
Loading…
Reference in new issue