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