nokiatech / heif

High Efficiency Image File Format
Other
1.74k stars 247 forks source link

[Magic numbers] Detect heif file format using header byte sequence #74

Open tuancoltech opened 4 years ago

tuancoltech commented 4 years ago

As per my question, is there anyway to detect if a file is in heif format using it's first bytes sequence? We can check that with other common types, but haven't found information on this file.

Thanks.

mylodavidt commented 4 years ago

Well, kinda, but it's a bit complicated. HEIF is based on the ISO base media file format (ISOBMFF). That spec specifies that each file should start with an 'ftyp' box that specifies the file type.

"Boxes" start with a 32-bit Big Endian size of the box followed by the type (it's actually more complicated than this, but this is what's used for the ftyp):

aligned(8) class Box (unsigned int(32) boxtype) {
   unsigned int(32) size;
   unsigned int(32) type = boxtype;
}

The ftyp box is defined as:

aligned(8) class FileTypeBox
extends Box(‘ftyp’) {
unsigned int(32) major_brand;
unsigned int(32) minor_version;
unsigned int(32) compatible_brands[]; // to end of the box
}

The type, major_brand, and compatible_brands[] typically use text chars. An example start of a HEIF file would look like this:

0x00000018  // 24-bytes: size of 'ftyp' box.
'ftyp'      // boxtype
'heic'      // major_brand
0x00000000  // minor_version
'mif1'      // compatible_brands[0]
'heic'      // compatible_brands[1]

So for many, but definitely not all HEIF images you could skip the first 4-bytes (box size) and look for the byte sequence of 'ftypheic' (0x66747970 68656963 in HEX). However that will definitely miss some HEIF images. That's because some images may use something else for the major_brand but include heic in the list of compatible_brands[].

Here are some examples of the ftyp box from other HEIF images (taken from Nokia's conformance images):

C034.heic:

0x00000014  // 20-bytes: size of 'ftyp' box.
'ftyp'      // boxtype
'mif1'      // major_brand
0x00000000  // minor_version
'mif1'      // compatible_brands[0]

multilayer001.heic:

0x0000001C  // 28-bytes: size of 'ftyp' box.
'ftyp'      // boxtype
'heis'      // major_brand
0x00000000  // minor_version
'mif1'      // compatible_brands[0]
'heic'      // compatible_brands[1]
'heis'      // compatible_brands[2]

C038.heic:

0x00000020  // 32-bytes: size of 'ftyp' box.
'ftyp'      // boxtype
'hevc'      // major_brand
0x00000000  // minor_version
'msf1'      // compatible_brands[0]
'hevc'      // compatible_brands[1]
'iso8'      // compatible_brands[2]
'mp41'      // compatible_brands[3]