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