aboutsummaryrefslogtreecommitdiffstats
path: root/graphics/jpeg/files
diff options
context:
space:
mode:
authordinoex <dinoex@FreeBSD.org>2004-03-18 22:53:47 +0800
committerdinoex <dinoex@FreeBSD.org>2004-03-18 22:53:47 +0800
commit7bab82777232174a5b09f21c258e67143b79b88a (patch)
treeb9ac9d413532e19ff8fd5de7ce595ce6258c23ee /graphics/jpeg/files
parentc48ffc8c32c5acfc4eb1a2187e073119994cf709 (diff)
downloadfreebsd-ports-gnome-7bab82777232174a5b09f21c258e67143b79b88a.tar.gz
freebsd-ports-gnome-7bab82777232174a5b09f21c258e67143b79b88a.tar.zst
freebsd-ports-gnome-7bab82777232174a5b09f21c258e67143b79b88a.zip
- Patches from
http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=106060 , http://sylvana.net/jpegcrop/exifpatch.html Which add EXIF support to jpegtran (lossless JPEG transforms) and to rdjpgcom to add reporting of EXIF orientation in verbose mode. - Tools from http://sylvana.net/jpegcrop/exif_orientation.html which allow automatic JPEG orientation using the EXIF tag from the camera. (I think it should be done with DISTFILES rather than with PATCH_SITES, though). Roman Shterenzon (some cleanup done)
Diffstat (limited to 'graphics/jpeg/files')
-rw-r--r--graphics/jpeg/files/patch-ae18
-rw-r--r--graphics/jpeg/files/patch-configure (renamed from graphics/jpeg/files/patch-ab)0
-rw-r--r--graphics/jpeg/files/patch-djpeg.c (renamed from graphics/jpeg/files/patch-ad)0
-rw-r--r--graphics/jpeg/files/patch-exifautotran7
-rw-r--r--graphics/jpeg/files/patch-jpegtran.144
-rw-r--r--graphics/jpeg/files/patch-jpegtran.c99
-rw-r--r--graphics/jpeg/files/patch-rdjpgcom.c218
-rw-r--r--graphics/jpeg/files/patch-transupp.c284
-rw-r--r--graphics/jpeg/files/patch-transupp.h12
9 files changed, 664 insertions, 18 deletions
diff --git a/graphics/jpeg/files/patch-ae b/graphics/jpeg/files/patch-ae
deleted file mode 100644
index 5004e6cd3040..000000000000
--- a/graphics/jpeg/files/patch-ae
+++ /dev/null
@@ -1,18 +0,0 @@
---- rdjpgcom.c.orig Sat Oct 11 18:41:04 1997
-+++ rdjpgcom.c Mon Apr 24 16:04:13 2000
-@@ -14,6 +14,7 @@
- #define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */
- #include "jinclude.h" /* get auto-config symbols, <stdio.h> */
-
-+#include <locale.h> /* to declare setlocale() */
- #include <ctype.h> /* to declare isupper(), tolower() */
- #ifdef USE_SETMODE
- #include <fcntl.h> /* to declare setmode()'s parameter macros */
-@@ -231,6 +232,7 @@
- ERREXIT("Erroneous JPEG marker length");
- length -= 2;
-
-+ setlocale(LC_ALL, "");
- while (length > 0) {
- ch = read_1_byte();
- /* Emit the character in a readable form.
diff --git a/graphics/jpeg/files/patch-ab b/graphics/jpeg/files/patch-configure
index 85392d80c6ae..85392d80c6ae 100644
--- a/graphics/jpeg/files/patch-ab
+++ b/graphics/jpeg/files/patch-configure
diff --git a/graphics/jpeg/files/patch-ad b/graphics/jpeg/files/patch-djpeg.c
index 224fefe2e850..224fefe2e850 100644
--- a/graphics/jpeg/files/patch-ad
+++ b/graphics/jpeg/files/patch-djpeg.c
diff --git a/graphics/jpeg/files/patch-exifautotran b/graphics/jpeg/files/patch-exifautotran
new file mode 100644
index 000000000000..418f618019ba
--- /dev/null
+++ b/graphics/jpeg/files/patch-exifautotran
@@ -0,0 +1,7 @@
+--- exifautotran.orig Thu Mar 18 06:25:27 2004
++++ exifautotran Thu Mar 18 06:28:29 2004
+@@ -1,3 +1,4 @@
++#!/bin/sh
+ # exifautotran [list of files]
+ #
+ # Transforms Exif files so that Orientation becomes 1
diff --git a/graphics/jpeg/files/patch-jpegtran.1 b/graphics/jpeg/files/patch-jpegtran.1
new file mode 100644
index 000000000000..fe4eb1372f4d
--- /dev/null
+++ b/graphics/jpeg/files/patch-jpegtran.1
@@ -0,0 +1,44 @@
+--- jpegtran.1.exif 1997-08-03 22:01:01.000000000 +0200
++++ jpegtran.1 2003-09-30 14:35:36.000000000 +0200
+@@ -161,6 +161,14 @@
+ Copy all extra markers. This setting preserves miscellaneous markers
+ found in the source file, such as JFIF thumbnails and Photoshop settings.
+ In some files these extra markers can be sizable.
++See 'EXIF FILES' for special tratement of EXIF markers.
++.TP
++.B \-copy exif
++This setting preserves the EXIF marker, commonly found in JPEG files produced
++by digital cameras, in addition to any comment markers. If there is an EXIF
++marker it is copied and the JFIF marker (incompatible with EXIF) is
++omitted. If there is no EXIF marker a JFIF one is emitted as usual. See 'EXIF
++FILES' for special tratement of EXIF markers.
+ .PP
+ The default behavior is
+ .BR "\-copy comments" .
+@@ -189,6 +197,26 @@
+ .B \-debug
+ Same as
+ .BR \-verbose .
++.SH EXIF FILES
++The EXIF variety of JPEG files, which are often produced by digital cameras,
++are recognized by jpegtran as EXIF files (i.e. not as JFIF, the
++usual variety of JPEG files). If the input file is recognized as EXIF (i.e.,
++there is an EXIF marker and no JFIF marker) the '-copy exif' option is
++automatically turned on if '-copy comments', or no '-copy' option, was
++specified. Thus, unless '-copy none' is specified an EXIF file is kept as EXIF
++and not converted to JFIF.
++.PP
++If a geometrical transformation is applied (e.g., rotate, transpose) the EXIF
++width and height fields are set to the width and height of the output
++image. Furthermore, the orientation field is reset to one, meaning tha the
++orientation of the output image is upright (i.e. normal).
++.PP
++Note that an explicitely given '-copy exif' option will output an EXIF file if
++the input is an EXIF file that was saved as JFIF, and that the EXIF marker is
++still present. This option is useful for recovering EXIF files that where
++converted to JFIF by a non EXIF-aware software. Note however, that the data in
++the EXIF marker is not validated, unless a geometrical transformation is
++applied.
+ .SH EXAMPLES
+ .LP
+ This example converts a baseline JPEG file to progressive form:
diff --git a/graphics/jpeg/files/patch-jpegtran.c b/graphics/jpeg/files/patch-jpegtran.c
new file mode 100644
index 000000000000..429d1099e56d
--- /dev/null
+++ b/graphics/jpeg/files/patch-jpegtran.c
@@ -0,0 +1,99 @@
+--- jpegtran.c.exif 1997-07-24 04:37:26.000000000 +0200
++++ jpegtran.c 2003-09-29 22:31:22.000000000 +0200
+@@ -56,6 +56,7 @@
+ fprintf(stderr, " -copy none Copy no extra markers from source file\n");
+ fprintf(stderr, " -copy comments Copy only comment markers (default)\n");
+ fprintf(stderr, " -copy all Copy all extra markers\n");
++ fprintf(stderr, " -copy exif Copy EXIF marker and omit JFIF if EXIF\n");
+ #ifdef ENTROPY_OPT_SUPPORTED
+ fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
+ #endif
+@@ -109,6 +110,50 @@
+ #endif
+ }
+
++LOCAL(void)
++handle_exif (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
++ JCOPY_OPTION *copyoption)
++/* Adjust the marker writing options to create an EXIF file, instead of JFIF,
++ * if so requested or an EXIF file is detected as input. Must be called after
++ * jpeg_copy_critical_parameters() as that sets the defaults. */
++{
++ jpeg_saved_marker_ptr cur_marker, prev_marker;
++
++ /* Look for an exif marker */
++ prev_marker = NULL;
++ cur_marker = srcinfo->marker_list;
++ while (cur_marker != NULL) {
++ if (cur_marker->marker == JPEG_APP0+1 &&
++ cur_marker->data_length >= 6 &&
++ GETJOCTET(cur_marker->data[0]) == 0x45 &&
++ GETJOCTET(cur_marker->data[1]) == 0x78 &&
++ GETJOCTET(cur_marker->data[2]) == 0x69 &&
++ GETJOCTET(cur_marker->data[3]) == 0x66 &&
++ GETJOCTET(cur_marker->data[4]) == 0 &&
++ GETJOCTET(cur_marker->data[5]) == 0)
++ break; /* found an EXIF marker */
++ prev_marker = cur_marker;
++ cur_marker = cur_marker->next;
++ }
++ /* If we've found an EXIF marker but not JFIF this is an EXIF file. Unless
++ * explicitely requested, make sure we keep the EXIF marker and do not
++ * emit a JFIF marker (which would come before). EXIF requires that the
++ * first marker be EXIF. */
++ if (cur_marker != NULL &&
++ ((*copyoption != JCOPYOPT_NONE && !srcinfo->saw_JFIF_marker) ||
++ (*copyoption == JCOPYOPT_EXIF))) {
++ dstinfo->write_JFIF_header = FALSE;
++ if (*copyoption == JCOPYOPT_COMMENTS)
++ *copyoption = JCOPYOPT_EXIF;
++ }
++ /* If making an EXIF file, make sure that EXIF is first marker */
++ if (cur_marker != NULL && prev_marker != NULL &&
++ *copyoption == JCOPYOPT_EXIF) {
++ prev_marker->next = cur_marker->next;
++ cur_marker->next = srcinfo->marker_list;
++ srcinfo->marker_list = cur_marker;
++ }
++}
+
+ LOCAL(int)
+ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
+@@ -170,6 +215,8 @@
+ copyoption = JCOPYOPT_COMMENTS;
+ } else if (keymatch(argv[argn], "all", 1)) {
+ copyoption = JCOPYOPT_ALL;
++ } else if (keymatch(argv[argn], "exif", 1)) {
++ copyoption = JCOPYOPT_EXIF;
+ } else
+ usage();
+
+@@ -181,6 +228,7 @@
+ if (! printed_version) {
+ fprintf(stderr, "Independent JPEG Group's JPEGTRAN, version %s\n%s\n",
+ JVERSION, JCOPYRIGHT);
++ fprintf(stderr, "EXIF support v 0.1 added 29-Sep-2003\n");
+ printed_version = TRUE;
+ }
+ cinfo->err->trace_level++;
+@@ -452,6 +500,7 @@
+ /* Initialize destination compression parameters from source values */
+ jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
+
++
+ /* Adjust destination parameters if required by transform options;
+ * also find out which set of coefficient arrays will hold the output.
+ */
+@@ -464,8 +513,12 @@
+ #endif
+
+ /* Adjust default compression parameters by re-parsing the options */
++ /* Save value of copyoption */
+ file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);
+
++ /* If we want EXIF, make sure we do not write incompatible markers */
++ handle_exif(&srcinfo,&dstinfo,&copyoption);
++
+ /* Specify data destination for compression */
+ jpeg_stdio_dest(&dstinfo, output_file);
+
diff --git a/graphics/jpeg/files/patch-rdjpgcom.c b/graphics/jpeg/files/patch-rdjpgcom.c
new file mode 100644
index 000000000000..db6bd23c249f
--- /dev/null
+++ b/graphics/jpeg/files/patch-rdjpgcom.c
@@ -0,0 +1,218 @@
+--- rdjpgcom.c.orig Sun Oct 12 00:41:04 1997
++++ rdjpgcom.c Thu Mar 18 06:37:23 2004
+@@ -14,6 +14,7 @@
+ #define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */
+ #include "jinclude.h" /* get auto-config symbols, <stdio.h> */
+
++#include <locale.h> /* to declare setlocale() */
+ #include <ctype.h> /* to declare isupper(), tolower() */
+ #ifdef USE_SETMODE
+ #include <fcntl.h> /* to declare setmode()'s parameter macros */
+@@ -120,6 +121,7 @@
+ #define M_EOI 0xD9 /* End Of Image (end of datastream) */
+ #define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
+ #define M_APP0 0xE0 /* Application-specific marker, type N */
++#define M_APP1 0xE1 /* Typically EXIF marker */
+ #define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */
+ #define M_COM 0xFE /* COMment */
+
+@@ -210,6 +212,175 @@
+ }
+ }
+
++/*
++ * Helper routine to skip the given number of bytes.
++ */
++
++static void
++skip_n (unsigned int length)
++{
++ while (length > 0) {
++ (void) read_1_byte();
++ length--;
++ }
++}
++
++/*
++ * Parses an APP1 marker looking for EXIF data. If EXIF, the orientation is
++ * reported to stdout.
++ */
++
++static void
++process_APP1 (void)
++{
++ unsigned int length, i;
++ int is_motorola; /* byte order indicator */
++ unsigned int offset, number_of_tags, tagnum;
++ int orientation;
++ char *ostr;
++ /* This 64K buffer would probably be best if allocated dynamically, but it's
++ * the only one on this program so it's really not that
++ * important. Allocating on the stack is not an option, as 64K might be too
++ * big for some (crippled) platforms. */
++ static unsigned char exif_data[65536L];
++
++ /* Get the marker parameter length count */
++ length = read_2_bytes();
++ /* Length includes itself, so must be at least 2 */
++ if (length < 2)
++ ERREXIT("Erroneous JPEG marker length");
++ length -= 2;
++
++ /* We only care if APP1 is really an EXIF marker. Minimum length is 6 for
++ * signature plus 12 for an IFD. */
++ if (length < 18) {
++ skip_n(length);
++ return;
++ }
++
++ /* Check for actual EXIF marker */
++ for (i=0; i < 6; i++)
++ exif_data[i] = (unsigned char) read_1_byte();
++ length -= 6;
++ 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) {
++ skip_n(length);
++ return;
++ }
++
++ /* Read all EXIF body */
++ for (i=0; i < length; i++)
++ exif_data[i] = (unsigned char) read_1_byte();
++
++ /* 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;
++
++ /* Check Tag Mark */
++ if (is_motorola) {
++ if (exif_data[2] != 0) return;
++ if (exif_data[3] != 0x2A) return;
++ } else {
++ if (exif_data[3] != 0) return;
++ if (exif_data[2] != 0x2A) return;
++ }
++
++ /* Get first IFD offset (offset to IFD0) */
++ if (is_motorola) {
++ if (exif_data[4] != 0) return;
++ if (exif_data[5] != 0) return;
++ offset = exif_data[6];
++ offset <<= 8;
++ offset += exif_data[7];
++ } else {
++ if (exif_data[7] != 0) return;
++ if (exif_data[6] != 0) return;
++ offset = exif_data[5];
++ offset <<= 8;
++ offset += exif_data[4];
++ }
++ if (offset > length - 2) return; /* 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;
++ offset += 2;
++
++ /* Search for Orientation Tag in IFD0 */
++ for (;;) {
++ if (offset > length - 12) return; /* 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;
++ offset += 12;
++ }
++
++ /* Get the Orientation value */
++ if (is_motorola) {
++ if (exif_data[offset+8] != 0) return;
++ orientation = exif_data[offset+9];
++ } else {
++ if (exif_data[offset+9] != 0) return;
++ orientation = exif_data[offset+8];
++ }
++ if (orientation == 0 || orientation > 8) return;
++
++ /* Print the orientation (position of the 0th row - 0th column) */
++ switch (orientation) {
++ case 1:
++ ostr = "top-left";
++ break;
++ case 2:
++ ostr = "top-right";
++ break;
++ case 3:
++ ostr = "bottom-right";
++ break;
++ case 4:
++ ostr = "bottom-left";
++ break;
++ case 5:
++ ostr = "left-top";
++ break;
++ case 6:
++ ostr = "right-top";
++ break;
++ case 7:
++ ostr = "right-bottom";
++ break;
++ case 8:
++ ostr = "left-bottom";
++ break;
++ default:
++ return;
++ }
++ printf("EXIF orientation: %s\n",ostr);
++}
+
+ /*
+ * Process a COM marker.
+@@ -231,6 +402,7 @@
+ ERREXIT("Erroneous JPEG marker length");
+ length -= 2;
+
++ setlocale(LC_ALL, "");
+ while (length > 0) {
+ ch = read_1_byte();
+ /* Emit the character in a readable form.
+@@ -363,6 +535,15 @@
+
+ case M_COM:
+ process_COM();
++ break;
++
++ case M_APP1:
++ /* APP1 is usually the EXIF marker used by digital cameras, attempt to
++ * process it to give some useful info. */
++ if (verbose) {
++ process_APP1();
++ } else
++ skip_variable();
+ break;
+
+ case M_APP12:
diff --git a/graphics/jpeg/files/patch-transupp.c b/graphics/jpeg/files/patch-transupp.c
new file mode 100644
index 000000000000..48927aa80bc0
--- /dev/null
+++ b/graphics/jpeg/files/patch-transupp.c
@@ -0,0 +1,284 @@
+--- transupp.c.exif 1997-08-10 02:15:26.000000000 +0200
++++ transupp.c 2003-09-29 22:28:42.000000000 +0200
+@@ -717,6 +717,194 @@
+ }
+
+
++/* Adjust Exif image parameters.
++ *
++ * We try to adjust the Tags ExifImageWidth, ExifImageHeight and
++ * ExifOrientation if possible. If the given new_* value is zero the
++ * corresponding tag is not adjusted.
++ */
++
++LOCAL(void)
++adjust_exif_parameters (JOCTET FAR * data, unsigned int length,
++ JDIMENSION new_width, JDIMENSION new_height,
++ unsigned int new_orient)
++{
++ boolean is_motorola; /* Flag for byte order */
++ unsigned int number_of_tags, tagnum;
++ unsigned int firstoffset, offset, exifsuboffset;
++ JDIMENSION new_value;
++
++ if (length < 12) return; /* Length of an IFD entry */
++
++ /* Discover byte order */
++ if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49)
++ is_motorola = FALSE;
++ else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D)
++ is_motorola = TRUE;
++ else
++ return;
++
++ /* Check Tag Mark */
++ if (is_motorola) {
++ if (GETJOCTET(data[2]) != 0) return;
++ if (GETJOCTET(data[3]) != 0x2A) return;
++ } else {
++ if (GETJOCTET(data[3]) != 0) return;
++ if (GETJOCTET(data[2]) != 0x2A) return;
++ }
++
++ /* Get first IFD offset (offset to IFD0) */
++ if (is_motorola) {
++ if (GETJOCTET(data[4]) != 0) return;
++ if (GETJOCTET(data[5]) != 0) return;
++ firstoffset = GETJOCTET(data[6]);
++ firstoffset <<= 8;
++ firstoffset += GETJOCTET(data[7]);
++ } else {
++ if (GETJOCTET(data[7]) != 0) return;
++ if (GETJOCTET(data[6]) != 0) return;
++ firstoffset = GETJOCTET(data[5]);
++ firstoffset <<= 8;
++ firstoffset += GETJOCTET(data[4]);
++ }
++ if (firstoffset > length - 2) return; /* check end of data segment */
++
++ /* Get the number of directory entries contained in this IFD */
++ if (is_motorola) {
++ number_of_tags = GETJOCTET(data[firstoffset]);
++ number_of_tags <<= 8;
++ number_of_tags += GETJOCTET(data[firstoffset+1]);
++ } else {
++ number_of_tags = GETJOCTET(data[firstoffset+1]);
++ number_of_tags <<= 8;
++ number_of_tags += GETJOCTET(data[firstoffset]);
++ }
++ if (number_of_tags == 0) return;
++ firstoffset += 2;
++
++ /* Search for ExifSubIFD offset and ExifOrient Tag in IFD0 */
++ exifsuboffset = 0;
++ for (;;) {
++ if (firstoffset > length - 12) break; /* check end of data segment */
++ /* Get Tag number */
++ if (is_motorola) {
++ tagnum = GETJOCTET(data[firstoffset]);
++ tagnum <<= 8;
++ tagnum += GETJOCTET(data[firstoffset+1]);
++ } else {
++ tagnum = GETJOCTET(data[firstoffset+1]);
++ tagnum <<= 8;
++ tagnum += GETJOCTET(data[firstoffset]);
++ }
++ if (tagnum == 0x0112 && new_orient > 0) { /* found ExifOrientation */
++ if (is_motorola) {
++ data[firstoffset+2] = 0; /* Format = unsigned short (2 octets) */
++ data[firstoffset+3] = 3;
++ data[firstoffset+4] = 0; /* Number Of Components = 1 */
++ data[firstoffset+5] = 0;
++ data[firstoffset+6] = 0;
++ data[firstoffset+7] = 1;
++ data[firstoffset+8] = 0;
++ data[firstoffset+9] = (JOCTET)new_orient;
++ data[firstoffset+10] = 0;
++ data[firstoffset+11] = 0;
++ } else {
++ data[firstoffset+2] = 3; /* Format = unsigned short (2 octets) */
++ data[firstoffset+3] = 0;
++ data[firstoffset+4] = 1; /* Number Of Components = 1 */
++ data[firstoffset+5] = 0;
++ data[firstoffset+6] = 0;
++ data[firstoffset+7] = 0;
++ data[firstoffset+8] = (JOCTET)new_orient;
++ data[firstoffset+9] = 0;
++ data[firstoffset+10] = 0;
++ data[firstoffset+11] = 0;
++ }
++ } else if (tagnum == 0x8769) {
++ exifsuboffset = firstoffset; /* found ExifSubIFD offset Tag */
++ }
++ if (--number_of_tags == 0) break;
++ firstoffset += 12;
++ }
++ if (exifsuboffset == 0) return;
++
++ /* Get the ExifSubIFD offset */
++ if (is_motorola) {
++ if (GETJOCTET(data[exifsuboffset+8]) != 0) return;
++ if (GETJOCTET(data[exifsuboffset+9]) != 0) return;
++ offset = GETJOCTET(data[exifsuboffset+10]);
++ offset <<= 8;
++ offset += GETJOCTET(data[exifsuboffset+11]);
++ } else {
++ if (GETJOCTET(data[exifsuboffset+11]) != 0) return;
++ if (GETJOCTET(data[exifsuboffset+10]) != 0) return;
++ offset = GETJOCTET(data[exifsuboffset+9]);
++ offset <<= 8;
++ offset += GETJOCTET(data[exifsuboffset+8]);
++ }
++ if (offset > length - 2) return; /* check end of data segment */
++
++ /* Get the number of directory entries contained in this SubIFD */
++ if (is_motorola) {
++ number_of_tags = GETJOCTET(data[offset]);
++ number_of_tags <<= 8;
++ number_of_tags += GETJOCTET(data[offset+1]);
++ } else {
++ number_of_tags = GETJOCTET(data[offset+1]);
++ number_of_tags <<= 8;
++ number_of_tags += GETJOCTET(data[offset]);
++ }
++ if (number_of_tags < 2) return;
++ offset += 2;
++
++ /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
++ do {
++ if (offset > length - 12) return; /* check end of data segment */
++ /* Get Tag number */
++ if (is_motorola) {
++ tagnum = GETJOCTET(data[offset]);
++ tagnum <<= 8;
++ tagnum += GETJOCTET(data[offset+1]);
++ } else {
++ tagnum = GETJOCTET(data[offset+1]);
++ tagnum <<= 8;
++ tagnum += GETJOCTET(data[offset]);
++ }
++ if ((tagnum == 0xA002 && new_width > 0) ||
++ (tagnum == 0xA003 && new_height > 0)) {
++ if (tagnum == 0xA002)
++ new_value = new_width; /* ExifImageWidth Tag */
++ else
++ new_value = new_height; /* ExifImageHeight Tag */
++ if (is_motorola) {
++ data[offset+2] = 0; /* Format = unsigned long (4 octets) */
++ data[offset+3] = 4;
++ data[offset+4] = 0; /* Number Of Components = 1 */
++ data[offset+5] = 0;
++ data[offset+6] = 0;
++ data[offset+7] = 1;
++ data[offset+8] = 0;
++ data[offset+9] = 0;
++ data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF);
++ data[offset+11] = (JOCTET)(new_value & 0xFF);
++ } else {
++ data[offset+2] = 4; /* Format = unsigned long (4 octets) */
++ data[offset+3] = 0;
++ data[offset+4] = 1; /* Number Of Components = 1 */
++ data[offset+5] = 0;
++ data[offset+6] = 0;
++ data[offset+7] = 0;
++ data[offset+8] = (JOCTET)(new_value & 0xFF);
++ data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF);
++ data[offset+10] = 0;
++ data[offset+11] = 0;
++ }
++ }
++ offset += 12;
++ } while (--number_of_tags);
++}
++
++
+ /* Adjust output image parameters as needed.
+ *
+ * This must be called after jpeg_copy_critical_parameters()
+@@ -734,6 +922,8 @@
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info)
+ {
++ jpeg_saved_marker_ptr cur_marker; /* ptr to walk the marker list */
++
+ /* If force-to-grayscale is requested, adjust destination parameters */
+ if (info->force_grayscale) {
+ /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
+@@ -799,6 +989,28 @@
+ break;
+ }
+
++ /* Adjust Exif properties. Exif requires its APP marker to be the first
++ * one, but we allow other locations for mixed JFIF/Exif files. */
++ cur_marker = srcinfo->marker_list;
++ while (cur_marker != NULL) {
++ if (cur_marker->marker == JPEG_APP0+1 &&
++ cur_marker->data_length >= 6 &&
++ GETJOCTET(cur_marker->data[0]) == 0x45 &&
++ GETJOCTET(cur_marker->data[1]) == 0x78 &&
++ GETJOCTET(cur_marker->data[2]) == 0x69 &&
++ GETJOCTET(cur_marker->data[3]) == 0x66 &&
++ GETJOCTET(cur_marker->data[4]) == 0 &&
++ GETJOCTET(cur_marker->data[5]) == 0) {
++ /* Adjust Exif image parameters */
++ if (info->transform != JXFORM_NONE)
++ /* Align data segment to start of TIFF structure for parsing */
++ adjust_exif_parameters(cur_marker->data + 6,
++ cur_marker->data_length - 6,
++ dstinfo->image_width, dstinfo->image_height, 1);
++ }
++ cur_marker = cur_marker->next;
++ }
++
+ /* Return the appropriate output data set */
+ if (info->workspace_coef_arrays != NULL)
+ return info->workspace_coef_arrays;
+@@ -854,6 +1066,8 @@
+
+
+ /* Setup decompression object to save desired markers in memory.
++ * Unless JCOPYOPT_NONE is given, the COM and potential EXIF markers (APP1)
++ * are always saved.
+ * This must be called before jpeg_read_header() to have the desired effect.
+ */
+
+@@ -871,6 +1085,8 @@
+ if (option == JCOPYOPT_ALL) {
+ for (m = 0; m < 16; m++)
+ jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
++ } else if (option != JCOPYOPT_NONE) {
++ jpeg_save_markers(srcinfo, JPEG_APP0 + 1, 0xFFFF);
+ }
+ #endif /* SAVE_MARKERS_SUPPORTED */
+ }
+@@ -888,12 +1104,27 @@
+ {
+ jpeg_saved_marker_ptr marker;
+
+- /* In the current implementation, we don't actually need to examine the
+- * option flag here; we just copy everything that got saved.
+- * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
++ /* NOTE: to avoid confusion, we do not output JFIF and Adobe APP14 markers
+ * if the encoder library already wrote one.
+ */
++ if (option == JCOPYOPT_NONE) return;
+ for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
++ if (option == JCOPYOPT_COMMENTS &&
++ marker->marker != JPEG_COM) {
++ continue; /* only COM accpeted if JCOPYOPT_COMMENTS */
++ }
++ if (option == JCOPYOPT_EXIF &&
++ marker->marker != JPEG_COM &&
++ !(marker->marker == JPEG_APP0+1 &&
++ marker->data_length >= 6 &&
++ GETJOCTET(marker->data[0]) == 0x45 &&
++ GETJOCTET(marker->data[1]) == 0x78 &&
++ GETJOCTET(marker->data[2]) == 0x69 &&
++ GETJOCTET(marker->data[3]) == 0x66 &&
++ GETJOCTET(marker->data[4]) == 0 &&
++ GETJOCTET(marker->data[5]) == 0)) {
++ continue; /* only COM and APP1-EXIF if JCOPYOPT_EXIF */
++ }
+ if (dstinfo->write_JFIF_header &&
+ marker->marker == JPEG_APP0 &&
+ marker->data_length >= 5 &&
diff --git a/graphics/jpeg/files/patch-transupp.h b/graphics/jpeg/files/patch-transupp.h
new file mode 100644
index 000000000000..f295b2803445
--- /dev/null
+++ b/graphics/jpeg/files/patch-transupp.h
@@ -0,0 +1,12 @@
+--- transupp.h.exif 1997-07-24 04:39:12.000000000 +0200
++++ transupp.h 2003-09-25 01:05:12.000000000 +0200
+@@ -121,7 +121,8 @@
+ typedef enum {
+ JCOPYOPT_NONE, /* copy no optional markers */
+ JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */
+- JCOPYOPT_ALL /* copy all optional markers */
++ JCOPYOPT_ALL, /* copy all optional markers */
++ JCOPYOPT_EXIF /* copy Exif APP1 marker */
+ } JCOPY_OPTION;
+
+ #define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */