Exemple #1
0
/*
 * 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);
}
Exemple #2
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);
}
Exemple #3
0
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);
}
Exemple #4
0
/*
 * 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;
	}
}