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;
+}