1/** \file test-parse.c 2 * \brief Completely parse all files given on the command line. 3 * 4 * Copyright (C) 2007 Hans Ulrich Niedermann <gp@n-dimensional.de> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the 18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301 USA. 20 * 21 */ 22 23#include "libexif/exif-data.h" 24#include "libexif/exif-system.h" 25 26#include <string.h> 27#include <stdio.h> 28#include <stdlib.h> 29 30static unsigned entry_count; 31 32/** Callback function handling an ExifEntry. */ 33static void content_foreach_func(ExifEntry *entry, void *UNUSED(callback_data)) 34{ 35 char buf[2000]; 36 exif_entry_get_value(entry, buf, sizeof(buf)); 37 printf(" Entry %u: %s (%s)\n" 38 " Size, Comps: %d, %d\n" 39 " Value: %s\n", 40 entry_count, 41 exif_tag_get_name(entry->tag), 42 exif_format_get_name(entry->format), 43 entry->size, 44 (int)(entry->components), 45 exif_entry_get_value(entry, buf, sizeof(buf))); 46 ++entry_count; 47} 48 49 50/** Callback function handling an ExifContent (corresponds 1:1 to an IFD). */ 51static void data_foreach_func(ExifContent *content, void *callback_data) 52{ 53 static unsigned content_count; 54 entry_count = 0; 55 printf(" Content %u: ifd=%d\n", content_count, exif_content_get_ifd(content)); 56 exif_content_foreach_entry(content, content_foreach_func, callback_data); 57 ++content_count; 58} 59 60static void dump_makernote(ExifData *d) { 61 ExifMnoteData *mn = exif_data_get_mnote_data(d); 62 if (mn) { 63 char buf[2000]; 64 int i; 65 int num = exif_mnote_data_count(mn); 66 printf(" MakerNote\n"); 67 for (i=0; i < num; ++i) { 68 if (exif_mnote_data_get_value(mn, i, buf, sizeof(buf))) { 69 const char *name = exif_mnote_data_get_name(mn, i); 70 unsigned int id = exif_mnote_data_get_id(mn, i); 71 if (!name) 72 name = "(unknown)"; 73 printf(" Entry %u: %u, %s\n" 74 " Size: %u\n" 75 " Value: %s\n", i, id, name, (unsigned)strlen(buf), buf); 76 } 77 } 78 } 79} 80 81/** Run EXIF parsing test on the given file. */ 82static void test_parse(const char *filename, void *callback_data, int swap) 83{ 84 ExifData *d; 85 86 /* Skip over path to display only the file name */ 87 const char *fn = strrchr(filename, '/'); 88 if (fn) 89 ++fn; 90 else 91 fn = filename; 92 printf("File %s\n", fn); 93 94 d = exif_data_new_from_file(filename); 95 if (!d) { 96 fprintf (stderr, "Could not load data from '%s'!\n", filename); 97 return; 98 } 99 printf("Byte order: %s\n", 100 exif_byte_order_get_name(exif_data_get_byte_order(d))); 101 102 if (swap) { 103 ExifByteOrder order = EXIF_BYTE_ORDER_INTEL; 104 if (exif_data_get_byte_order(d) == order) { 105 order = EXIF_BYTE_ORDER_MOTOROLA; 106 } 107 /* This switches the byte order of the entire EXIF data structure, 108 * including the MakerNote */ 109 exif_data_set_byte_order(d, order); 110 printf("New byte order: %s\n", 111 exif_byte_order_get_name(exif_data_get_byte_order(d))); 112 } 113 114 exif_data_foreach_content(d, data_foreach_func, callback_data); 115 116 dump_makernote(d); 117 118 exif_data_unref(d); 119} 120 121 122/** Callback function prototype for string parsing. */ 123typedef void (*test_parse_func) (const char *filename, void *callback_data, int swap); 124 125 126/** Split string at whitespace and call callback with each substring. */ 127static void split_ws_string(const char *string, test_parse_func func, void *callback_data) 128{ 129 const char *start = string; 130 const char *p = start; 131 for (;;) { 132 if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == '\0' ) { 133 size_t len = p-start; 134 if (len > 0) { 135 /* emulate strndup */ 136 char *str = malloc(1+len); 137 if (str) { 138 memcpy(str, start, len); 139 str[len] = '\0'; 140 func(str, callback_data, 0); 141 free(str); 142 start = p+1; 143 } 144 } else { 145 start = p+1; 146 } 147 } 148 if (*p == '\0') { 149 break; 150 } 151 p++; 152 } 153} 154 155 156/** Main program. */ 157int main(const int argc, const char *argv[]) 158{ 159 int i; 160 void *callback_data = NULL; 161 int swap = 0; 162 int first = 1; 163 164 if (argc > 1 && !strcmp(argv[1], "--swap-byte-order")) { 165 swap = 1; 166 ++first; 167 } 168 169 if (argc > first) { 170 for (i=first; i<argc; i++) { 171 test_parse(argv[i], callback_data, swap); 172 } 173 } else { 174 /* If no command-line argument is found, get the file names from 175 the environment. */ 176 const char *envar = getenv("TEST_IMAGES"); 177 if (envar) { 178 split_ws_string(envar, test_parse, callback_data); 179 } 180 } 181 182 return 0; 183} 184