示例#1
0
文件: exiftime.c 项目: dpt/PrivateEye
/*
 * Scan the JPEG file for Exif data and parse it.
 */
static int
doit(FILE *fp, int n)
{
	int mark, gotapp1, first, rc;
	unsigned int len, rlen;
	unsigned char *exifbuf;
	struct exiftags *t;
	long app1;

	gotapp1 = FALSE;
	first = 0;
	exifbuf = NULL;
	rc = 0;

	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));

		app1 = ftell(fp);
		rlen = fread(exifbuf, 1, len, fp);
		if (rlen != len) {
			fprintf(stderr, "%s: error reading JPEG (length "
			    "mismatch)\n", fname);
			free(exifbuf);
			return (1);
		}

		t = exifscan(exifbuf, len, FALSE);

		if (t && t->props) {
			gotapp1 = TRUE;
			if (lflag)
				rc = listts(t, &lorder[n]);
			else
				rc = procall(fp, app1, t, exifbuf);
		}
		exiffree(t);
		free(exifbuf);
	}

	if (!gotapp1) {
		fprintf(stderr, "%s: couldn't find Exif data\n", fname);
		return (1);
	}

	return (rc);
}
示例#2
0
文件: exiftime.c 项目: dpt/PrivateEye
/*
 * Overwrite a timestamp with the adjusted value.
 */
static int
writets(FILE *fp, long pos, struct exiftags *t, struct exifprop *p,
    const unsigned char *buf, const char *ttype, const char *nts)
{
	int ch, checkch;
	long psave;

	/* Some sanity checking. */

	if (strlen(nts) != EXIFTIMELEN - 1) {
		fprintf(stderr, "%s: invalid timestamp -- %s\n", fname, nts);
		return (1);
	}

	if (!strcmp(nts, p->str)) {
		fprintf(stderr, "%s: new %s timestamp identical to old\n",
		    fname, ttype);
		return (1);
	}

	/* Prompt user, if desired. */

	if (iflag) {
		fprintf(stderr, "adjust time %s in %s from\n  %s to %s? "
		    "(y/n [n]) ", ttype, fname, p->str, nts);
		checkch = ch = getchar();
		while (ch != '\n' && ch != EOF)
			ch = getchar();
		if (checkch != 'y' && checkch != 'Y') {
			fprintf(stderr, "not adjusted\n");
			return (1);
		}
	}

	/* Remember where we are and move to the comment in our file. */

	psave = ftell(fp);
	if (fseek(fp, pos + (t->md.btiff - buf) + p->value, SEEK_SET))
		exifdie((const char *)strerror(errno));

	/* Write the new timestamp. */

	if (fwrite(nts, EXIFTIMELEN, 1, fp) != 1)
		exifdie((const char *)strerror(errno));

	/* Restore the file pointer. */

	if (fseek(fp, psave, SEEK_SET))
		exifdie((const char *)strerror(errno));

	if (!qflag)
		printf("%s%s%s -> %s\n", p->descr, delim, p->str, nts);
	return (0);
}
示例#3
0
/*
 * Collect image data from the start of frame.
 * XXX Note that we clobber any previously collected info...
 */
static void
sofmrk(int mark)
{
	int i;
	unsigned int l;

	l = mkrlen();
	jpg_prcsn = jpg1byte();
	jpg_height = jpg2byte();
	jpg_width = jpg2byte();
	jpg_cmpnts = jpg1byte();

	for (i = 0; process[i].sof < JPEG_M_ERR; i++)
		if (process[i].sof == mark)
			break;
	jpg_prcss = process[i].str;

	/* Verify length. */

	if (l != (unsigned int)(6 + jpg_cmpnts * 3)) {
		exifdie("invalid JPEG SOF marker (length mismatch)");
		return;
	}

	/* Skip over component info we don't care about. */

	for (i = 0; i < jpg_cmpnts; i++) {
		jpg1byte(); jpg1byte(); jpg1byte();
	}

	seensof = TRUE;
}
示例#4
0
/*
 * Fetch one byte of the JPEG file.
 */
static int
jpg1byte(void)
{
	int b;

	b = fgetc(infile);
	if (b == EOF)
	    return(-1);
#if 0
		exifdie("invalid JPEG format");
#endif
	return (b);
}
示例#5
0
/*
 * Fetch the length of a marker.
 */
