44 #undef JPEG_MARKER_SOI
45 #define JPEG_MARKER_SOI 0xd8
46 #undef JPEG_MARKER_APP0
47 #define JPEG_MARKER_APP0 0xe0
48 #undef JPEG_MARKER_APP1
49 #define JPEG_MARKER_APP1 0xe1
51 #define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))
53 static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
138 #ifndef NO_VERBOSE_TAG_STRINGS
165 const unsigned char *d,
166 unsigned int size,
unsigned int offset)
168 unsigned int s, doff;
178 "Loading entry 0x%x ('%s')...", entry->
tag,
184 if ((s < entry->components) || (s == 0)){
200 "Tag starts past end of buffer (%u > %u)", doff,
size);
204 if (s >
size - doff) {
206 "Tag data goes past end of buffer (%u > %u)", doff+s,
size);
213 memcpy (entry->
data, d + doff, s);
223 "MakerNote found with empty data");
224 }
else if (entry->
size > 6) {
227 "MakerNote found (%02x %02x %02x %02x "
228 "%02x %02x %02x...).",
240 unsigned char **d,
unsigned int *ds,
243 unsigned int doff, s;
246 if (!data || !data->
priv)
306 *(*d + *ds - 1) =
'\0';
314 unsigned int len = s;
316 memcpy (*d + 6 + doff, e->
data, len);
318 memset (*d + 6 + doff, 0, s);
321 memset (*d + 6 + doff + s, 0, (4 - s));
345 memcpy (data->
data, d + o, s);
349 #define CHECK_REC(i) \
351 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \
352 "ExifData", "Recursive entry in IFD " \
353 "'%s' detected. Skipping...", \
354 exif_ifd_get_name (i)); \
357 if (data->ifd[(i)]->count) { \
358 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \
359 "ExifData", "Attempt to load IFD " \
360 "'%s' multiple times detected. " \
362 exif_ifd_get_name (i)); \
374 static const double log_1_1 = 0.09531017980432493;
377 return ceil(log(n + 0.1)/log_1_1);
392 const unsigned char *d,
393 unsigned int ds,
unsigned int offset,
unsigned int recursion_cost)
395 ExifLong o, thumbnail_offset = 0, thumbnail_length = 0;
401 if (!data || !data->
priv)
408 if (recursion_cost > 170) {
421 "Deep/expensive recursion detected!");
428 "Tag data past end of buffer (%u+2 > %u)", offset, ds);
433 "Loading %hu entries...", n);
438 n = (ds - offset) / 12;
440 "Short data; only loading %hu entries...", n);
443 for (i = 0; i < n; i++) {
456 "Tag data past end of buffer (%u > %u)", offset+2, ds);
463 "Sub-IFD entry 0x%x ('%s') at %u.",
tag,
482 thumbnail_offset = o;
483 if (thumbnail_offset && thumbnail_length)
485 ds, thumbnail_offset,
489 thumbnail_length = o;
490 if (thumbnail_offset && thumbnail_length)
492 ds, thumbnail_offset,
512 if (!memcmp (d + offset + 12 * i,
"\0\0\0\0", 4)) {
514 "Skipping empty entry at position %u in '%s'.", i,
519 "Unknown tag 0x%04x (entry %u in '%s'). Please report this tag "
520 "to <libexif-devel@lists.sourceforge.net>.",
tag, i,
528 "Could not allocate memory");
546 return (tag1 < tag2) ? -1 : (tag1 > tag2) ? 1 : 0;
552 return cmp_func ((
const unsigned char *) elem1,
559 return cmp_func ((
const unsigned char *) elem1,
565 unsigned char **d,
unsigned int *ds,
568 unsigned int j, n_ptr = 0, n_thumb = 0;
573 if (!data || !data->
priv || !
ifd || !d || !ds)
616 ts = *ds + (2 + (
ifd->count + n_ptr + n_thumb) * 12 + 4);
635 "Saving %i entries (IFD '%s', offset: %i)...",
637 for (j = 0; j <
ifd->count; j++) {
638 if (
ifd->entries[j]) {
644 offset += 12 *
ifd->count;
726 ts = *ds + data->
size;
756 qsort (*d + 6 + offset - (
ifd->count + n_ptr + n_thumb) * 12,
757 (
ifd->count + n_ptr + n_thumb), 12,
801 "ExifData",
"Olympus MakerNote variant type %d", mnoteid);
806 "ExifData",
"Canon MakerNote variant type %d", mnoteid);
811 "ExifData",
"Fuji MakerNote variant type %d", mnoteid);
818 "ExifData",
"Pentax MakerNote variant type %d", mnoteid);
822 "ExifData",
"Apple MakerNote variant type %d", mnoteid);
839 #define LOG_TOO_SMALL \
840 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", \
841 _("Size of data too small to allow for EXIF data."));
850 const unsigned char *d = d_orig;
851 unsigned int len, fullds;
853 if (!data || !data->
priv || !d || !ds)
857 "Parsing %i byte(s) EXIF data...\n", ds);
869 "Found EXIF header at start.");
872 while (ds && (d[0] == 0xff)) {
892 if ((ds >= 9) && !memcmp (d+3,
ExifHeader, 6))
901 if (ds >= 3 && d[0] >= 0xe0 && d[0] <= 0xef) {
904 l = (((
unsigned int)d[0]) << 8) | d[1];
914 "ExifData",
_(
"EXIF marker not found."));
923 len = (((
unsigned int)d[0]) << 8) | d[1];
926 "ExifData",
_(
"Read length %d is longer than data length %d."), len, ds);
931 "ExifData",
_(
"APP Tag too short."));
935 "We have to deal with %i byte(s) of EXIF data.",
951 "ExifData",
_(
"EXIF header not found."));
956 "Found EXIF header.");
970 if (!memcmp (d + 6,
"II", 2))
972 else if (!memcmp (d + 6,
"MM", 2))
976 "ExifData",
_(
"Unknown encoding."));
987 "IFD 0 at %i.", (
int) offset);
990 if (offset > ds || offset + 6 + 2 > ds)
999 if (offset + 6 + 2 + 12 * n + 4 > ds)
1005 "IFD 1 at %i.", (
int) offset);
1008 if (offset > ds - 6) {
1010 "ExifData",
"Bogus offset of IFD1.");
1035 if (!data || !d || !ds)
1049 memcpy (*d + 6,
"II", 2);
1051 memcpy (*d + 6,
"MM", 2);
1071 "Saved %i byte(s) EXIF data.", *ds);
1120 data->
ifd[i] = NULL;
1155 printf (
"Dumping IFD '%s'...\n",
1162 printf (
"%i byte(s) thumbnail data available: ", data->
size);
1163 if (data->
size >= 4) {
1164 printf (
"0x%02x 0x%02x ... 0x%02x 0x%02x\n",
1191 func (data->
ifd[i], user_data);
1221 if (!data || (order == data->
priv->
order))
1237 if (!data || !data->
priv)
1252 if (!data || !data->
priv)
1257 static const struct {
1263 N_(
"Ignore unknown tags when loading EXIF data.")},
1265 N_(
"Add, correct and remove entries to get EXIF data that follows "
1266 "the specification.")},
1268 N_(
"When loading and resaving Exif data, save the maker note unmodified."
1269 " Be aware that the maker note can get corrupted.")},
1320 else if (c->
count) {
1322 "No thumbnail but entries on thumbnail. These entries have been "
1325 unsigned int cnt = c->
count;
1327 if (cnt == c->
count) {
1330 "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.
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.
ExifContent * exif_content_new_mem(ExifMem *mem)
Reserve memory for and initialize new ExifContent using the specified memory allocator.
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(void)
Allocate a new ExifData.
static void fix_func(ExifContent *c, void *UNUSED(data))
void exif_data_unref(ExifData *data)
void exif_data_free(ExifData *data)
const char * exif_data_option_get_name(ExifDataOption o)
Return a short textual description of the given ExifDataOption.
ExifByteOrder exif_data_get_byte_order(ExifData *data)
Return the byte order in use by this EXIF structure.
@ 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)
const char * exif_data_option_get_description(ExifDataOption o)
Return a verbose textual description of the given ExifDataOption.
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.
static void content_set_byte_order(ExifContent *content, void *data)
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 const unsigned char ExifHeader[]
static void * exif_data_alloc(ExifData *data, unsigned int i)
ExifMnoteData * exif_data_get_mnote_data(ExifData *d)
Return the MakerNote data out of the EXIF data.
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.
ExifData * exif_data_new_mem(ExifMem *mem)
Allocate a new ExifData using the given memory allocator.
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.
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)
ExifData * exif_data_new_from_file(const char *path)
Allocate a new ExifData and load EXIF data from a JPEG file.
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.
void exif_loader_unref(ExifLoader *loader)
Decrease the refcount of the ExifLoader.
ExifData * exif_loader_get_data(ExifLoader *loader)
Create an ExifData from the data in the loader.
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_realloc(ExifMem *mem, void *d, ExifLong ds)
void exif_mem_free(ExifMem *mem, void *d)
void exif_mem_unref(ExifMem *mem)
Unrefcount an ExifMem.
ExifMem * exif_mem_new_default(void)
Create a new ExifMem with default values for your convenience.
void * exif_mem_alloc(ExifMem *mem, ExifLong ds)
void exif_mem_ref(ExifMem *mem)
Refcount an ExifMem.
int exif_mnote_data_apple_identify(const ExifData *ed, const ExifEntry *e)
ExifMnoteData * exif_mnote_data_apple_new(ExifMem *mem)
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.
ExifMnoteData * exif_mnote_data_olympus_new(ExifMem *mem)
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_pentax_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.
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(ExifTag tag)
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.
@ 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.