From 96b92e847b4360bd58aac1f33bd1189f32ab5017 Mon Sep 17 00:00:00 2001 From: Ynse Hoornenborg Date: Wed, 27 Dec 2023 03:08:54 +0100 Subject: [PATCH] 4CC generated by template --- .../Formats/Heic/FourCharacterCode.cs | 219 ------------------ src/ImageSharp/Formats/Heic/HeicConstants.cs | 4 +- .../Formats/Heic/HeicDecoderCore.cs | 138 ++++++----- .../Formats/Heic/HeicFourCharacterCodes.cs | 201 ++++++++++++++++ .../Formats/Heic/HeicFourCharacterCodes.tt | 84 +++++++ .../Formats/Heic/HeicImageFormatDetector.cs | 4 +- src/ImageSharp/Formats/Heic/HeicItem.cs | 47 ++-- src/ImageSharp/Formats/Heic/HeicItemLink.cs | 4 +- .../Formats/Heic/HeicNalUnitType.cs | 36 --- src/ImageSharp/ImageSharp.csproj | 9 + 10 files changed, 416 insertions(+), 330 deletions(-) delete mode 100644 src/ImageSharp/Formats/Heic/FourCharacterCode.cs create mode 100644 src/ImageSharp/Formats/Heic/HeicFourCharacterCodes.cs create mode 100644 src/ImageSharp/Formats/Heic/HeicFourCharacterCodes.tt delete mode 100644 src/ImageSharp/Formats/Heic/HeicNalUnitType.cs 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