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