1b8bc0d8aSopenharmony_ci/** \file test-parse-from-data.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#include <unistd.h> 30b8bc0d8aSopenharmony_ci#include <fcntl.h> 31b8bc0d8aSopenharmony_ci#include <sys/stat.h> 32b8bc0d8aSopenharmony_ci 33b8bc0d8aSopenharmony_ci 34b8bc0d8aSopenharmony_cistatic unsigned entry_count; 35b8bc0d8aSopenharmony_ci 36b8bc0d8aSopenharmony_ci/** Callback function handling an ExifEntry. */ 37b8bc0d8aSopenharmony_cistatic void content_foreach_func(ExifEntry *entry, void *UNUSED(callback_data)) 38b8bc0d8aSopenharmony_ci{ 39b8bc0d8aSopenharmony_ci char buf[2000]; 40b8bc0d8aSopenharmony_ci exif_entry_get_value(entry, buf, sizeof(buf)); 41b8bc0d8aSopenharmony_ci printf(" Entry %u: %s (%s)\n" 42b8bc0d8aSopenharmony_ci " Size, Comps: %d, %d\n" 43b8bc0d8aSopenharmony_ci " Value: %s\n", 44b8bc0d8aSopenharmony_ci entry_count, 45b8bc0d8aSopenharmony_ci exif_tag_get_name(entry->tag), 46b8bc0d8aSopenharmony_ci exif_format_get_name(entry->format), 47b8bc0d8aSopenharmony_ci entry->size, 48b8bc0d8aSopenharmony_ci (int)(entry->components), 49b8bc0d8aSopenharmony_ci exif_entry_get_value(entry, buf, sizeof(buf))); 50b8bc0d8aSopenharmony_ci ++entry_count; 51b8bc0d8aSopenharmony_ci} 52b8bc0d8aSopenharmony_ci 53b8bc0d8aSopenharmony_ci 54b8bc0d8aSopenharmony_ci/** Callback function handling an ExifContent (corresponds 1:1 to an IFD). */ 55b8bc0d8aSopenharmony_cistatic void data_foreach_func(ExifContent *content, void *callback_data) 56b8bc0d8aSopenharmony_ci{ 57b8bc0d8aSopenharmony_ci static unsigned content_count; 58b8bc0d8aSopenharmony_ci entry_count = 0; 59b8bc0d8aSopenharmony_ci printf(" Content %u: ifd=%d\n", content_count, exif_content_get_ifd(content)); 60b8bc0d8aSopenharmony_ci exif_content_foreach_entry(content, content_foreach_func, callback_data); 61b8bc0d8aSopenharmony_ci ++content_count; 62b8bc0d8aSopenharmony_ci} 63b8bc0d8aSopenharmony_ci 64b8bc0d8aSopenharmony_cistatic void dump_makernote(ExifData *d) { 65b8bc0d8aSopenharmony_ci ExifMnoteData *mn = exif_data_get_mnote_data(d); 66b8bc0d8aSopenharmony_ci if (mn) { 67b8bc0d8aSopenharmony_ci char buf[2000]; 68b8bc0d8aSopenharmony_ci int i; 69b8bc0d8aSopenharmony_ci int num = exif_mnote_data_count(mn); 70b8bc0d8aSopenharmony_ci printf(" MakerNote\n"); 71b8bc0d8aSopenharmony_ci for (i=0; i < num; ++i) { 72b8bc0d8aSopenharmony_ci if (exif_mnote_data_get_value(mn, i, buf, sizeof(buf))) { 73b8bc0d8aSopenharmony_ci const char *name = exif_mnote_data_get_name(mn, i); 74b8bc0d8aSopenharmony_ci unsigned int id = exif_mnote_data_get_id(mn, i); 75b8bc0d8aSopenharmony_ci if (!name) 76b8bc0d8aSopenharmony_ci name = "(unknown)"; 77b8bc0d8aSopenharmony_ci printf(" Entry %u: %u, %s\n" 78b8bc0d8aSopenharmony_ci " Size: %u\n" 79b8bc0d8aSopenharmony_ci " Value: %s\n", i, id, name, (unsigned)strlen(buf), buf); 80b8bc0d8aSopenharmony_ci } 81b8bc0d8aSopenharmony_ci } 82b8bc0d8aSopenharmony_ci } 83b8bc0d8aSopenharmony_ci} 84b8bc0d8aSopenharmony_ci 85b8bc0d8aSopenharmony_ci/** Run EXIF parsing test on the given file. */ 86b8bc0d8aSopenharmony_cistatic void test_parse(const char *filename, void *callback_data, int swap) 87b8bc0d8aSopenharmony_ci{ 88b8bc0d8aSopenharmony_ci ExifData *d; 89b8bc0d8aSopenharmony_ci int fd; 90b8bc0d8aSopenharmony_ci unsigned char *data; 91b8bc0d8aSopenharmony_ci struct stat stbuf; 92b8bc0d8aSopenharmony_ci 93b8bc0d8aSopenharmony_ci /* Skip over path to display only the file name */ 94b8bc0d8aSopenharmony_ci const char *fn = strrchr(filename, '/'); 95b8bc0d8aSopenharmony_ci if (fn) 96b8bc0d8aSopenharmony_ci ++fn; 97b8bc0d8aSopenharmony_ci else 98b8bc0d8aSopenharmony_ci fn = filename; 99b8bc0d8aSopenharmony_ci printf("File %s\n", fn); 100b8bc0d8aSopenharmony_ci 101b8bc0d8aSopenharmony_ci d = exif_data_new_from_file(filename); 102b8bc0d8aSopenharmony_ci fd = open(filename,O_RDONLY); 103b8bc0d8aSopenharmony_ci if (fd == -1) { 104b8bc0d8aSopenharmony_ci perror(filename); 105b8bc0d8aSopenharmony_ci return; 106b8bc0d8aSopenharmony_ci } 107b8bc0d8aSopenharmony_ci if (-1 == fstat(fd, &stbuf)) { 108b8bc0d8aSopenharmony_ci perror(filename); 109b8bc0d8aSopenharmony_ci return; 110b8bc0d8aSopenharmony_ci } 111b8bc0d8aSopenharmony_ci data = malloc(stbuf.st_size); 112b8bc0d8aSopenharmony_ci if (!data) { 113b8bc0d8aSopenharmony_ci fprintf (stderr, "Failed to allocate %ld bytes for reading %s\n", stbuf.st_size, filename); 114b8bc0d8aSopenharmony_ci return; 115b8bc0d8aSopenharmony_ci } 116b8bc0d8aSopenharmony_ci if (-1 == read(fd, data, stbuf.st_size)) { 117b8bc0d8aSopenharmony_ci perror ("read"); 118b8bc0d8aSopenharmony_ci free(data); 119b8bc0d8aSopenharmony_ci close(fd); 120b8bc0d8aSopenharmony_ci return; 121b8bc0d8aSopenharmony_ci } 122b8bc0d8aSopenharmony_ci close(fd); 123b8bc0d8aSopenharmony_ci 124b8bc0d8aSopenharmony_ci d = exif_data_new_from_data(data, stbuf.st_size); 125b8bc0d8aSopenharmony_ci if (!d) { 126b8bc0d8aSopenharmony_ci fprintf (stderr, "Could not load data from '%s'!\n", filename); 127b8bc0d8aSopenharmony_ci free(data); 128b8bc0d8aSopenharmony_ci return; 129b8bc0d8aSopenharmony_ci } 130b8bc0d8aSopenharmony_ci printf("Byte order: %s\n", 131b8bc0d8aSopenharmony_ci exif_byte_order_get_name(exif_data_get_byte_order(d))); 132b8bc0d8aSopenharmony_ci 133b8bc0d8aSopenharmony_ci if (swap) { 134b8bc0d8aSopenharmony_ci ExifByteOrder order = EXIF_BYTE_ORDER_INTEL; 135b8bc0d8aSopenharmony_ci if (exif_data_get_byte_order(d) == order) { 136b8bc0d8aSopenharmony_ci order = EXIF_BYTE_ORDER_MOTOROLA; 137b8bc0d8aSopenharmony_ci } 138b8bc0d8aSopenharmony_ci /* This switches the byte order of the entire EXIF data structure, 139b8bc0d8aSopenharmony_ci * including the MakerNote */ 140b8bc0d8aSopenharmony_ci exif_data_set_byte_order(d, order); 141b8bc0d8aSopenharmony_ci printf("New byte order: %s\n", 142b8bc0d8aSopenharmony_ci exif_byte_order_get_name(exif_data_get_byte_order(d))); 143b8bc0d8aSopenharmony_ci } 144b8bc0d8aSopenharmony_ci 145b8bc0d8aSopenharmony_ci exif_data_foreach_content(d, data_foreach_func, callback_data); 146b8bc0d8aSopenharmony_ci 147b8bc0d8aSopenharmony_ci dump_makernote(d); 148b8bc0d8aSopenharmony_ci 149b8bc0d8aSopenharmony_ci exif_data_unref(d); 150b8bc0d8aSopenharmony_ci} 151b8bc0d8aSopenharmony_ci 152b8bc0d8aSopenharmony_ci 153b8bc0d8aSopenharmony_ci/** Callback function prototype for string parsing. */ 154b8bc0d8aSopenharmony_citypedef void (*test_parse_func) (const char *filename, void *callback_data, int swap); 155b8bc0d8aSopenharmony_ci 156b8bc0d8aSopenharmony_ci 157b8bc0d8aSopenharmony_ci/** Split string at whitespace and call callback with each substring. */ 158b8bc0d8aSopenharmony_cistatic void split_ws_string(const char *string, test_parse_func func, void *callback_data) 159b8bc0d8aSopenharmony_ci{ 160b8bc0d8aSopenharmony_ci const char *start = string; 161b8bc0d8aSopenharmony_ci const char *p = start; 162b8bc0d8aSopenharmony_ci for (;;) { 163b8bc0d8aSopenharmony_ci if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == '\0' ) { 164b8bc0d8aSopenharmony_ci size_t len = p-start; 165b8bc0d8aSopenharmony_ci if (len > 0) { 166b8bc0d8aSopenharmony_ci /* emulate strndup */ 167b8bc0d8aSopenharmony_ci char *str = malloc(1+len); 168b8bc0d8aSopenharmony_ci if (str) { 169b8bc0d8aSopenharmony_ci memcpy(str, start, len); 170b8bc0d8aSopenharmony_ci str[len] = '\0'; 171b8bc0d8aSopenharmony_ci func(str, callback_data, 0); 172b8bc0d8aSopenharmony_ci free(str); 173b8bc0d8aSopenharmony_ci start = p+1; 174b8bc0d8aSopenharmony_ci } 175b8bc0d8aSopenharmony_ci } else { 176b8bc0d8aSopenharmony_ci start = p+1; 177b8bc0d8aSopenharmony_ci } 178b8bc0d8aSopenharmony_ci } 179b8bc0d8aSopenharmony_ci if (*p == '\0') { 180b8bc0d8aSopenharmony_ci break; 181b8bc0d8aSopenharmony_ci } 182b8bc0d8aSopenharmony_ci p++; 183b8bc0d8aSopenharmony_ci } 184b8bc0d8aSopenharmony_ci} 185b8bc0d8aSopenharmony_ci 186b8bc0d8aSopenharmony_ci 187b8bc0d8aSopenharmony_ci/** Main program. */ 188b8bc0d8aSopenharmony_ciint main(const int argc, const char *argv[]) 189b8bc0d8aSopenharmony_ci{ 190b8bc0d8aSopenharmony_ci int i; 191b8bc0d8aSopenharmony_ci void *callback_data = NULL; 192b8bc0d8aSopenharmony_ci int swap = 0; 193b8bc0d8aSopenharmony_ci int first = 1; 194b8bc0d8aSopenharmony_ci 195b8bc0d8aSopenharmony_ci if (argc > 1 && !strcmp(argv[1], "--swap-byte-order")) { 196b8bc0d8aSopenharmony_ci swap = 1; 197b8bc0d8aSopenharmony_ci ++first; 198b8bc0d8aSopenharmony_ci } 199b8bc0d8aSopenharmony_ci 200b8bc0d8aSopenharmony_ci if (argc > first) { 201b8bc0d8aSopenharmony_ci for (i=first; i<argc; i++) { 202b8bc0d8aSopenharmony_ci test_parse(argv[i], callback_data, swap); 203b8bc0d8aSopenharmony_ci } 204b8bc0d8aSopenharmony_ci } else { 205b8bc0d8aSopenharmony_ci /* If no command-line argument is found, get the file names from 206b8bc0d8aSopenharmony_ci the environment. */ 207b8bc0d8aSopenharmony_ci const char *envar = getenv("TEST_IMAGES"); 208b8bc0d8aSopenharmony_ci if (envar) { 209b8bc0d8aSopenharmony_ci split_ws_string(envar, test_parse, callback_data); 210b8bc0d8aSopenharmony_ci } 211b8bc0d8aSopenharmony_ci } 212b8bc0d8aSopenharmony_ci 213b8bc0d8aSopenharmony_ci return 0; 214b8bc0d8aSopenharmony_ci} 215