From bc9755473ea93212a5ec1535bbf7d9565c2bfc10 Mon Sep 17 00:00:00 2001 From: Ynse Hoornenborg Date: Tue, 26 Dec 2023 12:15:28 +0100 Subject: [PATCH] Initial Metadata parsing --- .../Formats/Heic/FourCharacterCode.cs | 209 ++++++++++ src/ImageSharp/Formats/Heic/HeicBoxType.cs | 26 ++ src/ImageSharp/Formats/Heic/HeicConstants.cs | 2 + .../Formats/Heic/HeicDecoderCore.cs | 363 +++++++++++++++++- .../Formats/Heic/HeicImageFormatDetector.cs | 10 +- src/ImageSharp/Formats/Heic/HeicItem.cs | 32 ++ .../Formats/Heic/HeicItemPropertyType.cs | 23 ++ .../Formats/Heic/HeicMetaSubBoxType.cs | 22 ++ .../Formats/Heic/HeicNalUnitType.cs | 52 ++- src/ImageSharp/Formats/Heic/Readme.md | 9 + 10 files changed, 712 insertions(+), 36 deletions(-) create mode 100644 src/ImageSharp/Formats/Heic/FourCharacterCode.cs create mode 100644 src/ImageSharp/Formats/Heic/HeicBoxType.cs create mode 100644 src/ImageSharp/Formats/Heic/HeicItem.cs create mode 100644 src/ImageSharp/Formats/Heic/HeicItemPropertyType.cs create mode 100644 src/ImageSharp/Formats/Heic/HeicMetaSubBoxType.cs create mode 100644 src/ImageSharp/Formats/Heic/Readme.md diff --git a/src/ImageSharp/Formats/Heic/FourCharacterCode.cs b/src/ImageSharp/Formats/Heic/FourCharacterCode.cs new file mode 100644 index 0000000000..ad4cad7443 --- /dev/null +++ b/src/ImageSharp/Formats/Heic/FourCharacterCode.cs @@ -0,0 +1,209 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Heic; + +/// +/// Provides constants for 4 Character codes used in HEIC images. +/// +public static class FourCharacterCode +{ + // TODO: Create T4 template for this file + + /// + /// File Type + /// + public const uint ftyp = 0x66747970U, + + /// + /// Metadata container + /// + public const uint meta = 0x6D657461U, + + /// + /// Media Data + /// + public const uint mdat = 0x6D646174U, + + /// + /// Item Information Entry + /// + public const uint infe = 0x696E6665U, + + /// + /// Item Data + /// + public const uint idat = 0x69646174U, + + /// + /// Item Location + /// + public const uint iloc = 0x696C6F63U, + + /// + /// EXIF metadata + /// + public const uint Exif = 0x45786966U, + + /// + /// Data Reference + /// + public const uint dref = 0x64726566U, + + /// + /// Primary Item + /// + public const uint pitm = 0x7069746DU, + + /// + /// Item Spatial Extent + /// + public const uint ispe = 0x69737064U, + + /// + /// Alternative text + /// + public const uint altt = 0, // 'altt' + + /// + /// Colour information + /// + public const uint colr = 0, // 'colr' + + /// + /// HVC configuration + /// + public const uint hvcC = 0, // 'hvcC' + + /// + /// Image Mirror + /// + public const uint imir = 0, // 'imir' + + /// + /// Image Rotation + /// + public const uint irot = 0, // 'irot' + + /// + /// Image Scaling + /// + public const uint iscl = 0, // 'iscl' + + /// + /// Pixel Aspect Ration + /// + public const uint pasp = 0, // 'pasp' + + /// + /// Pixel Information + /// + public const uint pixi = 0x70697869U, + + /// + /// Reference Location + /// + public const uint rloc = 0, // 'rloc + + /// + /// User Description + /// + public const uint udes = 0, // 'udes' + + /// + /// Item Property Container + /// + public const uint ipco = 0, + + /// + /// Item Property Association + /// + public const uint ipma = 0, + + /// + /// High Efficient Image Coding + /// + public const uint heic = 0, + + /// + /// High Efficiency Coding tile + /// + public const uint hvc1 = 0, + + /// + /// Data Information + /// + public const uint dinf = 0, + + /// + /// Group list + /// + public const uint grpl = 0, + + /// + /// Handler + /// + public const uint hdlr = 0, + + /// + /// Item Data + /// + public const uint idat = 0, // 'idat' + + /// + /// Item Information + /// + public const uint iinf = 0, // 'iinf' + + /// + /// Item Property + /// + public const uint iprp = 0, // 'iprp' + + /// + /// Item Protection + /// + public const uint ipro = 0, // 'ipro' + + /// + /// Item Reference + /// + public const uint iref = 0, // 'iref' + + /// + /// Grid + /// + public const uint grid = 0, // 'grid' + + /// + /// Derived Image + /// + public const uint dimg = 0, // 'dimg' + + /// + /// Thumbnail + /// + public const uint thmb = 0, // 'thmb' + + /// + /// Content Description + /// + public const uint cdsc = 0, // 'cdsc' + + public static uint Parse(string code) + { + if (code.Length != 4) + { + throw new ImageFormatException(); + } + Span span = Encoding.UTF8.GetBytes(code); + return BinaryPrimitives.ReadUInt32BigEndian(buffer); + } + + public static string ToString(uint fourcc) + { + Span span = stackalloc new byte[4]; + BinaryPrimitives.WriteUInt32BigEndian(buffer, fourcc); + return Encoding.UTF8.GetString(span); + } +} diff --git a/src/ImageSharp/Formats/Heic/HeicBoxType.cs b/src/ImageSharp/Formats/Heic/HeicBoxType.cs new file mode 100644 index 0000000000..45cecacb68 --- /dev/null +++ b/src/ImageSharp/Formats/Heic/HeicBoxType.cs @@ -0,0 +1,26 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Heic; + +/// +/// Provides enumeration of supported ISO Base Format Box Types for HEIC. +/// +public enum HeicBoxType : uint +{ + FileType = FourCharacterCode.ftyp, + Meta = FourCharacterCode.meta, + MediaData = FourCharacterCode.mdat, + ItemInfo = FourCharacterCode.infe + ItemData = FourCharacterCode.idat, + ItemLocation = FourCharacterCode.iloc, + Exif = FourCharacterCode.Exif, + ItemPropertyAssociation = FourCharacterCode.ipma, + DataReference = FourCharacterCode.dref, + PrimaryItemReference = FourCharacterCode.pitm, + ImageSpatialExtentsProperty = FourCharacterCode.ispe, + + // Possible box types outside of HEIC images: + Movie = FourCharacterCode.moov, + Track = FourCharacterCode.trak, +} diff --git a/src/ImageSharp/Formats/Heic/HeicConstants.cs b/src/ImageSharp/Formats/Heic/HeicConstants.cs index 99c9b8da66..62ee248f01 100644 --- a/src/ImageSharp/Formats/Heic/HeicConstants.cs +++ b/src/ImageSharp/Formats/Heic/HeicConstants.cs @@ -8,6 +8,8 @@ namespace SixLabors.ImageSharp.Formats.Heic; /// internal static class HeicConstants { + public const uint HeicBrand = FourCharacterCode.heic; + /// /// The list of mimetypes that equate to a HEIC. /// diff --git a/src/ImageSharp/Formats/Heic/HeicDecoderCore.cs b/src/ImageSharp/Formats/Heic/HeicDecoderCore.cs index 34369e26e8..551696e912 100644 --- a/src/ImageSharp/Formats/Heic/HeicDecoderCore.cs +++ b/src/ImageSharp/Formats/Heic/HeicDecoderCore.cs @@ -25,6 +25,10 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals /// private ImageMetadata? metadata; + private List items; + + private List itemLinks; + /// /// Initializes a new instance of the class. /// @@ -45,28 +49,375 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { - this.ProcessHeader(stream); + if (!this.CheckFileTypeBox(stream)) + { + throw new InvalidImageFormatException(); + } + + while (!stream.Eof) + { + var length = ReadBoxHeader(stream, out var boxType); + switch (boxType) + { + case HeicBoxType.Meta: + ParseMetadata(stream, length); + break; + case HeicBoxType.MediaData: + ParseMediaData(stream, length); + break; + default: + throw new ImageFormatException($"Unknown box type of '{FourCharacterCode.ToString(boxType)}'"); + } + } var image = new Image(this.configuration, this.pixelSize.Width, this.pixelSize.Height, this.metadata); Buffer2D pixels = image.GetRootFramePixelBuffer(); - // TODO: Implement - return image; } /// public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken) { - this.ProcessHeader(stream); + this.CheckFileTypeBox(stream); - // TODO: Implement + while (!stream.Eof) + { + var length = ReadBoxHeader(stream, out var boxType); + var buffer = new byte[length]; + stream.Read(buffer); + switch (boxType) + { + case HeicBoxType.Metadata: + ParseMetadata(buffer); + break; + default: + // Silently skip all other box types. + break; + } + } return new ImageInfo(new PixelTypeInfo(bitsPerPixel), new(this.pixelSize.Width, this.pixelSize.Height), this.metadata); } - private void ReadNals(BufferedReadStream stream) { + private bool CheckFileTypeBox(BufferedReadStream stream) + { + var boxLength = ReadBoxHeader(stream, out var boxType); + Span buffer = stackalloc new byte[boxLength]; + stream.Read(buffer); + var majorBrand = BinaryPrimitives.ReadUInt32BigEndian(buf); + // TODO: Interpret minorVersion and compatible brands. + return boxTypepe == HeicBoxType.FileType && majorBrand == HeicConstants.HeicBrand; + } + + private ulong ReadBoxHeader(BufferedReadStream stream, out uint boxType) + { + // Read 4 bytes of length of box + Span buf = stackalloc new byte[8]; + stream.Read(buf); + ulong boxSize = BinaryPrimitives.ReadUInt32BigEndian(buf); + ulong headerSize = 8; + // Read 4 bytes of box type + boxType = BinaryPrimitives.ReadUInt32BigEndian(buf.Slice(4)); + + if (boxSize == 1) + { + stream.Read(buf); + boxSize = BinaryPrimitives.ReadUInt64BigEndian(buf); + headerSize += 8UL; + } + + return boxSize - headerSize; + } + + private uint ParseBoxHeader(Span buffer, out ulong length, out uint boxType) + { + ulong boxSize = BinaryPrimitives.ReadUInt32BigEndian(buffer); + ulong bytesRead = 4; + boxType = BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(bytesRead)); + bytesRead += 4; + if (boxSize == 1) + { + boxSize = BinaryPrimitives.ReadUInt64BigEndian(buffer.Slice(bytesRead)); + bytesRead += 8; + } + + length = boxSize - bytesRead; + return bytesRead; + } + + private void ParseMetadata(BufferedReadStream stream, uint boxLength) + { + var endPosition = stream.Position + boxLength; + while (stream.Position < endPosition) + { + var length = ReadBoxHeader(stream, out var boxType); + switch (boxType) + { + case HeicMetaSubBoxType.ItemProperty: + ParseItemPropertyContainer(stream, length); + break; + case HeicMetaSubBoxType.ItemInfo: + ParseItemInfo(stream, length); + break; + case HeicMetaSubBoxType.ItemReference: + ParseItemReference(stream, length); + break; + case HeicMetaSubBoxType.DataInformation: + case HeicMetaSubBoxType.GroupsList: + case HeicMetaSubBoxType.Handler: + case HeicMetaSubBoxType.ItemData: + case HeicMetaSubBoxType.ItemLocation: + case HeicMetaSubBoxType.ItemProtection: + case HeicMetaSubBoxType.PrimaryItem: + // TODO: Implement + break; + default: + throw new ImageFormatException($"Unknown metadata box type of '{FourCharacterCode.ToString(boxType)}'"); + } + } + } + + private void ParseItemInfo(BufferedReadStream stream, uint boxLength) + { + Span buffer = new byte[length]; + stream.Read(buffer); + uint entryCount; + int bytesRead = 0; + if (buffer[bytesRead] == 0) + { + bytesRead += 4; + entryCount = BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(bytesRead)); + bytesRead += 2; + } + else + { + bytesRead += 4; + entryCount = BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(bytesRead)); + bytesRead += 4; + } + + for(uint i = 0; i < entryCount; i++) + { + bytesRead += ParseBoxHeader(out var subBoxLength, out var boxType); + ParseItemInfoEntry(buffer.Slice(bytesRead, subBoxLength)); + bytesRead += subBoxLength; + } + } + + private void ParseItemInfoEntry(Span buffer, uint boxLength) + { + int bytesRead = 0; + var version = buffer[bytesRead]; + bytesRead += 4; + var item = new HeicItem(); + if (version == 0 || version == 1) + { + item.Id = BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(bytesRead)); + bytesRead += 2; + item.ProtectionIndex = BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(bytesRead)); + bytesRead += 2; + item.Name = ReadNullTerminatedString(buffer.Slice(bytesRead)); + bytesRead += item.Name.Length + 1; + item.ContentType = ReadNullTerminatedString(buffer.Slice(bytesRead)); + bytesRead += item.ContentType.Length + 1; + // Optional field. + if (bytesRead < boxLength) + { + item.ContentEncoding = ReadNullTerminatedString(buffer.Slice(bytesRead)); + bytesRead += item.ContentEncoding.Length + 1; + } + } + + if (version == 1) + { + // Optional fields. + if (bytesRead < boxLength) + { + item.ExtensionType = BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(bytesRead)); + bytesRead += 4; + } + + if (bytesRead < boxLength) + { + // TODO: Parse item.Extension + } + } + + if (version >= 2) + { + if (getVersion() == 2) + { + item.Id = BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(bytesRead)); + bytesRead += 2; + } + else if (getVersion() == 3) + { + item.Id = BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(bytesRead)); + bytesRead += 4; + } + + item.ProtectionIndex = BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(bytesRead)); + bytesRead += 2; + item.Type = BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(bytesRead)); + bytesRead += 4; + item.Name = ReadNullTerminatedString(buffer.Slice(bytesRead)); + bytesRead += item.Name.Length + 1; + if (item.Type == "mime") + { + item.ContentType = ReadNullTerminatedString(buffer.Slice(bytesRead)); + bytesRead += item.ContentType.Length + 1; + // Optional field. + if (bytesRead < boxLength) + { + item.ContentEncoding = ReadNullTerminatedString(buffer.Slice(bytesRead)); + bytesRead += item.ContentEncoding.Length + 1; + } + } + else if (item.Type == "uri ") + { + item.UriType = ReadNullTerminatedString(buffer.Slice(bytesRead)); + bytesRead += item.ContentEncoding.Length + 1; + } + } + } + + private void ParseItemReference(BufferedReadStream stream, uint boxLength) + { + Span buffer = new byte[length]; + stream.Read(buffer); + int bytesRead = 0; + bool largeIds = buffer[bytesRead] != 0; + bytesRead += 4; + while(bytesRead < boxLength) + { + ParseBoxHeader(buffer.Slice(bytesRead), out var subBoxLength, out var linkType); + var link = new HeicItemLink(); + link.Type = linkType; + if (largeIds) + { + link.Source = BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(bytesRead)); + bytesRead += 4; + } + else + { + link.Source = BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(bytesRead)); + bytesRead += 2; + } + + var count = BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(bytesRead)); + bytesRead += 2; + for(uint i = 0; i < count; i++) + { + uint destId; + if (largeIds) + { + destId = BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(bytesRead)); + bytesRead += 4; + } + else + { + destId = BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(bytesRead)); + bytesRead += 2; + } + link.Destinations.Add(destId); + } + itemLinks.Add(link); + } } + private void ParseItemPropertyContainer(BufferedReadStream stream, uint boxLength) + { + var containerLength = ReadBoxHeader(stream, out var containerType); + if (containerType == FourCharacterCode.ipco) + { + // Parse Item Property Container, which is just an array of preperty boxes. + var endPosition = stream.Position + containerLength; + while (stream.Position < endPosition) + { + var length = ReadBoxHeader(stream, out var boxType); + switch (boxType) + { + case HeicItemPropertyType.ImageSpatialExtents: + // Length should be 12. + Span buffer = stackalloc new byte[length]; + stream.Read(buffer); + // Skip over version (8 bits) and flags (24 bits). + var width = BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(4)); + var height = BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(8)); + break; + case HeicItemPropertyType.PixelAspectRatio: + // Length should be 8. + Span buffer = stackalloc new byte[length]; + stream.Read(buffer); + var horizontalSpacing = BinaryPrimitives.ReadUInt32BigEndian(buffer); + var verticalSpacing = BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(4)); + break; + case HeicItemPropertyType.PixelInformation: + Span buffer = stackalloc new byte[length]; + stream.Read(buffer); + // Skip over version (8 bits) and flags (24 bits). + var channelCount = buffer[4]; + int offset = 5; + int bitsPerPixel = 0; + for (int i = 0; i < channelCount; i++) + { + bitsPerPixel += buffer[i]; + } + break; + case HeicItemPropertyType.AcessibilityText: + case HeicItemPropertyType.ImageMirror: + case HeicItemPropertyType.ImageRotation: + case HeicItemPropertyType.ImageScaling: + case HeicItemPropertyType.RelativeLocation: + case HeicItemPropertyType.UserDescription; + // TODO: Implement + break; + default: + throw new ImageFormatException($"Unknown item property box type of '{FourCharacterCode.ToString(boxType)}'"); + } + } + } + else if (containerType == FourCharacterCode.ipma) + { + // Parse Item Property Association + } + } + + private void ParseMediaData(BufferedReadStream stream, uint boxLength) + { + // TODO: Implement + } + + /// + /// Forwards the stream to just past the Start of NAL marker. + /// + private void FindStartOfNal(BufferedReadStream stream) + { + uint i = stream.Position; + uint length = 0; + var dataLength = stream.Length; + + while (i < streamLength) + { + var current = stream.ReadByte(); + if (current == 0) + { + length++; + } + else if (length > 1 && current == 1) + { + // Found the marker ! + //length++; + break; + } + else + { + // False alarm, resetting... + length = 0; + } + i++; + } + } } diff --git a/src/ImageSharp/Formats/Heic/HeicImageFormatDetector.cs b/src/ImageSharp/Formats/Heic/HeicImageFormatDetector.cs index a220320f35..583d9f4f54 100644 --- a/src/ImageSharp/Formats/Heic/HeicImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Heic/HeicImageFormatDetector.cs @@ -10,6 +10,10 @@ namespace SixLabors.ImageSharp.Formats.Heic; /// public sealed class HeicImageFormatDetector : IImageFormatDetector { + /// + int HeaderSize => 12; + + /// public bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format) { @@ -19,8 +23,8 @@ public sealed class HeicImageFormatDetector : IImageFormatDetector private static bool IsSupportedFileFormat(ReadOnlySpan header) { - // TODO: Implement - - return false; + return + BinaryPrimitives.ReadUInt32BigEndian(header.Slice(4)) == FourCharacterCode.ftyp && + BinaryPrimitives.ReadUInt32BigEndian(header.Slice(8)) == FourCharacterCode.heic } } diff --git a/src/ImageSharp/Formats/Heic/HeicItem.cs b/src/ImageSharp/Formats/Heic/HeicItem.cs new file mode 100644 index 0000000000..0dfc442d47 --- /dev/null +++ b/src/ImageSharp/Formats/Heic/HeicItem.cs @@ -0,0 +1,32 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Heic; + +public enum HeicItemType +{ + Hvc1, + Grid, + Exif +} + +public class HeicItemLink +{ + public uint Type; + public HeicItem Source; + public List Destinations = new List(); +} + +/// +/// Provides definition for a HEIC Item. +/// +public class HeicItem +{ + public uint Id; + public HeicItemType type; + public string Name; + public string ContentType; + public string ContentEncoding; + public uint ExtensionType; + public string UriType; +} diff --git a/src/ImageSharp/Formats/Heic/HeicItemPropertyType.cs b/src/ImageSharp/Formats/Heic/HeicItemPropertyType.cs new file mode 100644 index 0000000000..157860f184 --- /dev/null +++ b/src/ImageSharp/Formats/Heic/HeicItemPropertyType.cs @@ -0,0 +1,23 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Heic; + +/// +/// Provides enumeration of supported Item Property Types for HEIC. +/// +public enum HeicItemPropertyType : uint +{ + Invalid = 0, + AcessibilityText = FourCharacterCode.altt, + Colour = FourCharacterCode.colr, + HvcConfiguration = FourCharacterCode.hvcC, + ImageMirror = FourCharacterCode.imir, + ImageRotation = FourCharacterCode.irot, + ImageScaling = FourCharacterCode.iscl, + ImageSpatialExtents = FourCharacterCode.ispe, + PixelAspectRatio = FourCharacterCode.pasp, + PixelInformation = FourCharacterCode.pixi, + RelativeLocation = FourCharacterCode.rloc, + UserDescription = FourCharacterCode.udes, +} diff --git a/src/ImageSharp/Formats/Heic/HeicMetaSubBoxType.cs b/src/ImageSharp/Formats/Heic/HeicMetaSubBoxType.cs new file mode 100644 index 0000000000..46d29878c3 --- /dev/null +++ b/src/ImageSharp/Formats/Heic/HeicMetaSubBoxType.cs @@ -0,0 +1,22 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Heic; + +/// +/// Provides enumeration of supported sub type boxes within the 'meta' box for HEIC. +/// +public enum HeicMetaSubBoxType : uint +{ + Invalid = 0, + DataInformation = 0, // 'dinf' + GroupsList = 0, // 'grpl' + Handler = 0, // 'hdlr' + ItemData = 0, // 'idat' + ItemInfo = 0, // 'iinf' + ItemLocation = 0, // 'iloc' + ItemProperty = 0, // 'iprp' + ItemProtection = 0, // 'ipro' + ItemReference = 0, // 'iref' + PrimaryItem = 0, // 'pitm' +} diff --git a/src/ImageSharp/Formats/Heic/HeicNalUnitType.cs b/src/ImageSharp/Formats/Heic/HeicNalUnitType.cs index 127a8dcdca..e12abf3c8d 100644 --- a/src/ImageSharp/Formats/Heic/HeicNalUnitType.cs +++ b/src/ImageSharp/Formats/Heic/HeicNalUnitType.cs @@ -6,33 +6,31 @@ namespace SixLabors.ImageSharp.Formats.Heic; /// /// Provides enumeration of supported x265's LAN Unit Types. /// -public enum HeicNalUnitType : uint +public enum HeicNalUnitType : byte { - NAL_UNIT_CODED_SLICE_TRAIL_N = 0, - NAL_UNIT_CODED_SLICE_TRAIL_R, - NAL_UNIT_CODED_SLICE_TSA_N, - NAL_UNIT_CODED_SLICE_TSA_R, - NAL_UNIT_CODED_SLICE_STSA_N, - NAL_UNIT_CODED_SLICE_STSA_R, - NAL_UNIT_CODED_SLICE_RADL_N, - NAL_UNIT_CODED_SLICE_RADL_R, - NAL_UNIT_CODED_SLICE_RASL_N, - NAL_UNIT_CODED_SLICE_RASL_R, - NAL_UNIT_CODED_SLICE_BLA_W_LP = 16, - NAL_UNIT_CODED_SLICE_BLA_W_RADL, - NAL_UNIT_CODED_SLICE_BLA_N_LP, - NAL_UNIT_CODED_SLICE_IDR_W_RADL, - NAL_UNIT_CODED_SLICE_IDR_N_LP, - NAL_UNIT_CODED_SLICE_CRA, - NAL_UNIT_VPS = 32, - NAL_UNIT_SPS, - NAL_UNIT_PPS, - NAL_UNIT_ACCESS_UNIT_DELIMITER, - NAL_UNIT_EOS, - NAL_UNIT_EOB, - NAL_UNIT_FILLER_DATA, - NAL_UNIT_PREFIX_SEI, - NAL_UNIT_SUFFIX_SEI, - Unspecified = 62, + CODED_SLICE_TRAIL_N = 0, + CODED_SLICE_TRAIL_R = 1, + + CODED_SLICE_TSA_N = 2, + CODED_SLICE_TSA_R = 3, + + CODED_SLICE_STSA_N = 4, + CODED_SLICE_STSA_R = 5, + + CODED_SLICE_RADL_N = 6, + CODED_SLICE_RADL_R = 7, + + CODED_SLICE_RASL_N = 8, + CODED_SLICE_RASL_R = 9, + + VParameterSet = 32, + SequenceParameterSet = 33, + PictureParameterSet = 34, + AccessUnitDelimiter = 35, + EndOfSequence = 36, + IsEndOfStream = 37, + FillerData = 38, + PrefixSei = 39, + SuffixSei = 40, Invalid = 64, } diff --git a/src/ImageSharp/Formats/Heic/Readme.md b/src/ImageSharp/Formats/Heic/Readme.md new file mode 100644 index 0000000000..330b27fd6a --- /dev/null +++ b/src/ImageSharp/Formats/Heic/Readme.md @@ -0,0 +1,9 @@ +# Implementation references + +[MPEG-4 register authority](https://mp4ra.org/) + +[HEIF reference implementation from Nokia](https://github.com/nokiatech/heif) + +[Open Source H265 implementation](https://bitbucket.org/multicoreware/x265_git/src) + +[Apple's metadata syntax in HEIC images](http://cheeky4n6monkey.blogspot.com/2017/10/monkey-takes-heic.html)