I suggest you read the Exif Specification (PDF); it is understandable and fairly easy to follow. For a quick guide, here is a summary of the article I wrote:
A JPEG / Exif file starts at the beginning of an image marker (SOI). SOI consists of two magic bytes 0xFF 0xD8
, identifying the file as a JPEG file. After SOI, there are a number of Mark Marker sections (APP0, APP1, APP2, APP3, ...), including metadata.
Application Token Sections
Each APPn section begins with a marker. For the APP0 section, the marker is 0xFF 0xE0
for the APP1 section 0xFF 0xE1
, etc. Token bytes are followed by two bytes for the size of the partition (excluding the token, including size bytes). The length field is followed by the data of the variable size application. APPn sections are sequential, so you can skip entire sections (using the size of the section) until you reach the one that interests you. The content of APPn partitions depends on the following: Exif APP1 partition only.
Exif APP1 Section
Exif metadata is stored in the APP1 section (there can be more than one APP1 section). Application data in the Exif APP1 section consists of the Exif marker 0x45 0x78 0x69 0x66 0x00 0x00
( "Exif\0\0"
), the TIFF header, and several sections of the image file directory (IFD).
TIFF Header
The TIFF header contains information about the byte order of the IFD sections and the pointer to the 0th IFD. The first two bytes: 0x49 0x49
( II
for Intel), if the byte order is not significant or 0x4D 0x4D
( MM
for Motorola) for big-endian. The next two bytes are magic bytes 0x00 0x2A
( 42
;)). And the next four important bytes will tell you the offset to the 0th IFD from the beginning of the TIFF header.
Important: The JPEG file itself (what you read so far) will always be in big-endian format. However, the byte order in the IFD subkeys may be different and must be converted (you know the byte order from the TIFF header above).
Image File Directories
Once you achieve this, you have a pointer to the IFD section 0 and you are ready to read the actual metadata. The remaining IFDs are mentioned in various places. Offsets to IFF Exif and GPS IFDs are given in the 0th IFD fields. The offset of the first IFD is given after the 0th IFD field. An offset to IFD compatibility is given in IFF Exif.
IFDs are simply sequential records of metadata fields. The field counter is set in the first two bytes of the IFD. After counting the fields, 12 byte fields. After the fields, there is a 4-byte offset from the beginning of the TIFF header to the beginning of the first IFD. This value only makes sense for the 0th IFD. After that there is an IFD data section.
IFD Fields
Fields are 12-byte subkeys of IFD sections. The first two bytes of each field give the tag identifier defined in the Exif standard. The next two bytes give the data type of the field. You will have 1
for byte
, 2
for ascii
, 3
for short
( uint16
), 4
for long
( uint32
), etc. Check Exif Specification for a complete list.
The next four bytes can be a bit confusing. For byte arrays ( ascii
and undefined types
), the byte length of the array is specified. For example, for the Ascii: "Exif"
, the counter will be 5, including the null terminator. For other types, this is the number of field components (for example, 4 shorts, 3 rationals).
Following the count, we have a 4-byte field value. However, if the field data is longer than 4 bytes, it will be stored in the IFD data section. In this case, this value will be the offset from the beginning of the TIFF header to the beginning of the field data. For example, for long
( uint32
, 4 bytes) this will be the value of the field. For rational
( 2 x uint32
, 8 bytes) this will be an offset to the 8-byte field data.
This is basically how metadata is placed in a JPEG / Exif file. There are a few caveats to keep in mind (remember that if necessary you need to convert the byte order, offsets from the beginning of the TIFF header, go to data sections to read long fields ...), but the format is pretty easy to read, the color representation of HEX is given below JPEG / Exif file. The blue block is the SOI, the orange is the TIFF header, the green is the IFD size and offset bytes, the light purple blocks are IFD fields, and dark purple are field data.
