aboutsummaryrefslogtreecommitdiffstats
path: root/exiftran.c
diff options
context:
space:
mode:
Diffstat (limited to 'exiftran.c')
-rw-r--r--exiftran.c262
1 files changed, 262 insertions, 0 deletions
diff --git a/exiftran.c b/exiftran.c
new file mode 100644
index 0000000..6db3fd2
--- /dev/null
+++ b/exiftran.c
@@ -0,0 +1,262 @@
+/*
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <libexif/exif-data.h>
+
+#include <jpeglib.h>
+#include "jpeg/transupp.h" /* Support routines for jpegtran */
+#include "jpegtools.h"
+#include "genthumbnail.h"
+
+/* ---------------------------------------------------------------------- */
+
+static void dump_exif(FILE *out, ExifData *ed)
+{
+ const char *title, *value;
+ ExifEntry *ee;
+ int tag,i;
+
+ for (i = 0; i < EXIF_IFD_COUNT; i++) {
+ fprintf(out," ifd %s\n", exif_ifd_get_name (i));
+ for (tag = 0; tag < 0xffff; tag++) {
+ title = exif_tag_get_title(tag);
+ if (!title)
+ continue;
+ ee = exif_content_get_entry (ed->ifd[i], tag);
+ if (NULL == ee)
+ continue;
+ value = exif_entry_get_value(ee);
+ fprintf(out," 0x%04x %-30s %s\n", tag, title, value);
+ }
+ }
+ if (ed->data && ed->size)
+ fprintf(out," thumbnail\n %d bytes data\n", ed->size);
+}
+
+static int dump_file(FILE *out, char *filename)
+{
+ ExifData *ed;
+
+ ed = exif_data_new_from_file (filename);
+ if (NULL == ed) {
+ fprintf(stderr,"%s: no EXIF data\n",filename);
+ return -1;
+ }
+
+ fprintf(out,"%s\n",filename);
+ dump_exif(out,ed);
+ fprintf(out,"--\n");
+
+ exif_data_unref (ed);
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#define THUMB_MAX 65536
+
+static void
+usage(FILE *fp, char *name)
+{
+ char *h;
+
+ if (NULL != (h = strrchr(name, '/')))
+ name = h+1;
+ fprintf(fp,
+ "usage: %s [ options ] file\n"
+ "\n"
+ "transform options:\n"
+ " -a automatic (using exif orientation tag)\n"
+ " -9 rotate by 90 degrees\n"
+ " -1 rotate by 180 degrees\n"
+ " -2 rotate by 270 degrees\n"
+ " -f flip vertical\n"
+ " -F flip horizontal\n"
+ " -t transpose\n"
+ " -T transverse\n"
+ "\n"
+ " -nt don't rotate exif thumbnail\n"
+ " -ni don't rotate jpeg image\n"
+ " -no don't update the orientation tag\n"
+ "\n"
+ "other options:\n"
+ " -h print this text\n"
+ " -d dump exif data\n"
+ " -c <text> create/update comment\n"
+ " -g (re)generate thumbnail\n"
+ " -o <file> output file\n"
+ " -i change files inplace\n"
+ " -b create a backup file (with -i)\n"
+ " -p preserve timestamps (with -i)\n"
+ "\n"
+ "-- \n"
+ "Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]\n",
+ name);
+}
+
+int main(int argc, char *argv[])
+{
+ JXFORM_CODE transform = JXFORM_NONE;
+ unsigned char *comment = NULL;
+ unsigned char *outfile = NULL;
+ unsigned char *thumbnail = NULL;
+ int tsize = 0;
+ int inplace = 0;
+ unsigned int flags =
+ JFLAG_TRANSFORM_IMAGE |
+ JFLAG_TRANSFORM_THUMBNAIL |
+ JFLAG_UPDATE_ORIENTATION;
+ int dump = 0;
+ int i, c, rc;
+
+ for (;;) {
+ c = getopt(argc, argv, "hbpid912fFtTagc:o:n:");
+ if (c == -1)
+ break;
+ switch (c) {
+ case '9':
+ transform = JXFORM_ROT_90;
+ break;
+ case '1':
+ transform = JXFORM_ROT_180;
+ break;
+ case '2':
+ transform = JXFORM_ROT_270;
+ break;
+ case 'f':
+ transform = JXFORM_FLIP_V;
+ break;
+ case 'F':
+ transform = JXFORM_FLIP_H;
+ break;
+ case 't':
+ transform = JXFORM_TRANSPOSE;
+ break;
+ case 'T':
+ transform = JXFORM_TRANSVERSE;
+ break;
+ case 'a':
+ transform = -1; /* automagic */
+ break;
+
+ case 'n':
+ /* don't ... */
+ switch (optarg[0]) {
+ case 't':
+ flags &= ~JFLAG_TRANSFORM_THUMBNAIL;
+ break;
+ case 'i':
+ flags &= ~JFLAG_TRANSFORM_IMAGE;
+ break;
+ case 'o':
+ flags &= ~JFLAG_UPDATE_ORIENTATION;
+ break;
+ default:
+ fprintf(stderr,"unknown option -n%c\n",optarg[0]);
+ exit(1);
+ }
+ break;
+
+ case 'c':
+ flags |= JFLAG_UPDATE_COMMENT;
+ comment = optarg;
+ break;
+ case 'g':
+ flags |= JFLAG_UPDATE_THUMBNAIL;
+ break;
+ case 'o':
+ outfile = optarg;
+ break;
+ case 'd':
+ dump = 1;
+ break;
+
+ case 'b':
+ flags |= JFLAG_FILE_BACKUP;
+ break;
+ case 'p':
+ flags |= JFLAG_FILE_KEEP_TIME;
+ break;
+ case 'i':
+ inplace = 1;
+ break;
+
+ case 'h':
+ usage(stdout,argv[0]);
+ exit(0);
+ default:
+ usage(stderr,argv[0]);
+ exit(1);
+ }
+ }
+
+ /* sanity checks on the arguments */
+ if (optind == argc) {
+ fprintf(stderr,
+ "no image file specified (try -h for more info)\n");
+ exit(1);
+ }
+
+ /* read-only stuff */
+ if (dump) {
+ rc = 0;
+ for (i = optind; i < argc; i++) {
+ if (0 != dump_file(stdout,argv[i]))
+ rc = 1;
+ }
+ return rc;
+ }
+
+ /* r/w sanity checks */
+ if (NULL != outfile && optind+1 > argc) {
+ fprintf(stderr,
+ "when specifying a output file you can process\n"
+ "one file at a time only (try -h for more info).\n");
+ exit(1);
+ }
+ if (NULL == outfile && 0 == inplace) {
+ fprintf(stderr,
+ "you have to either specify a output file (-o <file>)\n"
+ "or enable inplace editing (-i). Try -h for more info.\n");
+ exit(1);
+ }
+ if (JXFORM_NONE == transform &&
+ !(flags & JFLAG_UPDATE_COMMENT) &&
+ !(flags & JFLAG_UPDATE_THUMBNAIL)) {
+ fprintf(stderr,
+ "What do you want to do today? Neither a new comment nor a\n"
+ "tranformation operation was specified (try -h for more info).\n");
+ exit(1);
+ }
+
+ /* do actual update work */
+ if (outfile) {
+ if (flags & JFLAG_UPDATE_THUMBNAIL) {
+ thumbnail = malloc(THUMB_MAX);
+ tsize = create_thumbnail(argv[optind],thumbnail,THUMB_MAX);
+ }
+ return jpeg_transform_files(argv[optind], outfile, transform,
+ comment, thumbnail, tsize, flags);
+ } else {
+ rc = 0;
+ for (i = optind; i < argc; i++) {
+ fprintf(stderr,"processing %s\n",argv[i]);
+ if (flags & JFLAG_UPDATE_THUMBNAIL) {
+ thumbnail = malloc(THUMB_MAX);
+ tsize = create_thumbnail(argv[i],thumbnail,THUMB_MAX);
+ }
+ if (0 != jpeg_transform_inplace(argv[i], transform, comment,
+ thumbnail, tsize, flags))
+ rc = 1;
+ }
+ return rc;
+ }
+}