Browse Source

Casing in Heif4CharCode

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
db44498536
  1. 98
      src/ImageSharp/Formats/Heif/Heif4CharCode.cs
  2. 13
      src/ImageSharp/Formats/Heif/Heif4CharCode.tt
  3. 2
      src/ImageSharp/Formats/Heif/HeifConstants.cs
  4. 92
      src/ImageSharp/Formats/Heif/HeifDecoderCore.cs
  5. 42
      src/ImageSharp/Formats/Heif/HeifEncoderCore.cs
  6. 4
      src/ImageSharp/Formats/Heif/HeifImageFormatDetector.cs

98
src/ImageSharp/Formats/Heif/Heif4CharCode.cs

@ -10,38 +10,38 @@ namespace SixLabors.ImageSharp.Formats.Heif;
/// <summary>
/// Supported 4 character codes for use in HEIF images.
/// </summary>
[GeneratedCode("T4", "")]
[GeneratedCode("TextTemplateFileGenerator", "")]
public enum Heif4CharCode : uint
{
/// <summary>
/// File Type.
/// </summary>
ftyp = 0x66747970U,
Ftyp = 0x66747970U,
/// <summary>
/// Metadata.
/// </summary>
meta = 0x6D657461U,
Meta = 0x6D657461U,
/// <summary>
/// Media Data.
/// </summary>
mdat = 0x6D646174U,
Mdat = 0x6D646174U,
/// <summary>
/// Item Information Entry.
/// </summary>
infe = 0x696E6665U,
Infe = 0x696E6665U,
/// <summary>
/// Item Data.
/// </summary>
idat = 0x69646174U,
Idat = 0x69646174U,
/// <summary>
/// Item Location.
/// </summary>
iloc = 0x696C6F63U,
Iloc = 0x696C6F63U,
/// <summary>
/// EXIF metadata.
@ -51,211 +51,211 @@ public enum Heif4CharCode : uint
/// <summary>
/// Data Reference.
/// </summary>
dref = 0x64726566U,
Dref = 0x64726566U,
/// <summary>
/// Primary Item.
/// </summary>
pitm = 0x7069746DU,
Pitm = 0x7069746DU,
/// <summary>
/// Item Spatial Extent.
/// </summary>
ispe = 0x69737065U,
Ispe = 0x69737065U,
/// <summary>
/// Alternative text.
/// </summary>
altt = 0x616C7474U,
Altt = 0x616C7474U,
/// <summary>
/// Colour information.
/// </summary>
colr = 0x636F6C72U,
Colr = 0x636F6C72U,
/// <summary>
/// HVC configuration.
/// </summary>
hvcC = 0x68766343U,
HvcC = 0x68766343U,
/// <summary>
/// AV1 configuration.
/// </summary>
av1C = 0x61763143U,
Av1C = 0x61763143U,
/// <summary>
/// Image Mirror.
/// </summary>
imir = 0x696D6972U,
Imir = 0x696D6972U,
/// <summary>
/// Image Rotation.
/// </summary>
irot = 0x69726F74U,
Irot = 0x69726F74U,
/// <summary>
/// Image Scaling.
/// </summary>
iscl = 0x6973636CU,
Iscl = 0x6973636CU,
/// <summary>
/// Pixel Aspect Ratio.
/// </summary>
pasp = 0x70617370U,
Pasp = 0x70617370U,
/// <summary>
/// Pixel Information.
/// </summary>
pixi = 0x70697869U,
Pixi = 0x70697869U,
/// <summary>
/// Reference Location.
/// </summary>
rloc = 0x726C6F63U,
Rloc = 0x726C6F63U,
/// <summary>
/// User Description.
/// </summary>
udes = 0x75646573U,
Udes = 0x75646573U,
/// <summary>
/// IPMP Control Box.
/// </summary>
ipmc = 0x69706D63U,
Ipmc = 0x69706D63U,
/// <summary>
/// Item Property Container.
/// </summary>
ipco = 0x6970636FU,
Ipco = 0x6970636FU,
/// <summary>
/// Item Property Association.
/// </summary>
ipma = 0x69706D61U,
Ipma = 0x69706D61U,
/// <summary>
/// High Efficient Image Coding brand.
/// </summary>
heic = 0x68656963U,
Heic = 0x68656963U,
/// <summary>
/// High Efficient Image Coding brand (legacy name).
/// </summary>
heix = 0x68656978U,
Heix = 0x68656978U,
/// <summary>
/// High Efficient File brand.
/// </summary>
mif1 = 0x6D696631U,
Mif1 = 0x6D696631U,
/// <summary>
/// AVIF brand.
/// </summary>
avif = 0x61766966U,
Avif = 0x61766966U,
/// <summary>
/// High Efficiency Coding tile.
/// </summary>
hvc1 = 0x68766331U,
Hvc1 = 0x68766331U,
/// <summary>
/// Legacy JPEG coded tile.
/// </summary>
jpeg = 0x6A706567U,
Jpeg = 0x6A706567U,
/// <summary>
/// AOMedia Video Coding tile.
/// </summary>
av01 = 0x61763031U,
Av01 = 0x61763031U,
/// <summary>
/// Data Information.
/// </summary>
dinf = 0x64696E66U,
Dinf = 0x64696E66U,
/// <summary>
/// Group list.
/// </summary>
grpl = 0x6772706CU,
Grpl = 0x6772706CU,
/// <summary>
/// Handler.
/// </summary>
hdlr = 0x68646C72U,
Hdlr = 0x68646C72U,
/// <summary>
/// Item Information.
/// </summary>
iinf = 0x69696E66U,
Iinf = 0x69696E66U,
/// <summary>
/// Item Property.
/// </summary>
iprp = 0x69707270U,
Iprp = 0x69707270U,
/// <summary>
/// Item Protection.
/// </summary>
ipro = 0x6970726FU,
Ipro = 0x6970726FU,
/// <summary>
/// Item Reference.
/// </summary>
iref = 0x69726566U,
Iref = 0x69726566U,
/// <summary>
/// Grid.
/// </summary>
grid = 0x67726964U,
Grid = 0x67726964U,
/// <summary>
/// Derived Image.
/// </summary>
dimg = 0x64696D67U,
Dimg = 0x64696D67U,
/// <summary>
/// Thumbnail.
/// </summary>
thmb = 0x74686D62U,
Thmb = 0x74686D62U,
/// <summary>
/// Content Description.
/// </summary>
cdsc = 0x63647363U,
Cdsc = 0x63647363U,
/// <summary>
/// MIME type.
/// </summary>
mime = 0x6D696D65U,
Mime = 0x6D696D65U,
/// <summary>
/// URI.
/// </summary>
uri = 0x75726920U,
Uri = 0x75726920U,
/// <summary>
/// Picture handler type.
/// </summary>
pict = 0x70696374U,
Pict = 0x70696374U,
/// <summary>
/// Unique Identifier.
/// </summary>
uuid = 0x75756964U,
Uuid = 0x75756964U,
/// <summary>
/// Free space.
/// </summary>
free = 0x66726565U,
Free = 0x66726565U,
/// <summary>
/// ICC Color Profile.
/// </summary>
rICC = 0x72494343U,
RICC = 0x72494343U,
/// <summary>
/// ICC Color Profile.
/// </summary>
prof = 0x70726F66U,
Prof = 0x70726F66U,
}

