Browse Source

4CC generated by template

pull/2633/head
Ynse Hoornenborg 3 years ago
parent
commit
96b92e847b
  1. 219
      src/ImageSharp/Formats/Heic/FourCharacterCode.cs
  2. 4
      src/ImageSharp/Formats/Heic/HeicConstants.cs
  3. 138
      src/ImageSharp/Formats/Heic/HeicDecoderCore.cs
  4. 201
      src/ImageSharp/Formats/Heic/HeicFourCharacterCodes.cs
  5. 84
      src/ImageSharp/Formats/Heic/HeicFourCharacterCodes.tt
  6. 4
      src/ImageSharp/Formats/Heic/HeicImageFormatDetector.cs
  7. 47
      src/ImageSharp/Formats/Heic/HeicItem.cs
  8. 4
      src/ImageSharp/Formats/Heic/HeicItemLink.cs
  9. 36
      src/ImageSharp/Formats/Heic/HeicNalUnitType.cs
  10. 9
      src/ImageSharp/ImageSharp.csproj

219
src/ImageSharp/Formats/Heic/FourCharacterCode.cs

@ -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;
/// <summary>
/// Provides constants for 4 Character codes used in HEIC images.
/// </summary>
[GeneratedCode("T4", null)]
public static class FourCharacterCode
{
// TODO: Create T4 template for this file
/// <summary>
/// File Type
/// </summary>
public const uint ftyp = 0x66747970U;
/// <summary>
/// Metadata container
/// </summary>
public const uint meta = 0x6D657461U;
/// <summary>
/// Media Data
/// </summary>
public const uint mdat = 0x6D646174U;
/// <summary>
/// Item Information Entry
/// </summary>
public const uint infe = 0x696E6665U;
/// <summary>
/// Item Data
/// </summary>
public const uint idat = 0x69646174U;
/// <summary>
/// Item Location
/// </summary>
public const uint iloc = 0x696C6F63U;
/// <summary>
/// EXIF metadata
/// </summary>
public const uint Exif = 0x45786966U;
/// <summary>
/// Data Reference
/// </summary>
public const uint dref = 0x64726566U;
/// <summary>
/// Primary Item
/// </summary>
public const uint pitm = 0x7069746DU;
/// <summary>
/// Item Spatial Extent
/// </summary>
public const uint ispe = 0x69737064U;
/// <summary>
/// Alternative text
/// </summary>
public const uint altt = 0; // 'altt'
/// <summary>
/// Colour information
/// </summary>
public const uint colr = 0; // 'colr'
/// <summary>
/// HVC configuration
/// </summary>
public const uint hvcC = 0; // 'hvcC'
/// <summary>
/// Image Mirror
/// </summary>
public const uint imir = 0; // 'imir'
/// <summary>
/// Image Rotation
/// </summary>
public const uint irot = 0; // 'irot'
/// <summary>
/// Image Scaling
/// </summary>
public const uint iscl = 0; // 'iscl'
/// <summary>
/// Pixel Aspect Ration
/// </summary>
public const uint pasp = 0; // 'pasp'
/// <summary>
/// Pixel Information
/// </summary>
public const uint pixi = 0x70697869U;
/// <summary>
/// Reference Location
/// </summary>
public const uint rloc = 0; // 'rloc
/// <summary>
/// User Description
/// </summary>
public const uint udes = 0; // 'udes'
/// <summary>
/// Item Property Container
/// </summary>
public const uint ipco = 0;
/// <summary>
/// Item Property Association
/// </summary>
public const uint ipma = 0;
/// <summary>
/// High Efficient Image Coding
/// </summary>
public const uint heic = 0;
/// <summary>
/// High Efficiency Coding tile
/// </summary>
public const uint hvc1 = 0;
/// <summary>
/// Data Information
/// </summary>
public const uint dinf = 0;
/// <summary>
/// Group list
/// </summary>
public const uint grpl = 0;
/// <summary>
/// Handler
/// </summary>
public const uint hdlr = 0;
/// <summary>
/// Item Information
/// </summary>
public const uint iinf = 0; // 'iinf'
/// <summary>
/// Item Property
/// </summary>
public const uint iprp = 0; // 'iprp'
/// <summary>
/// Item Protection
/// </summary>
public const uint ipro = 0; // 'ipro'
/// <summary>
/// Item Reference
/// </summary>
public const uint iref = 0; // 'iref'
/// <summary>
/// Grid
/// </summary>
public const uint grid = 0; // 'grid'
/// <summary>
/// Derived Image
/// </summary>
public const uint dimg = 0; // 'dimg'
/// <summary>
/// Thumbnail
/// </summary>
public const uint thmb = 0; // 'thmb'
/// <summary>
/// Content Description
/// </summary>
public const uint cdsc = 0; // 'cdsc'
/// <summary>
/// MIME type
/// </summary>
public const uint mime = 0; // 'mime'
/// <summary>
/// URI
/// </summary>
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<byte> span = Encoding.UTF8.GetBytes(code);
return BinaryPrimitives.ReadUInt32BigEndian(span);
}
public static string ToString(uint fourcc)
{
Span<byte> span = stackalloc byte[4];
BinaryPrimitives.WriteUInt32BigEndian(span, fourcc);
return Encoding.UTF8.GetString(span);
}
}

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

