Browse Source

More HIF support

pull/2633/head
Ynse Hoornenborg 3 years ago
parent
commit
f90d4ebe95
  1. 5
      src/ImageSharp/Formats/Heic/Heic4CharCode.cs
  2. 1
      src/ImageSharp/Formats/Heic/Heic4CharCode.tt
  3. 2
      src/ImageSharp/Formats/Heic/HeicConstants.cs
  4. 17
      src/ImageSharp/Formats/Heic/HeicDecoderCore.cs
  5. 6
      src/ImageSharp/Formats/Heic/HeicItem.cs
  6. 20
      src/ImageSharp/Formats/Heic/HeicLocation.cs

5
src/ImageSharp/Formats/Heic/Heic4CharCode.cs

@ -223,4 +223,9 @@ public enum Heic4CharCode : uint
/// </summary> /// </summary>
uuid = 0x75756964U, uuid = 0x75756964U,
/// <summary>
/// Free space.
/// </summary>
free = 0x66726565U,
} }

1
src/ImageSharp/Formats/Heic/Heic4CharCode.tt

@ -49,6 +49,7 @@
"uri ", "URI", "uri ", "URI",
"pict", "Picture handler type", "pict", "Picture handler type",
"uuid", "Unique Identifier", "uuid", "Unique Identifier",
"free", "Free space",
}; };
#> #>

2
src/ImageSharp/Formats/Heic/HeicConstants.cs

@ -18,5 +18,5 @@ internal static class HeicConstants
/// <summary> /// <summary>
/// The list of file extensions that equate to a HEIC. /// The list of file extensions that equate to a HEIC.
/// </summary> /// </summary>
public static readonly IEnumerable<string> FileExtensions = new[] { "heic", "heif", "avif" }; public static readonly IEnumerable<string> FileExtensions = new[] { "heic", "heif", "hif", "avif" };
} }

17
src/ImageSharp/Formats/Heic/HeicDecoderCore.cs

@ -75,8 +75,15 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
case Heic4CharCode.mdat: case Heic4CharCode.mdat:
this.ParseMediaData(stream, boxLength); this.ParseMediaData(stream, boxLength);
break; 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: 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); long boxLength = this.ReadBoxHeader(stream, out Heic4CharCode boxType);
Span<byte> buffer = this.ReadIntoBuffer(stream, boxLength); Span<byte> buffer = this.ReadIntoBuffer(stream, boxLength);
uint majorBrand = BinaryPrimitives.ReadUInt32BigEndian(buffer); uint majorBrand = BinaryPrimitives.ReadUInt32BigEndian(buffer);
bool correctBrand = majorBrand == (uint)Heic4CharCode.heic || majorBrand == (uint)Heic4CharCode.heix;
// TODO: Interpret minorVersion and compatible brands. // 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) private long ReadBoxHeader(BufferedReadStream stream, out Heic4CharCode boxType)
@ -490,6 +498,7 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
for (uint i = 0; i < itemCount; i++) for (uint i = 0; i < itemCount; i++)
{ {
uint itemId = ReadUInt16Or32(buffer, version == 2, ref bytesRead); uint itemId = ReadUInt16Or32(buffer, version == 2, ref bytesRead);
HeicItem? item = this.FindItemById(itemId);
if (version is 1 or 2) if (version is 1 or 2)
{ {
bytesRead++; bytesRead++;
@ -506,11 +515,13 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
{ {
if (version is 1 or 2 && indexSize > 0) 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 extentOffset = ReadUIntVariable(buffer, offsetSize, ref bytesRead);
ulong extentLength = ReadUIntVariable(buffer, lengthSize, ref bytesRead); ulong extentLength = ReadUIntVariable(buffer, lengthSize, ref bytesRead);
HeicLocation loc = new HeicLocation((long)extentOffset, (long)extentLength);
item?.DataLocations.Add(loc);
} }
} }
} }

6
src/ImageSharp/Formats/Heic/HeicItem.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Formats.Heic; namespace SixLabors.ImageSharp.Formats.Heic;
/// <summary> /// <summary>
@ -68,6 +69,11 @@ public class HeicItem(Heic4CharCode type, uint id)
/// </summary> /// </summary>
public Size GridCellExtent { get; private set; } public Size GridCellExtent { get; private set; }
/// <summary>
/// Gets the list of data locations for this item.
/// </summary>
public List<HeicLocation> DataLocations { get; } = new List<HeicLocation>();
/// <summary> /// <summary>
/// Set the image extent. /// Set the image extent.
/// </summary> /// </summary>

20
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;
/// <summary>
/// Location within the file of an <see cref="HeicItem"/>.
/// </summary>
public class HeicLocation(long offset, long length)
{
/// <summary>
/// Gets the file offset of this location.
/// </summary>
public long Offset { get; } = offset;
/// <summary>
/// Gets the length of this location.
/// </summary>
public long Length { get; } = length;
}
Loading…
Cancel
Save