13
src/ImageSharp/Formats/Heif/Heif4CharCode.tt

@ -1,6 +1,6 @@
<#@ template language="C#" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Text" #>
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.Formats.Heif;
/// <summary>
/// Supported 4 character codes for use in HEIF images.
/// </summary>
[GeneratedCode("T4", "")]
[GeneratedCode("TextTemplateFileGenerator", "")]
public enum Heif4CharCode : uint
{
<#
@ -74,12 +74,13 @@ public enum Heif4CharCode : uint
{
string shortName = codes[i];
string longName = codes[i + 1];
string pascal = PascalCasing(shortName);
string hex = Code2Hex(shortName);
#>
/// <summary>
/// <#= longName #>.
/// </summary>
<#= shortName #> = <#= hex #>,
<#= pascal #> = <#= hex #>,
<#
}
@ -87,6 +88,12 @@ public enum Heif4CharCode : uint
}
<#+
private string PascalCasing(string code)
{
char firstChar = char.ToUpper(code[0], System.Globalization.CultureInfo.InvariantCulture);
return string.Concat(firstChar, code.Substring(1));
}
private string Code2Hex(string code)
{
byte[] b = Encoding.ASCII.GetBytes(code);

2
src/ImageSharp/Formats/Heif/HeifConstants.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Heif;
/// </summary>
internal static class HeifConstants
{
public const Heif4CharCode HeicBrand = Heif4CharCode.heic;
public const Heif4CharCode HeicBrand = Heif4CharCode.Heic;
/// <summary>
/// The list of mimetypes that equate to a HEIC.

92
src/ImageSharp/Formats/Heif/HeifDecoderCore.cs

@ -71,13 +71,13 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
EnsureBoxBoundary(boxLength, stream);
switch (boxType)
{
case Heif4CharCode.meta:
case Heif4CharCode.Meta:
this.ParseMetadata(stream, boxLength);
break;
case Heif4CharCode.mdat:
case Heif4CharCode.Mdat:
image = this.ParseMediaData<TPixel>(stream, boxLength);
break;
case Heif4CharCode.free:
case Heif4CharCode.Free:
SkipBox(stream, boxLength);
break;
case 0U:
@ -115,7 +115,7 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
EnsureBoxBoundary(boxLength, stream);
switch (boxType)
{
case Heif4CharCode.meta:
case Heif4CharCode.Meta:
this.ParseMetadata(stream, boxLength);
break;
default:
@ -141,21 +141,21 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
long boxLength = this.ReadBoxHeader(stream, out Heif4CharCode boxType);
Span<byte> buffer = this.ReadIntoBuffer(stream, boxLength);
uint majorBrand = BinaryPrimitives.ReadUInt32BigEndian(buffer);
bool correctBrand = majorBrand is (uint)Heif4CharCode.heic or (uint)Heif4CharCode.heix or (uint)Heif4CharCode.avif;
bool correctBrand = majorBrand is (uint)Heif4CharCode.Heic or (uint)Heif4CharCode.Heix or (uint)Heif4CharCode.Avif;
// TODO: Interpret minorVersion and compatible brands.
return boxType == Heif4CharCode.ftyp && correctBrand;
return boxType == Heif4CharCode.Ftyp && correctBrand;
}
private void UpdateMetadata(ImageMetadata metadata, HeifItem item)
{
HeifMetadata meta = metadata.GetHeifMetadata();
HeifCompressionMethod compressionMethod = HeifCompressionMethod.Hevc;
if (item.Type == Heif4CharCode.av01)
if (item.Type == Heif4CharCode.Av01)
{
compressionMethod = HeifCompressionMethod.Av1;
}
else if (item.Type == Heif4CharCode.jpeg || this.itemLinks.Any(link => link.Type == Heif4CharCode.thmb))
else if (item.Type == Heif4CharCode.Jpeg || this.itemLinks.Any(link => link.Type == Heif4CharCode.Thmb))
{
compressionMethod = HeifCompressionMethod.LegacyJpeg;
}
@ -209,30 +209,30 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
EnsureBoxBoundary(length, boxLength);
switch (boxType)
{
case Heif4CharCode.iprp:
case Heif4CharCode.Iprp:
this.ParseItemProperties(stream, length);
break;
case Heif4CharCode.iinf:
case Heif4CharCode.Iinf:
this.ParseItemInfo(stream, length);
break;
case Heif4CharCode.iref:
case Heif4CharCode.Iref:
this.ParseItemReference(stream, length);
break;
case Heif4CharCode.pitm:
case Heif4CharCode.Pitm:
this.ParsePrimaryItem(stream, length);
break;
case Heif4CharCode.hdlr:
case Heif4CharCode.Hdlr:
this.ParseHandler(stream, length);
break;
case Heif4CharCode.iloc:
case Heif4CharCode.Iloc:
this.ParseItemLocation(stream, length);
break;
case Heif4CharCode.dinf:
case Heif4CharCode.idat:
case Heif4CharCode.grpl:
case Heif4CharCode.ipro:
case Heif4CharCode.uuid:
case Heif4CharCode.ipmc:
case Heif4CharCode.Dinf:
case Heif4CharCode.Idat:
case Heif4CharCode.Grpl:
case Heif4CharCode.Ipro:
case Heif4CharCode.Uuid:
case Heif4CharCode.Ipmc:
// Silently skip these boxes.
SkipBox(stream, length);
break;
@ -249,7 +249,7 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
// Only read the handler type, to check if this is not a movie file.
int bytesRead = 8;
Heif4CharCode handlerType = (Heif4CharCode)BinaryPrimitives.ReadUInt32BigEndian(buffer[bytesRead..]);
if (handlerType != Heif4CharCode.pict)
if (handlerType != Heif4CharCode.Pict)
{
throw new ImageFormatException("Not a picture file.");
}
@ -323,7 +323,7 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
item = new HeifItem(itemType, itemId);
item.Name = ReadNullTerminatedString(buffer[bytesRead..]);
bytesRead += item.Name.Length + 1;
if (item.Type == Heif4CharCode.mime)
if (item.Type == Heif4CharCode.Mime)
{
item.ContentType = ReadNullTerminatedString(buffer[bytesRead..]);
bytesRead += item.ContentType.Length + 1;
@ -335,7 +335,7 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
bytesRead += item.ContentEncoding.Length + 1;
}
}
else if (item.Type == Heif4CharCode.uri)
else if (item.Type == Heif4CharCode.Uri)
{
item.UriType = ReadNullTerminatedString(buffer[bytesRead..]);
bytesRead += item.UriType.Length + 1;
@ -392,12 +392,12 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
{
long containerLength = this.ReadBoxHeader(stream, out Heif4CharCode containerType);
EnsureBoxBoundary(containerLength, boxLength);
if (containerType == Heif4CharCode.ipco)
if (containerType == Heif4CharCode.Ipco)
{
// Parse Item Property Container, which is just an array of property boxes.
this.ParsePropertyContainer(stream, containerLength, properties);
}
else if (containerType == Heif4CharCode.ipma)
else if (containerType == Heif4CharCode.Ipma)
{
// Parse Item Property Association
this.ParsePropertyAssociation(stream, containerLength, properties);
@ -419,18 +419,18 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
Span<byte> buffer = this.ReadIntoBuffer(stream, itemLength);
switch (itemType)
{
case Heif4CharCode.ispe:
case Heif4CharCode.Ispe:
// Skip over version (8 bits) and flags (24 bits).
int width = (int)BinaryPrimitives.ReadUInt32BigEndian(buffer[4..]);
int height = (int)BinaryPrimitives.ReadUInt32BigEndian(buffer[8..]);
properties.Add(new KeyValuePair<Heif4CharCode, object>(Heif4CharCode.ispe, new Size(width, height)));
properties.Add(new KeyValuePair<Heif4CharCode, object>(Heif4CharCode.Ispe, new Size(width, height)));
break;
case Heif4CharCode.pasp:
case Heif4CharCode.Pasp:
int horizontalSpacing = (int)BinaryPrimitives.ReadUInt32BigEndian(buffer);
int verticalSpacing = (int)BinaryPrimitives.ReadUInt32BigEndian(buffer[4..]);
properties.Add(new KeyValuePair<Heif4CharCode, object>(Heif4CharCode.pasp, new Size(horizontalSpacing, verticalSpacing)));
properties.Add(new KeyValuePair<Heif4CharCode, object>(Heif4CharCode.Pasp, new Size(horizontalSpacing, verticalSpacing)));
break;
case Heif4CharCode.pixi:
case Heif4CharCode.Pixi:
// Skip over version (8 bits) and flags (24 bits).
int channelCount = buffer[4];
int offset = 5;
@ -440,12 +440,12 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
bitsPerPixel += buffer[offset + i];
}
properties.Add(new KeyValuePair<Heif4CharCode, object>(Heif4CharCode.pixi, new int[] { channelCount, bitsPerPixel }));
properties.Add(new KeyValuePair<Heif4CharCode, object>(Heif4CharCode.Pixi, new int[] { channelCount, bitsPerPixel }));
break;
case Heif4CharCode.colr:
case Heif4CharCode.Colr:
Heif4CharCode profileType = (Heif4CharCode)BinaryPrimitives.ReadUInt32BigEndian(buffer);
if (profileType is Heif4CharCode.rICC or Heif4CharCode.prof)
if (profileType is Heif4CharCode.RICC or Heif4CharCode.Prof)
{
byte[] iccData = new byte[itemLength - 4];
buffer[4..].CopyTo(iccData);
@ -453,14 +453,14 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
}
break;
case Heif4CharCode.altt:
case Heif4CharCode.imir:
case Heif4CharCode.irot:
case Heif4CharCode.iscl:
case Heif4CharCode.hvcC:
case Heif4CharCode.av1C:
case Heif4CharCode.rloc:
case Heif4CharCode.udes:
case Heif4CharCode.Altt:
case Heif4CharCode.Imir:
case Heif4CharCode.Irot:
case Heif4CharCode.Iscl:
case Heif4CharCode.HvcC:
case Heif4CharCode.Av1C:
case Heif4CharCode.Rloc:
case Heif4CharCode.Udes:
// TODO: Implement
properties.Add(new KeyValuePair<Heif4CharCode, object>(itemType, new object()));
break;
@ -495,13 +495,13 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
KeyValuePair<Heif4CharCode, object> prop = properties[(int)propId];
switch (prop.Key)
{
case Heif4CharCode.ispe:
case Heif4CharCode.Ispe:
this.items[itemId].SetExtent((Size)prop.Value);
break;
case Heif4CharCode.pasp:
case Heif4CharCode.Pasp:
this.items[itemId].PixelAspectRatio = (Size)prop.Value;
break;
case Heif4CharCode.pixi:
case Heif4CharCode.Pixi:
int[] values = (int[])prop.Value;
this.items[itemId].ChannelCount = values[0];
this.items[itemId].BitsPerPixel = values[1];
@ -606,14 +606,14 @@ internal sealed class HeifDecoderCore : IImageDecoderInternals
where TPixel : unmanaged, IPixel<TPixel>
{
// FIXME: No HVC decoding yet, so parse only a JPEG thumbnail.
HeifItemLink? thumbLink = this.itemLinks.FirstOrDefault(link => link.Type == Heif4CharCode.thmb);
HeifItemLink? thumbLink = this.itemLinks.FirstOrDefault(link => link.Type == Heif4CharCode.Thmb);
if (thumbLink == null)
{
throw new NotImplementedException("No thumbnail found");
}
HeifItem? thumbItem = this.FindItemById(thumbLink.SourceId);
if (thumbItem == null || thumbItem.Type != Heif4CharCode.jpeg)
if (thumbItem == null || thumbItem.Type != Heif4CharCode.Jpeg)
{
throw new NotImplementedException("No HVC decoding implemented yet");
}

42
src/ImageSharp/Formats/Heif/HeifEncoderCore.cs

@ -16,7 +16,7 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
/// <summary>
/// The global configuration.
/// </summary>
private Configuration configuration;
private readonly Configuration configuration;
/// <summary>
/// The encoder with options.
@ -65,7 +65,7 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
private static void GenerateItems<TPixel>(Image<TPixel> image, byte[] pixels, List<HeifItem> items, List<HeifItemLink> links)
where TPixel : unmanaged, IPixel<TPixel>
{
HeifItem primaryItem = new(Heif4CharCode.jpeg, 1u);
HeifItem primaryItem = new(Heif4CharCode.Jpeg, 1u);
primaryItem.DataLocations.Add(new HeifLocation(0L, pixels.LongLength));
primaryItem.BitsPerPixel = 24;
primaryItem.ChannelCount = 3;
@ -73,7 +73,7 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
items.Add(primaryItem);
// Create a fake thumbnail, to make our own Decoder happy.
HeifItemLink thumbnail = new(Heif4CharCode.thmb, 1u);
HeifItemLink thumbnail = new(Heif4CharCode.Thmb, 1u);
thumbnail.DestinationIds.Add(1u);
links.Add(thumbnail);
}
@ -108,14 +108,14 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
private void WriteFileTypeBox(Stream stream)
{
Span<byte> buffer = stackalloc byte[24];
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.ftyp);
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], (uint)Heif4CharCode.heic);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.Ftyp);
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], (uint)Heif4CharCode.Heic);
bytesWritten += 4;
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], 0);
bytesWritten += 4;
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], (uint)Heif4CharCode.mif1);
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], (uint)Heif4CharCode.Mif1);
bytesWritten += 4;
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], (uint)Heif4CharCode.heic);
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], (uint)Heif4CharCode.Heic);
bytesWritten += 4;
BinaryPrimitives.WriteUInt32BigEndian(buffer, (uint)bytesWritten);
@ -126,7 +126,7 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
{
using AutoExpandingMemory<byte> memory = new(this.configuration, 0x1000);
Span<byte> buffer = memory.GetSpan(12);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.meta, 0, 0);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.Meta, 0, 0);
bytesWritten += WriteHandlerBox(memory, bytesWritten);
bytesWritten += WritePrimaryItemBox(memory, bytesWritten);
bytesWritten += WriteItemInfoBox(memory, bytesWritten, items);
@ -143,10 +143,10 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
private static int WriteHandlerBox(AutoExpandingMemory<byte> memory, int memoryOffset)
{
Span<byte> buffer = memory.GetSpan(memoryOffset, 33);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.hdlr, 0, 0);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.Hdlr, 0, 0);
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], 0);
bytesWritten += 4;
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], (uint)Heif4CharCode.pict);
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], (uint)Heif4CharCode.Pict);
bytesWritten += 4;
for (int i = 0; i < 13; i++)
{
@ -160,7 +160,7 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
private static int WritePrimaryItemBox(AutoExpandingMemory<byte> memory, int memoryOffset)
{
Span<byte> buffer = memory.GetSpan(memoryOffset, 14);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.pitm, 0, 0);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.Pitm, 0, 0);
BinaryPrimitives.WriteUInt16BigEndian(buffer[bytesWritten..], 1);
bytesWritten += 2;
@ -171,13 +171,13 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
private static int WriteItemInfoBox(AutoExpandingMemory<byte> memory, int memoryOffset, List<HeifItem> items)
{
Span<byte> buffer = memory.GetSpan(memoryOffset, 14 + (items.Count * 21));
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.iinf, 0, 0);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.Iinf, 0, 0);
BinaryPrimitives.WriteUInt16BigEndian(buffer[bytesWritten..], (ushort)items.Count);
bytesWritten += 2;
foreach (HeifItem item in items)
{
int itemLengthOffset = bytesWritten;
bytesWritten += WriteBoxHeader(buffer[bytesWritten..], Heif4CharCode.infe, 2, 0);
bytesWritten += WriteBoxHeader(buffer[bytesWritten..], Heif4CharCode.Infe, 2, 0);
BinaryPrimitives.WriteUInt16BigEndian(buffer[bytesWritten..], (ushort)item.Id);
bytesWritten += 2;
BinaryPrimitives.WriteUInt16BigEndian(buffer[bytesWritten..], 0);
@ -196,7 +196,7 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
private static int WriteItemReferenceBox(AutoExpandingMemory<byte> memory, int memoryOffset, List<HeifItem> items, List<HeifItemLink> links)
{
Span<byte> buffer = memory.GetSpan(memoryOffset, 12 + (links.Count * (12 + (items.Count * 2))));
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.iref, 0, 0);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.Iref, 0, 0);
foreach (HeifItemLink link in links)
{
int itemLengthOffset = bytesWritten;
@ -222,11 +222,11 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
{
const ushort numPropPerItem = 1;
Span<byte> buffer = memory.GetSpan(memoryOffset, 20);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.iprp);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.Iprp);
// Write 'ipco' box
int ipcoLengthOffset = bytesWritten;
bytesWritten += WriteBoxHeader(buffer[bytesWritten..], Heif4CharCode.ipco);
bytesWritten += WriteBoxHeader(buffer[bytesWritten..], Heif4CharCode.Ipco);
foreach (HeifItem item in items)
{
bytesWritten += WriteSpatialExtentPropertyBox(memory, memoryOffset + bytesWritten, item);
@ -237,7 +237,7 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
// Write 'ipma' box
int ipmaLengthOffset = bytesWritten;
bytesWritten += WriteBoxHeader(buffer[bytesWritten..], Heif4CharCode.ipma, 0, 0);
bytesWritten += WriteBoxHeader(buffer[bytesWritten..], Heif4CharCode.Ipma, 0, 0);
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], (uint)(items.Count * numPropPerItem));
bytesWritten += 4;
ushort propIndex = 0;
@ -261,7 +261,7 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
private static int WriteSpatialExtentPropertyBox(AutoExpandingMemory<byte> memory, int memoryOffset, HeifItem item)
{
Span<byte> buffer = memory.GetSpan(memoryOffset, 20);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.ispe, 0, 0);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.Ispe, 0, 0);
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], (uint)item.Extent.Width);
bytesWritten += 4;
BinaryPrimitives.WriteUInt32BigEndian(buffer[bytesWritten..], (uint)item.Extent.Height);
@ -274,7 +274,7 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
private static int WriteItemDataBox(AutoExpandingMemory<byte> memory, int memoryOffset)
{
Span<byte> buffer = memory.GetSpan(memoryOffset, 10);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.idat);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.Idat);
BinaryPrimitives.WriteUInt32BigEndian(buffer, (uint)bytesWritten);
return bytesWritten;
@ -283,7 +283,7 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
private static int WriteItemLocationBox(AutoExpandingMemory<byte> memory, int memoryOffset, List<HeifItem> items)
{
Span<byte> buffer = memory.GetSpan(memoryOffset, 30 + (items.Count * 8));
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.iloc, 1, 0);
int bytesWritten = WriteBoxHeader(buffer, Heif4CharCode.Iloc, 1, 0);
buffer[bytesWritten++] = 0x44;
buffer[bytesWritten++] = 0;
BinaryPrimitives.WriteUInt16BigEndian(buffer[bytesWritten..], 1);
@ -313,7 +313,7 @@ internal sealed class HeifEncoderCore : IImageEncoderInternals
private void WriteMediaDataBox(Span<byte> data, Stream stream)
{
Span<byte> buf = stackalloc byte[12];
int bytesWritten = WriteBoxHeader(buf, Heif4CharCode.mdat);
int bytesWritten = WriteBoxHeader(buf, Heif4CharCode.Mdat);
BinaryPrimitives.WriteUInt32BigEndian(buf, (uint)(data.Length + bytesWritten));
stream.Write(buf[..bytesWritten]);

4
src/ImageSharp/Formats/Heif/HeifImageFormatDetector.cs

@ -23,8 +23,8 @@ public sealed class HeifImageFormatDetector : IImageFormatDetector
private static bool IsSupportedFileFormat(ReadOnlySpan<byte> header)
{
bool hasFtyp = BinaryPrimitives.ReadUInt32BigEndian(header.Slice(4)) == (uint)Heif4CharCode.ftyp;
bool hasFtyp = BinaryPrimitives.ReadUInt32BigEndian(header.Slice(4)) == (uint)Heif4CharCode.Ftyp;
uint brand = BinaryPrimitives.ReadUInt32BigEndian(header.Slice(8));
return hasFtyp && (brand == (uint)Heif4CharCode.heic || brand == (uint)Heif4CharCode.heix || brand == (uint)Heif4CharCode.avif);
return hasFtyp && (brand == (uint)Heif4CharCode.Heic || brand == (uint)Heif4CharCode.Heix || brand == (uint)Heif4CharCode.Avif);
}
}

Loading…
Cancel
Save