static unsigned int
mkrlen(void)
{
	unsigned int l;

	/* Length includes itself. */

	if ((l = jpg2byte()) < 2) {
		exifdie("invalid JPEG marker (length mismatch)");
		return(-1);
	}
	return (l - 2);
}
示例#6
0
/*
 * Fetch two bytes of the JPEG file.
 */
static unsigned int
jpg2byte(void)
{
	unsigned int b1, b2;

	b1 = fgetc(infile);
	b2 = fgetc(infile);
	if (b1 == EOF || b2 == EOF)
	    return(-1);
#if 0
		exifdie("invalid JPEG format");
#endif

	return ((b1 << 8) | b2);
}
示例#7
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);
}
示例#8
0
/*
 * Scan the JPEG file for Exif data and parse it.
 */
static int
doit(FILE *fp, const char *fname)
{
	int mark, gotapp1, first, rc;
	unsigned int len, rlen;
	unsigned char *exifbuf;
	struct exiftags *t;
	long app1;

	gotapp1 = FALSE;
	first = 0;
	exifbuf = NULL;
	rc = 0;

	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));

		app1 = ftell(fp);
		rlen = fread(exifbuf, 1, len, fp);
		if (rlen != len) {
			fprintf(stderr, "%s: error reading JPEG (length "
			    "mismatch)\n", fname);
			free(exifbuf);
			return (1);
		}

		gotapp1 = TRUE;
		t = exifscan(exifbuf, len, FALSE);

		if (t && t->props) {
			if (bflag || com)
				rc = writecom(fp, fname, app1,
				    findprop(t->props, tags,
				    EXIF_T_USERCOMMENT), exifbuf, t->md.btiff);
			else
				rc = printcom(fname, findprop(t->props, tags,
				    EXIF_T_USERCOMMENT), t->md.btiff);
		} else {
			fprintf(stderr, "%s: couldn't find Exif properties\n",
			    fname);
			rc = 1;
		}
		exiffree(t);
		free(exifbuf);
	}

	if (!gotapp1) {
		fprintf(stderr, "%s: couldn't find Exif data\n", fname);
		return (1);
	}

	return (rc);
}
示例#9
0
/*
 * Blank or write a comment.
 */
