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)