/* * Grab the timestamps for listing. Doesn't modify the file. */ static int listts(struct exiftags *t, struct linfo *li) { struct exifprop *p; struct tm tv; /* * Try for DateTime, DateTimeOriginal, then DateTimeDigitized. * If none found, print error and list first. */ p = findprop(t->props, tags, EXIF_T_DATETIME); if (!p || !p->str || etstrptm(p->str, &tv)) { p = findprop(t->props, tags, EXIF_T_DATETIMEORIG); if (!p || !p->str || etstrptm(p->str, &tv)) { p = findprop(t->props, tags, EXIF_T_DATETIMEDIGI); if (!p || !p->str || etstrptm(p->str, &tv)) { exifwarn("no timestamp available"); li->ts = 0; return (1); } } } li->ts = mktime(&tv); return (0); }
/* * Try to read a Casio maker note IFD. */ struct ifd * casio_ifd(u_int32_t offset, struct tiffmeta *md) { struct ifd *myifd; /* * It appears that there are two different types of maker notes * for Casio cameras: one, for older cameras, uses a standard IFD * format; the other starts at offset + 6 ("QVC\0\0\0"). */ if (!memcmp("QVC\0\0\0", md->btiff + offset, 6)) { readifd(offset + strlen("QVC") + 3, &myifd, casio_tags1, md); exifwarn("Casio maker note version not supported"); } else readifd(offset, &myifd, casio_tags0, md); return (myifd); }
static Epsilon_Exif_Info * epsilon_read_exif_data (FILE * fp, int dumplvl, int pas) { int mark, gotapp1, first; unsigned int len, rlen; unsigned char *exifbuf; struct exiftags *t = NULL; gotapp1 = FALSE; first = 0; exifbuf = NULL; while (jpegscan (fp, &mark, &len, !(first++))) { if (mark != JPEG_M_APP1) { if (fseek (fp, len, SEEK_CUR)) exifdie ((const char *) strerror (errno)); continue; } exifbuf = (unsigned char *) malloc (len); if (!exifbuf) exifdie ((const char *) strerror (errno)); rlen = fread (exifbuf, 1, len, fp); if (rlen != len) { exifwarn ("error reading JPEG (length mismatch)"); free (exifbuf); return (NULL); } t = exifparse (exifbuf, len); if (t && t->props) { gotapp1 = TRUE; #if 0 if (dumplvl & ED_CAM) _epsilon_exif_info_props_get (t->props, ED_CAM, pas); if (dumplvl & ED_IMG) _epsilon_exif_info_props_get (t->props, ED_IMG, pas); if (dumplvl & ED_VRB) _epsilon_exif_info_props_get (t->props, ED_VRB, pas); if (dumplvl & ED_UNK) _epsilon_exif_info_props_get (t->props, ED_UNK, pas); #endif } free (exifbuf); } if (!gotapp1) { exifwarn ("couldn't find Exif data"); if (t) exiffree (t); return (NULL); } return ((Epsilon_Exif_Info *) t); }
/* * Process GPS tags. */ void gpsprop(struct exifprop *prop, struct exiftags *t) { u_int32_t i, n, d; double deg, min, sec, alt; char fmt[32], buf[16]; struct exifprop *tmpprop; enum byteorder o = t->md.order; switch (prop->tag) { /* Version. */ case 0x0000: exifstralloc(&prop->str, 8); /* Convert the value back into a string. */ byte4exif(prop->value, (unsigned char *)buf, o); for (i = 0; i < 4; i++) { prop->str[i * 2] = '0' + buf[i]; prop->str[i * 2 + 1] = '.'; } prop->str[7] = '\0'; break; /* * Reference values. The value is 2-count nul-terminated ASCII, * not an offset to the ASCII string. * XXX Shouldn't really be necessary now that short ASCII strings work. */ case 0x0001: case 0x0003: case 0x0009: case 0x000a: case 0x000c: case 0x000e: case 0x0010: case 0x0013: case 0x0015: case 0x0017: case 0x0019: /* Clean-up from any earlier processing. */ free(prop->str); prop->str = NULL; byte4exif(prop->value, (unsigned char *)buf, o); for (i = 0; gpstags[i].tag < EXIF_T_UNKNOWN && gpstags[i].tag != prop->tag; i++); if (gpstags[i].table) prop->str = finddescr(gpstags[i].table, (unsigned char)buf[0]); else { exifstralloc(&prop->str, 2); prop->str[0] = buf[0]; } break; /* * Coordinate values. * * This is really kind of a mess. The display behavior here is * based on image samples from a Nikon D1X and a Fuji FinePix S1 Pro. * The specification allows for fractional minutes (and no seconds). * Not sure if there are any other combinations... */ case 0x0002: case 0x0004: case 0x0014: case 0x0016: if (prop->count != 3 || prop->value + prop->count * 8 > (u_int32_t)(t->md.etiff - t->md.btiff)) { exifwarn("unexpected GPS coordinate values"); break; } free(prop->str); prop->str = NULL; exifstralloc(&prop->str, 32); /* Figure out the reference prefix. */ switch (prop->tag) { case 0x0002: tmpprop = findprop(t->props, gpstags, 0x0001); break; case 0x0004: tmpprop = findprop(t->props, gpstags, 0x0003); break; case 0x0014: tmpprop = findprop(t->props, gpstags, 0x0013); break; case 0x0016: tmpprop = findprop(t->props, gpstags, 0x0015); break; default: tmpprop = NULL; } /* Degrees. */ i = 0; n = exif4byte(t->md.btiff + prop->value + i * 8, o); d = exif4byte(t->md.btiff + prop->value + 4 + i * 8, o); strcpy(fmt, "%s %.f%s "); if (!n || !d) /* Punt. */ deg = 0.0; else { deg = (double)n / (double)d; if (d != 1) sprintf(fmt, "%%s %%.%df%%s ", (int)log10((double)d)); } /* Minutes. */ i++; n = exif4byte(t->md.btiff + prop->value + i * 8, o); d = exif4byte(t->md.btiff + prop->value + 4 + i * 8, o); if (!n || !d) { /* Punt. */ min = 0.0; strcat(fmt, "%.f'"); } else { min = (double)n / (double)d; if (d != 1) { sprintf(buf, "%%.%df'", (int)log10((double)d)); strcat(fmt, buf); } else strcat(fmt, "%.f'"); } /* * Seconds. We'll assume if minutes are fractional, we * should just ignore seconds. */ i++; n = exif4byte(t->md.btiff + prop->value + i * 8, o); d = exif4byte(t->md.btiff + prop->value + 4 + i * 8, o); if (!n || !d) { /* Assume no seconds. */ snprintf(prop->str, 31, fmt, tmpprop && tmpprop->str ? tmpprop->str : "", deg, DEGREE, min); break; } else { sec = (double)n / (double)d; if (d != 1) { sprintf(buf, " %%.%df", (int)log10((double)d)); strcat(fmt, buf); } else strcat(fmt, " %.f"); } snprintf(prop->str, 31, fmt, tmpprop && tmpprop->str ? tmpprop->str : "", deg, DEGREE, min, sec); break; /* Altitude. */ case 0x0006: n = exif4byte(t->md.btiff + prop->value, o); d = exif4byte(t->md.btiff + prop->value + 4, o); /* Look up reference. Non-zero means negative altitude. */ tmpprop = findprop(t->props, gpstags, 0x0005); if (tmpprop && tmpprop->value) n *= -1; if (!n || !d) alt = 0.0; else alt = (double)n / (double)d; /* Should already have a 32-byte buffer from parsetag(). */ snprintf(prop->str, 31, "%.2f m", alt); prop->str[31] = '\0'; break; /* Time. */ case 0x0007: /* Should already have a 32-byte buffer from parsetag(). */ prop->str[0] = '\0'; for (i = 0; i < prop->count; i++) { n = exif4byte(t->md.btiff + prop->value + i * 8, o); d = exif4byte(t->md.btiff + prop->value + 4 + i * 8, o); if (!d) break; if (!i) sprintf(fmt, "%%02.%df", (int)log10((double)d)); else sprintf(fmt, ":%%02.%df", (int)log10((double)d)); snprintf(buf, 8, fmt, (double)n / (double)d); strcat(prop->str, buf); } break; } }