static int
writecom(FILE *fp, const char *fname, long pos, struct exifprop *p,
    const unsigned char *buf, const unsigned char *btiff)
{
	u_int32_t l;
	int ch, checkch;
	long psave;

	/* No comment tag or it's zero length. */

	if (!p) {
		fprintf(stderr, "%s: comment not available\n", fname);
		return (1);
	}

	if (p->count < 9) {
		fprintf(stderr, "%s: comment size zero\n", fname);
		return (1);
	}

	/* Be careful with existing or unsupported comments. */

	if (iflag && *(btiff + p->value)) {

		if (memcmp(ASCCOM, btiff + p->value, 8)) {
			if (nflag)
				return (1);
			fprintf(stderr, "overwrite %.8s comment in %s? "
			    "(y/n [n]) ", btiff + p->value, fname);

			checkch = ch = getchar();
			while (ch != '\n' && ch != EOF)
				ch = getchar();
			if (checkch != 'y' && checkch != 'Y') {
				fprintf(stderr, "not overwritten\n");
				return (1);
			}

		} else if (p->str && *(p->str)) {
			if (nflag)
				return (1);
			fprintf(stderr, "overwrite comment in %s? (y/n [n]) ",
			    fname);

			checkch = ch = getchar();
			while (ch != '\n' && ch != EOF)
				ch = getchar();
			if (checkch != 'y' && checkch != 'Y') {
				fprintf(stderr, "not overwritten\n");
				return (1);
			}
		}
	}

	/* Remember where we are and move to the comment in our file. */

	psave = ftell(fp);
	if (fseek(fp, pos + (btiff - buf) + p->value, SEEK_SET))
		exifdie((const char *)strerror(errno));

	/*
	 * Blank it with zeros and then reset the position.
	 * XXX Note that this is counter to the spec's recommendation:
	 * "When a UserComment area is set aside, it is recommended that
	 * the ID code be ASCII and that the following user comment part
	 * be filled with blank characters [20.H]."  However, cameras (Canon)
	 * seem to make it all zero; the rationale is that one can restore
	 * the image file to its original state.
	 */

	if (bflag) {
		for (l = 0; l < p->count; l++)
			if (fwrite("\0", 1, 1, fp) != 1)
				exifdie((const char *)strerror(errno));
		if (fseek(fp, pos + (btiff - buf) + p->value, SEEK_SET))
			exifdie((const char *)strerror(errno));
	}

	/* Write the character code and comment. */

	if (com) {
		l = strlen(com);
		if (l > p->count - 8) {
			fprintf(stderr, "%s: truncating comment to fit\n",
			    fname);
			l = p->count - 8;
		}

		/* Character code. */

		if (fwrite(ASCCOM, 8, 1, fp) != 1)
			exifdie((const char *)strerror(errno));

		/* Comment. */

		if (fwrite(com, l, 1, fp) != 1)
			exifdie((const char *)strerror(errno));

		/*
		 * Pad with spaces (this seems to be standard practice).
		 * XXX For now we're not NUL terminating the string.
		 * This doesn't appear to be required by the spec, but it's
		 * always possible that something out there will break.
		 * I've seen some utilities pad with spaces and set the
		 * last byte to NUL.
		 */

		for (l = p->count - 8 - l; l; l--)
			if (fwrite(" ", 1, 1, fp) != 1)
				exifdie((const char *)strerror(errno));
	}

	/* Restore the file pointer. */

	if (fseek(fp, psave, SEEK_SET))
		exifdie((const char *)strerror(errno));

	return (0);
}
示例#10
0
文件: exiftime.c 项目: dpt/PrivateEye
int
main(int argc, char **argv)
{
	register int ch;
	int eval, fnum, wantall;
	char *rmode, *wmode;
	FILE *fp;

	progname = argv[0];
	debug = FALSE;
	ttags = wantall = eval = 0;
	lflag = qflag = wflag = FALSE;
	iflag = TRUE;
	v = NULL;
#ifdef WIN32
	rmode = "rb";
	wmode = "r+b";
#else
	rmode = "r";
	wmode = "r+";
#endif

	while ((ch = getopt(argc, argv, "filqs:t:v:w")) != -1)
		switch (ch) {
		case 'f':
			iflag = FALSE;
			break;
		case 'i':
			iflag = TRUE;
			break;
		case 'l':
			lflag = TRUE;
			break;
		case 'q':
			qflag = TRUE;
			break;
		case 's':
			delim = optarg;
			break;
		case 't':
			while (*optarg) {
				switch (*optarg) {
				case 'c':
					ttags |= ET_CREATE;
					break;
				case 'd':
					ttags |= ET_DIGI;
					break;
				case 'g':
					ttags |= ET_GEN;
					break;
				case 'a':
					wantall = 1;
					break;
				default:
					usage();
				}
				optarg++;
			}
			if (wantall) ttags = 0;
			break;
		case 'v':
			v = vary_append(v, optarg);
			break;
		case 'w':
			wflag = TRUE;
			break;
		case '?':
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	if (!*argv)
		usage();

	/* Don't be quiet if we're not writing. */

	if (qflag && !wflag)
		qflag = FALSE;

	/* Prepare an array for sorting. */

	if (lflag) {
		wflag = 0;
		lorder = (struct linfo *)calloc(argc, sizeof(struct linfo));
		if (!lorder)
			exifdie((const char *)strerror(errno));
	}

	/* Run through the files... */

	for (fnum = 0; *argv; ++argv, fnum++) {

		fname = *argv;

		/* Only open for read+write if we need to. */

		if ((fp = fopen(*argv, wflag ? wmode : rmode)) == NULL) {
			exifwarn2(strerror(errno), *argv);
			eval = 1;
			continue;
		}

		/* Print filenames if more than one. */

		if (argc > 1 && !lflag && !qflag)
			printf("%s%s:\n", fnum == 0 ? "" : "\n", *argv);

		if (lflag)
			lorder[fnum].fn = fname;

		if (doit(fp, fnum))
			eval = 1;
		fclose(fp);
	}

	/*
	 * We'd like to use mergesort() here (instead of qsort()) because
	 * qsort() isn't stable w/members that compare equal and we exepect
	 * the list of files to frequently already be in order.  However,
	 * FreeBSD seems to be the only platform with mergesort(), and I'm
	 * not inclined to include the function...
	 */
	if (lflag) {
		qsort(lorder, argc, sizeof(struct linfo), lcomp);
		for (fnum = 0; fnum < argc; fnum++)
			printf("%s\n", lorder[fnum].fn);
		free(lorder);	/* XXX Over in usage()? */
	}

	vary_destroy(v);
	return (eval);
}