@ -8,12 +8,12 @@ namespace SixLabors.ImageSharp.Formats.Heic;
/// </summary>
internal static class HeicConstants
{
public const uint HeicBrand = FourCharacterCode.heic;
public const Heic4CharCode HeicBrand = Heic4CharCode.heic;
/// <summary>
/// The list of mimetypes that equate to a HEIC.
/// </summary>
public static readonly IEnumerable<string> MimeTypes = new[] { "image/heif", "image/heif-sequence", "image/heic", "image/heic-sequence", "image/avif" };
public static readonly IEnumerable<string> MimeTypes = new[] { "image/heif", "image/heic", "image/avif" };
/// <summary>
/// The list of file extensions that equate to a HEIC.

138
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<TPixel>(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<TPixel>(this.configuration, item.Extent.Width, item.Extent.Height, this.metadata);
Buffer2D<TPixel> 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<byte> 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<byte> 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<byte> buffer, out long length, out uint boxType)
private static int ParseBoxHeader(Span<byte> 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<byte> 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<KeyValuePair<uint, object>> properties = new();
long containerLength = this.ReadBoxHeader(stream, out uint containerType);
if (containerType == FourCharacterCode.ipco)
List<KeyValuePair<Heic4CharCode, object>> 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<byte> 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<uint, object>(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, object>(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<uint, object>(FourCharacterCode.pasp, new uint[] { horizontalSpacing, verticalSpacing }));
int horizontalSpacing = (int)BinaryPrimitives.ReadUInt32BigEndian(buffer);
int verticalSpacing = (int)BinaryPrimitives.ReadUInt32BigEndian(buffer[4..]);
properties.Add(new KeyValuePair<Heic4CharCode, object>(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<uint, object>(FourCharacterCode.pixi, new int[] { channelCount, bitsPerPixel }));
properties.Add(new KeyValuePair<Heic4CharCode, object>(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<byte> 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<Heic4CharCode, object> 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<byte> span)
{
Span<byte> bytes = span[..span.IndexOf((byte)0)];

201
src/ImageSharp/Formats/Heic/HeicFourCharacterCodes.cs

@ -0,0 +1,201 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
// <auto-generated />
using System.CodeDom.Compiler;
namespace SixLabors.ImageSharp.Formats.Heic;
/// <summary>
/// Supported 4 character codes for use in HEIC images.
/// </summary>
[GeneratedCode("T4", null)]
public enum Heic4CharCode : uint
{
/// <summary>
/// File Type.
/// </summary>
ftyp = 0x66747970U,
/// <summary>
/// Metadata.
/// </summary>
meta = 0x6D657461U,
/// <summary>
/// Media Data.
/// </summary>
mdat = 0x6D646174U,
/// <summary>
/// Item Information Entry.
/// </summary>
infe = 0x696E6665U,
/// <summary>
/// Item Data.
/// </summary>
idat = 0x69646174U,
/// <summary>
/// Item Location.
/// </summary>
iloc = 0x696C6F63U,
/// <summary>
/// EXIF metadata.
/// </summary>
Exif = 0x45786966U,
/// <summary>
/// Data Reference.
/// </summary>
dref = 0x64726566U,
/// <summary>
/// Primary Item.
/// </summary>
pitm = 0x7069746DU,
/// <summary>
/// Item Spatial Extent.
/// </summary>
ispe = 0x69737065U,
/// <summary>
/// Alternative text.
/// </summary>
altt = 0x616C7474U,
/// <summary>
/// Colour information.
/// </summary>
colr = 0x636F6C72U,
/// <summary>
/// HVC configuration.
/// </summary>
hvcC = 0x68766343U,
/// <summary>
/// Image Mirror.
/// </summary>
imir = 0x696D6972U,
/// <summary>
/// Image Rotation.
/// </summary>
irot = 0x69726F74U,
/// <summary>
/// Image Scaling.
/// </summary>
iscl = 0x6973636CU,
/// <summary>
/// Pixel Aspect Ratio.
/// </summary>
pasp = 0x70617370U,
/// <summary>
/// Pixel Information.
/// </summary>
pixi = 0x70697869U,
/// <summary>
/// Reference Location.
/// </summary>
rloc = 0x726C6F63U,
/// <summary>
/// User Description.
/// </summary>
udes = 0x75646573U,
/// <summary>
/// Item Property Container.
/// </summary>
ipco = 0x6970636FU,
/// <summary>
/// Item Property Association.
/// </summary>
ipma = 0x69706D61U,
/// <summary>
/// High Efficient Image Coding.
/// </summary>
heic = 0x68656963U,
/// <summary>
/// High Efficiency Coding tile.
/// </summary>
hvc1 = 0x68766331U,
/// <summary>
/// Data Information.
/// </summary>
dinf = 0x64696E66U,
/// <summary>
/// Group list.
/// </summary>
grpl = 0x6772706CU,
/// <summary>
/// Handler.
/// </summary>
hdlr = 0x68646C72U,
/// <summary>
/// Item Information.
/// </summary>
iinf = 0x69696E66U,
/// <summary>
/// Item Property.
/// </summary>
iprp = 0x69707270U,
/// <summary>
/// Item Protection.
/// </summary>
ipro = 0x6970726FU,
/// <summary>
/// Item Reference.
/// </summary>
iref = 0x69726566U,
/// <summary>
/// Grid.
/// </summary>
grid = 0x67726964U,
/// <summary>
/// Derived Image.
/// </summary>
dimg = 0x64696D67U,
/// <summary>
/// Thumbnail.
/// </summary>
thmb = 0x74686D62U,
/// <summary>
/// Content Description.
/// </summary>
cdsc = 0x63647363U,
/// <summary>
/// MIME type.
/// </summary>
mime = 0x6D696D65U,
/// <summary>
/// URI.
/// </summary>
uri = 0x75726920U,
}

84
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.
// <auto-generated />
<#
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;
/// <summary>
/// Supported 4 character codes for use in HEIC images.
/// </summary>
[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);
#>
/// <summary>
/// <#= longName #>.
/// </summary>
<#= 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]);
}
#>

4
src/ImageSharp/Formats/Heic/HeicImageFormatDetector.cs

@ -22,6 +22,6 @@ public sealed class HeicImageFormatDetector : IImageFormatDetector
}
private static bool IsSupportedFileFormat(ReadOnlySpan<byte> 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;
}

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

@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Heic;
/// <summary>
/// Provides definition for a HEIC Item.
/// </summary>
public class HeicItem(uint type, uint id)
public class HeicItem(Heic4CharCode type, uint id)
{
/// <summary>
/// Gets the ID of this Item.
@ -16,7 +16,7 @@ public class HeicItem(uint type, uint id)
/// <summary>
/// Gets the type of this Item.
/// </summary>
public uint Type { get; } = type;
public Heic4CharCode Type { get; } = type;
/// <summary>
/// Gets or sets the name of this item.
@ -44,21 +44,40 @@ public class HeicItem(uint type, uint id)
public string? UriType { get; set; }
/// <summary>
/// Sets a property on this item.
/// Gets or sets the aspect ratio of the pixels.
/// </summary>
public void SetProperty(KeyValuePair<uint, object> pair)
public Size PixelAspectRatio { get; set; }
/// <summary>
/// Gets or sets the number of color channels in each pixel.
/// </summary>
public int ChannelCount { get; set; }
/// <summary>
/// Gets or sets the number of bits in a single pixel.
/// </summary>
public int BitsPerPixel { get; set; }
/// <summary>
/// Gets the spatial extent of this item.
/// </summary>
public Size Extent { get; private set; }
/// <summary>
/// Gets the spatial extent of this grid cells in this item.
/// </summary>
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;
}
}
}

4
src/ImageSharp/Formats/Heic/HeicItemLink.cs

@ -6,12 +6,12 @@ namespace SixLabors.ImageSharp.Formats.Heic;
/// <summary>
/// Link between <see cref="HeicItem"/> instances within the same HEIC file.
/// </summary>
public class HeicItemLink(uint type, uint sourceId)
public class HeicItemLink(Heic4CharCode type, uint sourceId)
{
/// <summary>
/// Gets the type of link.
/// </summary>
public uint Type { get; } = type;
public Heic4CharCode Type { get; } = type;
/// <summary>
/// Gets the ID of the source item of this link.

36
src/ImageSharp/Formats/Heic/HeicNalUnitType.cs

@ -1,36 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Formats.Heic;
/// <summary>
/// Provides enumeration of supported x265's LAN Unit Types.
/// </summary>
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,
}

9
src/ImageSharp/ImageSharp.csproj

@ -52,6 +52,11 @@
</ItemGroup>
<ItemGroup>
<Compile Update="Formats\Heic\HeicFourCharacterCodes.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>HeicFourCharacterCodes.tt</DependentUpon>
</Compile>
<Compile Update="Formats\Jpeg\Components\Block8x8F.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
@ -150,6 +155,10 @@
</ItemGroup>
<ItemGroup>
<None Update="Formats\Heic\HeicFourCharacterCodes.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>HeicFourCharacterCodes.cs</LastGenOutput>
</None>
<None Update="Formats\Jpeg\Components\Block8x8F.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Block8x8F.Generated.cs</LastGenOutput>

Loading…
Cancel
Save