47#define JPEG_MARKER_SOI 0xd8
48#undef JPEG_MARKER_APP0
49#define JPEG_MARKER_APP0 0xe0
50#undef JPEG_MARKER_APP1
51#define JPEG_MARKER_APP1 0xe1
53#define CHECKOVERFLOW(offset,datasize,structsize) (( (offset) >= (datasize)) || ((structsize) > (datasize)) || ((offset) > (datasize) - (structsize) ))
55static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
140#ifndef NO_VERBOSE_TAG_STRINGS
167 const unsigned char *d,
168 unsigned int size,
unsigned int offset)
170 unsigned int s, doff;
180 "Loading entry 0x%x ('%s')...", entry->
tag,
186 if ((s < entry->components) || (s == 0)){
202 "Tag starts past end of buffer (%u > %u)", doff,
size);
206 if (s >
size - doff) {
208 "Tag data goes past end of buffer (%u > %u)", doff+s,
size);
215 memcpy (entry->
data, d + doff, s);
225 "MakerNote found with empty data");
226 }
else if (entry->
size > 6) {
229 "MakerNote found (%02x %02x %02x %02x "
230 "%02x %02x %02x...).",
242 unsigned char **d,
unsigned int *ds,
245 unsigned int doff, s;
248 if (!data || !data->
priv)
313 *(*d + *ds - 1) =
'\0';
321 unsigned int len = s;
323 memcpy (*d + 6 + doff, e->
data, len);
325 memset (*d + 6 + doff, 0, s);
328 memset (*d + 6 + doff + s, 0, (4 - s));
352 memcpy (data->
data, d + o, s);
356#define CHECK_REC(i) \
358 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \
359 "ExifData", "Recursive entry in IFD " \
360 "'%s' detected. Skipping...", \
361 exif_ifd_get_name (i)); \
364if (data->ifd[(i)]->count) { \
365 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \
366 "ExifData", "Attempt to load IFD " \
367 "'%s' multiple times detected. " \
369 exif_ifd_get_name (i)); \
381 static const double log_1_1 = 0.09531017980432493;
384 return ceil(log(n + 0.1)/log_1_1);
399 const unsigned char *d,
400 unsigned int ds,
unsigned int offset,
unsigned int recursion_cost)
402 ExifLong o, thumbnail_offset = 0, thumbnail_length = 0;
408 if (!data || !data->
priv)
415 if (recursion_cost > 170) {
428 "Deep/expensive recursion detected!");
435 "Tag data past end of buffer (%u+2 > %u)", offset, ds);
440 "Loading %hu entries...", n);
445 n = (ds - offset) / 12;
447 "Short data; only loading %hu entries...", n);
450 for (i = 0; i < n; i++) {
463 "Tag data past end of buffer (%u > %u)", offset+2, ds);
464 if (recursion_cost > 0)
472 "Sub-IFD entry 0x%x ('%s') at %u.",
tag,
491 thumbnail_offset = o;
492 if (thumbnail_offset && thumbnail_length)
494 ds, thumbnail_offset,
498 thumbnail_length = o;
499 if (thumbnail_offset && thumbnail_length)
501 ds, thumbnail_offset,
521 if (!memcmp (d + offset + 12 * i,
"\0\0\0\0", 4)) {
523 "Skipping empty entry at position %u in '%s'.", i,
528 "Unknown tag 0x%04x (entry %u in '%s'). Please report this tag "
529 "to <libexif-devel@lists.sourceforge.net>.",
tag, i,
537 "Could not allocate memory");
555 return (tag1 < tag2) ? -1 : (tag1 > tag2) ? 1 : 0;
561 return cmp_func ((
const unsigned char *) elem1,
568 return cmp_func ((
const unsigned char *) elem1,
574 unsigned char **d,
unsigned int *ds,
577 unsigned int j, n_ptr = 0, n_thumb = 0;
582 if (!data || !data->
priv || !
ifd || !d || !ds)
625 ts = *ds + (2 + (
ifd->count + n_ptr + n_thumb) * 12 + 4);
644 "Saving %i entries (IFD '%s', offset: %i)...",
646 for (j = 0; j <
ifd->count; j++) {
647 if (
ifd->entries[j]) {
653 offset += 12 *
ifd->count;
735 ts = *ds + data->
size;
765 qsort (*d + 6 + offset - (
ifd->count + n_ptr + n_thumb) * 12,
766 (
ifd->count + n_ptr + n_thumb), 12,
810 "ExifData",
"Olympus MakerNote variant type %d", mnoteid);
815 "ExifData",
"Canon MakerNote variant type %d", mnoteid);
820 "ExifData",
"Fuji MakerNote variant type %d", mnoteid);
827 "ExifData",
"Pentax MakerNote variant type %d", mnoteid);
851#define LOG_TOO_SMALL \
852exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", \
853 _("Size of data too small to allow for EXIF data."))
862 const unsigned char *d = d_orig;
863 unsigned int len, fullds;
865 if (!data || !data->
priv || !d || !ds)
869 "Parsing %i byte(s) EXIF data...\n", ds);
881 "Found EXIF header at start.");
884 while (ds && (d[0] == 0xff)) {
904 if ((ds >= 9) && !memcmp (d+3,
ExifHeader, 6))
913 if (ds >= 3 && d[0] >= 0xe0 && d[0] <= 0xef) {
916 l = (((
unsigned int)d[0]) << 8) | d[1];
926 "ExifData",
_(
"EXIF marker not found."));
935 len = (((
unsigned int)d[0]) << 8) | d[1];
938 "ExifData",
_(
"Read length %d is longer than data length %d."), len, ds);
943 "ExifData",
_(
"APP Tag too short."));
947 "We have to deal with %i byte(s) of EXIF data.",
963 "ExifData",
_(
"EXIF header not found."));
968 "Found EXIF header.");
982 if (!memcmp (d + 6,
"II", 2))
984 else if (!memcmp (d + 6,
"MM", 2))
988 "ExifData",
_(
"Unknown encoding."));
999 "IFD 0 at %i.", (
int) offset);
1002 if (offset > ds || offset + 6 + 2 > ds)
1011 if (offset + 6 + 2 + 12 * n + 4 > ds)
1017 "IFD 1 at %i.", (
int) offset);
1020 if (offset > ds - 6) {
1022 "ExifData",
"Bogus offset of IFD1.");
1047 if (!data || !d || !ds)
1061 memcpy (*d + 6,
"II", 2);
1063 memcpy (*d + 6,
"MM", 2);
1083 "Saved %i byte(s) EXIF data.", *ds);
1132 data->
ifd[i] = NULL;
1167 printf (
"Dumping IFD '%s'...\n",
1174 printf (
"%i byte(s) thumbnail data available: ", data->
size);
1175 if (data->
size >= 4) {
1176 printf (
"0x%02x 0x%02x ... 0x%02x 0x%02x\n",
1203 func (data->
ifd[i], user_data);
1233 if (!data || (order == data->
priv->
order))
1249 if (!data || !data->
priv)
1264 if (!data || !data->
priv)
1269static const struct {
1275 N_(
"Ignore unknown tags when loading EXIF data.")},
1277 N_(
"Add, correct and remove entries to get EXIF data that follows "
1278 "the specification.")},
1280 N_(
"When loading and resaving Exif data, save the maker note unmodified."
1281 " Be aware that the maker note can get corrupted.")},
1332 else if (c->
count) {
1334 "No thumbnail but entries on thumbnail. These entries have been "
1337 unsigned int cnt = c->
count;
1339 if (cnt == c->
count) {
1342 "failed to remove last entry from entries.");
ExifByteOrder
Which byte order to use.
@ EXIF_BYTE_ORDER_INTEL
Little-endian byte order.
@ EXIF_BYTE_ORDER_MOTOROLA
Big-endian byte order.
void exif_content_remove_entry(ExifContent *c, ExifEntry *e)
Remove an EXIF tag from an IFD.
ExifIfd exif_content_get_ifd(ExifContent *c)
Return the IFD number in which the given ExifContent is found.
void exif_content_fix(ExifContent *c)
Fix the IFD to bring it into specification.
ExifContent * exif_content_new_mem(ExifMem *mem)
Reserve memory for and initialize new ExifContent using the specified memory allocator.
void exif_content_unref(ExifContent *content)
Decrease reference counter for ExifContent.
void exif_content_add_entry(ExifContent *c, ExifEntry *entry)
Add an EXIF tag to an IFD.
void exif_content_dump(ExifContent *content, unsigned int indent)
Dump contents of the IFD to stdout.
void exif_content_log(ExifContent *content, ExifLog *log)
Set the log message object for this IFD.
void exif_content_foreach_entry(ExifContent *content, ExifContentForeachEntryFunc func, void *data)
Executes function on each EXIF tag in this IFD in turn.
ExifDataType
Represents the type of image data to which the EXIF data applies.
static void exif_data_load_data_thumbnail(ExifData *data, const unsigned char *d, unsigned int ds, ExifLong o, ExifLong s)
static unsigned int level_cost(unsigned int n)
Calculate the recursion cost added by one level of IFD loading.
static int cmp_func(const unsigned char *p1, const unsigned char *p2, ExifByteOrder o)
void exif_data_set_byte_order(ExifData *data, ExifByteOrder order)
Set the byte order to use for this EXIF data.
ExifData * exif_data_new_mem(ExifMem *mem)
Allocate a new ExifData using the given memory allocator.
static void fix_func(ExifContent *c, void *UNUSED(data))
void exif_data_unref(ExifData *data)
void exif_data_free(ExifData *data)
ExifByteOrder exif_data_get_byte_order(ExifData *data)
Return the byte order in use by this EXIF structure.
ExifMnoteData * exif_data_get_mnote_data(ExifData *d)
Return the MakerNote data out of the EXIF data.
@ EXIF_DATA_TYPE_MAKER_NOTE_CANON
@ EXIF_DATA_TYPE_MAKER_NOTE_CASIO
@ EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS
@ EXIF_DATA_TYPE_MAKER_NOTE_NONE
@ EXIF_DATA_TYPE_MAKER_NOTE_FUJI
@ EXIF_DATA_TYPE_MAKER_NOTE_NIKON
@ EXIF_DATA_TYPE_MAKER_NOTE_PENTAX
void exif_data_ref(ExifData *data)
static void * exif_data_alloc(ExifData *data, unsigned int i)
void exif_data_load_data(ExifData *data, const unsigned char *d_orig, unsigned int ds)
Load the ExifData structure from the raw JPEG or EXIF data in the given memory buffer.
ExifDataType exif_data_get_data_type(ExifData *d)
Return the data type for the given ExifData.
const char * exif_data_option_get_description(ExifDataOption o)
Return a verbose textual description of the given ExifDataOption.
static void content_set_byte_order(ExifContent *content, void *data)
static const unsigned char ExifHeader[]
const char * exif_data_option_get_name(ExifDataOption o)
Return a short textual description of the given ExifDataOption.
ExifData * exif_data_new(void)
Allocate a new ExifData.
ExifData * exif_data_new_from_data(const unsigned char *data, unsigned int size)
Allocate a new ExifData and load EXIF data from a memory buffer.
static void exif_data_save_data_entry(ExifData *data, ExifEntry *e, unsigned char **d, unsigned int *ds, unsigned int offset)
void exif_data_fix(ExifData *d)
Fix the EXIF data to bring it into specification.
ExifLog * exif_data_get_log(ExifData *)
static void entry_set_byte_order(ExifEntry *e, void *data)
static void interpret_maker_note(ExifData *data, const unsigned char *d, unsigned int ds)
If MakerNote is recognized, load it.
static const struct @3 exif_data_option[]
void exif_data_dump(ExifData *data)
Dump all EXIF data to stdout.
void exif_data_unset_option(ExifData *d, ExifDataOption o)
Clear the given option on the given ExifData.
void exif_data_set_data_type(ExifData *d, ExifDataType dt)
Set the data type for the given ExifData.
ExifData * exif_data_new_from_file(const char *path)
Allocate a new ExifData and load EXIF data from a JPEG file.
static int cmp_func_intel(const void *elem1, const void *elem2)
static int exif_data_load_data_entry(ExifData *data, ExifEntry *entry, const unsigned char *d, unsigned int size, unsigned int offset)
void exif_data_save_data(ExifData *data, unsigned char **d, unsigned int *ds)
Store raw EXIF data representing the ExifData structure into a memory buffer.
static void exif_data_save_data_content(ExifData *data, ExifContent *ifd, unsigned char **d, unsigned int *ds, unsigned int offset)
void exif_data_foreach_content(ExifData *data, ExifDataForeachContentFunc func, void *user_data)
Execute a function on each IFD in turn.
#define CHECKOVERFLOW(offset, datasize, structsize)
static int cmp_func_motorola(const void *elem1, const void *elem2)
static void exif_data_load_data_content(ExifData *data, ExifIfd ifd, const unsigned char *d, unsigned int ds, unsigned int offset, unsigned int recursion_cost)
Load data for an IFD.
void exif_data_log(ExifData *data, ExifLog *log)
Set the log message object for all IFDs.
void exif_data_set_option(ExifData *d, ExifDataOption o)
Set the given option on the given ExifData.
Defines the ExifData type and the associated functions.
ExifDataOption
Options to configure the behaviour of ExifData.
@ EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE
Leave the MakerNote alone, which could cause it to be corrupted.
@ EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS
Act as though unknown tags are not present.
@ EXIF_DATA_OPTION_FOLLOW_SPECIFICATION
Fix the EXIF tags to follow the spec.
#define exif_data_get_entry(d, t)
Return an ExifEntry for the given tag if found in any IFD.
void(* ExifDataForeachContentFunc)(ExifContent *, void *user_data)
ExifEntry * exif_entry_new_mem(ExifMem *mem)
Reserve memory for and initialize new ExifEntry using the specified memory allocator.
void exif_entry_unref(ExifEntry *e)
Decrease reference counter for ExifEntry.
const char * exif_ifd_get_name(ExifIfd ifd)
Return a textual name of the given IFD.
ExifIfd
Possible EXIF Image File Directories.
@ EXIF_IFD_INTEROPERABILITY
@ EXIF_IFD_COUNT
Not a real value, just (max_value + 1).
ExifLoader * exif_loader_new(void)
Allocate a new ExifLoader.
ExifData * exif_loader_get_data(ExifLoader *loader)
Create an ExifData from the data in the loader.
void exif_loader_unref(ExifLoader *loader)
Decrease the refcount of the ExifLoader.
void exif_loader_write_file(ExifLoader *l, const char *path)
Load a file into the given ExifLoader from the filesystem.
Defines the ExifLoader type.
void exif_log(ExifLog *log, ExifLogCode code, const char *domain, const char *format,...)
void exif_log_unref(ExifLog *log)
void exif_log_ref(ExifLog *log)
Log message infrastructure.
@ EXIF_LOG_CODE_NO_MEMORY
@ EXIF_LOG_CODE_CORRUPT_DATA
#define EXIF_LOG_NO_MEMORY(l, d, s)
void exif_mem_free(ExifMem *mem, void *d)
void exif_mem_unref(ExifMem *mem)
Unrefcount an ExifMem.
void * exif_mem_alloc(ExifMem *mem, ExifLong ds)
void * exif_mem_realloc(ExifMem *mem, void *d, ExifLong ds)
ExifMem * exif_mem_new_default(void)
Create a new ExifMem with default values for your convenience.
void exif_mem_ref(ExifMem *mem)
Refcount an ExifMem.
ExifMnoteData * exif_mnote_data_canon_new(ExifMem *mem, ExifDataOption o)
int exif_mnote_data_canon_identify(const ExifData *ed, const ExifEntry *e)
Detect if MakerNote is recognized as one handled by the Canon module.
ExifMnoteData * exif_mnote_data_fuji_new(ExifMem *mem)
int exif_mnote_data_fuji_identify(const ExifData *ed, const ExifEntry *e)
Detect if MakerNote is recognized as one handled by the Fuji module.
int exif_mnote_data_olympus_identify(const ExifData *ed, const ExifEntry *e)
Detect if MakerNote is recognized as one handled by the Olympus module.
ExifMnoteData * exif_mnote_data_olympus_new(ExifMem *mem)
int exif_mnote_data_pentax_identify(const ExifData *ed, const ExifEntry *e)
Detect if MakerNote is recognized as one handled by the Pentax module.
ExifMnoteData * exif_mnote_data_pentax_new(ExifMem *mem)
void exif_mnote_data_set_offset(ExifMnoteData *, unsigned int)
void exif_mnote_data_set_byte_order(ExifMnoteData *, ExifByteOrder)
void exif_mnote_data_load(ExifMnoteData *d, const unsigned char *buf, unsigned int buf_size)
Load the MakerNote data from a memory buffer.
void exif_mnote_data_save(ExifMnoteData *d, unsigned char **buf, unsigned int *buf_size)
Save the raw MakerNote data into a memory buffer.
void exif_mnote_data_log(ExifMnoteData *d, ExifLog *log)
void exif_mnote_data_unref(ExifMnoteData *d)
Handling EXIF MakerNote tags.
System specific definitions, not for installation!
const char * exif_tag_get_name_in_ifd(ExifTag tag, ExifIfd ifd)
Return a textual name of the given tag when found in the given IFD.
const char * exif_tag_get_name(ExifTag tag)
@ EXIF_TAG_EXIF_IFD_POINTER
@ EXIF_TAG_GPS_INFO_IFD_POINTER
@ EXIF_TAG_INTEROPERABILITY_IFD_POINTER
@ EXIF_TAG_JPEG_INTERCHANGE_FORMAT
@ EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH
ExifLong exif_get_long(const unsigned char *buf, ExifByteOrder order)
Retrieve an ExifLong value from memory.
ExifShort exif_get_short(const unsigned char *buf, ExifByteOrder order)
Retrieve an ExifShort value from memory.
void exif_array_set_byte_order(ExifFormat f, unsigned char *b, unsigned int n, ExifByteOrder o_orig, ExifByteOrder o_new)
void exif_set_long(unsigned char *b, ExifByteOrder order, ExifLong value)
Store an ExifLong value into memory in EXIF format.
void exif_set_short(unsigned char *b, ExifByteOrder order, ExifShort value)
Store an ExifShort value into memory in EXIF format.
EXIF data manipulation functions and types.
uint32_t ExifLong
EXIF Unsigned Long data type.
uint16_t ExifShort
EXIF Unsigned Short data type.
ExifData * parent
Data containing this content.
unsigned int offset_mnote
Represents the entire EXIF data found in an image.
unsigned char * data
Pointer to thumbnail image, or NULL if not available.
unsigned int size
Number of bytes in thumbnail image at data.
ExifContent * ifd[EXIF_IFD_COUNT]
Data for each IFD.
Data found in one EXIF tag.
unsigned long components
Number of elements in the array, if this is an array entry.
ExifFormat format
Type of data in this entry.
unsigned char * data
Pointer to the raw EXIF data for this entry.
ExifTag tag
EXIF tag for this entry.
unsigned int size
Number of bytes in the buffer at data.