PageRenderTime 38ms CodeModel.GetById 21ms app.highlight 14ms RepoModel.GetById 0ms app.codeStats 1ms

/exiftags/exifutil.c

https://code.google.com/p/xee/
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}