diff --git a/src/ImageSharp/Formats/Heic/FourCharacterCode.cs b/src/ImageSharp/Formats/Heic/FourCharacterCode.cs
deleted file mode 100644
index fc9ac748dc..0000000000
--- a/src/ImageSharp/Formats/Heic/FourCharacterCode.cs
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using System.Buffers.Binary;
-using System.CodeDom.Compiler;
-using System.Text;
-
-namespace SixLabors.ImageSharp.Formats.Heic;
-
-///
-/// Provides constants for 4 Character codes used in HEIC images.
-///
-[GeneratedCode("T4", null)]
-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 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'
-
- ///
- /// MIME type
- ///
- public const uint mime = 0; // 'mime'
-
- ///
- /// URI
- ///
- public const uint uri = 0; // 'uri '
-
- public static uint Parse(string code)
- {
- if (code.Length != 4)
- {
- throw new ImageFormatException("Unbale to parse FourCC code of more than 4 characters.");
- }
- Span span = Encoding.UTF8.GetBytes(code);
- return BinaryPrimitives.ReadUInt32BigEndian(span);
- }
-
- public static string ToString(uint fourcc)
- {
- Span span = stackalloc byte[4];
- BinaryPrimitives.WriteUInt32BigEndian(span, fourcc);
- return Encoding.UTF8.GetString(span);
- }
-}
diff --git a/src/ImageSharp/Formats/Heic/HeicConstants.cs b/src/ImageSharp/Formats/Heic/HeicConstants.cs
index 62ee248f01..809818e403 100644
--- a/src/ImageSharp/Formats/Heic/HeicConstants.cs
+++ b/src/ImageSharp/Formats/Heic/HeicConstants.cs
@@ -8,12 +8,12 @@ namespace SixLabors.ImageSharp.Formats.Heic;
///
internal static class HeicConstants
{
- public const uint HeicBrand = FourCharacterCode.heic;
+ public const Heic4CharCode HeicBrand = Heic4CharCode.heic;
///
/// The list of mimetypes that equate to a HEIC.
///
- public static readonly IEnumerable MimeTypes = new[] { "image/heif", "image/heif-sequence", "image/heic", "image/heic-sequence", "image/avif" };
+ public static readonly IEnumerable MimeTypes = new[] { "image/heif", "image/heic", "image/avif" };
///
/// The list of file extensions that equate to a HEIC.
diff --git a/src/ImageSharp/Formats/Heic/HeicDecoderCore.cs b/src/ImageSharp/Formats/Heic/HeicDecoderCore.cs
index a9e7c4d056..93efcd21d1 100644
--- a/src/ImageSharp/Formats/Heic/HeicDecoderCore.cs
+++ b/src/ImageSharp/Formats/Heic/HeicDecoderCore.cs
@@ -61,21 +61,27 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
while (stream.EofHitCount == 0)
{
- long length = this.ReadBoxHeader(stream, out var boxType);
+ long length = this.ReadBoxHeader(stream, out Heic4CharCode boxType);
switch (boxType)
{
- case FourCharacterCode.meta:
+ case Heic4CharCode.meta:
this.ParseMetadata(stream, length);
break;
- case FourCharacterCode.mdat:
+ case Heic4CharCode.mdat:
this.ParseMediaData(stream, length);
break;
default:
- throw new ImageFormatException($"Unknown box type of '{FourCharacterCode.ToString(boxType)}'");
+ throw new ImageFormatException($"Unknown box type of '{Enum.GetName(boxType)}'");
}
}
- var image = new Image(this.configuration, this.pixelSize.Width, this.pixelSize.Height, this.metadata);
+ HeicItem? item = this.FindItemById(this.primaryItem);
+ if (item == null)
+ {
+ throw new ImageFormatException("No primary item found");
+ }
+
+ var image = new Image(this.configuration, item.Extent.Width, item.Extent.Height, this.metadata);
Buffer2D pixels = image.GetRootFramePixelBuffer();
@@ -89,10 +95,10 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
while (stream.EofHitCount == 0)
{
- long length = this.ReadBoxHeader(stream, out uint boxType);
+ long length = this.ReadBoxHeader(stream, out Heic4CharCode boxType);
switch (boxType)
{
- case FourCharacterCode.meta:
+ case Heic4CharCode.meta:
this.ParseMetadata(stream, length);
break;
default:
@@ -101,21 +107,27 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
}
}
- return new ImageInfo(new PixelTypeInfo(bitsPerPixel), new(this.pixelSize.Width, this.pixelSize.Height), this.metadata);
+ HeicItem? item = this.FindItemById(this.primaryItem);
+ if (item == null)
+ {
+ throw new ImageFormatException("No primary item found");
+ }
+
+ return new ImageInfo(new PixelTypeInfo(item.BitsPerPixel), new(item.Extent.Width, item.Extent.Height), this.metadata);
}
private bool CheckFileTypeBox(BufferedReadStream stream)
{
- var boxLength = this.ReadBoxHeader(stream, out var boxType);
+ var boxLength = this.ReadBoxHeader(stream, out Heic4CharCode boxType);
Span buffer = stackalloc byte[(int)boxLength];
stream.Read(buffer);
var majorBrand = BinaryPrimitives.ReadUInt32BigEndian(buffer);
// TODO: Interpret minorVersion and compatible brands.
- return boxType == FourCharacterCode.ftyp && majorBrand == FourCharacterCode.heic;
+ return boxType == Heic4CharCode.ftyp && majorBrand == (uint)Heic4CharCode.heic;
}
- private long ReadBoxHeader(BufferedReadStream stream, out uint boxType)
+ private long ReadBoxHeader(BufferedReadStream stream, out Heic4CharCode boxType)
{
// Read 4 bytes of length of box
Span buf = stackalloc byte[8];
@@ -124,7 +136,7 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
long headerSize = 8;
// Read 4 bytes of box type
- boxType = BinaryPrimitives.ReadUInt32BigEndian(buf[4..]);
+ boxType = (Heic4CharCode)BinaryPrimitives.ReadUInt32BigEndian(buf[4..]);
if (boxSize == 1)
{
@@ -136,11 +148,11 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
return boxSize - headerSize;
}
- private static int ParseBoxHeader(Span buffer, out long length, out uint boxType)
+ private static int ParseBoxHeader(Span buffer, out long length, out Heic4CharCode boxType)
{
long boxSize = BinaryPrimitives.ReadUInt32BigEndian(buffer);
int bytesRead = 4;
- boxType = BinaryPrimitives.ReadUInt32BigEndian(buffer[bytesRead..]);
+ boxType = (Heic4CharCode)BinaryPrimitives.ReadUInt32BigEndian(buffer[bytesRead..]);
bytesRead += 4;
if (boxSize == 1)
{
@@ -157,31 +169,31 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
long endPosition = stream.Position + boxLength;
while (stream.Position < endPosition)
{
- long length = this.ReadBoxHeader(stream, out uint boxType);
+ long length = this.ReadBoxHeader(stream, out Heic4CharCode boxType);
switch (boxType)
{
- case FourCharacterCode.iprp:
+ case Heic4CharCode.iprp:
this.ParseItemPropertyContainer(stream, length);
break;
- case FourCharacterCode.iinf:
+ case Heic4CharCode.iinf:
this.ParseItemInfo(stream, length);
break;
- case FourCharacterCode.iref:
+ case Heic4CharCode.iref:
this.ParseItemReference(stream, length);
break;
- case FourCharacterCode.pitm:
+ case Heic4CharCode.pitm:
this.ParsePrimaryItem(stream, length);
break;
- case FourCharacterCode.dinf:
- case FourCharacterCode.grpl:
- case FourCharacterCode.hdlr:
- case FourCharacterCode.idat:
- case FourCharacterCode.iloc:
- case FourCharacterCode.ipro:
+ case Heic4CharCode.dinf:
+ case Heic4CharCode.grpl:
+ case Heic4CharCode.hdlr:
+ case Heic4CharCode.idat:
+ case Heic4CharCode.iloc:
+ case Heic4CharCode.ipro:
// TODO: Implement
break;
default:
- throw new ImageFormatException($"Unknown metadata box type of '{FourCharacterCode.ToString(boxType)}'");
+ throw new ImageFormatException($"Unknown metadata box type of '{Enum.GetName(boxType)}'");
}
}
}
@@ -213,7 +225,7 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
private int ParseItemInfoEntry(Span buffer)
{
- int bytesRead = ParseBoxHeader(buffer, out long boxLength, out uint boxType);
+ int bytesRead = ParseBoxHeader(buffer, out long boxLength, out Heic4CharCode boxType);
byte version = buffer[bytesRead];
bytesRead += 4;
HeicItem? item = null;
@@ -240,7 +252,6 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
if (version == 1)
{
-
// Optional fields.
if (bytesRead < boxLength)
{
@@ -272,10 +283,10 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
bytesRead += 2;
uint itemType = BinaryPrimitives.ReadUInt32BigEndian(buffer[bytesRead..]);
bytesRead += 4;
- item = new HeicItem(itemId, itemType);
+ item = new HeicItem((Heic4CharCode)itemId, itemType);
item.Name = ReadNullTerminatedString(buffer[bytesRead..]);
bytesRead += item.Name.Length + 1;
- if (item.Type == FourCharacterCode.mime)
+ if (item.Type == Heic4CharCode.mime)
{
item.ContentType = ReadNullTerminatedString(buffer[bytesRead..]);
bytesRead += item.ContentType.Length + 1;
@@ -287,7 +298,7 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
bytesRead += item.ContentEncoding.Length + 1;
}
}
- else if (item.Type == FourCharacterCode.uri)
+ else if (item.Type == Heic4CharCode.uri)
{
item.UriType = ReadNullTerminatedString(buffer[bytesRead..]);
bytesRead += item.UriType.Length + 1;
@@ -306,7 +317,7 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
bytesRead += 4;
while (bytesRead < boxLength)
{
- ParseBoxHeader(buffer[bytesRead..], out long subBoxLength, out uint linkType);
+ ParseBoxHeader(buffer[bytesRead..], out long subBoxLength, out Heic4CharCode linkType);
uint sourceId;
if (largeIds)
{
@@ -363,35 +374,35 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
private void ParseItemPropertyContainer(BufferedReadStream stream, long boxLength)
{
// Cannot use Dictionary here, Properties can have multiple instances with the same key.
- List> properties = new();
- long containerLength = this.ReadBoxHeader(stream, out uint containerType);
- if (containerType == FourCharacterCode.ipco)
+ List> properties = new();
+ long containerLength = this.ReadBoxHeader(stream, out Heic4CharCode containerType);
+ if (containerType == Heic4CharCode.ipco)
{
// Parse Item Property Container, which is just an array of preperty boxes.
long endPosition = stream.Position + containerLength;
while (stream.Position < endPosition)
{
- int length = (int)this.ReadBoxHeader(stream, out uint boxType);
+ int length = (int)this.ReadBoxHeader(stream, out Heic4CharCode boxType);
Span buffer = stackalloc byte[length];
switch (boxType)
{
- case FourCharacterCode.ispe:
+ case Heic4CharCode.ispe:
// Length should be 12.
stream.Read(buffer);
// Skip over version (8 bits) and flags (24 bits).
- uint width = BinaryPrimitives.ReadUInt32BigEndian(buffer[4..]);
- uint height = BinaryPrimitives.ReadUInt32BigEndian(buffer[8..]);
- properties.Add(new KeyValuePair(FourCharacterCode.ispe, new uint[] { width, height }));
+ int width = (int)BinaryPrimitives.ReadUInt32BigEndian(buffer[4..]);
+ int height = (int)BinaryPrimitives.ReadUInt32BigEndian(buffer[8..]);
+ properties.Add(new KeyValuePair(Heic4CharCode.ispe, new Size(width, height)));
break;
- case FourCharacterCode.pasp:
+ case Heic4CharCode.pasp:
// Length should be 8.
stream.Read(buffer);
- uint horizontalSpacing = BinaryPrimitives.ReadUInt32BigEndian(buffer);
- uint verticalSpacing = BinaryPrimitives.ReadUInt32BigEndian(buffer[4..]);
- properties.Add(new KeyValuePair(FourCharacterCode.pasp, new uint[] { horizontalSpacing, verticalSpacing }));
+ int horizontalSpacing = (int)BinaryPrimitives.ReadUInt32BigEndian(buffer);
+ int verticalSpacing = (int)BinaryPrimitives.ReadUInt32BigEndian(buffer[4..]);
+ properties.Add(new KeyValuePair(Heic4CharCode.pasp, new Size(horizontalSpacing, verticalSpacing)));
break;
- case FourCharacterCode.pixi:
+ case Heic4CharCode.pixi:
stream.Read(buffer);
// Skip over version (8 bits) and flags (24 bits).
@@ -403,23 +414,23 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
bitsPerPixel += buffer[offset + i];
}
- properties.Add(new KeyValuePair(FourCharacterCode.pixi, new int[] { channelCount, bitsPerPixel }));
+ properties.Add(new KeyValuePair(Heic4CharCode.pixi, new int[] { channelCount, bitsPerPixel }));
break;
- case FourCharacterCode.altt:
- case FourCharacterCode.imir:
- case FourCharacterCode.irot:
- case FourCharacterCode.iscl:
- case FourCharacterCode.rloc:
- case FourCharacterCode.udes:
+ case Heic4CharCode.altt:
+ case Heic4CharCode.imir:
+ case Heic4CharCode.irot:
+ case Heic4CharCode.iscl:
+ case Heic4CharCode.rloc:
+ case Heic4CharCode.udes:
// TODO: Implement
break;
default:
- throw new ImageFormatException($"Unknown item property box type of '{FourCharacterCode.ToString(boxType)}'");
+ throw new ImageFormatException($"Unknown item property box type of '{Enum.GetName(boxType)}'");
}
}
}
- else if (containerType == FourCharacterCode.ipma)
+ else if (containerType == Heic4CharCode.ipma)
{
// Parse Item Property Association
Span buffer = stackalloc byte[(int)boxLength];
@@ -452,7 +463,21 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
propId = buffer[bytesRead++] & 0x4FU;
}
- this.items![itemId].SetProperty(properties[(int)propId]);
+ KeyValuePair prop = properties[(int)propId];
+ switch (prop.Key)
+ {
+ case Heic4CharCode.ispe:
+ this.items[itemId].SetExtent((Size)prop.Value);
+ break;
+ case Heic4CharCode.pasp:
+ this.items[itemId].PixelAspectRatio = (Size)prop.Value;
+ break;
+ case Heic4CharCode.pixi:
+ int[] values = (int[])prop.Value;
+ this.items[itemId].ChannelCount = values[0];
+ this.items[itemId].BitsPerPixel = values[1];
+ break;
+ }
}
}
}
@@ -462,6 +487,9 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
// TODO: Implement
}
+ private HeicItem? FindItemById(uint itemId)
+ => this.items.FirstOrDefault(item => item.Id == itemId);
+
private static string ReadNullTerminatedString(Span span)
{
Span bytes = span[..span.IndexOf((byte)0)];
diff --git a/src/ImageSharp/Formats/Heic/HeicFourCharacterCodes.cs b/src/ImageSharp/Formats/Heic/HeicFourCharacterCodes.cs
new file mode 100644
index 0000000000..c7da21d0fb
--- /dev/null
+++ b/src/ImageSharp/Formats/Heic/HeicFourCharacterCodes.cs
@@ -0,0 +1,201 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+//
+
+using System.CodeDom.Compiler;
+
+namespace SixLabors.ImageSharp.Formats.Heic;
+
+///
+/// Supported 4 character codes for use in HEIC images.
+///
+[GeneratedCode("T4", null)]
+public enum Heic4CharCode : uint
+{
+ ///
+ /// File Type.
+ ///
+ ftyp = 0x66747970U,
+
+ ///
+ /// Metadata.
+ ///
+ meta = 0x6D657461U,
+
+ ///
+ /// Media Data.
+ ///
+ mdat = 0x6D646174U,
+
+ ///
+ /// Item Information Entry.
+ ///
+ infe = 0x696E6665U,
+
+ ///
+ /// Item Data.
+ ///
+ idat = 0x69646174U,
+
+ ///
+ /// Item Location.
+ ///
+ iloc = 0x696C6F63U,
+
+ ///
+ /// EXIF metadata.
+ ///
+ Exif = 0x45786966U,
+
+ ///
+ /// Data Reference.
+ ///
+ dref = 0x64726566U,
+
+ ///
+ /// Primary Item.
+ ///
+ pitm = 0x7069746DU,
+
+ ///
+ /// Item Spatial Extent.
+ ///
+ ispe = 0x69737065U,
+
+ ///
+ /// Alternative text.
+ ///
+ altt = 0x616C7474U,
+
+ ///
+ /// Colour information.
+ ///
+ colr = 0x636F6C72U,
+
+ ///
+ /// HVC configuration.
+ ///
+ hvcC = 0x68766343U,
+
+ ///
+ /// Image Mirror.
+ ///
+ imir = 0x696D6972U,
+
+ ///
+ /// Image Rotation.
+ ///
+ irot = 0x69726F74U,
+
+ ///
+ /// Image Scaling.
+ ///
+ iscl = 0x6973636CU,
+
+ ///
+ /// Pixel Aspect Ratio.
+ ///
+ pasp = 0x70617370U,
+
+ ///
+ /// Pixel Information.
+ ///
+ pixi = 0x70697869U,
+
+ ///
+ /// Reference Location.
+ ///
+ rloc = 0x726C6F63U,
+
+ ///
+ /// User Description.
+ ///
+ udes = 0x75646573U,
+
+ ///
+ /// Item Property Container.
+ ///
+ ipco = 0x6970636FU,
+
+ ///
+ /// Item Property Association.
+ ///
+ ipma = 0x69706D61U,
+
+ ///
+ /// High Efficient Image Coding.
+ ///
+ heic = 0x68656963U,
+
+ ///
+ /// High Efficiency Coding tile.
+ ///
+ hvc1 = 0x68766331U,
+
+ ///
+ /// Data Information.
+ ///
+ dinf = 0x64696E66U,
+
+ ///
+ /// Group list.
+ ///
+ grpl = 0x6772706CU,
+
+ ///
+ /// Handler.
+ ///
+ hdlr = 0x68646C72U,
+
+ ///
+ /// Item Information.
+ ///
+ iinf = 0x69696E66U,
+
+ ///
+ /// Item Property.
+ ///
+ iprp = 0x69707270U,
+
+ ///
+ /// Item Protection.
+ ///
+ ipro = 0x6970726FU,
+
+ ///
+ /// Item Reference.
+ ///
+ iref = 0x69726566U,
+
+ ///
+ /// Grid.
+ ///
+ grid = 0x67726964U,
+
+ ///
+ /// Derived Image.
+ ///
+ dimg = 0x64696D67U,
+
+ ///
+ /// Thumbnail.
+ ///
+ thmb = 0x74686D62U,
+
+ ///
+ /// Content Description.
+ ///
+ cdsc = 0x63647363U,
+
+ ///
+ /// MIME type.
+ ///
+ mime = 0x6D696D65U,
+
+ ///
+ /// URI.
+ ///
+ uri = 0x75726920U,
+
+}
diff --git a/src/ImageSharp/Formats/Heic/HeicFourCharacterCodes.tt b/src/ImageSharp/Formats/Heic/HeicFourCharacterCodes.tt
new file mode 100644
index 0000000000..f2b1ec7cc8
--- /dev/null
+++ b/src/ImageSharp/Formats/Heic/HeicFourCharacterCodes.tt
@@ -0,0 +1,84 @@
+<#@ template language="C#" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+//
+<#
+ var codes = new []{
+ "ftyp", "File Type",
+ "meta", "Metadata",
+ "mdat", "Media Data",
+ "infe", "Item Information Entry",
+ "idat", "Item Data",
+ "iloc", "Item Location",
+ "Exif", "EXIF metadata",
+ "dref", "Data Reference",
+ "pitm", "Primary Item",
+ "ispe", "Item Spatial Extent",
+ "altt", "Alternative text",
+ "colr", "Colour information",
+ "hvcC", "HVC configuration",
+ "imir", "Image Mirror",
+ "irot", "Image Rotation",
+ "iscl", "Image Scaling",
+ "pasp", "Pixel Aspect Ratio",
+ "pixi", "Pixel Information",
+ "rloc", "Reference Location",
+ "udes", "User Description",
+ "ipco", "Item Property Container",
+ "ipma", "Item Property Association",
+ "heic", "High Efficient Image Coding",
+ "hvc1", "High Efficiency Coding tile",
+ "dinf", "Data Information",
+ "grpl", "Group list",
+ "hdlr", "Handler",
+ "iinf", "Item Information",
+ "iprp", "Item Property",
+ "ipro", "Item Protection",
+ "iref", "Item Reference",
+ "grid", "Grid",
+ "dimg", "Derived Image",
+ "thmb", "Thumbnail",
+ "cdsc", "Content Description",
+ "mime", "MIME type",
+ "uri ", "URI",
+ };
+#>
+
+using System.CodeDom.Compiler;
+
+namespace SixLabors.ImageSharp.Formats.Heic;
+
+///
+/// Supported 4 character codes for use in HEIC images.
+///
+[GeneratedCode("T4", null)]
+public enum Heic4CharCode : uint
+{
+<#
+ for (int i = 0; i < codes.Length; i += 2)
+ {
+ string shortName = codes[i];
+ string longName = codes[i + 1];
+ string hex = Code2Hex(shortName);
+#>
+ ///
+ /// <#= longName #>.
+ ///
+ <#= shortName #> = <#= hex #>,
+
+<#
+ }
+#>
+}
+<#+
+
+private string Code2Hex(string code)
+{
+ byte[] b = Encoding.ASCII.GetBytes(code);
+ return String.Format("0x{0:X2}{1:X2}{2:X2}{3:X2}U", b[0], b[1], b[2], b[3]);
+}
+
+#>
diff --git a/src/ImageSharp/Formats/Heic/HeicImageFormatDetector.cs b/src/ImageSharp/Formats/Heic/HeicImageFormatDetector.cs
index eeda941092..4a8195e2bd 100644
--- a/src/ImageSharp/Formats/Heic/HeicImageFormatDetector.cs
+++ b/src/ImageSharp/Formats/Heic/HeicImageFormatDetector.cs
@@ -22,6 +22,6 @@ public sealed class HeicImageFormatDetector : IImageFormatDetector
}
private static bool IsSupportedFileFormat(ReadOnlySpan header) =>
- BinaryPrimitives.ReadUInt32BigEndian(header.Slice(4)) == FourCharacterCode.ftyp &&
- BinaryPrimitives.ReadUInt32BigEndian(header.Slice(8)) == FourCharacterCode.heic;
+ BinaryPrimitives.ReadUInt32BigEndian(header.Slice(4)) == (uint)Heic4CharCode.ftyp &&
+ BinaryPrimitives.ReadUInt32BigEndian(header.Slice(8)) == (uint)Heic4CharCode.heic;
}
diff --git a/src/ImageSharp/Formats/Heic/HeicItem.cs b/src/ImageSharp/Formats/Heic/HeicItem.cs
index 4349a65858..654eecd53d 100644
--- a/src/ImageSharp/Formats/Heic/HeicItem.cs
+++ b/src/ImageSharp/Formats/Heic/HeicItem.cs
@@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Heic;
///
/// Provides definition for a HEIC Item.
///
-public class HeicItem(uint type, uint id)
+public class HeicItem(Heic4CharCode type, uint id)
{
///
/// Gets the ID of this Item.
@@ -16,7 +16,7 @@ public class HeicItem(uint type, uint id)
///
/// Gets the type of this Item.
///
- public uint Type { get; } = type;
+ public Heic4CharCode Type { get; } = type;
///
/// Gets or sets the name of this item.
@@ -44,21 +44,40 @@ public class HeicItem(uint type, uint id)
public string? UriType { get; set; }
///
- /// Sets a property on this item.
+ /// Gets or sets the aspect ratio of the pixels.
///
- public void SetProperty(KeyValuePair pair)
+ public Size PixelAspectRatio { get; set; }
+
+ ///
+ /// Gets or sets the number of color channels in each pixel.
+ ///
+ public int ChannelCount { get; set; }
+
+ ///
+ /// Gets or sets the number of bits in a single pixel.
+ ///
+ public int BitsPerPixel { get; set; }
+
+ ///
+ /// Gets the spatial extent of this item.
+ ///
+ public Size Extent { get; private set; }
+
+ ///
+ /// Gets the spatial extent of this grid cells in this item.
+ ///
+ public Size GridCellExtent { get; private set; }
+
+ public void SetExtent(Size extent)
{
- switch (pair.Key)
+ if (this.Extent == default)
+ {
+ this.Extent = extent;
+ }
+ else
{
- case FourCharacterCode.ispe:
- // Set image extents
- break;
- case FourCharacterCode.pasp:
- // Set pixel aspact ratio
- break;
- case FourCharacterCode.pixi:
- // Set pixel information
- break;
+ this.GridCellExtent = extent;
}
}
+
}
diff --git a/src/ImageSharp/Formats/Heic/HeicItemLink.cs b/src/ImageSharp/Formats/Heic/HeicItemLink.cs
index a93946c2c4..da1578fcfa 100644
--- a/src/ImageSharp/Formats/Heic/HeicItemLink.cs
+++ b/src/ImageSharp/Formats/Heic/HeicItemLink.cs
@@ -6,12 +6,12 @@ namespace SixLabors.ImageSharp.Formats.Heic;
///
/// Link between instances within the same HEIC file.
///
-public class HeicItemLink(uint type, uint sourceId)
+public class HeicItemLink(Heic4CharCode type, uint sourceId)
{
///
/// Gets the type of link.
///
- public uint Type { get; } = type;
+ public Heic4CharCode Type { get; } = type;
///
/// Gets the ID of the source item of this link.
diff --git a/src/ImageSharp/Formats/Heic/HeicNalUnitType.cs b/src/ImageSharp/Formats/Heic/HeicNalUnitType.cs
deleted file mode 100644
index e12abf3c8d..0000000000
--- a/src/ImageSharp/Formats/Heic/HeicNalUnitType.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-namespace SixLabors.ImageSharp.Formats.Heic;
-
-///
-/// Provides enumeration of supported x265's LAN Unit Types.
-///
-public enum HeicNalUnitType : byte
-{
- 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/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj
index 6096bd33e3..c34250b71c 100644
--- a/src/ImageSharp/ImageSharp.csproj
+++ b/src/ImageSharp/ImageSharp.csproj
@@ -52,6 +52,11 @@
+
+ True
+ True
+ HeicFourCharacterCodes.tt
+
True
True
@@ -150,6 +155,10 @@
+
+ TextTemplatingFileGenerator
+ HeicFourCharacterCodes.cs
+
TextTemplatingFileGenerator
Block8x8F.Generated.cs