/exiftags/exifutil.c
C | 433 lines | 223 code | 84 blank | 126 comment | 53 complexity | ee636219f9fa90c4e3337dd8800d1ae1 MD5 | raw file
1/* 2 * Copyright (c) 2001-2003, Eric M. Johnston <emj@postal.net> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Eric M. Johnston. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: exifutil.c,v 1.26 2004/11/06 18:36:46 ejohnst Exp $ 33 */ 34 35/* 36 * Utilities for dealing with Exif data. 37 * 38 */ 39 40#include <stdlib.h> 41#include <string.h> 42#include <stdio.h> 43#include <errno.h> 44 45#include "exif.h" 46#include "exifint.h" 47 48 49/* 50 * Some global variables we all need. 51 */ 52 53int debug; 54const char *progname; 55 56 57/* 58 * Logging and error functions. 59 */ 60void 61exifdie(const char *msg) 62{ 63 64 fprintf(stderr, "%s: %s\n", progname, msg); 65 exit(1); 66} 67 68void 69exifwarn(const char *msg) 70{ 71 72 fprintf(stderr, "%s: %s\n", progname, msg); 73} 74 75void 76exifwarn2(const char *msg1, const char *msg2) 77{ 78 79 fprintf(stderr, "%s: %s (%s)\n", progname, msg1, msg2); 80} 81 82 83/* 84 * Read an unsigned 2-byte int from the buffer. 85 */ 86u_int16_t 87exif2byte(unsigned char *b, struct tiffmeta *md) 88{ 89 if (b < md->btiff || b+2 > md->etiff) return 0; 90 91 if (md->order == BIG) 92 return ((b[0] << 8) | b[1]); 93 else 94 return ((b[1] << 8) | b[0]); 95} 96 97 98/* 99 * Read a signed 2-byte int from the buffer. 100 */ 101int16_t 102exif2sbyte(unsigned char *b, struct tiffmeta *md) 103{ 104 if (b < md->btiff || b+2 > md->etiff) return 0; 105 106 if (md->order == BIG) 107 return ((b[0] << 8) | b[1]); 108 else 109 return ((b[1] << 8) | b[0]); 110} 111 112 113/* 114 * Read an unsigned 4-byte int from the buffer. 115 */ 116u_int32_t 117exif4byte(unsigned char *b, struct tiffmeta *md) 118{ 119 if (b < md->btiff || b+4 > md->etiff) return 0; 120 121 if (md->order == BIG) 122 return ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]); 123 else 124 return ((b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]); 125} 126 127 128/* 129 * Write an unsigned 4-byte int to a buffer. 130 */ 131void 132byte4exif(u_int32_t n, unsigned char *b, enum byteorder o) 133{ 134 int i; 135 136 if (o == BIG) 137 for (i = 0; i < 4; i++) 138 b[3 - i] = (unsigned char)((n >> (i * 8)) & 0xff); 139 else 140 for (i = 0; i < 4; i++) 141 b[i] = (unsigned char)((n >> (i * 8)) & 0xff); 142} 143 144 145/* 146 * Read a signed 4-byte int from the buffer. 147 */ 148int32_t 149exif4sbyte(unsigned char *b, struct tiffmeta *md) 150{ 151 if (b < md->btiff || b+4 > md->etiff) return 0; 152 153 if (md->order == BIG) 154 return ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]); 155 else 156 return ((b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]); 157} 158 159 160/* 161 * Lookup and allocate description for a value. 162 */ 163char * 164finddescr(struct descrip *table, u_int16_t val) 165{ 166 int i; 167 char *c; 168 169 for (i = 0; table[i].val != -1 && table[i].val != val; i++); 170 if (!(c = (char *)malloc(strlen(table[i].descr) + 1))) 171 exifdie((const char *)strerror(errno)); 172 strcpy(c, table[i].descr); 173 return (c); 174} 175 176 177/* 178 * Lookup and append description for a value. 179 * Doesn't do anything if the value is unknown; first adds ", " if dest 180 * contains a value; returns number of bytes added. len is total size 181 * of destination buffer. 182 */ 183int 184catdescr(char *c, struct descrip *table, u_int16_t val, int len) 185{ 186 int i, l; 187 188 l = 0; 189 len -= 1; 190 c[len] = '\0'; 191 192 for (i = 0; table[i].val != -1 && table[i].val != val; i++); 193 if (table[i].val == -1) 194 return (0); 195 196 if (strlen(c)) { 197 strncat(c, ", ", len - strlen(c)); 198 l += 2; 199 } 200 strncat(c, table[i].descr, len - strlen(c)); 201 l += strlen(table[i].descr); 202 return (l); 203} 204 205 206/* 207 * Lookup a property entry belonging to a particular set of tags. 208 */ 209struct exifprop * 210findprop(struct exifprop *prop, struct exiftag *tagset, u_int16_t tag) 211{ 212 213 for (; prop && (prop->tagset != tagset || prop->tag != tag); 214 prop = prop->next); 215 return (prop); 216} 217 218 219/* 220 * Allocate memory for an Exif property. 221 */ 222struct exifprop * 223newprop(void) 224{ 225 struct exifprop *prop; 226 227 prop = (struct exifprop *)malloc(sizeof(struct exifprop)); 228 if (!prop) 229 exifdie((const char *)strerror(errno)); 230 memset(prop, 0, sizeof(struct exifprop)); 231 return (prop); 232} 233 234 235/* 236 * Given a parent, create a new child Exif property. These are 237 * typically used by maker note modules when a single tag may contain 238 * multiple items of interest. 239 */ 240struct exifprop * 241childprop(struct exifprop *parent) 242{ 243 struct exifprop *prop; 244 245 prop = newprop(); 246 247 /* By default, the child inherits most values from its parent. */ 248 249 prop->tag = parent->tag; 250 prop->type = TIFF_UNKN; 251 prop->name = parent->name; 252 prop->descr = parent->descr; 253 prop->lvl = parent->lvl; 254 prop->ifdseq = parent->ifdseq; 255 prop->par = parent; 256 prop->next = parent->next; 257 258 /* Now insert the new property into our list. */ 259 260 parent->next = prop; 261 262 return (prop); 263} 264 265 266/* 267 * Allocate a buffer for a property's display string. 268 */ 269void 270exifstralloc(char **str, int len) 271{ 272 273 if (*str) { 274 exifwarn("tried to alloc over non-null string"); 275 // XeeHack 276 free(*str); 277 //abort(); 278 } 279 if (!(*str = (char *)calloc(1, len))) 280 exifdie((const char *)strerror(errno)); 281} 282 283 284/* 285 * Print hex values of a buffer. 286 */ 287void 288hexprint(unsigned char *b, int len) 289{ 290 int i; 291 292 for (i = 0; i < len; i++) 293 printf(" %02X", b[i]); 294} 295 296 297/* 298 * Print debug info for a property. 299 */ 300void 301dumpprop(struct exifprop *prop, struct field *afield) 302{ 303 int i; 304 305 if (!debug) return; 306 307 for (i = 0; ftypes[i].type && ftypes[i].type != prop->type; i++); 308 if (afield) { 309 printf(" %s (0x%04X): %s, %d; %d\n", prop->name, 310 prop->tag, ftypes[i].name, prop->count, 311 prop->value); 312 printf(" "); 313 hexprint(afield->tag, 2); 314 printf(" |"); 315 hexprint(afield->type, 2); 316 printf(" |"); 317 hexprint(afield->count, 4); 318 printf(" |"); 319 hexprint(afield->value, 4); 320 printf("\n"); 321 } else 322 printf(" %s (0x%04X): %s, %d; %d, 0x%04X\n", 323 prop->name, prop->tag, ftypes[i].name, 324 prop->count, prop->value, prop->value); 325} 326 327 328/* 329 * Allocate and read an individual IFD. Takes the beginning and end of the 330 * Exif buffer, returns the IFD and an offset to the next IFD. 331 */ 332u_int32_t 333readifd(u_int32_t offset, struct ifd **dir, struct exiftag *tagset, 334 struct tiffmeta *md) 335{ 336 u_int32_t ifdsize; 337 unsigned char *b; 338 339 b = md->btiff; 340 341 /* 342 * Verify that we have a valid offset. Some maker note IFDs prepend 343 * a string and will screw us up otherwise (e.g., Olympus). 344 * (Number of directory entries is in the first 2 bytes.) 345 */ 346 347 if (b + offset + 2 > md->etiff) { 348 *dir = NULL; 349 return (0); 350 } 351 352 *dir = (struct ifd *)malloc(sizeof(struct ifd)); 353 if (!*dir) 354 exifdie((const char *)strerror(errno)); 355 356 (*dir)->num = exif2byte(b + offset, md); 357 (*dir)->par = NULL; 358 (*dir)->tagset = tagset; 359 (*dir)->md = *md; 360 (*dir)->next = NULL; 361 362 ifdsize = (*dir)->num * sizeof(struct field); 363 b += offset + 2; 364 365 /* Sanity check our sizes. */ 366 367 if (b + ifdsize > md->etiff) { 368 free(*dir); 369 *dir = NULL; 370 return (0); 371 } 372 373 /* Point to our array of fields. */ 374 375 (*dir)->fields = (struct field *)b; 376 377 /* 378 * While we're here, find the offset to the next IFD. 379 * 380 * Note that this offset isn't always going to be valid. It 381 * seems that some camera implementations of Exif ignore the spec 382 * and do not include the offset for all IFDs (e.g., maker note). 383 * Therefore, it may be necessary to call readifd() directly (in 384 * leiu of readifds()) to avoid problems when reading these non- 385 * standard IFDs. 386 */ 387 388 return exif4byte(b + ifdsize, md); 389} 390 391 392/* 393 * Read a chain of IFDs. Takes the IFD offset and returns the first 394 * node in a chain of IFDs. Note that it can return NULL. 395 */ 396struct ifd * 397readifds(u_int32_t offset, struct exiftag *tagset, struct tiffmeta *md) 398{ 399 struct ifd *firstifd, *curifd; 400 401 /* 402 * XXX Note: we really should be checking to see if this IFD 403 * has already been visited... 404 */ 405 406 /* Fetch our first one. */ 407 408 offset = readifd(offset, &firstifd, tagset, md); 409 curifd = firstifd; 410 411 /* Fetch any remaining ones. */ 412 413 while (offset) { 414 // XeeFix 415 u_int32_t nextoffset = readifd(offset, &(curifd->next), tagset, md); 416 if (nextoffset == offset) break; 417 offset = nextoffset; 418 curifd = curifd->next; 419 } 420 return (firstifd); 421} 422 423 424/* 425 * Euclid's algorithm to find the GCD. 426 */ 427u_int32_t 428gcd(u_int32_t a, u_int32_t b) 429{ 430 431 if (!b) return (a); 432 return (gcd(b, a % b)); 433}