diff --git a/src/ImageSharp/Formats/Heic/Heic4CharCode.cs b/src/ImageSharp/Formats/Heic/Heic4CharCode.cs index f80db91b83..42867059dd 100644 --- a/src/ImageSharp/Formats/Heic/Heic4CharCode.cs +++ b/src/ImageSharp/Formats/Heic/Heic4CharCode.cs @@ -223,4 +223,9 @@ public enum Heic4CharCode : uint /// uuid = 0x75756964U, + /// + /// Free space. + /// + free = 0x66726565U, + } diff --git a/src/ImageSharp/Formats/Heic/Heic4CharCode.tt b/src/ImageSharp/Formats/Heic/Heic4CharCode.tt index 7744763771..1bcbc8312a 100644 --- a/src/ImageSharp/Formats/Heic/Heic4CharCode.tt +++ b/src/ImageSharp/Formats/Heic/Heic4CharCode.tt @@ -49,6 +49,7 @@ "uri ", "URI", "pict", "Picture handler type", "uuid", "Unique Identifier", + "free", "Free space", }; #> diff --git a/src/ImageSharp/Formats/Heic/HeicConstants.cs b/src/ImageSharp/Formats/Heic/HeicConstants.cs index 809818e403..03a394a9fb 100644 --- a/src/ImageSharp/Formats/Heic/HeicConstants.cs +++ b/src/ImageSharp/Formats/Heic/HeicConstants.cs @@ -18,5 +18,5 @@ internal static class HeicConstants /// /// The list of file extensions that equate to a HEIC. /// - public static readonly IEnumerable FileExtensions = new[] { "heic", "heif", "avif" }; + public static readonly IEnumerable FileExtensions = new[] { "heic", "heif", "hif", "avif" }; } diff --git a/src/ImageSharp/Formats/Heic/HeicDecoderCore.cs b/src/ImageSharp/Formats/Heic/HeicDecoderCore.cs index 232efce594..23679740e6 100644 --- a/src/ImageSharp/Formats/Heic/HeicDecoderCore.cs +++ b/src/ImageSharp/Formats/Heic/HeicDecoderCore.cs @@ -75,8 +75,15 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals case Heic4CharCode.mdat: this.ParseMediaData(stream, boxLength); break; + case Heic4CharCode.free: + SkipBox(stream, boxLength); + break; + case 0U: + // Some files have trailing zeros, skiping to EOF. + stream.Skip((int)(stream.Length - stream.Position)); + break; default: - throw new ImageFormatException($"Unknown box type of '{Enum.GetName(boxType)}'"); + throw new ImageFormatException($"Unknown box type of '{PrettyPrint(boxType)}'"); } } @@ -129,9 +136,10 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals long boxLength = this.ReadBoxHeader(stream, out Heic4CharCode boxType); Span buffer = this.ReadIntoBuffer(stream, boxLength); uint majorBrand = BinaryPrimitives.ReadUInt32BigEndian(buffer); + bool correctBrand = majorBrand == (uint)Heic4CharCode.heic || majorBrand == (uint)Heic4CharCode.heix; // TODO: Interpret minorVersion and compatible brands. - return boxType == Heic4CharCode.ftyp && majorBrand == (uint)Heic4CharCode.heic; + return boxType == Heic4CharCode.ftyp && correctBrand; } private long ReadBoxHeader(BufferedReadStream stream, out Heic4CharCode boxType) @@ -490,6 +498,7 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals for (uint i = 0; i < itemCount; i++) { uint itemId = ReadUInt16Or32(buffer, version == 2, ref bytesRead); + HeicItem? item = this.FindItemById(itemId); if (version is 1 or 2) { bytesRead++; @@ -506,11 +515,13 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals { if (version is 1 or 2 && indexSize > 0) { - ulong extentIndex = ReadUIntVariable(buffer, indexSize, ref bytesRead); + _ = ReadUIntVariable(buffer, indexSize, ref bytesRead); } ulong extentOffset = ReadUIntVariable(buffer, offsetSize, ref bytesRead); ulong extentLength = ReadUIntVariable(buffer, lengthSize, ref bytesRead); + HeicLocation loc = new HeicLocation((long)extentOffset, (long)extentLength); + item?.DataLocations.Add(loc); } } } diff --git a/src/ImageSharp/Formats/Heic/HeicItem.cs b/src/ImageSharp/Formats/Heic/HeicItem.cs index 481ed04860..beccfada38 100644 --- a/src/ImageSharp/Formats/Heic/HeicItem.cs +++ b/src/ImageSharp/Formats/Heic/HeicItem.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. + namespace SixLabors.ImageSharp.Formats.Heic; /// @@ -68,6 +69,11 @@ public class HeicItem(Heic4CharCode type, uint id) /// public Size GridCellExtent { get; private set; } + /// + /// Gets the list of data locations for this item. + /// + public List DataLocations { get; } = new List(); + /// /// Set the image extent. /// diff --git a/src/ImageSharp/Formats/Heic/HeicLocation.cs b/src/ImageSharp/Formats/Heic/HeicLocation.cs new file mode 100644 index 0000000000..7a342656e3 --- /dev/null +++ b/src/ImageSharp/Formats/Heic/HeicLocation.cs @@ -0,0 +1,20 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Heic; + +/// +/// Location within the file of an . +/// +public class HeicLocation(long offset, long length) +{ + /// + /// Gets the file offset of this location. + /// + public long Offset { get; } = offset; + + /// + /// Gets the length of this location. + /// + public long Length { get; } = length; +}