static gint get_orientation (j_decompress_ptr cinfo) { /* This function looks through the meta data in the libjpeg decompress structure to determine if an EXIF Orientation tag is present and if so return its value (1-8). If no EXIF Orientation tag is found 0 (zero) is returned. */ guint i; /* index into working buffer */ guint orient_tag_id; /* endianed version of orientation tag ID */ guint ret; /* Return value */ guint offset; /* de-endianed offset in various situations */ guint tags; /* number of tags in current ifd */ guint type; /* de-endianed type of tag used as index into types[] */ guint count; /* de-endianed count of elements in a tag */ guint tiff = 0; /* offset to active tiff header */ guint endian = 0; /* detected endian of data */ jpeg_saved_marker_ptr exif_marker; /* Location of the Exif APP1 marker */ jpeg_saved_marker_ptr cmarker; /* Location to check for Exif APP1 marker */ /* check for Exif marker (also called the APP1 marker) */ exif_marker = NULL; cmarker = cinfo->marker_list; while (cmarker) { if (cmarker->marker == EXIF_JPEG_MARKER) { /* The Exif APP1 marker should contain a unique identification string ("Exif\0\0"). Check for it. */ if (!memcmp (cmarker->data, EXIF_IDENT_STRING, 6)) { exif_marker = cmarker; } } cmarker = cmarker->next; } /* Did we find the Exif APP1 marker? */ if (exif_marker == NULL) return 0; /* Do we have enough data? */ if (exif_marker->data_length < 32) return 0; /* Check for TIFF header and catch endianess */ i = 0; /* Just skip data until TIFF header - it should be within 16 bytes from marker start. Normal structure relative to APP1 marker - 0x0000: APP1 marker entry = 2 bytes 0x0002: APP1 length entry = 2 bytes 0x0004: Exif Identifier entry = 6 bytes 0x000A: Start of TIFF header (Byte order entry) - 4 bytes - This is what we look for, to determine endianess. 0x000E: 0th IFD offset pointer - 4 bytes exif_marker->data points to the first data after the APP1 marker and length entries, which is the exif identification string. The TIFF header should thus normally be found at i=6, below, and the pointer to IFD0 will be at 6+4 = 10. */ while (i < 16) { /* Little endian TIFF header */ if (memcmp (&exif_marker->data[i], leth, 4) == 0){ endian = G_LITTLE_ENDIAN; } /* Big endian TIFF header */ else if (memcmp (&exif_marker->data[i], beth, 4) == 0){ endian = G_BIG_ENDIAN; } /* Keep looking through buffer */ else { i++; continue; } /* We have found either big or little endian TIFF header */ tiff = i; break; } /* So did we find a TIFF header or did we just hit end of buffer? */ if (tiff == 0) return 0; /* Endian the orientation tag ID, to locate it more easily */ orient_tag_id = ENDIAN16_IT(0x112); /* Read out the offset pointer to IFD0 */ offset = de_get32(&exif_marker->data[i] + 4, endian); i = i + offset; /* Check that we still are within the buffer and can read the tag count */ if ((i + 2) > exif_marker->data_length) return 0; /* Find out how many tags we have in IFD0. As per the TIFF spec, the first two bytes of the IFD contain a count of the number of tags. */ tags = de_get16(&exif_marker->data[i], endian); i = i + 2; /* Check that we still have enough data for all tags to check. The tags are listed in consecutive 12-byte blocks. The tag ID, type, size, and a pointer to the actual value, are packed into these 12 byte entries. */ if ((i + tags * 12) > exif_marker->data_length) return 0; /* Check through IFD0 for tags of interest */ while (tags--){ type = de_get16(&exif_marker->data[i + 2], endian); count = de_get32(&exif_marker->data[i + 4], endian); /* Is this the orientation tag? */ if (memcmp (&exif_marker->data[i], (char *) &orient_tag_id, 2) == 0){ /* Check that type and count fields are OK. The orientation field will consist of a single (count=1) 2-byte integer (type=3). */ if (type != 3 || count != 1) return 0; /* Return the orientation value. Within the 12-byte block, the pointer to the actual data is at offset 8. */ ret = de_get16(&exif_marker->data[i + 8], endian); return ret <= 8 ? ret : 0; } /* move the pointer to the next 12-byte tag field. */ i = i + 12; } return 0; /* No EXIF Orientation tag found */ }
static gboolean jpeg_parse_exif_app1 (JpegExifContext *context, jpeg_saved_marker_ptr marker) { guint i; guint ret = FALSE; guint offset; guint tags; /* number of tags in current ifd */ guint endian = 0; /* detected endian of data */ const char leth[] = {0x49, 0x49, 0x2a, 0x00}; // Little endian TIFF header const char beth[] = {0x4d, 0x4d, 0x00, 0x2a}; // Big endian TIFF header /* do we have enough data? */ if (marker->data_length < 4) goto out; /* unique identification string */ if (memcmp (marker->data, "Exif", 4) != 0) goto out; /* do we have enough data? */ if (marker->data_length < 32) goto out; /* Just skip data until TIFF header - it should be within 16 bytes from marker start. Normal structure relative to APP1 marker - 0x0000: APP1 marker entry = 2 bytes 0x0002: APP1 length entry = 2 bytes 0x0004: Exif Identifier entry = 6 bytes 0x000A: Start of TIFF header (Byte order entry) - 4 bytes - This is what we look for, to determine endianess. 0x000E: 0th IFD offset pointer - 4 bytes marker->data points to the first data after the APP1 marker and length entries, which is the exif identification string. The TIFF header should thus normally be found at i=6, below, and the pointer to IFD0 will be at 6+4 = 10. */ for (i=0; i<16; i++) { /* little endian TIFF header */ if (memcmp (&marker->data[i], leth, 4) == 0) { endian = G_LITTLE_ENDIAN; ret = TRUE; break; } /* big endian TIFF header */ if (memcmp (&marker->data[i], beth, 4) == 0) { endian = G_BIG_ENDIAN; ret = TRUE; break; } } /* could not find header */ if (!ret) goto out; /* read out the offset pointer to IFD0 */ offset = de_get32(&marker->data[i] + 4, endian); i = i + offset; /* check that we still are within the buffer and can read the tag count */ if ((i + 2) > marker->data_length) { ret = FALSE; goto out; } /* find out how many tags we have in IFD0. As per the TIFF spec, the first two bytes of the IFD contain a count of the number of tags. */ tags = de_get16(&marker->data[i], endian); i = i + 2; /* check that we still have enough data for all tags to check. The tags are listed in consecutive 12-byte blocks. The tag ID, type, size, and a pointer to the actual value, are packed into these 12 byte entries. */ if ((i + tags * 12) > marker->data_length) { ret = FALSE; goto out; } /* check through IFD0 for tags */ while (tags--){ guint tag = de_get16(&marker->data[i + 0], endian); guint type = de_get16(&marker->data[i + 2], endian); guint count = de_get32(&marker->data[i + 4], endian); /* values of types small enough to fit are stored directly in the (first) bytes of the Value Offset field */ guint short_value = de_get16(&marker->data[i + 8], endian); /* orientation tag? */ if (tag == 0x112){ /* The orientation field should consist of a single 2-byte integer */ if (type != 0x3 || count != 1) continue; /* get the orientation value */ context->orientation = short_value <= 8 ? short_value : 0; } /* move the pointer to the next 12-byte tag field. */ i = i + 12; } out: return ret; }