summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xexifautotran.sh41
-rw-r--r--jaricom.c13
-rw-r--r--jcarith.c22
-rw-r--r--jdarith.c22
-rw-r--r--jpegexiforient.c292
5 files changed, 390 insertions, 0 deletions
diff --git a/exifautotran.sh b/exifautotran.sh
new file mode 100755
index 0000000..fd5105e
--- /dev/null
+++ b/exifautotran.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# exifautotran [list of files]
+#
+# Transforms Exif files so that Orientation becomes 1
+#
+for i
+do
+ case $i in
+ -v|--version) echo "exifautotran"; exit 0;;
+ -h|--help)
+ cat <<EOF
+exifautotran [list of files]
+
+Transforms Exif files so that Orientation becomes 1
+EOF
+ exit 0;;
+ esac
+
+ case `jpegexiforient -n "$i"` in
+ 1) transform="";;
+ 2) transform="-flip horizontal";;
+ 3) transform="-rotate 180";;
+ 4) transform="-flip vertical";;
+ 5) transform="-transpose";;
+ 6) transform="-rotate 90";;
+ 7) transform="-transverse";;
+ 8) transform="-rotate 270";;
+ *) transform="";;
+ esac
+ if test -n "$transform"; then
+ echo Executing: jpegtran -copy all $transform $i >&2
+ jpegtran -copy all $transform "$i" > tempfile
+ if test $? -ne 0; then
+ echo Error while transforming $i - skipped. >&2
+ else
+ rm "$i"
+ mv tempfile "$i"
+ jpegexiforient -1 "$i" > /dev/null
+ fi
+ fi
+done
diff --git a/jaricom.c b/jaricom.c
new file mode 100644
index 0000000..1a15bdf
--- /dev/null
+++ b/jaricom.c
@@ -0,0 +1,13 @@
+/*
+ * jaricom.c
+ *
+ * [IJG Copyright notice]
+ *
+ * This file holds place for arithmetic entropy codec tables.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+INT32 jaritab[1]; /* dummy table */
diff --git a/jcarith.c b/jcarith.c
new file mode 100644
index 0000000..e9790a3
--- /dev/null
+++ b/jcarith.c
@@ -0,0 +1,22 @@
+/*
+ * jcarith.c
+ *
+ * [IJG Copyright notice]
+ *
+ * This file holds place for arithmetic entropy encoding routines.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Module initialization routine for arithmetic entropy encoding.
+ */
+
+GLOBAL(void)
+jinit_arith_encoder (j_compress_ptr cinfo)
+{
+ ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+}
diff --git a/jdarith.c b/jdarith.c
new file mode 100644
index 0000000..13709f2
--- /dev/null
+++ b/jdarith.c
@@ -0,0 +1,22 @@
+/*
+ * jdarith.c
+ *
+ * [IJG Copyright notice]
+ *
+ * This file holds place for arithmetic entropy decoding routines.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Module initialization routine for arithmetic entropy decoding.
+ */
+
+GLOBAL(void)
+jinit_arith_decoder (j_decompress_ptr cinfo)
+{
+ ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+}
diff --git a/jpegexiforient.c b/jpegexiforient.c
new file mode 100644
index 0000000..ac17d7d
--- /dev/null
+++ b/jpegexiforient.c
@@ -0,0 +1,292 @@
+/*
+ * jpegexiforient.c
+ *
+ * This is a utility program to get and set the Exif Orientation Tag.
+ * It can be used together with jpegtran in scripts for automatic
+ * orientation correction of digital camera pictures.
+ *
+ * The Exif orientation value gives the orientation of the camera
+ * relative to the scene when the image was captured. The relation
+ * of the '0th row' and '0th column' to visual position is shown as
+ * below.
+ *
+ * Value | 0th Row | 0th Column
+ * ------+-------------+-----------
+ * 1 | top | left side
+ * 2 | top | rigth side
+ * 3 | bottom | rigth side
+ * 4 | bottom | left side
+ * 5 | left side | top
+ * 6 | right side | top
+ * 7 | right side | bottom
+ * 8 | left side | bottom
+ *
+ * For convenience, here is what the letter F would look like if it were
+ * tagged correctly and displayed by a program that ignores the orientation
+ * tag:
+ *
+ * 1 2 3 4 5 6 7 8
+ *
+ * 888888 888888 88 88 8888888888 88 88 8888888888
+ * 88 88 88 88 88 88 88 88 88 88 88 88
+ * 8888 8888 8888 8888 88 8888888888 8888888888 88
+ * 88 88 88 88
+ * 88 88 888888 888888
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static FILE * myfile; /* My JPEG file */
+
+static unsigned char exif_data[65536L];
+
+/* Return next input byte, or EOF if no more */
+#define NEXTBYTE() getc(myfile)
+
+/* Error exit handler */
+#define ERREXIT(msg) (exit(0))
+
+/* Read one byte, testing for EOF */
+static int
+read_1_byte (void)
+{
+ int c;
+
+ c = NEXTBYTE();
+ if (c == EOF)
+ ERREXIT("Premature EOF in JPEG file");
+ return c;
+}
+
+/* Read 2 bytes, convert to unsigned int */
+/* All 2-byte quantities in JPEG markers are MSB first */
+static unsigned int
+read_2_bytes (void)
+{
+ int c1, c2;
+
+ c1 = NEXTBYTE();
+ if (c1 == EOF)
+ ERREXIT("Premature EOF in JPEG file");
+ c2 = NEXTBYTE();
+ if (c2 == EOF)
+ ERREXIT("Premature EOF in JPEG file");
+ return (((unsigned int) c1) << 8) + ((unsigned int) c2);
+}
+
+static const char * progname; /* program name for error messages */
+
+static void
+usage (void)
+/* complain about bad command line */
+{
+ fprintf(stderr, "jpegexiforient reads or writes the Exif Orientation Tag ");
+ fprintf(stderr, "in a JPEG Exif file.\n");
+
+ fprintf(stderr, "Usage: %s [switches] jpegfile\n", progname);
+
+ fprintf(stderr, "Switches:\n");
+ fprintf(stderr, " -n Do not output the trailing newline\n");
+ fprintf(stderr, " -1 .. -8 Set orientation value 1 .. 8\n");
+}
+
+/*
+ * The main program.
+ */
+
+int
+main (int argc, char **argv)
+{
+ int n_flag, set_flag;
+ unsigned int length, i;
+ int is_motorola; /* Flag for byte order */
+ unsigned int offset, number_of_tags, tagnum;
+
+ progname = argv[0];
+ if (progname == NULL || progname[0] == 0)
+ progname = "jpegexiforient"; /* in case C library doesn't provide it */
+
+ if (argc < 2) { usage(); return 0; }
+
+ n_flag = 0; set_flag = 0;
+
+ i = 1;
+ while (argv[i][0] == '-') {
+ switch (argv[i][1]) {
+ case 'n':
+ n_flag = 1;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ set_flag = argv[i][1] - '0';
+ break;
+ default:
+ usage(); return 0;
+ }
+ if (++i >= argc) { usage(); return 0; }
+ }
+
+ if (set_flag) {
+ if ((myfile = fopen(argv[i], "rb+")) == NULL) {
+ fprintf(stderr, "%s: can't open %s\n", progname, argv[i]);
+ return 0;
+ }
+ } else {
+ if ((myfile = fopen(argv[i], "rb")) == NULL) {
+ fprintf(stderr, "%s: can't open %s\n", progname, argv[i]);
+ return 0;
+ }
+ }
+
+ /* Read File head, check for JPEG SOI + Exif APP1 */
+ for (i = 0; i < 4; i++)
+ exif_data[i] = (unsigned char) read_1_byte();
+ if (exif_data[0] != 0xFF ||
+ exif_data[1] != 0xD8 ||
+ exif_data[2] != 0xFF ||
+ exif_data[3] != 0xE1)
+ return 0;
+
+ /* Get the marker parameter length count */
+ length = read_2_bytes();
+ /* Length includes itself, so must be at least 2 */
+ /* Following Exif data length must be at least 6 */
+ if (length < 8)
+ return 0;
+ length -= 8;
+ /* Read Exif head, check for "Exif" */
+ for (i = 0; i < 6; i++)
+ exif_data[i] = (unsigned char) read_1_byte();
+ if (exif_data[0] != 0x45 ||
+ exif_data[1] != 0x78 ||
+ exif_data[2] != 0x69 ||
+ exif_data[3] != 0x66 ||
+ exif_data[4] != 0 ||
+ exif_data[5] != 0)
+ return 0;
+ /* Read Exif body */
+ for (i = 0; i < length; i++)
+ exif_data[i] = (unsigned char) read_1_byte();
+
+ if (length < 12) return 0; /* Length of an IFD entry */
+
+ /* Discover byte order */
+ if (exif_data[0] == 0x49 && exif_data[1] == 0x49)
+ is_motorola = 0;
+ else if (exif_data[0] == 0x4D && exif_data[1] == 0x4D)
+ is_motorola = 1;
+ else
+ return 0;
+
+ /* Check Tag Mark */
+ if (is_motorola) {
+ if (exif_data[2] != 0) return 0;
+ if (exif_data[3] != 0x2A) return 0;
+ } else {
+ if (exif_data[3] != 0) return 0;
+ if (exif_data[2] != 0x2A) return 0;
+ }
+
+ /* Get first IFD offset (offset to IFD0) */
+ if (is_motorola) {
+ if (exif_data[4] != 0) return 0;
+ if (exif_data[5] != 0) return 0;
+ offset = exif_data[6];
+ offset <<= 8;
+ offset += exif_data[7];
+ } else {
+ if (exif_data[7] != 0) return 0;
+ if (exif_data[6] != 0) return 0;
+ offset = exif_data[5];
+ offset <<= 8;
+ offset += exif_data[4];
+ }
+ if (offset > length - 2) return 0; /* check end of data segment */
+
+ /* Get the number of directory entries contained in this IFD */
+ if (is_motorola) {
+ number_of_tags = exif_data[offset];
+ number_of_tags <<= 8;
+ number_of_tags += exif_data[offset+1];
+ } else {
+ number_of_tags = exif_data[offset+1];
+ number_of_tags <<= 8;
+ number_of_tags += exif_data[offset];
+ }
+ if (number_of_tags == 0) return 0;
+ offset += 2;
+
+ /* Search for Orientation Tag in IFD0 */
+ for (;;) {
+ if (offset > length - 12) return 0; /* check end of data segment */
+ /* Get Tag number */
+ if (is_motorola) {
+ tagnum = exif_data[offset];
+ tagnum <<= 8;
+ tagnum += exif_data[offset+1];
+ } else {
+ tagnum = exif_data[offset+1];
+ tagnum <<= 8;
+ tagnum += exif_data[offset];
+ }
+ if (tagnum == 0x0112) break; /* found Orientation Tag */
+ if (--number_of_tags == 0) return 0;
+ offset += 12;
+ }
+
+ if (set_flag) {
+ /* Set the Orientation value */
+ if (is_motorola) {
+ exif_data[offset+2] = 0; /* Format = unsigned short (2 octets) */
+ exif_data[offset+3] = 3;
+ exif_data[offset+4] = 0; /* Number Of Components = 1 */
+ exif_data[offset+5] = 0;
+ exif_data[offset+6] = 0;
+ exif_data[offset+7] = 1;
+ exif_data[offset+8] = 0;
+ exif_data[offset+9] = (unsigned char)set_flag;
+ exif_data[offset+10] = 0;
+ exif_data[offset+11] = 0;
+ } else {
+ exif_data[offset+2] = 3; /* Format = unsigned short (2 octets) */
+ exif_data[offset+3] = 0;
+ exif_data[offset+4] = 1; /* Number Of Components = 1 */
+ exif_data[offset+5] = 0;
+ exif_data[offset+6] = 0;
+ exif_data[offset+7] = 0;
+ exif_data[offset+8] = (unsigned char)set_flag;
+ exif_data[offset+9] = 0;
+ exif_data[offset+10] = 0;
+ exif_data[offset+11] = 0;
+ }
+ fseek(myfile, (4 + 2 + 6 + 2) + offset, SEEK_SET);
+ fwrite(exif_data + 2 + offset, 1, 10, myfile);
+ } else {
+ /* Get the Orientation value */
+ if (is_motorola) {
+ if (exif_data[offset+8] != 0) return 0;
+ set_flag = exif_data[offset+9];
+ } else {
+ if (exif_data[offset+9] != 0) return 0;
+ set_flag = exif_data[offset+8];
+ }
+ if (set_flag > 8) return 0;
+ }
+
+ /* Write out Orientation value */
+ if (n_flag)
+ printf("%c", '0' + set_flag);
+ else
+ printf("%c\n", '0' + set_flag);
+
+ /* All done. */
+ return 0;
+}