1/*
2 * libexif example program to display the contents of a number of specific
3 * EXIF and MakerNote tags. The tags selected are those that may aid in
4 * identification of the photographer who took the image.
5 *
6 * Placed into the public domain by Dan Fandrich
7 */
8
9#include <stdio.h>
10#include <string.h>
11#include <libexif/exif-data.h>
12
13/* Remove spaces on the right of the string */
14static void trim_spaces(char *buf)
15{
16    char *s = buf-1;
17    for (; *buf; ++buf) {
18        if (*buf != ' ')
19            s = buf;
20    }
21    *++s = 0; /* nul terminate the string on the first of the final spaces */
22}
23
24/* Show the tag name and contents if the tag exists */
25static void show_tag(ExifData *d, ExifIfd ifd, ExifTag tag)
26{
27    /* See if this tag exists */
28    ExifEntry *entry = exif_content_get_entry(d->ifd[ifd],tag);
29    if (entry) {
30        char buf[1024];
31
32        /* Get the contents of the tag in human-readable form */
33        exif_entry_get_value(entry, buf, sizeof(buf));
34
35        /* Don't bother printing it if it's entirely blank */
36        trim_spaces(buf);
37        if (*buf) {
38            printf("%s: %s\n", exif_tag_get_name_in_ifd(tag,ifd), buf);
39        }
40    }
41}
42
43/* Show the given MakerNote tag if it exists */
44static void show_mnote_tag(ExifData *d, unsigned tag)
45{
46    ExifMnoteData *mn = exif_data_get_mnote_data(d);
47    if (mn) {
48        int num = exif_mnote_data_count(mn);
49        int i;
50
51        /* Loop through all MakerNote tags, searching for the desired one */
52        for (i=0; i < num; ++i) {
53            char buf[1024];
54            if (exif_mnote_data_get_id(mn, i) == tag) {
55                if (exif_mnote_data_get_value(mn, i, buf, sizeof(buf))) {
56                    /* Don't bother printing it if it's entirely blank */
57                    trim_spaces(buf);
58                    if (*buf) {
59                        printf("%s: %s\n", exif_mnote_data_get_title(mn, i),
60                            buf);
61                    }
62                }
63            }
64        }
65    }
66}
67
68int main(int argc, char **argv)
69{
70    ExifData *ed;
71    ExifEntry *entry;
72
73    if (argc < 2) {
74        printf("Usage: %s image.jpg\n", argv[0]);
75        printf("Displays tags potentially relating to ownership "
76                "of the image.\n");
77        return 1;
78    }
79
80    /* Load an ExifData object from an EXIF file */
81    ed = exif_data_new_from_file(argv[1]);
82    if (!ed) {
83        printf("File not readable or no EXIF data in file %s\n", argv[1]);
84        return 2;
85    }
86
87    /* Show all the tags that might contain information about the
88     * photographer
89     */
90    show_tag(ed, EXIF_IFD_0, EXIF_TAG_ARTIST);
91    show_tag(ed, EXIF_IFD_0, EXIF_TAG_XP_AUTHOR);
92    show_tag(ed, EXIF_IFD_0, EXIF_TAG_COPYRIGHT);
93
94    /* These are much less likely to be useful */
95    show_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_USER_COMMENT);
96    show_tag(ed, EXIF_IFD_0, EXIF_TAG_IMAGE_DESCRIPTION);
97    show_tag(ed, EXIF_IFD_1, EXIF_TAG_IMAGE_DESCRIPTION);
98
99    /* A couple of MakerNote tags can contain useful data.  Read the
100     * manufacturer tag to see if this image could have one of the recognized
101     * MakerNote tags.
102     */
103    entry = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
104    if (entry) {
105        char buf[64];
106
107        /* Get the contents of the manufacturer tag as a string */
108        if (exif_entry_get_value(entry, buf, sizeof(buf))) {
109            trim_spaces(buf);
110
111            if (!strcmp(buf, "Canon")) {
112                show_mnote_tag(ed, 9); /* MNOTE_CANON_TAG_OWNER */
113
114            } else if (!strcmp(buf, "Asahi Optical Co.,Ltd.") ||
115                       !strcmp(buf, "PENTAX Corporation")) {
116                show_mnote_tag(ed, 0x23); /* MNOTE_PENTAX2_TAG_HOMETOWN_CITY */
117            }
118        }
119    }
120
121    /* Free the EXIF data */
122    exif_data_unref(ed);
123
124    return 0;
125}
126