diff -Nru gthumb-old/components/catalog-view/Makefile.am gthumb/components/catalog-view/Makefile.am
--- gthumb-old/components/catalog-view/Makefile.am	2006-04-08 14:07:12.000000000 -0600
+++ gthumb/components/catalog-view/Makefile.am	2006-09-29 12:17:29.000000000 -0600
@@ -29,6 +29,7 @@
 
 gthumb_catalog_view_LDADD = 			\
 	$(COMPONENT_LIBS)			\
+	$(EXIF_LIBS)				\
 	$(JPEG_LIBS)				\
 	$(IPTCDATA_LIBS)			\
 	$(TIFF_LIBS)				\
diff -Nru gthumb-old/components/image-viewer/Makefile.am gthumb/components/image-viewer/Makefile.am
--- gthumb-old/components/image-viewer/Makefile.am	2006-04-08 14:07:12.000000000 -0600
+++ gthumb/components/image-viewer/Makefile.am	2006-09-29 12:17:52.000000000 -0600
@@ -34,6 +34,7 @@
 
 gthumb_image_viewer_LDADD = 			\
 	$(COMPONENT_LIBS)			\
+	$(EXIF_LIBS)				\
 	$(JPEG_LIBS)				\
 	$(IPTCDATA_LIBS)			\
 	$(TIFF_LIBS)				\
diff -Nru gthumb-old/configure.in gthumb/configure.in
--- gthumb-old/configure.in	2006-09-11 02:24:10.000000000 -0600
+++ gthumb/configure.in	2006-09-29 12:59:20.000000000 -0600
@@ -330,9 +311,9 @@
 libgthumb/Makefile
 libgthumb/cursors/Makefile
 libgthumb/icons/Makefile
+libgthumb/jpegutils/Makefile
 src/Makefile
 src/icons/Makefile
-src/jpegutils/Makefile
 components/Makefile
 components/image-viewer/Makefile
 components/catalog-view/Makefile
diff -Nru gthumb-old/libgthumb/gth-exif-utils.c gthumb/libgthumb/gth-exif-utils.c
--- gthumb-old/libgthumb/gth-exif-utils.c	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/gth-exif-utils.c	2006-03-21 09:37:43.000000000 -0700
@@ -0,0 +1,347 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#ifdef HAVE_LIBEXIF
+
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <glib.h>
+
+#include "file-utils.h"
+#include "gth-exif-utils.h"
+
+
+char *
+get_exif_tag (const char *filename,
+	      ExifTag     etag)
+{
+	ExifData     *edata;
+	unsigned int  i, j;
+
+	filename = get_file_path_from_uri (filename);
+	if (filename == NULL)
+		return g_strdup ("-");
+
+	edata = exif_data_new_from_file (filename);
+
+	if (edata == NULL) 
+		return g_strdup ("-");
+
+	for (i = 0; i < EXIF_IFD_COUNT; i++) {
+		ExifContent *content = edata->ifd[i];
+
+		if (! edata->ifd[i] || ! edata->ifd[i]->count) 
+			continue;
+
+		for (j = 0; j < content->count; j++) {
+			ExifEntry *e = content->entries[j];
+
+			if (! content->entries[j]) 
+				continue;
+
+			if (e->tag == etag) {
+				const char *value;
+				char *retval = NULL;
+
+				value = get_exif_entry_value (e);
+				if (value != NULL)
+					retval = g_locale_to_utf8 (value, -1, 0, 0, 0);
+				else
+					retval = g_strdup ("-");
+				exif_data_unref (edata);
+
+				return retval;
+			}
+		}
+	}
+
+	exif_data_unref (edata);
+
+	return g_strdup ("-");
+}
+
+
+ExifShort
+get_exif_tag_short (const char *filename,
+		    ExifTag     etag)
+{
+	ExifData     *edata;
+	unsigned int  i, j;
+
+	filename = get_file_path_from_uri (filename);
+	if (filename == NULL)
+		return 0;
+
+	edata = exif_data_new_from_file (filename);
+
+	if (edata == NULL) 
+		return 0;
+
+	for (i = 0; i < EXIF_IFD_COUNT; i++) {
+		ExifContent *content = edata->ifd[i];
+
+		if (! edata->ifd[i] || ! edata->ifd[i]->count) 
+			continue;
+
+		for (j = 0; j < content->count; j++) {
+			ExifEntry *e = content->entries[j];
+
+			if (! content->entries[j]) 
+				continue;
+
+			if (e->tag == etag) {
+				ExifByteOrder o;
+				ExifShort retval = 0;
+
+				o = exif_data_get_byte_order (e->parent->parent);
+				if (e->data != NULL)
+					retval = exif_get_short (e->data, o);
+				exif_data_unref (edata);
+
+				return retval;
+			}
+		}
+	}
+
+	exif_data_unref (edata);
+
+	return 0;
+}
+
+
+time_t
+get_exif_time (const char *filename)
+{
+	ExifData     *edata;
+	unsigned int  i, j;
+	time_t        time = 0;
+	struct tm     tm = { 0, };
+
+	filename = get_file_path_from_uri (filename);
+	if (filename == NULL)
+		return (time_t)0;
+
+	edata = exif_data_new_from_file (filename);
+
+	if (edata == NULL) 
+                return (time_t)0;
+
+	for (i = 0; i < EXIF_IFD_COUNT; i++) {
+		ExifContent *content = edata->ifd[i];
+
+		if (! edata->ifd[i] || ! edata->ifd[i]->count) 
+			continue;
+
+		for (j = 0; j < content->count; j++) {
+			ExifEntry   *e = content->entries[j];
+			char        *data;
+
+			if (! content->entries[j]) 
+				continue;
+
+			if ((e->tag != EXIF_TAG_DATE_TIME) &&
+			    (e->tag != EXIF_TAG_DATE_TIME_ORIGINAL) &&
+			    (e->tag != EXIF_TAG_DATE_TIME_DIGITIZED))
+				continue;
+
+			if (e->data == NULL)
+				continue;
+
+			if (strlen ((char*)e->data) < 10)
+				continue;
+
+			data = g_strdup ((char*)e->data);
+
+			data[4] = data[7] = data[10] = '\0';
+
+			tm.tm_year = atoi (data) - 1900;
+			tm.tm_mon  = atoi (data + 5) - 1;
+			tm.tm_mday = atoi (data + 8);
+			tm.tm_hour = 0;
+			tm.tm_min  = 0;
+			tm.tm_sec  = 0;
+			tm.tm_isdst = -1;
+
+			if (strlen ((char*)e->data) > 10) {
+				data[13] = data[16] = '\0';
+				tm.tm_hour = atoi (data + 11);
+				tm.tm_min  = atoi (data + 14);
+				tm.tm_sec  = atoi (data + 17);
+			}
+
+			time = mktime (&tm);
+
+			g_free (data);
+
+			break;
+		}
+	}
+
+	exif_data_unref (edata);
+
+	return time;
+}
+
+
+char *
+get_exif_aperture_value (const char *filename)
+{
+	ExifData     *edata;
+	unsigned int  i, j;
+
+	filename = get_file_path_from_uri (filename);
+	if (filename == NULL)
+		return g_strdup ("-");
+
+	edata = exif_data_new_from_file (filename);
+
+	if (edata == NULL) 
+		return g_strdup ("-");
+
+	for (i = 0; i < EXIF_IFD_COUNT; i++) {
+		ExifContent *content = edata->ifd[i];
+
+		if (! edata->ifd[i] || ! edata->ifd[i]->count) 
+			continue;
+
+		for (j = 0; j < content->count; j++) {
+			ExifEntry   *e = content->entries[j];
+			const char  *value = NULL;
+			char        *retval = NULL;
+
+			if (! content->entries[j]) 
+				continue;
+
+			if ((e->tag != EXIF_TAG_APERTURE_VALUE) &&
+			    (e->tag != EXIF_TAG_FNUMBER))
+				continue;
+
+			value = get_exif_entry_value (e);
+			if (value)
+				retval = g_locale_to_utf8 (value, -1, 0, 0, 0);
+			else
+				retval = g_strdup ("-");
+			exif_data_unref (edata);
+
+			return retval;
+		}
+	}
+
+	exif_data_unref (edata);
+
+	return g_strdup ("-");
+}
+
+
+gboolean 
+have_exif_time (const char *filename)
+{
+	return get_exif_time (filename) != (time_t)0;
+}
+
+
+#define VALUE_LEN 1024
+
+
+const char *
+get_exif_entry_value (ExifEntry *entry)
+{
+#ifdef HAVE_LIBEXIF_0_5
+	return exif_entry_get_value (entry);
+#else
+	char value[VALUE_LEN + 1];
+	return exif_entry_get_value (entry, value, VALUE_LEN);
+#endif
+}
+
+
+ExifData *
+load_exif_data (const char *filename)
+{
+	JPEGData *jdata = NULL;
+	ExifData *exif_data = NULL;
+
+	filename = get_file_path_from_uri (filename);
+	if (filename == NULL)
+		return NULL;
+
+	jdata = jpeg_data_new_from_file (filename);
+	if (jdata == NULL) 
+		return NULL;
+
+	exif_data = jpeg_data_get_exif_data (jdata);
+	jpeg_data_unref (jdata);
+
+	return exif_data;
+}
+
+
+void 
+save_exif_data (const char *filename,
+		ExifData   *edata)
+{
+	JPEGData *jdata;
+
+	filename = get_file_path_from_uri (filename);
+	if (filename == NULL)
+		return;
+
+	jdata = jpeg_data_new_from_file (filename);
+	if (jdata == NULL) 
+		return;
+
+	if (edata != NULL)
+		jpeg_data_set_exif_data (jdata, edata);
+
+	jpeg_data_save_file (jdata, filename);
+	jpeg_data_unref (jdata);
+}
+
+
+void 
+copy_exif_data (const char *src,
+		const char *dest)
+{
+	ExifData *edata;
+
+	if (!image_is_jpeg (src) || !image_is_jpeg (dest))
+		return;
+	src = get_file_path_from_uri (src);
+	if (src == NULL)
+		return;
+	dest = get_file_path_from_uri (dest);
+	if (dest == NULL)
+		return;
+
+	edata = exif_data_new_from_file (src);
+	if (edata == NULL) 
+		return;
+	save_exif_data (dest, edata);
+
+	exif_data_unref (edata);
+}
+
+
+#endif /* HAVE_LIBEXIF */
diff -Nru gthumb-old/libgthumb/gth-exif-utils.h gthumb/libgthumb/gth-exif-utils.h
--- gthumb-old/libgthumb/gth-exif-utils.h	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/gth-exif-utils.h	2006-03-21 09:37:43.000000000 -0700
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EXIF_UTILS_H
+#define EXIF_UTILS_H
+
+
+#include <config.h>
+
+#ifdef HAVE_LIBEXIF
+
+#include <libexif/exif-data.h>
+#include <libexif/exif-content.h>
+#include <libexif/exif-entry.h>
+#include <libexif/exif-utils.h>
+#include "jpegutils/jpeg-data.h"
+
+
+typedef enum { /*< skip >*/
+	GTH_EXIF_ORIENTATION_NONE = 0,
+	GTH_EXIF_ORIENTATION_TOP_LEFT,
+	GTH_EXIF_ORIENTATION_TOP_RIGHT,
+	GTH_EXIF_ORIENTATION_BOTTOM_RIGHT,
+	GTH_EXIF_ORIENTATION_BOTTOM_LEFT,
+	GTH_EXIF_ORIENTATION_LEFT_TOP,
+	GTH_EXIF_ORIENTATION_RIGHT_TOP,
+	GTH_EXIF_ORIENTATION_RIGHT_BOTTOM,
+	GTH_EXIF_ORIENTATION_LEFT_BOTTOM
+} GthExifOrientation;
+
+
+char *      get_exif_tag            (const char *filename,
+				     ExifTag     etag);
+ExifShort   get_exif_tag_short      (const char *filename,
+				     ExifTag     etag);
+time_t      get_exif_time           (const char *filename);
+char *      get_exif_aperture_value (const char *filename);
+gboolean    have_exif_time          (const char *filename);
+const char *get_exif_entry_value    (ExifEntry  *entry);
+ExifData *  load_exif_data          (const char *filename);
+void        save_exif_data          (const char *filename,
+				     ExifData   *edata);
+void        copy_exif_data          (const char *src,
+				     const char *dest);
+
+#endif /* HAVE_LIBEXIF */
+
+#endif /* EXIF_UTILS_H */
--- gthumb-old/libgthumb/image-loader.c	2006-08-17 10:16:45.000000000 -0600
+++ gthumb/libgthumb/image-loader.c	2006-10-05 22:34:39.000000000 -0600
@@ -37,6 +37,8 @@
 #include "gthumb-marshal.h"
 #include "file-utils.h"
 #include "glib-utils.h"
+#include "gth-exif-utils.h"
+#include "pixbuf-utils.h"
 
 
 #define REFRESH_RATE 5
@@ -405,17 +407,77 @@ image_loader_set_pixbuf (ImageLoader *il
 	g_mutex_unlock (priv->yes_or_no);
 }
 
+/*
+ * Returns an image, transformed according
+ * to the Exif orientation data.
+ */
+#ifdef HAVE_LIBEXIF 
+static GdkPixbuf *
+_gdk_pixbuf_transform_exif_orientation (GdkPixbuf* src, 
+				GthExifOrientation orientation)
+{
+	GdkPixbuf *temp = NULL, *dest = NULL;
+	
+	if (!src) return NULL;
+	
+	switch (orientation) {
+	case GTH_EXIF_ORIENTATION_TOP_LEFT:
+		dest = src;
+		g_object_ref (dest);
+		break;
+	case GTH_EXIF_ORIENTATION_TOP_RIGHT:
+		dest = _gdk_pixbuf_copy_mirror (src, TRUE, FALSE);
+		break;
+	case GTH_EXIF_ORIENTATION_BOTTOM_RIGHT:
+		dest = _gdk_pixbuf_copy_mirror (src, TRUE, TRUE);
+		break;
+	case GTH_EXIF_ORIENTATION_BOTTOM_LEFT:
+		dest = _gdk_pixbuf_copy_mirror (src, FALSE, TRUE);
+		break;
+	case GTH_EXIF_ORIENTATION_LEFT_TOP:
+		temp = _gdk_pixbuf_copy_rotate_90 (src, FALSE);
+		dest = _gdk_pixbuf_copy_mirror (temp, TRUE, FALSE);
+		g_object_unref (temp);
+		break;
+	case GTH_EXIF_ORIENTATION_RIGHT_TOP:
+		dest = _gdk_pixbuf_copy_rotate_90 (src, FALSE);
+		break;
+	case GTH_EXIF_ORIENTATION_RIGHT_BOTTOM:
+		temp = _gdk_pixbuf_copy_rotate_90 (src, FALSE);
+		dest = _gdk_pixbuf_copy_mirror (temp, FALSE, TRUE);
+		g_object_unref (temp);
+		break;
+	case GTH_EXIF_ORIENTATION_LEFT_BOTTOM:
+		dest = _gdk_pixbuf_copy_rotate_90 (src, TRUE);
+		break;
+	default:
+		dest = src;
+		g_object_ref (dest);
+		break;
+	}
+	
+	return dest;
+}
+#endif /* HAVE_LIBEXIF */
 
 static void 
 image_loader_sync_pixbuf (ImageLoader *il)
 {
 	GdkPixbuf              *pixbuf;
+	GdkPixbuf              *temp;
 	ImageLoaderPrivateData *priv;
+#ifdef HAVE_LIBEXIF        
+	GthExifOrientation     orientation;
+#endif
   
 	g_return_if_fail (il != NULL);
      
 	priv = il->priv;
 
+#ifdef HAVE_LIBEXIF        
+	orientation = get_exif_tag_short (image_loader_get_path(il), EXIF_TAG_ORIENTATION);
+#endif
+
 	g_mutex_lock (priv->yes_or_no);
 
 	if (priv->animation == NULL) {
@@ -426,8 +488,13 @@ image_loader_sync_pixbuf (ImageLoader *i
 		return;
 	}
 
+#ifdef HAVE_LIBEXIF
+	temp = gdk_pixbuf_animation_get_static_image (priv->animation);
+	pixbuf = _gdk_pixbuf_transform_exif_orientation (temp, orientation);
+#else
 	pixbuf = gdk_pixbuf_animation_get_static_image (priv->animation);
 	g_object_ref (pixbuf);
+#endif
 
 	if (priv->pixbuf == pixbuf) {
 		g_object_unref (pixbuf);

diff -Nru gthumb-old/libgthumb/jpegutils/.cvsignore gthumb/libgthumb/jpegutils/.cvsignore
--- gthumb-old/libgthumb/jpegutils/.cvsignore	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/jpegutils/.cvsignore	2002-10-06 09:40:51.000000000 -0600
@@ -0,0 +1,5 @@
+.deps
+.libs
+Makefile
+Makefile.in
+libgthumb-jpegutils.a
diff -Nru gthumb-old/libgthumb/jpegutils/jpeg-data.c gthumb/libgthumb/jpegutils/jpeg-data.c
--- gthumb-old/libgthumb/jpegutils/jpeg-data.c	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/jpegutils/jpeg-data.c	2005-08-07 04:51:42.000000000 -0600
@@ -0,0 +1,481 @@
+/* jpeg-data.c
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "config.h"
+
+#include "jpeg-data.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* #define DEBUG */
+
+#ifdef HAVE_LIBEXIF
+
+
+struct _JPEGDataPrivate
+{
+	unsigned int ref_count;
+};
+
+JPEGData *
+jpeg_data_new (void)
+{
+	JPEGData *data;
+
+	data = malloc (sizeof (JPEGData));
+	if (!data)
+		return (NULL);
+	memset (data, 0, sizeof (JPEGData));
+	data->priv = malloc (sizeof (JPEGDataPrivate));
+	if (!data->priv) {
+		free (data);
+		return (NULL);
+	}
+	memset (data->priv, 0, sizeof (JPEGDataPrivate));
+	data->priv->ref_count = 1;
+
+	return (data);
+}
+
+void
+jpeg_data_append_section (JPEGData *data)
+{
+	JPEGSection *s;
+
+	if (!data->count)
+		s = malloc (sizeof (JPEGSection));
+	else
+		s = realloc (data->sections,
+			     sizeof (JPEGSection) * (data->count + 1));
+	if (!s)
+		return;
+
+	data->sections = s;
+	data->count++;
+}
+
+/* jpeg_data_save_file returns 1 on succes, 0 on failure */
+int
+jpeg_data_save_file (JPEGData *data, const char *path)
+{
+	FILE *f;
+	unsigned char *d = NULL;
+	unsigned int size = 0, written;
+
+	jpeg_data_save_data (data, &d, &size);
+	if (!d)
+		return 0;
+
+	remove (path);
+	f = fopen (path, "wb");
+	if (!f) {
+		free (d);
+		return 0;
+	}
+	written = fwrite (d, 1, size, f);
+	fclose (f);
+	free (d);
+	if (written == size)  {
+		return 1;
+	}
+	remove(path);
+	return 0;
+}
+
+void
+jpeg_data_save_data (JPEGData *data, unsigned char **d, unsigned int *ds)
+{
+	unsigned int i, eds = 0;
+	JPEGSection s;
+	unsigned char *ed = NULL;
+
+	if (!data)
+		return;
+	if (!d)
+		return;
+	if (!ds)
+		return;
+
+	for (*ds = i = 0; i < data->count; i++) {
+		s = data->sections[i];
+#ifdef DEBUG
+		printf ("Writing marker 0x%x at position %i...\n",
+			s.marker, *ds);
+#endif
+
+		/* Write the marker */
+		*d = realloc (*d, sizeof (char) * (*ds + 2));
+		(*d)[*ds + 0] = 0xff;
+		(*d)[*ds + 1] = s.marker;
+		*ds += 2;
+
+		switch (s.marker) {
+		case JPEG_MARKER_SOI:
+		case JPEG_MARKER_EOI:
+			break;
+		case JPEG_MARKER_APP1:
+			exif_data_save_data (s.content.app1, &ed, &eds);
+			if (!ed) break;
+			*d = realloc (*d, sizeof (char) * (*ds + 2));
+			(*d)[*ds + 0] = (eds + 2) >> 8;
+			(*d)[*ds + 1] = (eds + 2) >> 0;
+			*ds += 2;
+			*d = realloc (*d, sizeof (char) * (*ds + eds));
+			memcpy (*d + *ds, ed, eds);
+			*ds += eds;
+			free (ed);
+			break;
+		default:
+			*d = realloc (*d, sizeof (char) *
+					(*ds + s.content.generic.size + 2));
+			(*d)[*ds + 0] = (s.content.generic.size + 2) >> 8;
+			(*d)[*ds + 1] = (s.content.generic.size + 2) >> 0;
+			*ds += 2;
+			memcpy (*d + *ds, s.content.generic.data,
+				s.content.generic.size);
+			*ds += s.content.generic.size;
+
+			/* In case of SOS, we need to write the data. */
+			if (s.marker == JPEG_MARKER_SOS) {
+				*d = realloc (*d, *ds + data->size);
+				memcpy (*d + *ds, data->data, data->size);
+				*ds += data->size;
+			}
+			break;
+		}
+	}
+}
+
+JPEGData *
+jpeg_data_new_from_data (const unsigned char *d,
+			 unsigned int size)
+{
+	JPEGData *data;
+
+	data = jpeg_data_new ();
+	jpeg_data_load_data (data, d, size);
+	return (data);
+}
+
+void
+jpeg_data_load_data (JPEGData *data, const unsigned char *d,
+		     unsigned int size)
+{
+	unsigned int i, o, len;
+	JPEGSection *s;
+	JPEGMarker marker;
+
+	if (!data)
+		return;
+	if (!d)
+		return;
+
+#ifdef DEBUG
+	printf ("Parsing %i bytes...\n", size);
+#endif
+
+	for (o = 0; o < size;) {
+
+		/*
+		 * JPEG sections start with 0xff. The first byte that is
+		 * not 0xff is a marker (hopefully).
+		 */
+		for (i = 0; i < 7; i++)
+			if (d[o + i] != 0xff)
+				break;
+		if (!JPEG_IS_MARKER (d[o + i]))
+			return;
+		marker = d[o + i];
+
+#ifdef DEBUG
+		printf ("Found marker 0x%x ('%s') at %i.\n", marker,
+			jpeg_marker_get_name (marker), o + i);
+#endif
+
+		/* Append this section */
+		jpeg_data_append_section (data);
+		s = &data->sections[data->count - 1];
+		s->marker = marker;
+		s->content.generic.data = NULL;
+		o += i + 1;
+
+		switch (s->marker) {
+		case JPEG_MARKER_SOI:
+		case JPEG_MARKER_EOI:
+			break;
+		default:
+
+			/* Read the length of the section */
+			len = ((d[o] << 8) | d[o + 1]) - 2;
+			if (len > size) { o = size; break; }
+			o += 2;
+			if (o + len > size) { o = size; break; }
+
+			switch (s->marker) {
+			case JPEG_MARKER_APP1:
+				s->content.app1 = exif_data_new_from_data (
+							d + o - 4, len + 4);
+				break;
+			default:
+				s->content.generic.size = len;
+				s->content.generic.data =
+						malloc (sizeof (char) * len);
+				memcpy (s->content.generic.data, &d[o], len);
+
+				/* In case of SOS, image data will follow. */
+				if (s->marker == JPEG_MARKER_SOS) {
+					data->size = size - 2 - o - len;
+					data->data = malloc (
+						sizeof (char) * data->size);
+					memcpy (data->data, d + o + len,
+						data->size);
+					o += data->size;
+				}
+				break;
+			}
+			o += len;
+			break;
+		}
+	}
+}
+
+JPEGData *
+jpeg_data_new_from_file (const char *path)
+{
+	JPEGData *data;
+
+	data = jpeg_data_new ();
+	jpeg_data_load_file (data, path);
+	return (data);
+}
+
+void
+jpeg_data_load_file (JPEGData *data, const char *path)
+{
+	FILE *f;
+	unsigned char *d;
+	unsigned int size;
+
+	if (!data)
+		return;
+	if (!path)
+		return;
+
+	f = fopen (path, "rb");
+	if (!f)
+		return;
+
+	/* For now, we read the data into memory. Patches welcome... */
+	fseek (f, 0, SEEK_END);
+	size = ftell (f);
+	fseek (f, 0, SEEK_SET);
+	d = malloc (sizeof (char) * size);
+	if (!d) {
+		fclose (f);
+		return;
+	}
+	if (fread (d, 1, size, f) != size) {
+		free (d);
+		fclose (f);
+		return;
+	}
+	fclose (f);
+
+	jpeg_data_load_data (data, d, size);
+	free (d);
+}
+
+void
+jpeg_data_ref (JPEGData *data)
+{
+	if (!data)
+		return;
+
+	data->priv->ref_count++;
+}
+
+void
+jpeg_data_unref (JPEGData *data)
+{
+	if (!data)
+		return;
+
+	data->priv->ref_count--;
+	if (!data->priv->ref_count)
+		jpeg_data_free (data);
+}
+
+void
+jpeg_data_free (JPEGData *data)
+{
+	unsigned int i;
+	JPEGSection s;
+
+	if (!data)
+		return;
+
+	if (data->count) {
+		for (i = 0; i < data->count; i++) {
+			s = data->sections[i];
+			switch (s.marker) {
+			case JPEG_MARKER_SOI:
+			case JPEG_MARKER_EOI:
+				break;
+			case JPEG_MARKER_APP1:
+				exif_data_unref (s.content.app1);
+				break;
+			default:
+				free (s.content.generic.data);
+				break;
+			}
+		}
+		free (data->sections);
+	}
+
+	if (data->data)
+		free (data->data);
+	free (data->priv);
+	free (data);
+}
+
+
+static JPEGSection *
+jpeg_data_get_section (JPEGData *data, JPEGMarker marker)
+{
+	unsigned int i;
+
+	if (!data)
+		return (NULL);
+
+	for (i = 0; i < data->count; i++)
+		if (data->sections[i].marker == marker)
+			return (&data->sections[i]);
+	return (NULL);
+}
+
+
+void
+jpeg_data_dump (JPEGData *data)
+{
+	unsigned int i;
+	JPEGContent content;
+	JPEGMarker marker;
+
+	if (!data)
+		return;
+
+	printf ("Dumping JPEG data (%i bytes of data)...\n", data->size);
+	for (i = 0; i < data->count; i++) {
+		marker = data->sections[i].marker;
+		content = data->sections[i].content;
+		printf ("Section %i (marker 0x%x - %s):\n", i, marker,
+			jpeg_marker_get_name (marker));
+		printf ("  Description: %s\n",
+			jpeg_marker_get_description (marker));
+		switch (marker) {
+                case JPEG_MARKER_SOI:
+                case JPEG_MARKER_EOI:
+			break;
+                case JPEG_MARKER_APP1:
+			exif_data_dump (content.app1);
+			break;
+                default:
+			printf ("  Size: %i\n", content.generic.size);
+                        printf ("  Unknown content.\n");
+                        break;
+                }
+        }
+}
+
+
+ExifData *
+jpeg_data_get_exif_data (JPEGData *data)
+{
+	JPEGSection *section;
+
+	if (!data)
+		return NULL;
+
+	section = jpeg_data_get_section (data, JPEG_MARKER_APP1);
+	if (section) {
+		exif_data_ref (section->content.app1);
+		return (section->content.app1);
+	}
+
+	return (NULL);
+}
+
+void
+jpeg_data_set_exif_data (JPEGData *data, ExifData *exif_data)
+{
+	JPEGSection *section;
+
+	section = jpeg_data_get_section (data, JPEG_MARKER_APP1);
+	if (!section) {
+		jpeg_data_append_section (data);
+		memmove (&data->sections[2], &data->sections[1],
+			 sizeof (JPEGSection) * (data->count - 2));
+		section = &data->sections[1];
+	} else {
+		exif_data_unref (section->content.app1);
+	}
+	section->marker = JPEG_MARKER_APP1;
+	section->content.app1 = exif_data;
+	exif_data_ref (exif_data);
+}
+
+
+void
+jpeg_data_set_header_data (JPEGData *data, JPEGMarker marker,
+			   unsigned char *buf, unsigned int size)
+{
+	JPEGSection *section;
+	int i;
+	
+	section = jpeg_data_get_section (data, marker);
+	if (!section) {
+		jpeg_data_append_section (data);
+		for (i = 0; i < data->count - 1; i++) {
+			JPEGMarker m = data->sections[i].marker;
+			if (m != JPEG_MARKER_SOI &&
+			    (m < JPEG_MARKER_APP0 ||
+			     m > JPEG_MARKER_APP15)) {
+				memmove (&data->sections[i+1],
+					 &data->sections[i],
+					 sizeof (JPEGSection) *
+					 (data->count - i - 1));
+				break;
+			}
+		}
+		section = &data->sections[i];
+	} else {
+		free (section->content.generic.data);
+	}
+
+	section->marker = marker;
+	section->content.generic.data = malloc (size);
+	memcpy (section->content.generic.data, buf, size);
+	section->content.generic.size = size;
+}
+
+
+#endif /* HAVE_LIBEXIF */
diff -Nru gthumb-old/libgthumb/jpegutils/jpeg-data.h gthumb/libgthumb/jpegutils/jpeg-data.h
--- gthumb-old/libgthumb/jpegutils/jpeg-data.h	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/jpegutils/jpeg-data.h	2005-08-07 04:51:42.000000000 -0600
@@ -0,0 +1,96 @@
+/* jpeg-data.h
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details. 
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __JPEG_DATA_H__
+#define __JPEG_DATA_H__
+
+#ifdef HAVE_LIBEXIF
+
+#include "jpeg-marker.h"
+#include <libexif/exif-data.h>
+
+typedef ExifData * JPEGContentAPP1;
+
+typedef struct _JPEGContentGeneric JPEGContentGeneric;
+struct _JPEGContentGeneric
+{
+	unsigned char *data;
+	unsigned int size;
+};
+
+typedef union _JPEGContent JPEGContent;
+union _JPEGContent
+{
+	JPEGContentGeneric generic;
+	JPEGContentAPP1    app1;
+};
+
+typedef struct _JPEGSection JPEGSection;
+struct _JPEGSection
+{
+	JPEGMarker marker;
+	JPEGContent content;
+};
+
+typedef struct _JPEGData        JPEGData;
+typedef struct _JPEGDataPrivate JPEGDataPrivate;
+
+struct _JPEGData
+{
+	JPEGSection *sections;
+	unsigned int count;
+
+	unsigned char *data;
+	unsigned int size;
+
+	JPEGDataPrivate *priv;
+};
+
+JPEGData *jpeg_data_new           (void);
+JPEGData *jpeg_data_new_from_file (const char *path);
+JPEGData *jpeg_data_new_from_data (const unsigned char *data,
+				   unsigned int size);
+
+void      jpeg_data_ref   (JPEGData *data);
+void      jpeg_data_unref (JPEGData *data);
+void      jpeg_data_free  (JPEGData *data);
+
+void      jpeg_data_load_data     (JPEGData *data, const unsigned char *d,
+				   unsigned int size);
+void      jpeg_data_save_data     (JPEGData *data, unsigned char **d,
+				   unsigned int *size);
+
+void      jpeg_data_load_file     (JPEGData *data, const char *path);
+int       jpeg_data_save_file     (JPEGData *data, const char *path);
+
+void      jpeg_data_set_exif_data (JPEGData *data, ExifData *exif_data);
+
+ExifData *jpeg_data_get_exif_data (JPEGData *data);
+
+void      jpeg_data_set_header_data (JPEGData *data, JPEGMarker marker,
+				     unsigned char * buf, unsigned int size);
+
+void      jpeg_data_dump (JPEGData *data);
+
+void      jpeg_data_append_section (JPEGData *data);
+
+#endif /* HAVE_LIBEXIF */
+
+#endif /* __JPEG_DATA_H__ */
diff -Nru gthumb-old/libgthumb/jpegutils/jpeg-marker.c gthumb/libgthumb/jpegutils/jpeg-marker.c
--- gthumb-old/libgthumb/jpegutils/jpeg-marker.c	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/jpegutils/jpeg-marker.c	2004-07-10 04:55:25.000000000 -0600
@@ -0,0 +1,122 @@
+/* jpeg-marker.c
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details. 
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "config.h"
+#include "jpeg-marker.h"
+
+#include <stdlib.h>
+
+static struct {
+        JPEGMarker marker;
+        const char *name;
+        const char *description;
+} JPEGMarkerTable[] = {
+        {JPEG_MARKER_SOF0, "SOF0", "Encoding (baseline)"},
+        {JPEG_MARKER_SOF1, "SOF1", "Encoding (extended sequential)"},
+        {JPEG_MARKER_SOF2, "SOF2", "Encoding (progressive)"},
+        {JPEG_MARKER_SOF3, "SOF3", "Encoding (lossless)"},
+        {JPEG_MARKER_SOF5, "SOF5", "Encoding (differential sequential)"},
+        {JPEG_MARKER_SOF6, "SOF6", "Encoding (differential progressive)"},
+        {JPEG_MARKER_SOF7, "SOF7", "Encoding (differential lossless)"},
+        {JPEG_MARKER_SOF9, "SOF9",
+		"Encoding (extended sequential, arithmetic)"},
+        {JPEG_MARKER_SOF10, "SOF10", "Encoding (progressive, arithmetic)"},
+        {JPEG_MARKER_SOF11, "SOF11", "Encoding (lossless, arithmetic)"},
+        {JPEG_MARKER_SOF13, "SOF13",
+		"Encoding (differential sequential, arithmetic)"},
+        {JPEG_MARKER_SOF14, "SOF14",
+		"Encoding (differential progressive, arithmetic)"},
+        {JPEG_MARKER_SOF15, "SOF15",
+		"Encoding (differential lossless, arithmetic)"},
+	{JPEG_MARKER_SOI, "SOI", "Start of image"},
+	{JPEG_MARKER_EOI, "EOI", "End of image"},
+	{JPEG_MARKER_SOS, "SOS", "Start of scan"},
+	{JPEG_MARKER_COM, "COM", "Comment"},
+	{JPEG_MARKER_DHT, "DHT", "Define Huffman table"},
+	{JPEG_MARKER_JPG, "JPG", "Extension"},
+	{JPEG_MARKER_DAC, "DAC", "Define arithmetic coding conditioning"},
+	{JPEG_MARKER_RST1, "RST1", "Restart 1"},
+	{JPEG_MARKER_RST2, "RST2", "Restart 2"},
+	{JPEG_MARKER_RST3, "RST3", "Restart 3"},
+	{JPEG_MARKER_RST4, "RST4", "Restart 4"},
+	{JPEG_MARKER_RST5, "RST5", "Restart 5"},
+	{JPEG_MARKER_RST6, "RST6", "Restart 6"},
+	{JPEG_MARKER_RST7, "RST7", "Restart 7"},
+	{JPEG_MARKER_DQT, "DQT", "Define quantization table"},
+	{JPEG_MARKER_DNL, "DNL", "Define number of lines"},
+	{JPEG_MARKER_DRI, "DRI", "Define restart interval"},
+	{JPEG_MARKER_DHP, "DHP", "Define hierarchical progression"},
+	{JPEG_MARKER_EXP, "EXP", "Expand reference component"},
+	{JPEG_MARKER_APP0, "APP0", "Application segment 0"},
+	{JPEG_MARKER_APP1, "APP1", "Application segment 1"},
+	{JPEG_MARKER_APP2, "APP2", "Application segment 2"},
+	{JPEG_MARKER_APP3, "APP3", "Application segment 3"},
+	{JPEG_MARKER_APP4, "APP4", "Application segment 4"},
+	{JPEG_MARKER_APP5, "APP5", "Application segment 5"},
+	{JPEG_MARKER_APP6, "APP6", "Application segment 6"},
+	{JPEG_MARKER_APP7, "APP7", "Application segment 7"},
+	{JPEG_MARKER_APP8, "APP8", "Application segment 8"},
+	{JPEG_MARKER_APP9, "APP9", "Application segment 9"},
+	{JPEG_MARKER_APP10, "APP10", "Application segment 10"},
+	{JPEG_MARKER_APP11, "APP11", "Application segment 11"},
+	{JPEG_MARKER_APP12, "APP12", "Application segment 12"},
+	{JPEG_MARKER_APP13, "APP13", "Application segment 13"},
+	{JPEG_MARKER_APP14, "APP14", "Application segment 14"},
+	{JPEG_MARKER_APP15, "APP15", "Application segment 15"},
+	{JPEG_MARKER_JPG0, "JPG0", "Extension 0"},
+	{JPEG_MARKER_JPG1, "JPG1", "Extension 1"},
+	{JPEG_MARKER_JPG2, "JPG2", "Extension 2"},
+	{JPEG_MARKER_JPG3, "JPG3", "Extension 3"},
+	{JPEG_MARKER_JPG4, "JPG4", "Extension 4"},
+	{JPEG_MARKER_JPG5, "JPG5", "Extension 5"},
+	{JPEG_MARKER_JPG6, "JPG6", "Extension 6"},
+	{JPEG_MARKER_JPG7, "JPG7", "Extension 7"},
+	{JPEG_MARKER_JPG8, "JPG8", "Extension 8"},
+	{JPEG_MARKER_JPG9, "JPG9", "Extension 9"},
+	{JPEG_MARKER_JPG10, "JPG10", "Extension 10"},
+	{JPEG_MARKER_JPG11, "JPG11", "Extension 11"},
+	{JPEG_MARKER_JPG12, "JPG12", "Extension 12"},
+	{JPEG_MARKER_JPG13, "JPG13", "Extension 13"},
+	{0, NULL, NULL}
+};
+
+const char *
+jpeg_marker_get_name (JPEGMarker marker)
+{
+	unsigned int i;
+
+	for (i = 0; JPEGMarkerTable[i].name; i++)
+		if (JPEGMarkerTable[i].marker == marker)
+			break;
+
+	return (JPEGMarkerTable[i].name);
+}
+
+const char *
+jpeg_marker_get_description (JPEGMarker marker)
+{
+	unsigned int i;
+
+	for (i = 0; JPEGMarkerTable[i].description; i++)
+		if (JPEGMarkerTable[i].marker == marker)
+			break;
+
+	return (JPEGMarkerTable[i].description);
+}
+
diff -Nru gthumb-old/libgthumb/jpegutils/jpeg-marker.h gthumb/libgthumb/jpegutils/jpeg-marker.h
--- gthumb-old/libgthumb/jpegutils/jpeg-marker.h	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/jpegutils/jpeg-marker.h	2004-07-10 04:55:25.000000000 -0600
@@ -0,0 +1,103 @@
+/* jpeg-marker.h
+ *
+ * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details. 
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __JPEG_MARKER_H__
+#define __JPEG_MARKER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+        JPEG_MARKER_SOF0        = 0xc0,
+        JPEG_MARKER_SOF1        = 0xc1,
+        JPEG_MARKER_SOF2        = 0xc2,
+        JPEG_MARKER_SOF3        = 0xc3,
+	JPEG_MARKER_DHT		= 0xc4,
+        JPEG_MARKER_SOF5        = 0xc5,
+        JPEG_MARKER_SOF6        = 0xc6,
+        JPEG_MARKER_SOF7        = 0xc7,
+	JPEG_MARKER_JPG		= 0xc8,
+        JPEG_MARKER_SOF9        = 0xc9,
+        JPEG_MARKER_SOF10       = 0xca,
+        JPEG_MARKER_SOF11       = 0xcb,
+	JPEG_MARKER_DAC		= 0xcc,
+        JPEG_MARKER_SOF13       = 0xcd,
+        JPEG_MARKER_SOF14       = 0xce,
+        JPEG_MARKER_SOF15       = 0xcf,
+        JPEG_MARKER_RST0	= 0xd0,
+        JPEG_MARKER_RST1	= 0xd1,
+        JPEG_MARKER_RST2	= 0xd2,
+        JPEG_MARKER_RST3	= 0xd3,
+        JPEG_MARKER_RST4	= 0xd4,
+	JPEG_MARKER_RST5	= 0xd5,
+        JPEG_MARKER_RST6	= 0xd6,
+        JPEG_MARKER_RST7	= 0xd7,
+        JPEG_MARKER_SOI         = 0xd8,
+        JPEG_MARKER_EOI         = 0xd9,
+        JPEG_MARKER_SOS         = 0xda,
+        JPEG_MARKER_DQT		= 0xdb,
+        JPEG_MARKER_DNL		= 0xdc,
+        JPEG_MARKER_DRI		= 0xdd,
+        JPEG_MARKER_DHP		= 0xde,
+        JPEG_MARKER_EXP		= 0xdf,
+	JPEG_MARKER_APP0	= 0xe0,
+        JPEG_MARKER_APP1        = 0xe1,
+	JPEG_MARKER_APP2        = 0xe2,
+	JPEG_MARKER_APP3        = 0xe3,
+	JPEG_MARKER_APP4        = 0xe4,
+	JPEG_MARKER_APP5        = 0xe5,
+	JPEG_MARKER_APP6        = 0xe6,
+	JPEG_MARKER_APP7        = 0xe7,
+	JPEG_MARKER_APP8        = 0xe8,
+	JPEG_MARKER_APP9        = 0xe9,
+	JPEG_MARKER_APP10       = 0xea,
+	JPEG_MARKER_APP11       = 0xeb,
+	JPEG_MARKER_APP12       = 0xec,
+	JPEG_MARKER_APP13       = 0xed,
+	JPEG_MARKER_APP14       = 0xee,
+	JPEG_MARKER_APP15       = 0xef,
+	JPEG_MARKER_JPG0	= 0xf0,
+	JPEG_MARKER_JPG1	= 0xf1,
+	JPEG_MARKER_JPG2	= 0xf2,
+	JPEG_MARKER_JPG3	= 0xf3,
+	JPEG_MARKER_JPG4	= 0xf4,
+	JPEG_MARKER_JPG5	= 0xf5,
+	JPEG_MARKER_JPG6	= 0xf6,
+	JPEG_MARKER_JPG7	= 0xf7,
+	JPEG_MARKER_JPG8	= 0xf8,
+	JPEG_MARKER_JPG9	= 0xf9,
+	JPEG_MARKER_JPG10	= 0xfa,
+	JPEG_MARKER_JPG11	= 0xfb,
+	JPEG_MARKER_JPG12	= 0xfc,
+	JPEG_MARKER_JPG13	= 0xfd,
+        JPEG_MARKER_COM         = 0xfe
+} JPEGMarker;
+
+#define JPEG_IS_MARKER(m) (((m) >= JPEG_MARKER_SOF0) &&		\
+			   ((m) <= JPEG_MARKER_COM))
+
+const char *jpeg_marker_get_name        (JPEGMarker marker);
+const char *jpeg_marker_get_description (JPEGMarker marker);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __JPEG_MARKER_H__ */
diff -Nru gthumb-old/libgthumb/jpegutils/jpegtran.c gthumb/libgthumb/jpegutils/jpegtran.c
--- gthumb-old/libgthumb/jpegutils/jpegtran.c	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/jpegutils/jpegtran.c	2003-08-09 10:30:00.000000000 -0600
@@ -0,0 +1,258 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2001, 2002 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+/* based upon file jpegtran.c from the libjpeg package, original copyright 
+ * note follows:
+ *
+ * jpegtran.c
+ *
+ * Copyright (C) 1995-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a command-line user interface for JPEG transcoding.
+ * It is very similar to cjpeg.c, but provides lossless transcoding between
+ * different JPEG file formats.  It also provides some lossless and sort-of-
+ * lossless transformations of JPEG data.
+ */
+
+
+#include <config.h>
+
+#ifdef HAVE_LIBJPEG
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <jpeglib.h>
+#include <glib.h>
+#include "gthumb-error.h"
+#include "file-utils.h"
+#include "transupp.h"		/* Support routines for jpegtran */
+
+
+/* error handler data */
+struct error_handler_data {
+	struct jpeg_error_mgr pub;
+	sigjmp_buf setjmp_buffer;
+        GError **error;
+	const char *filename;
+};
+
+
+static void
+fatal_error_handler (j_common_ptr cinfo)
+{
+	struct error_handler_data *errmgr;
+        char buffer[JMSG_LENGTH_MAX];
+        
+	errmgr = (struct error_handler_data *) cinfo->err;
+        
+        /* Create the message */
+        (* cinfo->err->format_message) (cinfo, buffer);
+
+        /* broken check for *error == NULL for robustness against
+         * crappy JPEG library
+         */
+        if (errmgr->error && *errmgr->error == NULL) {
+                g_set_error (errmgr->error,
+			     GTHUMB_ERROR,
+			     0,
+			     "Error interpreting JPEG image file: %s\n\n%s",
+			     file_name_from_path (errmgr->filename),
+                             buffer);
+        }
+        
+	siglongjmp (errmgr->setjmp_buffer, 1);
+
+        g_assert_not_reached ();
+}
+
+
+static void
+output_message_handler (j_common_ptr cinfo)
+{
+	/* This method keeps libjpeg from dumping crap to stderr */
+	/* do nothing */
+}
+
+
+int
+jpegtran (char         *input_filename,
+	  char         *output_filename,
+	  JXFORM_CODE   transformation,
+	  GError      **error)
+{
+	struct jpeg_decompress_struct  srcinfo;
+	struct jpeg_compress_struct    dstinfo;
+	struct error_handler_data      jsrcerr, jdsterr;
+	jpeg_transform_info            transformoption; 
+	jvirt_barray_ptr              *src_coef_arrays;
+	jvirt_barray_ptr              *dst_coef_arrays;
+	FILE                          *input_file;
+	FILE                          *output_file;
+
+	transformoption.transform = transformation;
+	transformoption.trim = FALSE;
+	transformoption.force_grayscale = FALSE;
+	
+	/* Initialize the JPEG decompression object with default error 
+	 * handling. */
+	jsrcerr.filename = input_filename;
+	srcinfo.err = jpeg_std_error (&(jsrcerr.pub));
+	jsrcerr.pub.error_exit = fatal_error_handler;
+	jsrcerr.pub.output_message = output_message_handler;
+	jsrcerr.error = error;
+
+	jpeg_create_decompress (&srcinfo);
+
+	/* Initialize the JPEG compression object with default error 
+	 * handling. */
+	jdsterr.filename = output_filename;
+	dstinfo.err = jpeg_std_error (&(jdsterr.pub));
+	jdsterr.pub.error_exit = fatal_error_handler;
+	jdsterr.pub.output_message = output_message_handler;
+	jdsterr.error = error;
+
+	jpeg_create_compress (&dstinfo);
+	
+	dstinfo.err->trace_level = 0;
+	dstinfo.arith_code = FALSE;
+	dstinfo.optimize_coding = FALSE;
+
+	jsrcerr.pub.trace_level = jdsterr.pub.trace_level;
+	srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;
+
+	/* Open the input file. */
+	input_file = fopen (input_filename, "rb");
+	if (input_file == NULL) 
+		return 1;
+
+	output_file = fopen (output_filename, "wb");
+	if (output_file == NULL) {
+		fclose (input_file);
+		return 1;
+	}
+
+	if (sigsetjmp (jsrcerr.setjmp_buffer, 1)) {
+		jpeg_destroy_compress (&dstinfo);
+		jpeg_destroy_decompress (&srcinfo);
+		return 1;
+	}
+
+	if (sigsetjmp (jdsterr.setjmp_buffer, 1)) {
+		jpeg_destroy_compress (&dstinfo);
+		jpeg_destroy_decompress (&srcinfo);
+		return 1;
+	}
+
+	/* Specify data source for decompression */
+	jpeg_stdio_src (&srcinfo, input_file);
+
+	/* Enable saving of extra markers that we want to copy */
+	jcopy_markers_setup (&srcinfo, JCOPYOPT_ALL);
+
+	/* Read file header */
+	(void) jpeg_read_header (&srcinfo, TRUE);
+
+	/* Any space needed by a transform option must be requested before
+	 * jpeg_read_coefficients so that memory allocation will be done right.
+	 */
+	jtransform_request_workspace (&srcinfo, &transformoption);
+
+	/* Read source file as DCT coefficients */
+	src_coef_arrays = jpeg_read_coefficients (&srcinfo);
+
+	/* 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.
+	 */
+	dst_coef_arrays = jtransform_adjust_parameters (&srcinfo, 
+							&dstinfo,
+							src_coef_arrays,
+							&transformoption);
+
+	/* Specify data destination for compression */
+	jpeg_stdio_dest (&dstinfo, output_file);
+
+	/* Start compressor (note no image data is actually written here) */
+	jpeg_write_coefficients (&dstinfo, dst_coef_arrays);
+
+	/* Copy to the output file any extra markers that we want to 
+	 * preserve */
+	jcopy_markers_execute (&srcinfo, &dstinfo, JCOPYOPT_ALL);
+
+	/* Execute image transformation, if any */
+	jtransform_execute_transformation (&srcinfo, 
+					   &dstinfo,
+					   src_coef_arrays,
+					   &transformoption);
+
+	/* Finish compression and release memory */
+	jpeg_finish_compress (&dstinfo);
+	jpeg_destroy_compress (&dstinfo);
+	(void) jpeg_finish_decompress (&srcinfo);
+	jpeg_destroy_decompress (&srcinfo);
+
+	/* Close files */
+	fclose (input_file);
+	fclose (output_file);
+
+	return 0;
+}
+
+
+#ifdef TEST
+
+
+int
+main (int    argc, 
+      char **argv)
+{
+	char *input_filename;
+	char *output_filename;
+
+	if (argc != 3) {
+		fprintf (stderr, "%s input_image output_image", argv[0]);
+		return 1;
+	}
+	
+	input_filename  = argv[1];
+	output_filename = argv[2];
+
+	/*
+	  JXFORM_ROT_90
+	  JXFORM_ROT_180
+	  JXFORM_ROT_270
+	  JXFORM_FLIP_H
+	  JXFORM_FLIP_V
+	*/
+	
+	return jpegtran (input_filename, output_filename, JXFORM_FLIP_H);
+}
+
+#endif /* TEST */
+
+#endif /* HAVE_LIBJPEG */
diff -Nru gthumb-old/libgthumb/jpegutils/jpegtran.h gthumb/libgthumb/jpegutils/jpegtran.h
--- gthumb-old/libgthumb/jpegutils/jpegtran.h	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/jpegutils/jpegtran.h	2003-08-04 06:32:36.000000000 -0600
@@ -0,0 +1,41 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2001, 2002 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#ifdef HAVE_LIBJPEG
+
+#ifndef JPEGTRAN_H
+#define JPEGTRAN_H
+
+#include <glib.h>
+#include "transupp.h"
+
+
+int  jpegtran (char         *input_filename,
+	       char         *output_filename,
+	       JXFORM_CODE   transformation,
+	       GError      **error);
+
+#endif /* JPEGTRAN_H */
+
+#endif /* HAVE_LIBJPEG */
diff -Nru gthumb-old/libgthumb/jpegutils/Makefile.am gthumb/libgthumb/jpegutils/Makefile.am
--- gthumb-old/libgthumb/jpegutils/Makefile.am	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/jpegutils/Makefile.am	2003-12-25 12:23:50.000000000 -0700
@@ -0,0 +1,26 @@
+if ENABLE_DEPRECATIONS
+DISABLE_DEPRECATED = -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGNOME_VFS_DISABLE_DEPRECATED -DGNOME_DISABLE_DEPRECATED -DBONOBO_DISABLE_DEPRECATED
+else
+DISABLE_DEPRECATED =
+endif
+
+INCLUDES = 				\
+	$(DISABLE_DEPRECATED)		\
+	$(EXIF_CFLAGS)			\
+	$(GTHUMB_CFLAGS)		\
+	-I$(top_srcdir)/libgthumb		
+
+
+noinst_LTLIBRARIES = libgthumb-jpegutils.la
+
+libgthumb_jpegutils_la_SOURCES =	\
+	jpeg-data.c			\
+	jpeg-data.h			\
+	jpeg-marker.c			\
+	jpeg-marker.h			\
+	jpegtran.c			\
+	jpegtran.h			\
+	transupp.c			\
+	transupp.h
+
+EXTRA_DIST = README
diff -Nru gthumb-old/libgthumb/jpegutils/README gthumb/libgthumb/jpegutils/README
--- gthumb-old/libgthumb/jpegutils/README	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/jpegutils/README	2002-10-06 09:40:54.000000000 -0600
@@ -0,0 +1,385 @@
+The Independent JPEG Group's JPEG software
+==========================================
+
+README for release 6b of 27-Mar-1998
+====================================
+
+This distribution contains the sixth public release of the Independent JPEG
+Group's free JPEG software.  You are welcome to redistribute this software and
+to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
+
+Serious users of this software (particularly those incorporating it into
+larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to
+our electronic mailing list.  Mailing list members are notified of updates
+and have a chance to participate in technical discussions, etc.
+
+This software is the work of Tom Lane, Philip Gladstone, Jim Boucher,
+Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi,
+Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG
+Group.
+
+IJG is not affiliated with the official ISO JPEG standards committee.
+
+
+DOCUMENTATION ROADMAP
+=====================
+
+This file contains the following sections:
+
+OVERVIEW            General description of JPEG and the IJG software.
+LEGAL ISSUES        Copyright, lack of warranty, terms of distribution.
+REFERENCES          Where to learn more about JPEG.
+ARCHIVE LOCATIONS   Where to find newer versions of this software.
+RELATED SOFTWARE    Other stuff you should get.
+FILE FORMAT WARS    Software *not* to get.
+TO DO               Plans for future IJG releases.
+
+Other documentation files in the distribution are:
+
+User documentation:
+  install.doc       How to configure and install the IJG software.
+  usage.doc         Usage instructions for cjpeg, djpeg, jpegtran,
+                    rdjpgcom, and wrjpgcom.
+  *.1               Unix-style man pages for programs (same info as usage.doc).
+  wizard.doc        Advanced usage instructions for JPEG wizards only.
+  change.log        Version-to-version change highlights.
+Programmer and internal documentation:
+  libjpeg.doc       How to use the JPEG library in your own programs.
+  example.c         Sample code for calling the JPEG library.
+  structure.doc     Overview of the JPEG library's internal structure.
+  filelist.doc      Road map of IJG files.
+  coderules.doc     Coding style rules --- please read if you contribute code.
+
+Please read at least the files install.doc and usage.doc.  Useful information
+can also be found in the JPEG FAQ (Frequently Asked Questions) article.  See
+ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
+
+If you want to understand how the JPEG code works, we suggest reading one or
+more of the REFERENCES, then looking at the documentation files (in roughly
+the order listed) before diving into the code.
+
+
+OVERVIEW
+========
+
+This package contains C software to implement JPEG image compression and
+decompression.  JPEG (pronounced "jay-peg") is a standardized compression
+method for full-color and gray-scale images.  JPEG is intended for compressing
+"real-world" scenes; line drawings, cartoons and other non-realistic images
+are not its strong suit.  JPEG is lossy, meaning that the output image is not
+exactly identical to the input image.  Hence you must not use JPEG if you
+have to have identical output bits.  However, on typical photographic images,
+very good compression levels can be obtained with no visible change, and
+remarkably high compression levels are possible if you can tolerate a
+low-quality image.  For more details, see the references, or just experiment
+with various compression settings.
+
+This software implements JPEG baseline, extended-sequential, and progressive
+compression processes.  Provision is made for supporting all variants of these
+processes, although some uncommon parameter settings aren't implemented yet.
+For legal reasons, we are not distributing code for the arithmetic-coding
+variants of JPEG; see LEGAL ISSUES.  We have made no provision for supporting
+the hierarchical or lossless processes defined in the standard.
+
+We provide a set of library routines for reading and writing JPEG image files,
+plus two sample applications "cjpeg" and "djpeg", which use the library to
+perform conversion between JPEG and some other popular image file formats.
+The library is intended to be reused in other applications.
+
+In order to support file conversion and viewing software, we have included
+considerable functionality beyond the bare JPEG coding/decoding capability;
+for example, the color quantization modules are not strictly part of JPEG
+decoding, but they are essential for output to colormapped file formats or
+colormapped displays.  These extra functions can be compiled out of the
+library if not required for a particular application.  We have also included
+"jpegtran", a utility for lossless transcoding between different JPEG
+processes, and "rdjpgcom" and "wrjpgcom", two simple applications for
+inserting and extracting textual comments in JFIF files.
+
+The emphasis in designing this software has been on achieving portability and
+flexibility, while also making it fast enough to be useful.  In particular,
+the software is not intended to be read as a tutorial on JPEG.  (See the
+REFERENCES section for introductory material.)  Rather, it is intended to
+be reliable, portable, industrial-strength code.  We do not claim to have
+achieved that goal in every aspect of the software, but we strive for it.
+
+We welcome the use of this software as a component of commercial products.
+No royalty is required, but we do ask for an acknowledgement in product
+documentation, as described under LEGAL ISSUES.
+
+
+LEGAL ISSUES
+============
+
+In plain English:
+
+1. We don't promise that this software works.  (But if you find any bugs,
+   please let us know!)
+2. You can use this software for whatever you want.  You don't have to pay us.
+3. You may not pretend that you wrote this software.  If you use it in a
+   program, you must acknowledge somewhere in your documentation that
+   you've used the IJG code.
+
+In legalese:
+
+The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose.  This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-1998, Thomas G. Lane.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library.  If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author's name or company name
+in advertising or publicity relating to this software or products derived from
+it.  This software may be referred to only as "the Independent JPEG Group's
+software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+
+
+ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
+sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
+ansi2knr.c is NOT covered by the above copyright and conditions, but instead
+by the usual distribution terms of the Free Software Foundation; principally,
+that you must include source code if you redistribute it.  (See the file
+ansi2knr.c for full details.)  However, since ansi2knr.c is not needed as part
+of any program generated from the IJG code, this does not limit you more than
+the foregoing paragraphs do.
+
+The Unix configuration script "configure" was produced with GNU Autoconf.
+It is copyright by the Free Software Foundation but is freely distributable.
+The same holds for its supporting scripts (config.guess, config.sub,
+ltconfig, ltmain.sh).  Another support script, install-sh, is copyright
+by M.I.T. but is also freely distributable.
+
+It appears that the arithmetic coding option of the JPEG spec is covered by
+patents owned by IBM, AT&T, and Mitsubishi.  Hence arithmetic coding cannot
+legally be used without obtaining one or more licenses.  For this reason,
+support for arithmetic coding has been removed from the free JPEG software.
+(Since arithmetic coding provides only a marginal gain over the unpatented
+Huffman mode, it is unlikely that very many implementations will support it.)
+So far as we are aware, there are no patent restrictions on the remaining
+code.
+
+The IJG distribution formerly included code to read and write GIF files.
+To avoid entanglement with the Unisys LZW patent, GIF reading support has
+been removed altogether, and the GIF writer has been simplified to produce
+"uncompressed GIFs".  This technique does not use the LZW algorithm; the
+resulting GIF files are larger than usual, but are readable by all standard
+GIF decoders.
+
+We are required to state that
+    "The Graphics Interchange Format(c) is the Copyright property of
+    CompuServe Incorporated.  GIF(sm) is a Service Mark property of
+    CompuServe Incorporated."
+
+
+REFERENCES
+==========
+
+We highly recommend reading one or more of these references before trying to
+understand the innards of the JPEG software.
+
+The best short technical introduction to the JPEG compression algorithm is
+	Wallace, Gregory K.  "The JPEG Still Picture Compression Standard",
+	Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
+(Adjacent articles in that issue discuss MPEG motion picture compression,
+applications of JPEG, and related topics.)  If you don't have the CACM issue
+handy, a PostScript file containing a revised version of Wallace's article is
+available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz.  The file (actually
+a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
+omits the sample images that appeared in CACM, but it includes corrections
+and some added material.  Note: the Wallace article is copyright ACM and IEEE,
+and it may not be used for commercial purposes.
+
+A somewhat less technical, more leisurely introduction to JPEG can be found in
+"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
+M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1.  This book provides
+good explanations and example C code for a multitude of compression methods
+including JPEG.  It is an excellent source if you are comfortable reading C
+code but don't know much about data compression in general.  The book's JPEG
+sample code is far from industrial-strength, but when you are ready to look
+at a full implementation, you've got one here...
+
+The best full description of JPEG is the textbook "JPEG Still Image Data
+Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published
+by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1.  Price US$59.95, 638 pp.
+The book includes the complete text of the ISO JPEG standards (DIS 10918-1
+and draft DIS 10918-2).  This is by far the most complete exposition of JPEG
+in existence, and we highly recommend it.
+
+The JPEG standard itself is not available electronically; you must order a
+paper copy through ISO or ITU.  (Unless you feel a need to own a certified
+official copy, we recommend buying the Pennebaker and Mitchell book instead;
+it's much cheaper and includes a great deal of useful explanatory material.)
+In the USA, copies of the standard may be ordered from ANSI Sales at (212)
+642-4900, or from Global Engineering Documents at (800) 854-7179.  (ANSI
+doesn't take credit card orders, but Global does.)  It's not cheap: as of
+1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
+shipping/handling.  The standard is divided into two parts, Part 1 being the
+actual specification, while Part 2 covers compliance testing methods.  Part 1
+is titled "Digital Compression and Coding of Continuous-tone Still Images,
+Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
+10918-1, ITU-T T.81.  Part 2 is titled "Digital Compression and Coding of
+Continuous-tone Still Images, Part 2: Compliance testing" and has document
+numbers ISO/IEC IS 10918-2, ITU-T T.83.
+
+Some extensions to the original JPEG standard are defined in JPEG Part 3,
+a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84.  IJG
+currently does not support any Part 3 extensions.
+
+The JPEG standard does not specify all details of an interchangeable file
+format.  For the omitted details we follow the "JFIF" conventions, revision
+1.02.  A copy of the JFIF spec is available from:
+	Literature Department
+	C-Cube Microsystems, Inc.
+	1778 McCarthy Blvd.
+	Milpitas, CA 95035
+	phone (408) 944-6300,  fax (408) 944-6314
+A PostScript version of this document is available by FTP at
+ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz.  There is also a plain text
+version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing
+the figures.
+
+The TIFF 6.0 file format specification can be obtained by FTP from
+ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz.  The JPEG incorporation scheme
+found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
+IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
+Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
+(Compression tag 7).  Copies of this Note can be obtained from ftp.sgi.com or
+from ftp://ftp.uu.net/graphics/jpeg/.  It is expected that the next revision
+of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
+Although IJG's own code does not support TIFF/JPEG, the free libtiff library
+uses our library to implement TIFF/JPEG per the Note.  libtiff is available
+from ftp://ftp.sgi.com/graphics/tiff/.
+
+
+ARCHIVE LOCATIONS
+=================
+
+The "official" archive site for this software is ftp.uu.net (Internet
+address 192.48.96.9).  The most recent released version can always be found
+there in directory graphics/jpeg.  This particular version will be archived
+as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz.  If you don't have
+direct Internet access, UUNET's archives are also available via UUCP; contact
+help@uunet.uu.net for information on retrieving files that way.
+
+Numerous Internet sites maintain copies of the UUNET files.  However, only
+ftp.uu.net is guaranteed to have the latest official version.
+
+You can also obtain this software in DOS-compatible "zip" archive format from
+the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or
+on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12
+"JPEG Tools".  Again, these versions may sometimes lag behind the ftp.uu.net
+release.
+
+The JPEG FAQ (Frequently Asked Questions) article is a useful source of
+general information about JPEG.  It is updated constantly and therefore is
+not included in this distribution.  The FAQ is posted every two weeks to
+Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
+It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
+and other news.answers archive sites, including the official news.answers
+archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
+If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
+with body
+	send usenet/news.answers/jpeg-faq/part1
+	send usenet/news.answers/jpeg-faq/part2
+
+
+RELATED SOFTWARE
+================
+
+Numerous viewing and image manipulation programs now support JPEG.  (Quite a
+few of them use this library to do so.)  The JPEG FAQ described above lists
+some of the more popular free and shareware viewers, and tells where to
+obtain them on Internet.
+
+If you are on a Unix machine, we highly recommend Jef Poskanzer's free
+PBMPLUS software, which provides many useful operations on PPM-format image
+files.  In particular, it can convert PPM images to and from a wide range of
+other formats, thus making cjpeg/djpeg considerably more useful.  The latest
+version is distributed by the NetPBM group, and is available from numerous
+sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/.
+Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is;
+you are likely to have difficulty making it work on any non-Unix machine.
+
+A different free JPEG implementation, written by the PVRG group at Stanford,
+is available from ftp://havefun.stanford.edu/pub/jpeg/.  This program
+is designed for research and experimentation rather than production use;
+it is slower, harder to use, and less portable than the IJG code, but it
+is easier to read and modify.  Also, the PVRG code supports lossless JPEG,
+which we do not.  (On the other hand, it doesn't do progressive JPEG.)
+
+
+FILE FORMAT WARS
+================
+
+Some JPEG programs produce files that are not compatible with our library.
+The root of the problem is that the ISO JPEG committee failed to specify a
+concrete file format.  Some vendors "filled in the blanks" on their own,
+creating proprietary formats that no one else could read.  (For example, none
+of the early commercial JPEG implementations for the Macintosh were able to
+exchange compressed files.)
+
+The file format we have adopted is called JFIF (see REFERENCES).  This format
+has been agreed to by a number of major commercial JPEG vendors, and it has
+become the de facto standard.  JFIF is a minimal or "low end" representation.
+We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF
+Technical Note #2) for "high end" applications that need to record a lot of
+additional data about an image.  TIFF/JPEG is fairly new and not yet widely
+supported, unfortunately.
+
+The upcoming JPEG Part 3 standard defines a file format called SPIFF.
+SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should
+be able to read the most common variant of SPIFF.  SPIFF has some technical
+advantages over JFIF, but its major claim to fame is simply that it is an
+official standard rather than an informal one.  At this point it is unclear
+whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto
+standard.  IJG intends to support SPIFF once the standard is frozen, but we
+have not decided whether it should become our default output format or not.
+(In any case, our decoder will remain capable of reading JFIF indefinitely.)
+
+Various proprietary file formats incorporating JPEG compression also exist.
+We have little or no sympathy for the existence of these formats.  Indeed,
+one of the original reasons for developing this free software was to help
+force convergence on common, open format standards for JPEG files.  Don't
+use a proprietary file format!
+
+
+TO DO
+=====
+
+The major thrust for v7 will probably be improvement of visual quality.
+The current method for scaling the quantization tables is known not to be
+very good at low Q values.  We also intend to investigate block boundary
+smoothing, "poor man's variable quantization", and other means of improving
+quality-vs-file-size performance without sacrificing compatibility.
+
+In future versions, we are considering supporting some of the upcoming JPEG
+Part 3 extensions --- principally, variable quantization and the SPIFF file
+format.
+
+As always, speeding things up is of great interest.
+
+Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
diff -Nru gthumb-old/libgthumb/jpegutils/transupp.c gthumb/libgthumb/jpegutils/transupp.c
--- gthumb-old/libgthumb/jpegutils/transupp.c	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/jpegutils/transupp.c	2002-11-28 07:44:00.000000000 -0700
@@ -0,0 +1,992 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2001, 2002 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+/* based upon file transupp.c from the libjpeg package, original copyright 
+ * note follows:
+.*
+ *
+ * transupp.c
+ *
+ * Copyright (C) 1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains image transformation routines and other utility code
+ * used by the jpegtran sample application.  These are NOT part of the core
+ * JPEG library.  But we keep these routines separate from jpegtran.c to
+ * ease the task of maintaining jpegtran-like programs that have other user
+ * interfaces.
+ */
+
+#include <config.h>
+
+#ifdef HAVE_LIBJPEG
+
+#define SAVE_MARKERS_SUPPORTED 1
+
+#include <stdio.h>
+#include <jpeglib.h>
+#include "transupp.h"		/* My own external interface */
+
+#ifndef MAX
+#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
+#endif
+
+enum {
+  JERR_CONVERSION_NOTIMPL
+};
+
+#define ERREXIT(cinfo,code)  \
+  ((cinfo)->err->msg_code = (code), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+
+
+static long
+jround_up (long a, long b)
+/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
+/* Assumes a >= 0, b > 0 */
+{
+  a += b - 1L;
+  return a - (a % b);
+}
+
+
+static void
+jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
+		 JDIMENSION num_blocks)
+/* Copy a row of coefficient blocks from one place to another. */
+{
+  register JCOEFPTR inptr, outptr;
+  register long count;
+
+  inptr = (JCOEFPTR) input_row;
+  outptr = (JCOEFPTR) output_row;
+  for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) {
+    *outptr++ = *inptr++;
+  }
+}
+
+
+/*
+ * Lossless image transformation routines.  These routines work on DCT
+ * coefficient arrays and thus do not require any lossy decompression
+ * or recompression of the image.
+ * Thanks to Guido Vollbeding for the initial design and code of this feature.
+ *
+ * Horizontal flipping is done in-place, using a single top-to-bottom
+ * pass through the virtual source array.  It will thus be much the
+ * fastest option for images larger than main memory.
+ *
+ * The other routines require a set of destination virtual arrays, so they
+ * need twice as much memory as jpegtran normally does.  The destination
+ * arrays are always written in normal scan order (top to bottom) because
+ * the virtual array manager expects this.  The source arrays will be scanned
+ * in the corresponding order, which means multiple passes through the source
+ * arrays for most of the transforms.  That could result in much thrashing
+ * if the image is larger than main memory.
+ *
+ * Some notes about the operating environment of the individual transform
+ * routines:
+ * 1. Both the source and destination virtual arrays are allocated from the
+ *    source JPEG object, and therefore should be manipulated by calling the
+ *    source's memory manager.
+ * 2. The destination's component count should be used.  It may be smaller
+ *    than the source's when forcing to grayscale.
+ * 3. Likewise the destination's sampling factors should be used.  When
+ *    forcing to grayscale the destination's sampling factors will be all 1,
+ *    and we may as well take that as the effective iMCU size.
+ * 4. When "trim" is in effect, the destination's dimensions will be the
+ *    trimmed values but the source's will be untrimmed.
+ * 5. All the routines assume that the source and destination buffers are
+ *    padded out to a full iMCU boundary.  This is true, although for the
+ *    source buffer it is an undocumented property of jdcoefct.c.
+ * Notes 2,3,4 boil down to this: generally we should use the destination's
+ * dimensions and ignore the source's.
+ */
+
+
+static void
+do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+	   jvirt_barray_ptr *src_coef_arrays)
+/* Horizontal flip; done in-place, so no separate dest array is required */
+{
+  JDIMENSION MCU_cols, comp_width, blk_x, blk_y;
+  int ci, k, offset_y;
+  JBLOCKARRAY buffer;
+  JCOEFPTR ptr1, ptr2;
+  JCOEF temp1, temp2;
+  jpeg_component_info *compptr;
+
+  /* Horizontal mirroring of DCT blocks is accomplished by swapping
+   * pairs of blocks in-place.  Within a DCT block, we perform horizontal
+   * mirroring by changing the signs of odd-numbered columns.
+   * Partial iMCUs at the right edge are left untouched.
+   */
+  MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+
+  for (ci = 0; ci < dstinfo->num_components; ci++) {
+    compptr = dstinfo->comp_info + ci;
+    comp_width = MCU_cols * compptr->h_samp_factor;
+    for (blk_y = 0; blk_y < compptr->height_in_blocks;
+	 blk_y += compptr->v_samp_factor) {
+      buffer = (*srcinfo->mem->access_virt_barray)
+	((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
+	 (JDIMENSION) compptr->v_samp_factor, TRUE);
+      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+	for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
+	  ptr1 = buffer[offset_y][blk_x];
+	  ptr2 = buffer[offset_y][comp_width - blk_x - 1];
+	  /* this unrolled loop doesn't need to know which row it's on... */
+	  for (k = 0; k < DCTSIZE2; k += 2) {
+	    temp1 = *ptr1;	/* swap even column */
+	    temp2 = *ptr2;
+	    *ptr1++ = temp2;
+	    *ptr2++ = temp1;
+	    temp1 = *ptr1;	/* swap odd column with sign change */
+	    temp2 = *ptr2;
+	    *ptr1++ = -temp2;
+	    *ptr2++ = -temp1;
+	  }
+	}
+      }
+    }
+  }
+}
+
+
+static void
+do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+	   jvirt_barray_ptr *src_coef_arrays,
+	   jvirt_barray_ptr *dst_coef_arrays)
+/* Vertical flip */
+{
+  JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
+  int ci, i, j, offset_y;
+  JBLOCKARRAY src_buffer, dst_buffer;
+  JBLOCKROW src_row_ptr, dst_row_ptr;
+  JCOEFPTR src_ptr, dst_ptr;
+  jpeg_component_info *compptr;
+
+  /* We output into a separate array because we can't touch different
+   * rows of the source virtual array simultaneously.  Otherwise, this
+   * is a pretty straightforward analog of horizontal flip.
+   * Within a DCT block, vertical mirroring is done by changing the signs
+   * of odd-numbered rows.
+   * Partial iMCUs at the bottom edge are copied verbatim.
+   */
+  MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+  for (ci = 0; ci < dstinfo->num_components; ci++) {
+    compptr = dstinfo->comp_info + ci;
+    comp_height = MCU_rows * compptr->v_samp_factor;
+    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+	 dst_blk_y += compptr->v_samp_factor) {
+      dst_buffer = (*srcinfo->mem->access_virt_barray)
+	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+	 (JDIMENSION) compptr->v_samp_factor, TRUE);
+      if (dst_blk_y < comp_height) {
+	/* Row is within the mirrorable area. */
+	src_buffer = (*srcinfo->mem->access_virt_barray)
+	  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+	   comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
+	   (JDIMENSION) compptr->v_samp_factor, FALSE);
+      } else {
+	/* Bottom-edge blocks will be copied verbatim. */
+	src_buffer = (*srcinfo->mem->access_virt_barray)
+	  ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
+	   (JDIMENSION) compptr->v_samp_factor, FALSE);
+      }
+      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+	if (dst_blk_y < comp_height) {
+	  /* Row is within the mirrorable area. */
+	  dst_row_ptr = dst_buffer[offset_y];
+	  src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
+	  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+	       dst_blk_x++) {
+	    dst_ptr = dst_row_ptr[dst_blk_x];
+	    src_ptr = src_row_ptr[dst_blk_x];
+	    for (i = 0; i < DCTSIZE; i += 2) {
+	      /* copy even row */
+	      for (j = 0; j < DCTSIZE; j++)
+		*dst_ptr++ = *src_ptr++;
+	      /* copy odd row with sign change */
+	      for (j = 0; j < DCTSIZE; j++)
+		*dst_ptr++ = - *src_ptr++;
+	    }
+	  }
+	} else {
+	  /* Just copy row verbatim. */
+	  jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y],
+			  compptr->width_in_blocks);
+	}
+      }
+    }
+  }
+}
+
+
+static void
+do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+	      jvirt_barray_ptr *src_coef_arrays,
+	      jvirt_barray_ptr *dst_coef_arrays)
+/* Transpose source into destination */
+{
+  JDIMENSION dst_blk_x, dst_blk_y;
+  int ci, i, j, offset_x, offset_y;
+  JBLOCKARRAY src_buffer, dst_buffer;
+  JCOEFPTR src_ptr, dst_ptr;
+  jpeg_component_info *compptr;
+
+  /* Transposing pixels within a block just requires transposing the
+   * DCT coefficients.
+   * Partial iMCUs at the edges require no special treatment; we simply
+   * process all the available DCT blocks for every component.
+   */
+  for (ci = 0; ci < dstinfo->num_components; ci++) {
+    compptr = dstinfo->comp_info + ci;
+    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+	 dst_blk_y += compptr->v_samp_factor) {
+      dst_buffer = (*srcinfo->mem->access_virt_barray)
+	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+	 (JDIMENSION) compptr->v_samp_factor, TRUE);
+      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+	     dst_blk_x += compptr->h_samp_factor) {
+	  src_buffer = (*srcinfo->mem->access_virt_barray)
+	    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
+	     (JDIMENSION) compptr->h_samp_factor, FALSE);
+	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+	    src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
+	    dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+	    for (i = 0; i < DCTSIZE; i++)
+	      for (j = 0; j < DCTSIZE; j++)
+		dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+	  }
+	}
+      }
+    }
+  }
+}
+
+
+static void
+do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+	   jvirt_barray_ptr *src_coef_arrays,
+	   jvirt_barray_ptr *dst_coef_arrays)
+/* 90 degree rotation is equivalent to
+ *   1. Transposing the image;
+ *   2. Horizontal mirroring.
+ * These two steps are merged into a single processing routine.
+ */
+{
+  JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
+  int ci, i, j, offset_x, offset_y;
+  JBLOCKARRAY src_buffer, dst_buffer;
+  JCOEFPTR src_ptr, dst_ptr;
+  jpeg_component_info *compptr;
+
+  /* Because of the horizontal mirror step, we can't process partial iMCUs
+   * at the (output) right edge properly.  They just get transposed and
+   * not mirrored.
+   */
+  MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+
+  for (ci = 0; ci < dstinfo->num_components; ci++) {
+    compptr = dstinfo->comp_info + ci;
+    comp_width = MCU_cols * compptr->h_samp_factor;
+    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+	 dst_blk_y += compptr->v_samp_factor) {
+      dst_buffer = (*srcinfo->mem->access_virt_barray)
+	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+	 (JDIMENSION) compptr->v_samp_factor, TRUE);
+      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+	     dst_blk_x += compptr->h_samp_factor) {
+	  src_buffer = (*srcinfo->mem->access_virt_barray)
+	    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
+	     (JDIMENSION) compptr->h_samp_factor, FALSE);
+	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+	    src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
+	    if (dst_blk_x < comp_width) {
+	      /* Block is within the mirrorable area. */
+	      dst_ptr = dst_buffer[offset_y]
+		[comp_width - dst_blk_x - offset_x - 1];
+	      for (i = 0; i < DCTSIZE; i++) {
+		for (j = 0; j < DCTSIZE; j++)
+		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+		i++;
+		for (j = 0; j < DCTSIZE; j++)
+		  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+	      }
+	    } else {
+	      /* Edge blocks are transposed but not mirrored. */
+	      dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+	      for (i = 0; i < DCTSIZE; i++)
+		for (j = 0; j < DCTSIZE; j++)
+		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+	    }
+	  }
+	}
+      }
+    }
+  }
+}
+
+
+static void
+do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+	    jvirt_barray_ptr *src_coef_arrays,
+	    jvirt_barray_ptr *dst_coef_arrays)
+/* 270 degree rotation is equivalent to
+ *   1. Horizontal mirroring;
+ *   2. Transposing the image.
+ * These two steps are merged into a single processing routine.
+ */
+{
+  JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
+  int ci, i, j, offset_x, offset_y;
+  JBLOCKARRAY src_buffer, dst_buffer;
+  JCOEFPTR src_ptr, dst_ptr;
+  jpeg_component_info *compptr;
+
+  /* Because of the horizontal mirror step, we can't process partial iMCUs
+   * at the (output) bottom edge properly.  They just get transposed and
+   * not mirrored.
+   */
+  MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+  for (ci = 0; ci < dstinfo->num_components; ci++) {
+    compptr = dstinfo->comp_info + ci;
+    comp_height = MCU_rows * compptr->v_samp_factor;
+    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+	 dst_blk_y += compptr->v_samp_factor) {
+      dst_buffer = (*srcinfo->mem->access_virt_barray)
+	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+	 (JDIMENSION) compptr->v_samp_factor, TRUE);
+      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+	     dst_blk_x += compptr->h_samp_factor) {
+	  src_buffer = (*srcinfo->mem->access_virt_barray)
+	    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
+	     (JDIMENSION) compptr->h_samp_factor, FALSE);
+	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+	    dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+	    if (dst_blk_y < comp_height) {
+	      /* Block is within the mirrorable area. */
+	      src_ptr = src_buffer[offset_x]
+		[comp_height - dst_blk_y - offset_y - 1];
+	      for (i = 0; i < DCTSIZE; i++) {
+		for (j = 0; j < DCTSIZE; j++) {
+		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+		  j++;
+		  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+		}
+	      }
+	    } else {
+	      /* Edge blocks are transposed but not mirrored. */
+	      src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
+	      for (i = 0; i < DCTSIZE; i++)
+		for (j = 0; j < DCTSIZE; j++)
+		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+	    }
+	  }
+	}
+      }
+    }
+  }
+}
+
+
+static void
+do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+	    jvirt_barray_ptr *src_coef_arrays,
+	    jvirt_barray_ptr *dst_coef_arrays)
+/* 180 degree rotation is equivalent to
+ *   1. Vertical mirroring;
+ *   2. Horizontal mirroring.
+ * These two steps are merged into a single processing routine.
+ */
+{
+  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
+  int ci, i, j, offset_y;
+  JBLOCKARRAY src_buffer, dst_buffer;
+  JBLOCKROW src_row_ptr, dst_row_ptr;
+  JCOEFPTR src_ptr, dst_ptr;
+  jpeg_component_info *compptr;
+
+  MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+  MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+  for (ci = 0; ci < dstinfo->num_components; ci++) {
+    compptr = dstinfo->comp_info + ci;
+    comp_width = MCU_cols * compptr->h_samp_factor;
+    comp_height = MCU_rows * compptr->v_samp_factor;
+    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+	 dst_blk_y += compptr->v_samp_factor) {
+      dst_buffer = (*srcinfo->mem->access_virt_barray)
+	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+	 (JDIMENSION) compptr->v_samp_factor, TRUE);
+      if (dst_blk_y < comp_height) {
+	/* Row is within the vertically mirrorable area. */
+	src_buffer = (*srcinfo->mem->access_virt_barray)
+	  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+	   comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
+	   (JDIMENSION) compptr->v_samp_factor, FALSE);
+      } else {
+	/* Bottom-edge rows are only mirrored horizontally. */
+	src_buffer = (*srcinfo->mem->access_virt_barray)
+	  ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
+	   (JDIMENSION) compptr->v_samp_factor, FALSE);
+      }
+      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+	if (dst_blk_y < comp_height) {
+	  /* Row is within the mirrorable area. */
+	  dst_row_ptr = dst_buffer[offset_y];
+	  src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
+	  /* Process the blocks that can be mirrored both ways. */
+	  for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
+	    dst_ptr = dst_row_ptr[dst_blk_x];
+	    src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
+	    for (i = 0; i < DCTSIZE; i += 2) {
+	      /* For even row, negate every odd column. */
+	      for (j = 0; j < DCTSIZE; j += 2) {
+		*dst_ptr++ = *src_ptr++;
+		*dst_ptr++ = - *src_ptr++;
+	      }
+	      /* For odd row, negate every even column. */
+	      for (j = 0; j < DCTSIZE; j += 2) {
+		*dst_ptr++ = - *src_ptr++;
+		*dst_ptr++ = *src_ptr++;
+	      }
+	    }
+	  }
+	  /* Any remaining right-edge blocks are only mirrored vertically. */
+	  for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
+	    dst_ptr = dst_row_ptr[dst_blk_x];
+	    src_ptr = src_row_ptr[dst_blk_x];
+	    for (i = 0; i < DCTSIZE; i += 2) {
+	      for (j = 0; j < DCTSIZE; j++)
+		*dst_ptr++ = *src_ptr++;
+	      for (j = 0; j < DCTSIZE; j++)
+		*dst_ptr++ = - *src_ptr++;
+	    }
+	  }
+	} else {
+	  /* Remaining rows are just mirrored horizontally. */
+	  dst_row_ptr = dst_buffer[offset_y];
+	  src_row_ptr = src_buffer[offset_y];
+	  /* Process the blocks that can be mirrored. */
+	  for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
+	    dst_ptr = dst_row_ptr[dst_blk_x];
+	    src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
+	    for (i = 0; i < DCTSIZE2; i += 2) {
+	      *dst_ptr++ = *src_ptr++;
+	      *dst_ptr++ = - *src_ptr++;
+	    }
+	  }
+	  /* Any remaining right-edge blocks are only copied. */
+	  for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
+	    dst_ptr = dst_row_ptr[dst_blk_x];
+	    src_ptr = src_row_ptr[dst_blk_x];
+	    for (i = 0; i < DCTSIZE2; i++)
+	      *dst_ptr++ = *src_ptr++;
+	  }
+	}
+      }
+    }
+  }
+}
+
+
+static void
+do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+	       jvirt_barray_ptr *src_coef_arrays,
+	       jvirt_barray_ptr *dst_coef_arrays)
+/* Transverse transpose is equivalent to
+ *   1. 180 degree rotation;
+ *   2. Transposition;
+ * or
+ *   1. Horizontal mirroring;
+ *   2. Transposition;
+ *   3. Horizontal mirroring.
+ * These steps are merged into a single processing routine.
+ */
+{
+  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
+  int ci, i, j, offset_x, offset_y;
+  JBLOCKARRAY src_buffer, dst_buffer;
+  JCOEFPTR src_ptr, dst_ptr;
+  jpeg_component_info *compptr;
+
+  MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+  MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+  for (ci = 0; ci < dstinfo->num_components; ci++) {
+    compptr = dstinfo->comp_info + ci;
+    comp_width = MCU_cols * compptr->h_samp_factor;
+    comp_height = MCU_rows * compptr->v_samp_factor;
+    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+	 dst_blk_y += compptr->v_samp_factor) {
+      dst_buffer = (*srcinfo->mem->access_virt_barray)
+	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+	 (JDIMENSION) compptr->v_samp_factor, TRUE);
+      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+	     dst_blk_x += compptr->h_samp_factor) {
+	  src_buffer = (*srcinfo->mem->access_virt_barray)
+	    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
+	     (JDIMENSION) compptr->h_samp_factor, FALSE);
+	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+	    if (dst_blk_y < comp_height) {
+	      src_ptr = src_buffer[offset_x]
+		[comp_height - dst_blk_y - offset_y - 1];
+	      if (dst_blk_x < comp_width) {
+		/* Block is within the mirrorable area. */
+		dst_ptr = dst_buffer[offset_y]
+		  [comp_width - dst_blk_x - offset_x - 1];
+		for (i = 0; i < DCTSIZE; i++) {
+		  for (j = 0; j < DCTSIZE; j++) {
+		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+		    j++;
+		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+		  }
+		  i++;
+		  for (j = 0; j < DCTSIZE; j++) {
+		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+		    j++;
+		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+		  }
+		}
+	      } else {
+		/* Right-edge blocks are mirrored in y only */
+		dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+		for (i = 0; i < DCTSIZE; i++) {
+		  for (j = 0; j < DCTSIZE; j++) {
+		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+		    j++;
+		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+		  }
+		}
+	      }
+	    } else {
+	      src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
+	      if (dst_blk_x < comp_width) {
+		/* Bottom-edge blocks are mirrored in x only */
+		dst_ptr = dst_buffer[offset_y]
+		  [comp_width - dst_blk_x - offset_x - 1];
+		for (i = 0; i < DCTSIZE; i++) {
+		  for (j = 0; j < DCTSIZE; j++)
+		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+		  i++;
+		  for (j = 0; j < DCTSIZE; j++)
+		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+		}
+	      } else {
+		/* At lower right corner, just transpose, no mirroring */
+		dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+		for (i = 0; i < DCTSIZE; i++)
+		  for (j = 0; j < DCTSIZE; j++)
+		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+	      }
+	    }
+	  }
+	}
+      }
+    }
+  }
+}
+
+
+/* Request any required workspace.
+ *
+ * We allocate the workspace virtual arrays from the source decompression
+ * object, so that all the arrays (both the original data and the workspace)
+ * will be taken into account while making memory management decisions.
+ * Hence, this routine must be called after jpeg_read_header (which reads
+ * the image dimensions) and before jpeg_read_coefficients (which realizes
+ * the source's virtual arrays).
+ */
+
+void
+jtransform_request_workspace (j_decompress_ptr srcinfo,
+			      jpeg_transform_info *info)
+{
+  jvirt_barray_ptr *coef_arrays = NULL;
+  jpeg_component_info *compptr;
+  int ci;
+
+  if (info->force_grayscale &&
+      srcinfo->jpeg_color_space == JCS_YCbCr &&
+      srcinfo->num_components == 3) {
+    /* We'll only process the first component */
+    info->num_components = 1;
+  } else {
+    /* Process all the components */
+    info->num_components = srcinfo->num_components;
+  }
+
+  switch (info->transform) {
+  case JXFORM_NONE:
+  case JXFORM_FLIP_H:
+    /* Don't need a workspace array */
+    break;
+  case JXFORM_FLIP_V:
+  case JXFORM_ROT_180:
+    /* Need workspace arrays having same dimensions as source image.
+     * Note that we allocate arrays padded out to the next iMCU boundary,
+     * so that transform routines need not worry about missing edge blocks.
+     */
+    coef_arrays = (jvirt_barray_ptr *)
+      (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
+	sizeof(jvirt_barray_ptr) * info->num_components);
+    for (ci = 0; ci < info->num_components; ci++) {
+      compptr = srcinfo->comp_info + ci;
+      coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
+	((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
+	 (JDIMENSION) jround_up((long) compptr->width_in_blocks,
+				(long) compptr->h_samp_factor),
+	 (JDIMENSION) jround_up((long) compptr->height_in_blocks,
+				(long) compptr->v_samp_factor),
+	 (JDIMENSION) compptr->v_samp_factor);
+    }
+    break;
+  case JXFORM_TRANSPOSE:
+  case JXFORM_TRANSVERSE:
+  case JXFORM_ROT_90:
+  case JXFORM_ROT_270:
+    /* Need workspace arrays having transposed dimensions.
+     * Note that we allocate arrays padded out to the next iMCU boundary,
+     * so that transform routines need not worry about missing edge blocks.
+     */
+    coef_arrays = (jvirt_barray_ptr *)
+      (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
+	sizeof(jvirt_barray_ptr) * info->num_components);
+    for (ci = 0; ci < info->num_components; ci++) {
+      compptr = srcinfo->comp_info + ci;
+      coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
+	((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
+	 (JDIMENSION) jround_up((long) compptr->height_in_blocks,
+				(long) compptr->v_samp_factor),
+	 (JDIMENSION) jround_up((long) compptr->width_in_blocks,
+				(long) compptr->h_samp_factor),
+	 (JDIMENSION) compptr->h_samp_factor);
+    }
+    break;
+  }
+  info->workspace_coef_arrays = coef_arrays;
+}
+
+
+/* Transpose destination image parameters */
+
+static void
+transpose_critical_parameters (j_compress_ptr dstinfo)
+{
+  int tblno, i, j, ci, itemp;
+  jpeg_component_info *compptr;
+  JQUANT_TBL *qtblptr;
+  JDIMENSION dtemp;
+  UINT16 qtemp;
+
+  /* Transpose basic image dimensions */
+  dtemp = dstinfo->image_width;
+  dstinfo->image_width = dstinfo->image_height;
+  dstinfo->image_height = dtemp;
+
+  /* Transpose sampling factors */
+  for (ci = 0; ci < dstinfo->num_components; ci++) {
+    compptr = dstinfo->comp_info + ci;
+    itemp = compptr->h_samp_factor;
+    compptr->h_samp_factor = compptr->v_samp_factor;
+    compptr->v_samp_factor = itemp;
+  }
+
+  /* Transpose quantization tables */
+  for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
+    qtblptr = dstinfo->quant_tbl_ptrs[tblno];
+    if (qtblptr != NULL) {
+      for (i = 0; i < DCTSIZE; i++) {
+	for (j = 0; j < i; j++) {
+	  qtemp = qtblptr->quantval[i*DCTSIZE+j];
+	  qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
+	  qtblptr->quantval[j*DCTSIZE+i] = qtemp;
+	}
+      }
+    }
+  }
+}
+
+
+/* Trim off any partial iMCUs on the indicated destination edge */
+
+static void
+trim_right_edge (j_compress_ptr dstinfo)
+{
+  int ci, max_h_samp_factor;
+  JDIMENSION MCU_cols;
+
+  /* We have to compute max_h_samp_factor ourselves,
+   * because it hasn't been set yet in the destination
+   * (and we don't want to use the source's value).
+   */
+  max_h_samp_factor = 1;
+  for (ci = 0; ci < dstinfo->num_components; ci++) {
+    int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor;
+    max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor);
+  }
+  MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE);
+  if (MCU_cols > 0)		/* can't trim to 0 pixels */
+    dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE);
+}
+
+static void
+trim_bottom_edge (j_compress_ptr dstinfo)
+{
+  int ci, max_v_samp_factor;
+  JDIMENSION MCU_rows;
+
+  /* We have to compute max_v_samp_factor ourselves,
+   * because it hasn't been set yet in the destination
+   * (and we don't want to use the source's value).
+   */
+  max_v_samp_factor = 1;
+  for (ci = 0; ci < dstinfo->num_components; ci++) {
+    int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor;
+    max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor);
+  }
+  MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE);
+  if (MCU_rows > 0)		/* can't trim to 0 pixels */
+    dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE);
+}
+
+
+/* Adjust output image parameters as needed.
+ *
+ * This must be called after jpeg_copy_critical_parameters()
+ * and before jpeg_write_coefficients().
+ *
+ * The return value is the set of virtual coefficient arrays to be written
+ * (either the ones allocated by jtransform_request_workspace, or the
+ * original source data arrays).  The caller will need to pass this value
+ * to jpeg_write_coefficients().
+ */
+
+jvirt_barray_ptr *
+jtransform_adjust_parameters (j_decompress_ptr srcinfo,
+			      j_compress_ptr dstinfo,
+			      jvirt_barray_ptr *src_coef_arrays,
+			      jpeg_transform_info *info)
+{
+  /* 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
+     * properly.  Among other things, the target h_samp_factor & v_samp_factor
+     * will get set to 1, which typically won't match the source.
+     * In fact we do this even if the source is already grayscale; that
+     * provides an easy way of coercing a grayscale JPEG with funny sampling
+     * factors to the customary 1,1.  (Some decoders fail on other factors.)
+     */
+    if ((dstinfo->jpeg_color_space == JCS_YCbCr &&
+	 dstinfo->num_components == 3) ||
+	(dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
+	 dstinfo->num_components == 1)) {
+      /* We have to preserve the source's quantization table number. */
+      int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
+      jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
+      dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
+    } else {
+      /* Sorry, can't do it */
+      ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
+    }
+  }
+
+  /* Correct the destination's image dimensions etc if necessary */
+  switch (info->transform) {
+  case JXFORM_NONE:
+    /* Nothing to do */
+    break;
+  case JXFORM_FLIP_H:
+    if (info->trim)
+      trim_right_edge(dstinfo);
+    break;
+  case JXFORM_FLIP_V:
+    if (info->trim)
+      trim_bottom_edge(dstinfo);
+    break;
+  case JXFORM_TRANSPOSE:
+    transpose_critical_parameters(dstinfo);
+    /* transpose does NOT have to trim anything */
+    break;
+  case JXFORM_TRANSVERSE:
+    transpose_critical_parameters(dstinfo);
+    if (info->trim) {
+      trim_right_edge(dstinfo);
+      trim_bottom_edge(dstinfo);
+    }
+    break;
+  case JXFORM_ROT_90:
+    transpose_critical_parameters(dstinfo);
+    if (info->trim)
+      trim_right_edge(dstinfo);
+    break;
+  case JXFORM_ROT_180:
+    if (info->trim) {
+      trim_right_edge(dstinfo);
+      trim_bottom_edge(dstinfo);
+    }
+    break;
+  case JXFORM_ROT_270:
+    transpose_critical_parameters(dstinfo);
+    if (info->trim)
+      trim_bottom_edge(dstinfo);
+    break;
+  }
+
+  /* Return the appropriate output data set */
+  if (info->workspace_coef_arrays != NULL)
+    return info->workspace_coef_arrays;
+  return src_coef_arrays;
+}
+
+
+/* Execute the actual transformation, if any.
+ *
+ * This must be called *after* jpeg_write_coefficients, because it depends
+ * on jpeg_write_coefficients to have computed subsidiary values such as
+ * the per-component width and height fields in the destination object.
+ *
+ * Note that some transformations will modify the source data arrays!
+ */
+
+void
+jtransform_execute_transformation (j_decompress_ptr srcinfo,
+				   j_compress_ptr dstinfo,
+				   jvirt_barray_ptr *src_coef_arrays,
+				   jpeg_transform_info *info)
+{
+  jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
+
+  switch (info->transform) {
+  case JXFORM_NONE:
+    break;
+  case JXFORM_FLIP_H:
+    do_flip_h(srcinfo, dstinfo, src_coef_arrays);
+    break;
+  case JXFORM_FLIP_V:
+    do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+    break;
+  case JXFORM_TRANSPOSE:
+    do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+    break;
+  case JXFORM_TRANSVERSE:
+    do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+    break;
+  case JXFORM_ROT_90:
+    do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+    break;
+  case JXFORM_ROT_180:
+    do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+    break;
+  case JXFORM_ROT_270:
+    do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+    break;
+  }
+}
+
+
+/* Setup decompression object to save desired markers in memory.
+ * This must be called before jpeg_read_header() to have the desired effect.
+ */
+
+void
+jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
+{
+#ifdef SAVE_MARKERS_SUPPORTED
+  int m;
+
+  /* Save comments except under NONE option */
+  if (option != JCOPYOPT_NONE) {
+    jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
+  }
+  /* Save all types of APPn markers iff ALL option */
+  if (option == JCOPYOPT_ALL) {
+    for (m = 0; m < 16; m++)
+      jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
+  }
+#endif /* SAVE_MARKERS_SUPPORTED */
+}
+
+/* Copy markers saved in the given source object to the destination object.
+ * This should be called just after jpeg_start_compress() or
+ * jpeg_write_coefficients().
+ * Note that those routines will have written the SOI, and also the
+ * JFIF APP0 or Adobe APP14 markers if selected.
+ */
+
+void
+jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+		       JCOPY_OPTION option)
+{
+  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
+   * if the encoder library already wrote one.
+   */
+  for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
+    if (dstinfo->write_JFIF_header &&
+	marker->marker == JPEG_APP0 &&
+	marker->data_length >= 5 &&
+	GETJOCTET(marker->data[0]) == 0x4A &&
+	GETJOCTET(marker->data[1]) == 0x46 &&
+	GETJOCTET(marker->data[2]) == 0x49 &&
+	GETJOCTET(marker->data[3]) == 0x46 &&
+	GETJOCTET(marker->data[4]) == 0)
+      continue;			/* reject duplicate JFIF */
+    if (dstinfo->write_Adobe_marker &&
+	marker->marker == JPEG_APP0+14 &&
+	marker->data_length >= 5 &&
+	GETJOCTET(marker->data[0]) == 0x41 &&
+	GETJOCTET(marker->data[1]) == 0x64 &&
+	GETJOCTET(marker->data[2]) == 0x6F &&
+	GETJOCTET(marker->data[3]) == 0x62 &&
+	GETJOCTET(marker->data[4]) == 0x65)
+      continue;			/* reject duplicate Adobe */
+
+#ifdef NEED_FAR_POINTERS
+    /* We could use jpeg_write_marker if the data weren't FAR... */
+    {
+      unsigned int i;
+      jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
+      for (i = 0; i < marker->data_length; i++)
+	jpeg_write_m_byte(dstinfo, marker->data[i]);
+    }
+#else
+    jpeg_write_marker(dstinfo, marker->marker,
+		      marker->data, marker->data_length);
+#endif
+  }
+}
+
+
+#endif /* HAVE_LIBJPEG */
diff -Nru gthumb-old/libgthumb/jpegutils/transupp.h gthumb/libgthumb/jpegutils/transupp.h
--- gthumb-old/libgthumb/jpegutils/transupp.h	1969-12-31 17:00:00.000000000 -0700
+++ gthumb/libgthumb/jpegutils/transupp.h	2003-08-24 09:21:17.000000000 -0600
@@ -0,0 +1,157 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2001, 2002 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+/* based upon file transupp.h from the libjpeg package, original copyright 
+ * note follows:
+ *
+ * transupp.h
+ *
+ * Copyright (C) 1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains declarations for image transformation routines and
+ * other utility code used by the jpegtran sample application.  These are
+ * NOT part of the core JPEG library.  But we keep these routines separate
+ * from jpegtran.c to ease the task of maintaining jpegtran-like programs
+ * that have other user interfaces.
+ *
+ * NOTE: all the routines declared here have very specific requirements
+ * about when they are to be executed during the reading and writing of the
+ * source and destination files.  See the comments in transupp.c, or see
+ * jpegtran.c for an example of correct usage.
+ */
+
+/*
+ * Codes for supported types of image transformations.
+ */
+
+#ifdef HAVE_LIBJPEG
+
+
+#ifndef TRANSUPP_H
+#define TRANSUPP_H
+
+#include <jpeglib.h>
+
+
+typedef enum {
+	JXFORM_NONE,		/* no transformation */
+	JXFORM_FLIP_H,		/* horizontal flip */
+	JXFORM_FLIP_V,		/* vertical flip */
+	JXFORM_TRANSPOSE,	/* transpose across UL-to-LR axis */
+	JXFORM_TRANSVERSE,	/* transpose across UR-to-LL axis */
+	JXFORM_ROT_90,		/* 90-degree clockwise rotation */
+	JXFORM_ROT_180,		/* 180-degree rotation */
+	JXFORM_ROT_270		/* 270-degree clockwise (or 90 ccw) */
+} JXFORM_CODE;
+
+/*
+ * Although rotating and flipping data expressed as DCT coefficients is not
+ * hard, there is an asymmetry in the JPEG format specification for images
+ * whose dimensions aren't multiples of the iMCU size.  The right and bottom
+ * image edges are padded out to the next iMCU boundary with junk data; but
+ * no padding is possible at the top and left edges.  If we were to flip
+ * the whole image including the pad data, then pad garbage would become
+ * visible at the top and/or left, and real pixels would disappear into the
+ * pad margins --- perhaps permanently, since encoders & decoders may not
+ * bother to preserve DCT blocks that appear to be completely outside the
+ * nominal image area.  So, we have to exclude any partial iMCUs from the
+ * basic transformation.
+ *
+ * Transpose is the only transformation that can handle partial iMCUs at the
+ * right and bottom edges completely cleanly.  flip_h can flip partial iMCUs
+ * at the bottom, but leaves any partial iMCUs at the right edge untouched.
+ * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched.
+ * The other transforms are defined as combinations of these basic transforms
+ * and process edge blocks in a way that preserves the equivalence.
+ *
+ * The "trim" option causes untransformable partial iMCUs to be dropped;
+ * this is not strictly lossless, but it usually gives the best-looking
+ * result for odd-size images.  Note that when this option is active,
+ * the expected mathematical equivalences between the transforms may not hold.
+ * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim
+ * followed by -rot 180 -trim trims both edges.)
+ *
+ * We also offer a "force to grayscale" option, which simply discards the
+ * chrominance channels of a YCbCr image.  This is lossless in the sense that
+ * the luminance channel is preserved exactly.  It's not the same kind of
+ * thing as the rotate/flip transformations, but it's convenient to handle it
+ * as part of this package, mainly because the transformation routines have to
+ * be aware of the option to know how many components to work on.
+ */
+
+typedef struct {
+  /* Options: set by caller */
+  JXFORM_CODE transform;	/* image transform operator */
+  boolean trim;			/* if TRUE, trim partial MCUs as needed */
+  boolean force_grayscale;	/* if TRUE, convert color image to grayscale */
+
+  /* Internal workspace: caller should not touch these */
+  int num_components;		/* # of components in workspace */
+  jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */
+} jpeg_transform_info;
+
+
+/* Request any required workspace */
+void jtransform_request_workspace   (j_decompress_ptr     srcinfo, 
+				     jpeg_transform_info *info);
+
+/* Adjust output image parameters */
+
+jvirt_barray_ptr * jtransform_adjust_parameters (j_decompress_ptr     srcinfo, 
+						 j_compress_ptr       dstinfo,
+						 jvirt_barray_ptr    *src_coef_arrays,
+						 jpeg_transform_info *info);
+
+/* Execute the actual transformation, if any */
+void jtransform_execute_transformation (j_decompress_ptr     srcinfo, 
+					j_compress_ptr       dstinfo,
+					jvirt_barray_ptr    *src_coef_arrays,
+					jpeg_transform_info *info);
+
+
+/*
+ * Support for copying optional markers from source to destination file.
+ */
+
+typedef enum {
+	JCOPYOPT_NONE,		/* copy no optional markers */
+	JCOPYOPT_COMMENTS,	/* copy only comment (COM) markers */
+	JCOPYOPT_ALL		/* copy all optional markers */
+} JCOPY_OPTION;
+
+#define JCOPYOPT_DEFAULT  JCOPYOPT_COMMENTS	/* recommended default */
+
+/* Setup decompression object to save desired markers in memory */
+void jcopy_markers_setup (j_decompress_ptr srcinfo, 
+			  JCOPY_OPTION     option);
+
+/* Copy markers saved in the given source object to the destination object */
+void jcopy_markers_execute (j_decompress_ptr srcinfo, 
+			    j_compress_ptr   dstinfo,
+			    JCOPY_OPTION     option);
+
+
+#endif /* TRANSUPP_H */
+
+#endif /* HAVE_LIBJPEG */
diff -Nru gthumb-old/libgthumb/Makefile.am gthumb/libgthumb/Makefile.am
--- gthumb-old/libgthumb/Makefile.am	2006-08-14 01:25:04.000000000 -0600
+++ gthumb/libgthumb/Makefile.am	2006-09-29 12:57:17.000000000 -0600
@@ -1,5 +1,5 @@
-SUBDIRS = icons cursors
-DIST_SUBDIRS = icons cursors
+SUBDIRS = icons cursors jpegutils
+DIST_SUBDIRS = icons cursors jpegutils
 
 if ENABLE_DEPRECATIONS
 DISABLE_DEPRECATED = -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGNOME_VFS_DISABLE_DEPRECATED -DGNOME_DISABLE_DEPRECATED -DBONOBO_DISABLE_DEPRECATED
@@ -10,6 +10,7 @@
 gladedir = $(datadir)/gthumb/glade
 
 INCLUDES =							\
+	$(EXIF_CFLAGS)						\
 	$(GTHUMB_CFLAGS)					\
 	-DGTHUMB_MODULEDIR=\""$(libdir)/gthumb/modules"\"	\
 	-DGTHUMB_GLADEDIR=\""$(gladedir)"\"			\
@@ -44,6 +45,7 @@
 	gnome-print-font-picker.h	\
 	gnome-print-font-dialog.h	\
 	gstringlist.h			\
+	gth-exif-utils.h		\
 	gth-image-list.h		\
 	gth-iviewer.h			\
 	gth-file-list.h			\
@@ -100,6 +102,7 @@
 	gnome-print-font-picker.c	\
 	gnome-print-font-dialog.c	\
 	gstringlist.c			\
+	gth-exif-utils.c		\
 	gth-pixbuf-op.c			\
 	gth-image-list.c		\
 	gth-iviewer.c			\
@@ -129,9 +132,11 @@
 	thumb-loader.c
 
 libgthumb_la_LIBADD =		\
+	$(EXIF_LIBS)		\
 	$(TIFF_LIBS)		\
 	$(GTHUMB_LIBS)		\
-	$(IPTCDATA_LIBS)
+	$(IPTCDATA_LIBS)	\
+	$(top_builddir)/libgthumb/jpegutils/libgthumb-jpegutils.la
 
 gthumb-marshal.h: gthumb-marshal.list $(GLIB_GENMARSHAL)
 	$(GLIB_GENMARSHAL) gthumb-marshal.list --header --prefix=gthumb_marshal > $@
diff -Nru gthumb-old/src/gth-exif-utils.c gthumb/src/gth-exif-utils.c
--- gthumb-old/src/gth-exif-utils.c	2006-03-21 09:37:43.000000000 -0700
+++ gthumb/src/gth-exif-utils.c	1969-12-31 17:00:00.000000000 -0700
@@ -1,347 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- *  GThumb
- *
- *  Copyright (C) 2003 Free Software Foundation, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- */
-
-#include <config.h>
-
-#ifdef HAVE_LIBEXIF
-
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-#include <glib.h>
-
-#include "file-utils.h"
-#include "gth-exif-utils.h"
-
-
-char *
-get_exif_tag (const char *filename,
-	      ExifTag     etag)
-{
-	ExifData     *edata;
-	unsigned int  i, j;
-
-	filename = get_file_path_from_uri (filename);
-	if (filename == NULL)
-		return g_strdup ("-");
-
-	edata = exif_data_new_from_file (filename);
-
-	if (edata == NULL) 
-		return g_strdup ("-");
-
-	for (i = 0; i < EXIF_IFD_COUNT; i++) {
-		ExifContent *content = edata->ifd[i];
-
-		if (! edata->ifd[i] || ! edata->ifd[i]->count) 
-			continue;
-
-		for (j = 0; j < content->count; j++) {
-			ExifEntry *e = content->entries[j];
-
-			if (! content->entries[j]) 
-				continue;
-
-			if (e->tag == etag) {
-				const char *value;
-				char *retval = NULL;
-
-				value = get_exif_entry_value (e);
-				if (value != NULL)
-					retval = g_locale_to_utf8 (value, -1, 0, 0, 0);
-				else
-					retval = g_strdup ("-");
-				exif_data_unref (edata);
-
-				return retval;
-			}
-		}
-	}
-
-	exif_data_unref (edata);
-
-	return g_strdup ("-");
-}
-
-
-ExifShort
-get_exif_tag_short (const char *filename,
-		    ExifTag     etag)
-{
-	ExifData     *edata;
-	unsigned int  i, j;
-
-	filename = get_file_path_from_uri (filename);
-	if (filename == NULL)
-		return 0;
-
-	edata = exif_data_new_from_file (filename);
-
-	if (edata == NULL) 
-		return 0;
-
-	for (i = 0; i < EXIF_IFD_COUNT; i++) {
-		ExifContent *content = edata->ifd[i];
-
-		if (! edata->ifd[i] || ! edata->ifd[i]->count) 
-			continue;
-
-		for (j = 0; j < content->count; j++) {
-			ExifEntry *e = content->entries[j];
-
-			if (! content->entries[j]) 
-				continue;
-
-			if (e->tag == etag) {
-				ExifByteOrder o;
-				ExifShort retval = 0;
-
-				o = exif_data_get_byte_order (e->parent->parent);
-				if (e->data != NULL)
-					retval = exif_get_short (e->data, o);
-				exif_data_unref (edata);
-
-				return retval;
-			}
-		}
-	}
-
-	exif_data_unref (edata);
-
-	return 0;
-}
-
-
-time_t
-get_exif_time (const char *filename)
-{
-	ExifData     *edata;
-	unsigned int  i, j;
-	time_t        time = 0;
-	struct tm     tm = { 0, };
-
-	filename = get_file_path_from_uri (filename);
-	if (filename == NULL)
-		return (time_t)0;
-
-	edata = exif_data_new_from_file (filename);
-
-	if (edata == NULL) 
-                return (time_t)0;
-
-	for (i = 0; i < EXIF_IFD_COUNT; i++) {
-		ExifContent *content = edata->ifd[i];
-
-		if (! edata->ifd[i] || ! edata->ifd[i]->count) 
-			continue;
-
-		for (j = 0; j < content->count; j++) {
-			ExifEntry   *e = content->entries[j];
-			char        *data;
-
-			if (! content->entries[j]) 
-				continue;
-
-			if ((e->tag != EXIF_TAG_DATE_TIME) &&
-			    (e->tag != EXIF_TAG_DATE_TIME_ORIGINAL) &&
-			    (e->tag != EXIF_TAG_DATE_TIME_DIGITIZED))
-				continue;
-
-			if (e->data == NULL)
-				continue;
-
-			if (strlen ((char*)e->data) < 10)
-				continue;
-
-			data = g_strdup ((char*)e->data);
-
-			data[4] = data[7] = data[10] = '\0';
-
-			tm.tm_year = atoi (data) - 1900;
-			tm.tm_mon  = atoi (data + 5) - 1;
-			tm.tm_mday = atoi (data + 8);
-			tm.tm_hour = 0;
-			tm.tm_min  = 0;
-			tm.tm_sec  = 0;
-			tm.tm_isdst = -1;
-
-			if (strlen ((char*)e->data) > 10) {
-				data[13] = data[16] = '\0';
-				tm.tm_hour = atoi (data + 11);
-				tm.tm_min  = atoi (data + 14);
-				tm.tm_sec  = atoi (data + 17);
-			}
-
-			time = mktime (&tm);
-
-			g_free (data);
-
-			break;
-		}
-	}
-
-	exif_data_unref (edata);
-
-	return time;
-}
-
-
-char *
-get_exif_aperture_value (const char *filename)
-{
-	ExifData     *edata;
-	unsigned int  i, j;
-
-	filename = get_file_path_from_uri (filename);
-	if (filename == NULL)
-		return g_strdup ("-");
-
-	edata = exif_data_new_from_file (filename);
-
-	if (edata == NULL) 
-		return g_strdup ("-");
-
-	for (i = 0; i < EXIF_IFD_COUNT; i++) {
-		ExifContent *content = edata->ifd[i];
-
-		if (! edata->ifd[i] || ! edata->ifd[i]->count) 
-			continue;
-
-		for (j = 0; j < content->count; j++) {
-			ExifEntry   *e = content->entries[j];
-			const char  *value = NULL;
-			char        *retval = NULL;
-
-			if (! content->entries[j]) 
-				continue;
-
-			if ((e->tag != EXIF_TAG_APERTURE_VALUE) &&
-			    (e->tag != EXIF_TAG_FNUMBER))
-				continue;
-
-			value = get_exif_entry_value (e);
-			if (value)
-				retval = g_locale_to_utf8 (value, -1, 0, 0, 0);
-			else
-				retval = g_strdup ("-");
-			exif_data_unref (edata);
-
-			return retval;
-		}
-	}
-
-	exif_data_unref (edata);
-
-	return g_strdup ("-");
-}
-
-
-gboolean 
-have_exif_time (const char *filename)
-{
-	return get_exif_time (filename) != (time_t)0;
-}
-
-
-#define VALUE_LEN 1024
-
-
-const char *
-get_exif_entry_value (ExifEntry *entry)
-{
-#ifdef HAVE_LIBEXIF_0_5
-	return exif_entry_get_value (entry);
-#else
-	char value[VALUE_LEN + 1];
-	return exif_entry_get_value (entry, value, VALUE_LEN);
-#endif
-}
-
-
-ExifData *
-load_exif_data (const char *filename)
-{
-	JPEGData *jdata = NULL;
-	ExifData *exif_data = NULL;
-
-	filename = get_file_path_from_uri (filename);
-	if (filename == NULL)
-		return NULL;
-
-	jdata = jpeg_data_new_from_file (filename);
-	if (jdata == NULL) 
-		return NULL;
-
-	exif_data = jpeg_data_get_exif_data (jdata);
-	jpeg_data_unref (jdata);
-
-	return exif_data;
-}
-
-
-void 
-save_exif_data (const char *filename,
-		ExifData   *edata)
-{
-	JPEGData *jdata;
-
-	filename = get_file_path_from_uri (filename);
-	if (filename == NULL)
-		return;
-
-	jdata = jpeg_data_new_from_file (filename);
-	if (jdata == NULL) 
-		return;
-
-	if (edata != NULL)
-		jpeg_data_set_exif_data (jdata, edata);
-
-	jpeg_data_save_file (jdata, filename);
-	jpeg_data_unref (jdata);
-}
-
-
-void 
-copy_exif_data (const char *src,
-		const char *dest)
-{
-	ExifData *edata;
-
-	if (!image_is_jpeg (src) || !image_is_jpeg (dest))
-		return;
-	src = get_file_path_from_uri (src);
-	if (src == NULL)
-		return;
-	dest = get_file_path_from_uri (dest);
-	if (dest == NULL)
-		return;
-
-	edata = exif_data_new_from_file (src);
-	if (edata == NULL) 
-		return;
-	save_exif_data (dest, edata);
-
-	exif_data_unref (edata);
-}
-
-
-#endif /* HAVE_LIBEXIF */
diff -Nru gthumb-old/src/gth-exif-utils.h gthumb/src/gth-exif-utils.h
--- gthumb-old/src/gth-exif-utils.h	2006-03-21 09:37:43.000000000 -0700
+++ gthumb/src/gth-exif-utils.h	1969-12-31 17:00:00.000000000 -0700
@@ -1,67 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- *  GThumb
- *
- *  Copyright (C) 2003 Free Software Foundation, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef EXIF_UTILS_H
-#define EXIF_UTILS_H
-
-
-#include <config.h>
-
-#ifdef HAVE_LIBEXIF
-
-#include <libexif/exif-data.h>
-#include <libexif/exif-content.h>
-#include <libexif/exif-entry.h>
-#include <libexif/exif-utils.h>
-#include "jpegutils/jpeg-data.h"
-
-
-typedef enum { /*< skip >*/
-	GTH_EXIF_ORIENTATION_NONE = 0,
-	GTH_EXIF_ORIENTATION_TOP_LEFT,
-	GTH_EXIF_ORIENTATION_TOP_RIGHT,
-	GTH_EXIF_ORIENTATION_BOTTOM_RIGHT,
-	GTH_EXIF_ORIENTATION_BOTTOM_LEFT,
-	GTH_EXIF_ORIENTATION_LEFT_TOP,
-	GTH_EXIF_ORIENTATION_RIGHT_TOP,
-	GTH_EXIF_ORIENTATION_RIGHT_BOTTOM,
-	GTH_EXIF_ORIENTATION_LEFT_BOTTOM
-} GthExifOrientation;
-
-
-char *      get_exif_tag            (const char *filename,
-				     ExifTag     etag);
-ExifShort   get_exif_tag_short      (const char *filename,
-				     ExifTag     etag);
-time_t      get_exif_time           (const char *filename);
-char *      get_exif_aperture_value (const char *filename);
-gboolean    have_exif_time          (const char *filename);
-const char *get_exif_entry_value    (ExifEntry  *entry);
-ExifData *  load_exif_data          (const char *filename);
-void        save_exif_data          (const char *filename,
-				     ExifData   *edata);
-void        copy_exif_data          (const char *src,
-				     const char *dest);
-
-#endif /* HAVE_LIBEXIF */
-
-#endif /* EXIF_UTILS_H */
diff -Nru gthumb-old/src/jpegutils/.cvsignore gthumb/src/jpegutils/.cvsignore
--- gthumb-old/src/jpegutils/.cvsignore	2002-10-06 09:40:51.000000000 -0600
+++ gthumb/src/jpegutils/.cvsignore	1969-12-31 17:00:00.000000000 -0700
@@ -1,5 +0,0 @@
-.deps
-.libs
-Makefile
-Makefile.in
-libgthumb-jpegutils.a
diff -Nru gthumb-old/src/jpegutils/jpeg-data.c gthumb/src/jpegutils/jpeg-data.c
--- gthumb-old/src/jpegutils/jpeg-data.c	2005-08-07 04:51:42.000000000 -0600
+++ gthumb/src/jpegutils/jpeg-data.c	1969-12-31 17:00:00.000000000 -0700
@@ -1,481 +0,0 @@
-/* jpeg-data.c
- *
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-
-#include "config.h"
-
-#include "jpeg-data.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-/* #define DEBUG */
-
-#ifdef HAVE_LIBEXIF
-
-
-struct _JPEGDataPrivate
-{
-	unsigned int ref_count;
-};
-
-JPEGData *
-jpeg_data_new (void)
-{
-	JPEGData *data;
-
-	data = malloc (sizeof (JPEGData));
-	if (!data)
-		return (NULL);
-	memset (data, 0, sizeof (JPEGData));
-	data->priv = malloc (sizeof (JPEGDataPrivate));
-	if (!data->priv) {
-		free (data);
-		return (NULL);
-	}
-	memset (data->priv, 0, sizeof (JPEGDataPrivate));
-	data->priv->ref_count = 1;
-
-	return (data);
-}
-
-void
-jpeg_data_append_section (JPEGData *data)
-{
-	JPEGSection *s;
-
-	if (!data->count)
-		s = malloc (sizeof (JPEGSection));
-	else
-		s = realloc (data->sections,
-			     sizeof (JPEGSection) * (data->count + 1));
-	if (!s)
-		return;
-
-	data->sections = s;
-	data->count++;
-}
-
-/* jpeg_data_save_file returns 1 on succes, 0 on failure */
-int
-jpeg_data_save_file (JPEGData *data, const char *path)
-{
-	FILE *f;
-	unsigned char *d = NULL;
-	unsigned int size = 0, written;
-
-	jpeg_data_save_data (data, &d, &size);
-	if (!d)
-		return 0;
-
-	remove (path);
-	f = fopen (path, "wb");
-	if (!f) {
-		free (d);
-		return 0;
-	}
-	written = fwrite (d, 1, size, f);
-	fclose (f);
-	free (d);
-	if (written == size)  {
-		return 1;
-	}
-	remove(path);
-	return 0;
-}
-
-void
-jpeg_data_save_data (JPEGData *data, unsigned char **d, unsigned int *ds)
-{
-	unsigned int i, eds = 0;
-	JPEGSection s;
-	unsigned char *ed = NULL;
-
-	if (!data)
-		return;
-	if (!d)
-		return;
-	if (!ds)
-		return;
-
-	for (*ds = i = 0; i < data->count; i++) {
-		s = data->sections[i];
-#ifdef DEBUG
-		printf ("Writing marker 0x%x at position %i...\n",
-			s.marker, *ds);
-#endif
-
-		/* Write the marker */
-		*d = realloc (*d, sizeof (char) * (*ds + 2));
-		(*d)[*ds + 0] = 0xff;
-		(*d)[*ds + 1] = s.marker;
-		*ds += 2;
-
-		switch (s.marker) {
-		case JPEG_MARKER_SOI:
-		case JPEG_MARKER_EOI:
-			break;
-		case JPEG_MARKER_APP1:
-			exif_data_save_data (s.content.app1, &ed, &eds);
-			if (!ed) break;
-			*d = realloc (*d, sizeof (char) * (*ds + 2));
-			(*d)[*ds + 0] = (eds + 2) >> 8;
-			(*d)[*ds + 1] = (eds + 2) >> 0;
-			*ds += 2;
-			*d = realloc (*d, sizeof (char) * (*ds + eds));
-			memcpy (*d + *ds, ed, eds);
-			*ds += eds;
-			free (ed);
-			break;
-		default:
-			*d = realloc (*d, sizeof (char) *
-					(*ds + s.content.generic.size + 2));
-			(*d)[*ds + 0] = (s.content.generic.size + 2) >> 8;
-			(*d)[*ds + 1] = (s.content.generic.size + 2) >> 0;
-			*ds += 2;
-			memcpy (*d + *ds, s.content.generic.data,
-				s.content.generic.size);
-			*ds += s.content.generic.size;
-
-			/* In case of SOS, we need to write the data. */
-			if (s.marker == JPEG_MARKER_SOS) {
-				*d = realloc (*d, *ds + data->size);
-				memcpy (*d + *ds, data->data, data->size);
-				*ds += data->size;
-			}
-			break;
-		}
-	}
-}
-
-JPEGData *
-jpeg_data_new_from_data (const unsigned char *d,
-			 unsigned int size)
-{
-	JPEGData *data;
-
-	data = jpeg_data_new ();
-	jpeg_data_load_data (data, d, size);
-	return (data);
-}
-
-void
-jpeg_data_load_data (JPEGData *data, const unsigned char *d,
-		     unsigned int size)
-{
-	unsigned int i, o, len;
-	JPEGSection *s;
-	JPEGMarker marker;
-
-	if (!data)
-		return;
-	if (!d)
-		return;
-
-#ifdef DEBUG
-	printf ("Parsing %i bytes...\n", size);
-#endif
-
-	for (o = 0; o < size;) {
-
-		/*
-		 * JPEG sections start with 0xff. The first byte that is
-		 * not 0xff is a marker (hopefully).
-		 */
-		for (i = 0; i < 7; i++)
-			if (d[o + i] != 0xff)
-				break;
-		if (!JPEG_IS_MARKER (d[o + i]))
-			return;
-		marker = d[o + i];
-
-#ifdef DEBUG
-		printf ("Found marker 0x%x ('%s') at %i.\n", marker,
-			jpeg_marker_get_name (marker), o + i);
-#endif
-
-		/* Append this section */
-		jpeg_data_append_section (data);
-		s = &data->sections[data->count - 1];
-		s->marker = marker;
-		s->content.generic.data = NULL;
-		o += i + 1;
-
-		switch (s->marker) {
-		case JPEG_MARKER_SOI:
-		case JPEG_MARKER_EOI:
-			break;
-		default:
-
-			/* Read the length of the section */
-			len = ((d[o] << 8) | d[o + 1]) - 2;
-			if (len > size) { o = size; break; }
-			o += 2;
-			if (o + len > size) { o = size; break; }
-
-			switch (s->marker) {
-			case JPEG_MARKER_APP1:
-				s->content.app1 = exif_data_new_from_data (
-							d + o - 4, len + 4);
-				break;
-			default:
-				s->content.generic.size = len;
-				s->content.generic.data =
-						malloc (sizeof (char) * len);
-				memcpy (s->content.generic.data, &d[o], len);
-
-				/* In case of SOS, image data will follow. */
-				if (s->marker == JPEG_MARKER_SOS) {
-					data->size = size - 2 - o - len;
-					data->data = malloc (
-						sizeof (char) * data->size);
-					memcpy (data->data, d + o + len,
-						data->size);
-					o += data->size;
-				}
-				break;
-			}
-			o += len;
-			break;
-		}
-	}
-}
-
-JPEGData *
-jpeg_data_new_from_file (const char *path)
-{
-	JPEGData *data;
-
-	data = jpeg_data_new ();
-	jpeg_data_load_file (data, path);
-	return (data);
-}
-
-void
-jpeg_data_load_file (JPEGData *data, const char *path)
-{
-	FILE *f;
-	unsigned char *d;
-	unsigned int size;
-
-	if (!data)
-		return;
-	if (!path)
-		return;
-
-	f = fopen (path, "rb");
-	if (!f)
-		return;
-
-	/* For now, we read the data into memory. Patches welcome... */
-	fseek (f, 0, SEEK_END);
-	size = ftell (f);
-	fseek (f, 0, SEEK_SET);
-	d = malloc (sizeof (char) * size);
-	if (!d) {
-		fclose (f);
-		return;
-	}
-	if (fread (d, 1, size, f) != size) {
-		free (d);
-		fclose (f);
-		return;
-	}
-	fclose (f);
-
-	jpeg_data_load_data (data, d, size);
-	free (d);
-}
-
-void
-jpeg_data_ref (JPEGData *data)
-{
-	if (!data)
-		return;
-
-	data->priv->ref_count++;
-}
-
-void
-jpeg_data_unref (JPEGData *data)
-{
-	if (!data)
-		return;
-
-	data->priv->ref_count--;
-	if (!data->priv->ref_count)
-		jpeg_data_free (data);
-}
-
-void
-jpeg_data_free (JPEGData *data)
-{
-	unsigned int i;
-	JPEGSection s;
-
-	if (!data)
-		return;
-
-	if (data->count) {
-		for (i = 0; i < data->count; i++) {
-			s = data->sections[i];
-			switch (s.marker) {
-			case JPEG_MARKER_SOI:
-			case JPEG_MARKER_EOI:
-				break;
-			case JPEG_MARKER_APP1:
-				exif_data_unref (s.content.app1);
-				break;
-			default:
-				free (s.content.generic.data);
-				break;
-			}
-		}
-		free (data->sections);
-	}
-
-	if (data->data)
-		free (data->data);
-	free (data->priv);
-	free (data);
-}
-
-
-static JPEGSection *
-jpeg_data_get_section (JPEGData *data, JPEGMarker marker)
-{
-	unsigned int i;
-
-	if (!data)
-		return (NULL);
-
-	for (i = 0; i < data->count; i++)
-		if (data->sections[i].marker == marker)
-			return (&data->sections[i]);
-	return (NULL);
-}
-
-
-void
-jpeg_data_dump (JPEGData *data)
-{
-	unsigned int i;
-	JPEGContent content;
-	JPEGMarker marker;
-
-	if (!data)
-		return;
-
-	printf ("Dumping JPEG data (%i bytes of data)...\n", data->size);
-	for (i = 0; i < data->count; i++) {
-		marker = data->sections[i].marker;
-		content = data->sections[i].content;
-		printf ("Section %i (marker 0x%x - %s):\n", i, marker,
-			jpeg_marker_get_name (marker));
-		printf ("  Description: %s\n",
-			jpeg_marker_get_description (marker));
-		switch (marker) {
-                case JPEG_MARKER_SOI:
-                case JPEG_MARKER_EOI:
-			break;
-                case JPEG_MARKER_APP1:
-			exif_data_dump (content.app1);
-			break;
-                default:
-			printf ("  Size: %i\n", content.generic.size);
-                        printf ("  Unknown content.\n");
-                        break;
-                }
-        }
-}
-
-
-ExifData *
-jpeg_data_get_exif_data (JPEGData *data)
-{
-	JPEGSection *section;
-
-	if (!data)
-		return NULL;
-
-	section = jpeg_data_get_section (data, JPEG_MARKER_APP1);
-	if (section) {
-		exif_data_ref (section->content.app1);
-		return (section->content.app1);
-	}
-
-	return (NULL);
-}
-
-void
-jpeg_data_set_exif_data (JPEGData *data, ExifData *exif_data)
-{
-	JPEGSection *section;
-
-	section = jpeg_data_get_section (data, JPEG_MARKER_APP1);
-	if (!section) {
-		jpeg_data_append_section (data);
-		memmove (&data->sections[2], &data->sections[1],
-			 sizeof (JPEGSection) * (data->count - 2));
-		section = &data->sections[1];
-	} else {
-		exif_data_unref (section->content.app1);
-	}
-	section->marker = JPEG_MARKER_APP1;
-	section->content.app1 = exif_data;
-	exif_data_ref (exif_data);
-}
-
-
-void
-jpeg_data_set_header_data (JPEGData *data, JPEGMarker marker,
-			   unsigned char *buf, unsigned int size)
-{
-	JPEGSection *section;
-	int i;
-	
-	section = jpeg_data_get_section (data, marker);
-	if (!section) {
-		jpeg_data_append_section (data);
-		for (i = 0; i < data->count - 1; i++) {
-			JPEGMarker m = data->sections[i].marker;
-			if (m != JPEG_MARKER_SOI &&
-			    (m < JPEG_MARKER_APP0 ||
-			     m > JPEG_MARKER_APP15)) {
-				memmove (&data->sections[i+1],
-					 &data->sections[i],
-					 sizeof (JPEGSection) *
-					 (data->count - i - 1));
-				break;
-			}
-		}
-		section = &data->sections[i];
-	} else {
-		free (section->content.generic.data);
-	}
-
-	section->marker = marker;
-	section->content.generic.data = malloc (size);
-	memcpy (section->content.generic.data, buf, size);
-	section->content.generic.size = size;
-}
-
-
-#endif /* HAVE_LIBEXIF */
diff -Nru gthumb-old/src/jpegutils/jpeg-data.h gthumb/src/jpegutils/jpeg-data.h
--- gthumb-old/src/jpegutils/jpeg-data.h	2005-08-07 04:51:42.000000000 -0600
+++ gthumb/src/jpegutils/jpeg-data.h	1969-12-31 17:00:00.000000000 -0700
@@ -1,96 +0,0 @@
-/* jpeg-data.h
- *
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details. 
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __JPEG_DATA_H__
-#define __JPEG_DATA_H__
-
-#ifdef HAVE_LIBEXIF
-
-#include "jpeg-marker.h"
-#include <libexif/exif-data.h>
-
-typedef ExifData * JPEGContentAPP1;
-
-typedef struct _JPEGContentGeneric JPEGContentGeneric;
-struct _JPEGContentGeneric
-{
-	unsigned char *data;
-	unsigned int size;
-};
-
-typedef union _JPEGContent JPEGContent;
-union _JPEGContent
-{
-	JPEGContentGeneric generic;
-	JPEGContentAPP1    app1;
-};
-
-typedef struct _JPEGSection JPEGSection;
-struct _JPEGSection
-{
-	JPEGMarker marker;
-	JPEGContent content;
-};
-
-typedef struct _JPEGData        JPEGData;
-typedef struct _JPEGDataPrivate JPEGDataPrivate;
-
-struct _JPEGData
-{
-	JPEGSection *sections;
-	unsigned int count;
-
-	unsigned char *data;
-	unsigned int size;
-
-	JPEGDataPrivate *priv;
-};
-
-JPEGData *jpeg_data_new           (void);
-JPEGData *jpeg_data_new_from_file (const char *path);
-JPEGData *jpeg_data_new_from_data (const unsigned char *data,
-				   unsigned int size);
-
-void      jpeg_data_ref   (JPEGData *data);
-void      jpeg_data_unref (JPEGData *data);
-void      jpeg_data_free  (JPEGData *data);
-
-void      jpeg_data_load_data     (JPEGData *data, const unsigned char *d,
-				   unsigned int size);
-void      jpeg_data_save_data     (JPEGData *data, unsigned char **d,
-				   unsigned int *size);
-
-void      jpeg_data_load_file     (JPEGData *data, const char *path);
-int       jpeg_data_save_file     (JPEGData *data, const char *path);
-
-void      jpeg_data_set_exif_data (JPEGData *data, ExifData *exif_data);
-
-ExifData *jpeg_data_get_exif_data (JPEGData *data);
-
-void      jpeg_data_set_header_data (JPEGData *data, JPEGMarker marker,
-				     unsigned char * buf, unsigned int size);
-
-void      jpeg_data_dump (JPEGData *data);
-
-void      jpeg_data_append_section (JPEGData *data);
-
-#endif /* HAVE_LIBEXIF */
-
-#endif /* __JPEG_DATA_H__ */
diff -Nru gthumb-old/src/jpegutils/jpeg-marker.c gthumb/src/jpegutils/jpeg-marker.c
--- gthumb-old/src/jpegutils/jpeg-marker.c	2004-07-10 04:55:25.000000000 -0600
+++ gthumb/src/jpegutils/jpeg-marker.c	1969-12-31 17:00:00.000000000 -0700
@@ -1,122 +0,0 @@
-/* jpeg-marker.c
- *
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details. 
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#include "config.h"
-#include "jpeg-marker.h"
-
-#include <stdlib.h>
-
-static struct {
-        JPEGMarker marker;
-        const char *name;
-        const char *description;
-} JPEGMarkerTable[] = {
-        {JPEG_MARKER_SOF0, "SOF0", "Encoding (baseline)"},
-        {JPEG_MARKER_SOF1, "SOF1", "Encoding (extended sequential)"},
-        {JPEG_MARKER_SOF2, "SOF2", "Encoding (progressive)"},
-        {JPEG_MARKER_SOF3, "SOF3", "Encoding (lossless)"},
-        {JPEG_MARKER_SOF5, "SOF5", "Encoding (differential sequential)"},
-        {JPEG_MARKER_SOF6, "SOF6", "Encoding (differential progressive)"},
-        {JPEG_MARKER_SOF7, "SOF7", "Encoding (differential lossless)"},
-        {JPEG_MARKER_SOF9, "SOF9",
-		"Encoding (extended sequential, arithmetic)"},
-        {JPEG_MARKER_SOF10, "SOF10", "Encoding (progressive, arithmetic)"},
-        {JPEG_MARKER_SOF11, "SOF11", "Encoding (lossless, arithmetic)"},
-        {JPEG_MARKER_SOF13, "SOF13",
-		"Encoding (differential sequential, arithmetic)"},
-        {JPEG_MARKER_SOF14, "SOF14",
-		"Encoding (differential progressive, arithmetic)"},
-        {JPEG_MARKER_SOF15, "SOF15",
-		"Encoding (differential lossless, arithmetic)"},
-	{JPEG_MARKER_SOI, "SOI", "Start of image"},
-	{JPEG_MARKER_EOI, "EOI", "End of image"},
-	{JPEG_MARKER_SOS, "SOS", "Start of scan"},
-	{JPEG_MARKER_COM, "COM", "Comment"},
-	{JPEG_MARKER_DHT, "DHT", "Define Huffman table"},
-	{JPEG_MARKER_JPG, "JPG", "Extension"},
-	{JPEG_MARKER_DAC, "DAC", "Define arithmetic coding conditioning"},
-	{JPEG_MARKER_RST1, "RST1", "Restart 1"},
-	{JPEG_MARKER_RST2, "RST2", "Restart 2"},
-	{JPEG_MARKER_RST3, "RST3", "Restart 3"},
-	{JPEG_MARKER_RST4, "RST4", "Restart 4"},
-	{JPEG_MARKER_RST5, "RST5", "Restart 5"},
-	{JPEG_MARKER_RST6, "RST6", "Restart 6"},
-	{JPEG_MARKER_RST7, "RST7", "Restart 7"},
-	{JPEG_MARKER_DQT, "DQT", "Define quantization table"},
-	{JPEG_MARKER_DNL, "DNL", "Define number of lines"},
-	{JPEG_MARKER_DRI, "DRI", "Define restart interval"},
-	{JPEG_MARKER_DHP, "DHP", "Define hierarchical progression"},
-	{JPEG_MARKER_EXP, "EXP", "Expand reference component"},
-	{JPEG_MARKER_APP0, "APP0", "Application segment 0"},
-	{JPEG_MARKER_APP1, "APP1", "Application segment 1"},
-	{JPEG_MARKER_APP2, "APP2", "Application segment 2"},
-	{JPEG_MARKER_APP3, "APP3", "Application segment 3"},
-	{JPEG_MARKER_APP4, "APP4", "Application segment 4"},
-	{JPEG_MARKER_APP5, "APP5", "Application segment 5"},
-	{JPEG_MARKER_APP6, "APP6", "Application segment 6"},
-	{JPEG_MARKER_APP7, "APP7", "Application segment 7"},
-	{JPEG_MARKER_APP8, "APP8", "Application segment 8"},
-	{JPEG_MARKER_APP9, "APP9", "Application segment 9"},
-	{JPEG_MARKER_APP10, "APP10", "Application segment 10"},
-	{JPEG_MARKER_APP11, "APP11", "Application segment 11"},
-	{JPEG_MARKER_APP12, "APP12", "Application segment 12"},
-	{JPEG_MARKER_APP13, "APP13", "Application segment 13"},
-	{JPEG_MARKER_APP14, "APP14", "Application segment 14"},
-	{JPEG_MARKER_APP15, "APP15", "Application segment 15"},
-	{JPEG_MARKER_JPG0, "JPG0", "Extension 0"},
-	{JPEG_MARKER_JPG1, "JPG1", "Extension 1"},
-	{JPEG_MARKER_JPG2, "JPG2", "Extension 2"},
-	{JPEG_MARKER_JPG3, "JPG3", "Extension 3"},
-	{JPEG_MARKER_JPG4, "JPG4", "Extension 4"},
-	{JPEG_MARKER_JPG5, "JPG5", "Extension 5"},
-	{JPEG_MARKER_JPG6, "JPG6", "Extension 6"},
-	{JPEG_MARKER_JPG7, "JPG7", "Extension 7"},
-	{JPEG_MARKER_JPG8, "JPG8", "Extension 8"},
-	{JPEG_MARKER_JPG9, "JPG9", "Extension 9"},
-	{JPEG_MARKER_JPG10, "JPG10", "Extension 10"},
-	{JPEG_MARKER_JPG11, "JPG11", "Extension 11"},
-	{JPEG_MARKER_JPG12, "JPG12", "Extension 12"},
-	{JPEG_MARKER_JPG13, "JPG13", "Extension 13"},
-	{0, NULL, NULL}
-};
-
-const char *
-jpeg_marker_get_name (JPEGMarker marker)
-{
-	unsigned int i;
-
-	for (i = 0; JPEGMarkerTable[i].name; i++)
-		if (JPEGMarkerTable[i].marker == marker)
-			break;
-
-	return (JPEGMarkerTable[i].name);
-}
-
-const char *
-jpeg_marker_get_description (JPEGMarker marker)
-{
-	unsigned int i;
-
-	for (i = 0; JPEGMarkerTable[i].description; i++)
-		if (JPEGMarkerTable[i].marker == marker)
-			break;
-
-	return (JPEGMarkerTable[i].description);
-}
-
diff -Nru gthumb-old/src/jpegutils/jpeg-marker.h gthumb/src/jpegutils/jpeg-marker.h
--- gthumb-old/src/jpegutils/jpeg-marker.h	2004-07-10 04:55:25.000000000 -0600
+++ gthumb/src/jpegutils/jpeg-marker.h	1969-12-31 17:00:00.000000000 -0700
@@ -1,103 +0,0 @@
-/* jpeg-marker.h
- *
- * Copyright © 2001 Lutz Müller <lutz@users.sourceforge.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details. 
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#ifndef __JPEG_MARKER_H__
-#define __JPEG_MARKER_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-typedef enum {
-        JPEG_MARKER_SOF0        = 0xc0,
-        JPEG_MARKER_SOF1        = 0xc1,
-        JPEG_MARKER_SOF2        = 0xc2,
-        JPEG_MARKER_SOF3        = 0xc3,
-	JPEG_MARKER_DHT		= 0xc4,
-        JPEG_MARKER_SOF5        = 0xc5,
-        JPEG_MARKER_SOF6        = 0xc6,
-        JPEG_MARKER_SOF7        = 0xc7,
-	JPEG_MARKER_JPG		= 0xc8,
-        JPEG_MARKER_SOF9        = 0xc9,
-        JPEG_MARKER_SOF10       = 0xca,
-        JPEG_MARKER_SOF11       = 0xcb,
-	JPEG_MARKER_DAC		= 0xcc,
-        JPEG_MARKER_SOF13       = 0xcd,
-        JPEG_MARKER_SOF14       = 0xce,
-        JPEG_MARKER_SOF15       = 0xcf,
-        JPEG_MARKER_RST0	= 0xd0,
-        JPEG_MARKER_RST1	= 0xd1,
-        JPEG_MARKER_RST2	= 0xd2,
-        JPEG_MARKER_RST3	= 0xd3,
-        JPEG_MARKER_RST4	= 0xd4,
-	JPEG_MARKER_RST5	= 0xd5,
-        JPEG_MARKER_RST6	= 0xd6,
-        JPEG_MARKER_RST7	= 0xd7,
-        JPEG_MARKER_SOI         = 0xd8,
-        JPEG_MARKER_EOI         = 0xd9,
-        JPEG_MARKER_SOS         = 0xda,
-        JPEG_MARKER_DQT		= 0xdb,
-        JPEG_MARKER_DNL		= 0xdc,
-        JPEG_MARKER_DRI		= 0xdd,
-        JPEG_MARKER_DHP		= 0xde,
-        JPEG_MARKER_EXP		= 0xdf,
-	JPEG_MARKER_APP0	= 0xe0,
-        JPEG_MARKER_APP1        = 0xe1,
-	JPEG_MARKER_APP2        = 0xe2,
-	JPEG_MARKER_APP3        = 0xe3,
-	JPEG_MARKER_APP4        = 0xe4,
-	JPEG_MARKER_APP5        = 0xe5,
-	JPEG_MARKER_APP6        = 0xe6,
-	JPEG_MARKER_APP7        = 0xe7,
-	JPEG_MARKER_APP8        = 0xe8,
-	JPEG_MARKER_APP9        = 0xe9,
-	JPEG_MARKER_APP10       = 0xea,
-	JPEG_MARKER_APP11       = 0xeb,
-	JPEG_MARKER_APP12       = 0xec,
-	JPEG_MARKER_APP13       = 0xed,
-	JPEG_MARKER_APP14       = 0xee,
-	JPEG_MARKER_APP15       = 0xef,
-	JPEG_MARKER_JPG0	= 0xf0,
-	JPEG_MARKER_JPG1	= 0xf1,
-	JPEG_MARKER_JPG2	= 0xf2,
-	JPEG_MARKER_JPG3	= 0xf3,
-	JPEG_MARKER_JPG4	= 0xf4,
-	JPEG_MARKER_JPG5	= 0xf5,
-	JPEG_MARKER_JPG6	= 0xf6,
-	JPEG_MARKER_JPG7	= 0xf7,
-	JPEG_MARKER_JPG8	= 0xf8,
-	JPEG_MARKER_JPG9	= 0xf9,
-	JPEG_MARKER_JPG10	= 0xfa,
-	JPEG_MARKER_JPG11	= 0xfb,
-	JPEG_MARKER_JPG12	= 0xfc,
-	JPEG_MARKER_JPG13	= 0xfd,
-        JPEG_MARKER_COM         = 0xfe
-} JPEGMarker;
-
-#define JPEG_IS_MARKER(m) (((m) >= JPEG_MARKER_SOF0) &&		\
-			   ((m) <= JPEG_MARKER_COM))
-
-const char *jpeg_marker_get_name        (JPEGMarker marker);
-const char *jpeg_marker_get_description (JPEGMarker marker);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __JPEG_MARKER_H__ */
diff -Nru gthumb-old/src/jpegutils/jpegtran.c gthumb/src/jpegutils/jpegtran.c
--- gthumb-old/src/jpegutils/jpegtran.c	2003-08-09 10:30:00.000000000 -0600
+++ gthumb/src/jpegutils/jpegtran.c	1969-12-31 17:00:00.000000000 -0700
@@ -1,258 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- *  GThumb
- *
- *  Copyright (C) 2001, 2002 The Free Software Foundation, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- */
-
-/* based upon file jpegtran.c from the libjpeg package, original copyright 
- * note follows:
- *
- * jpegtran.c
- *
- * Copyright (C) 1995-1997, Thomas G. Lane.
- * This file is part of the Independent JPEG Group's software.
- * For conditions of distribution and use, see the accompanying README file.
- *
- * This file contains a command-line user interface for JPEG transcoding.
- * It is very similar to cjpeg.c, but provides lossless transcoding between
- * different JPEG file formats.  It also provides some lossless and sort-of-
- * lossless transformations of JPEG data.
- */
-
-
-#include <config.h>
-
-#ifdef HAVE_LIBJPEG
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <setjmp.h>
-#include <jpeglib.h>
-#include <glib.h>
-#include "gthumb-error.h"
-#include "file-utils.h"
-#include "transupp.h"		/* Support routines for jpegtran */
-
-
-/* error handler data */
-struct error_handler_data {
-	struct jpeg_error_mgr pub;
-	sigjmp_buf setjmp_buffer;
-        GError **error;
-	const char *filename;
-};
-
-
-static void
-fatal_error_handler (j_common_ptr cinfo)
-{
-	struct error_handler_data *errmgr;
-        char buffer[JMSG_LENGTH_MAX];
-        
-	errmgr = (struct error_handler_data *) cinfo->err;
-        
-        /* Create the message */
-        (* cinfo->err->format_message) (cinfo, buffer);
-
-        /* broken check for *error == NULL for robustness against
-         * crappy JPEG library
-         */
-        if (errmgr->error && *errmgr->error == NULL) {
-                g_set_error (errmgr->error,
-			     GTHUMB_ERROR,
-			     0,
-			     "Error interpreting JPEG image file: %s\n\n%s",
-			     file_name_from_path (errmgr->filename),
-                             buffer);
-        }
-        
-	siglongjmp (errmgr->setjmp_buffer, 1);
-
-        g_assert_not_reached ();
-}
-
-
-static void
-output_message_handler (j_common_ptr cinfo)
-{
-	/* This method keeps libjpeg from dumping crap to stderr */
-	/* do nothing */
-}
-
-
-int
-jpegtran (char         *input_filename,
-	  char         *output_filename,
-	  JXFORM_CODE   transformation,
-	  GError      **error)
-{
-	struct jpeg_decompress_struct  srcinfo;
-	struct jpeg_compress_struct    dstinfo;
-	struct error_handler_data      jsrcerr, jdsterr;
-	jpeg_transform_info            transformoption; 
-	jvirt_barray_ptr              *src_coef_arrays;
-	jvirt_barray_ptr              *dst_coef_arrays;
-	FILE                          *input_file;
-	FILE                          *output_file;
-
-	transformoption.transform = transformation;
-	transformoption.trim = FALSE;
-	transformoption.force_grayscale = FALSE;
-	
-	/* Initialize the JPEG decompression object with default error 
-	 * handling. */
-	jsrcerr.filename = input_filename;
-	srcinfo.err = jpeg_std_error (&(jsrcerr.pub));
-	jsrcerr.pub.error_exit = fatal_error_handler;
-	jsrcerr.pub.output_message = output_message_handler;
-	jsrcerr.error = error;
-
-	jpeg_create_decompress (&srcinfo);
-
-	/* Initialize the JPEG compression object with default error 
-	 * handling. */
-	jdsterr.filename = output_filename;
-	dstinfo.err = jpeg_std_error (&(jdsterr.pub));
-	jdsterr.pub.error_exit = fatal_error_handler;
-	jdsterr.pub.output_message = output_message_handler;
-	jdsterr.error = error;
-
-	jpeg_create_compress (&dstinfo);
-	
-	dstinfo.err->trace_level = 0;
-	dstinfo.arith_code = FALSE;
-	dstinfo.optimize_coding = FALSE;
-
-	jsrcerr.pub.trace_level = jdsterr.pub.trace_level;
-	srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;
-
-	/* Open the input file. */
-	input_file = fopen (input_filename, "rb");
-	if (input_file == NULL) 
-		return 1;
-
-	output_file = fopen (output_filename, "wb");
-	if (output_file == NULL) {
-		fclose (input_file);
-		return 1;
-	}
-
-	if (sigsetjmp (jsrcerr.setjmp_buffer, 1)) {
-		jpeg_destroy_compress (&dstinfo);
-		jpeg_destroy_decompress (&srcinfo);
-		return 1;
-	}
-
-	if (sigsetjmp (jdsterr.setjmp_buffer, 1)) {
-		jpeg_destroy_compress (&dstinfo);
-		jpeg_destroy_decompress (&srcinfo);
-		return 1;
-	}
-
-	/* Specify data source for decompression */
-	jpeg_stdio_src (&srcinfo, input_file);
-
-	/* Enable saving of extra markers that we want to copy */
-	jcopy_markers_setup (&srcinfo, JCOPYOPT_ALL);
-
-	/* Read file header */
-	(void) jpeg_read_header (&srcinfo, TRUE);
-
-	/* Any space needed by a transform option must be requested before
-	 * jpeg_read_coefficients so that memory allocation will be done right.
-	 */
-	jtransform_request_workspace (&srcinfo, &transformoption);
-
-	/* Read source file as DCT coefficients */
-	src_coef_arrays = jpeg_read_coefficients (&srcinfo);
-
-	/* 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.
-	 */
-	dst_coef_arrays = jtransform_adjust_parameters (&srcinfo, 
-							&dstinfo,
-							src_coef_arrays,
-							&transformoption);
-
-	/* Specify data destination for compression */
-	jpeg_stdio_dest (&dstinfo, output_file);
-
-	/* Start compressor (note no image data is actually written here) */
-	jpeg_write_coefficients (&dstinfo, dst_coef_arrays);
-
-	/* Copy to the output file any extra markers that we want to 
-	 * preserve */
-	jcopy_markers_execute (&srcinfo, &dstinfo, JCOPYOPT_ALL);
-
-	/* Execute image transformation, if any */
-	jtransform_execute_transformation (&srcinfo, 
-					   &dstinfo,
-					   src_coef_arrays,
-					   &transformoption);
-
-	/* Finish compression and release memory */
-	jpeg_finish_compress (&dstinfo);
-	jpeg_destroy_compress (&dstinfo);
-	(void) jpeg_finish_decompress (&srcinfo);
-	jpeg_destroy_decompress (&srcinfo);
-
-	/* Close files */
-	fclose (input_file);
-	fclose (output_file);
-
-	return 0;
-}
-
-
-#ifdef TEST
-
-
-int
-main (int    argc, 
-      char **argv)
-{
-	char *input_filename;
-	char *output_filename;
-
-	if (argc != 3) {
-		fprintf (stderr, "%s input_image output_image", argv[0]);
-		return 1;
-	}
-	
-	input_filename  = argv[1];
-	output_filename = argv[2];
-
-	/*
-	  JXFORM_ROT_90
-	  JXFORM_ROT_180
-	  JXFORM_ROT_270
-	  JXFORM_FLIP_H
-	  JXFORM_FLIP_V
-	*/
-	
-	return jpegtran (input_filename, output_filename, JXFORM_FLIP_H);
-}
-
-#endif /* TEST */
-
-#endif /* HAVE_LIBJPEG */
diff -Nru gthumb-old/src/jpegutils/jpegtran.h gthumb/src/jpegutils/jpegtran.h
--- gthumb-old/src/jpegutils/jpegtran.h	2003-08-04 06:32:36.000000000 -0600
+++ gthumb/src/jpegutils/jpegtran.h	1969-12-31 17:00:00.000000000 -0700
@@ -1,41 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- *  GThumb
- *
- *  Copyright (C) 2001, 2002 The Free Software Foundation, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- */
-
-#include <config.h>
-
-#ifdef HAVE_LIBJPEG
-
-#ifndef JPEGTRAN_H
-#define JPEGTRAN_H
-
-#include <glib.h>
-#include "transupp.h"
-
-
-int  jpegtran (char         *input_filename,
-	       char         *output_filename,
-	       JXFORM_CODE   transformation,
-	       GError      **error);
-
-#endif /* JPEGTRAN_H */
-
-#endif /* HAVE_LIBJPEG */
diff -Nru gthumb-old/src/jpegutils/Makefile.am gthumb/src/jpegutils/Makefile.am
--- gthumb-old/src/jpegutils/Makefile.am	2003-12-25 12:23:50.000000000 -0700
+++ gthumb/src/jpegutils/Makefile.am	1969-12-31 17:00:00.000000000 -0700
@@ -1,26 +0,0 @@
-if ENABLE_DEPRECATIONS
-DISABLE_DEPRECATED = -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGNOME_VFS_DISABLE_DEPRECATED -DGNOME_DISABLE_DEPRECATED -DBONOBO_DISABLE_DEPRECATED
-else
-DISABLE_DEPRECATED =
-endif
-
-INCLUDES = 				\
-	$(DISABLE_DEPRECATED)		\
-	$(EXIF_CFLAGS)			\
-	$(GTHUMB_CFLAGS)		\
-	-I$(top_srcdir)/libgthumb		
-
-
-noinst_LTLIBRARIES = libgthumb-jpegutils.la
-
-libgthumb_jpegutils_la_SOURCES =	\
-	jpeg-data.c			\
-	jpeg-data.h			\
-	jpeg-marker.c			\
-	jpeg-marker.h			\
-	jpegtran.c			\
-	jpegtran.h			\
-	transupp.c			\
-	transupp.h
-
-EXTRA_DIST = README
diff -Nru gthumb-old/src/jpegutils/README gthumb/src/jpegutils/README
--- gthumb-old/src/jpegutils/README	2002-10-06 09:40:54.000000000 -0600
+++ gthumb/src/jpegutils/README	1969-12-31 17:00:00.000000000 -0700
@@ -1,385 +0,0 @@
-The Independent JPEG Group's JPEG software
-==========================================
-
-README for release 6b of 27-Mar-1998
-====================================
-
-This distribution contains the sixth public release of the Independent JPEG
-Group's free JPEG software.  You are welcome to redistribute this software and
-to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
-
-Serious users of this software (particularly those incorporating it into
-larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to
-our electronic mailing list.  Mailing list members are notified of updates
-and have a chance to participate in technical discussions, etc.
-
-This software is the work of Tom Lane, Philip Gladstone, Jim Boucher,
-Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi,
-Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG
-Group.
-
-IJG is not affiliated with the official ISO JPEG standards committee.
-
-
-DOCUMENTATION ROADMAP
-=====================
-
-This file contains the following sections:
-
-OVERVIEW            General description of JPEG and the IJG software.
-LEGAL ISSUES        Copyright, lack of warranty, terms of distribution.
-REFERENCES          Where to learn more about JPEG.
-ARCHIVE LOCATIONS   Where to find newer versions of this software.
-RELATED SOFTWARE    Other stuff you should get.
-FILE FORMAT WARS    Software *not* to get.
-TO DO               Plans for future IJG releases.
-
-Other documentation files in the distribution are:
-
-User documentation:
-  install.doc       How to configure and install the IJG software.
-  usage.doc         Usage instructions for cjpeg, djpeg, jpegtran,
-                    rdjpgcom, and wrjpgcom.
-  *.1               Unix-style man pages for programs (same info as usage.doc).
-  wizard.doc        Advanced usage instructions for JPEG wizards only.
-  change.log        Version-to-version change highlights.
-Programmer and internal documentation:
-  libjpeg.doc       How to use the JPEG library in your own programs.
-  example.c         Sample code for calling the JPEG library.
-  structure.doc     Overview of the JPEG library's internal structure.
-  filelist.doc      Road map of IJG files.
-  coderules.doc     Coding style rules --- please read if you contribute code.
-
-Please read at least the files install.doc and usage.doc.  Useful information
-can also be found in the JPEG FAQ (Frequently Asked Questions) article.  See
-ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
-
-If you want to understand how the JPEG code works, we suggest reading one or
-more of the REFERENCES, then looking at the documentation files (in roughly
-the order listed) before diving into the code.
-
-
-OVERVIEW
-========
-
-This package contains C software to implement JPEG image compression and
-decompression.  JPEG (pronounced "jay-peg") is a standardized compression
-method for full-color and gray-scale images.  JPEG is intended for compressing
-"real-world" scenes; line drawings, cartoons and other non-realistic images
-are not its strong suit.  JPEG is lossy, meaning that the output image is not
-exactly identical to the input image.  Hence you must not use JPEG if you
-have to have identical output bits.  However, on typical photographic images,
-very good compression levels can be obtained with no visible change, and
-remarkably high compression levels are possible if you can tolerate a
-low-quality image.  For more details, see the references, or just experiment
-with various compression settings.
-
-This software implements JPEG baseline, extended-sequential, and progressive
-compression processes.  Provision is made for supporting all variants of these
-processes, although some uncommon parameter settings aren't implemented yet.
-For legal reasons, we are not distributing code for the arithmetic-coding
-variants of JPEG; see LEGAL ISSUES.  We have made no provision for supporting
-the hierarchical or lossless processes defined in the standard.
-
-We provide a set of library routines for reading and writing JPEG image files,
-plus two sample applications "cjpeg" and "djpeg", which use the library to
-perform conversion between JPEG and some other popular image file formats.
-The library is intended to be reused in other applications.
-
-In order to support file conversion and viewing software, we have included
-considerable functionality beyond the bare JPEG coding/decoding capability;
-for example, the color quantization modules are not strictly part of JPEG
-decoding, but they are essential for output to colormapped file formats or
-colormapped displays.  These extra functions can be compiled out of the
-library if not required for a particular application.  We have also included
-"jpegtran", a utility for lossless transcoding between different JPEG
-processes, and "rdjpgcom" and "wrjpgcom", two simple applications for
-inserting and extracting textual comments in JFIF files.
-
-The emphasis in designing this software has been on achieving portability and
-flexibility, while also making it fast enough to be useful.  In particular,
-the software is not intended to be read as a tutorial on JPEG.  (See the
-REFERENCES section for introductory material.)  Rather, it is intended to
-be reliable, portable, industrial-strength code.  We do not claim to have
-achieved that goal in every aspect of the software, but we strive for it.
-
-We welcome the use of this software as a component of commercial products.
-No royalty is required, but we do ask for an acknowledgement in product
-documentation, as described under LEGAL ISSUES.
-
-
-LEGAL ISSUES
-============
-
-In plain English:
-
-1. We don't promise that this software works.  (But if you find any bugs,
-   please let us know!)
-2. You can use this software for whatever you want.  You don't have to pay us.
-3. You may not pretend that you wrote this software.  If you use it in a
-   program, you must acknowledge somewhere in your documentation that
-   you've used the IJG code.
-
-In legalese:
-
-The authors make NO WARRANTY or representation, either express or implied,
-with respect to this software, its quality, accuracy, merchantability, or
-fitness for a particular purpose.  This software is provided "AS IS", and you,
-its user, assume the entire risk as to its quality and accuracy.
-
-This software is copyright (C) 1991-1998, Thomas G. Lane.
-All Rights Reserved except as specified below.
-
-Permission is hereby granted to use, copy, modify, and distribute this
-software (or portions thereof) for any purpose, without fee, subject to these
-conditions:
-(1) If any part of the source code for this software is distributed, then this
-README file must be included, with this copyright and no-warranty notice
-unaltered; and any additions, deletions, or changes to the original files
-must be clearly indicated in accompanying documentation.
-(2) If only executable code is distributed, then the accompanying
-documentation must state that "this software is based in part on the work of
-the Independent JPEG Group".
-(3) Permission for use of this software is granted only if the user accepts
-full responsibility for any undesirable consequences; the authors accept
-NO LIABILITY for damages of any kind.
-
-These conditions apply to any software derived from or based on the IJG code,
-not just to the unmodified library.  If you use our work, you ought to
-acknowledge us.
-
-Permission is NOT granted for the use of any IJG author's name or company name
-in advertising or publicity relating to this software or products derived from
-it.  This software may be referred to only as "the Independent JPEG Group's
-software".
-
-We specifically permit and encourage the use of this software as the basis of
-commercial products, provided that all warranty or liability claims are
-assumed by the product vendor.
-
-
-ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
-sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
-ansi2knr.c is NOT covered by the above copyright and conditions, but instead
-by the usual distribution terms of the Free Software Foundation; principally,
-that you must include source code if you redistribute it.  (See the file
-ansi2knr.c for full details.)  However, since ansi2knr.c is not needed as part
-of any program generated from the IJG code, this does not limit you more than
-the foregoing paragraphs do.
-
-The Unix configuration script "configure" was produced with GNU Autoconf.
-It is copyright by the Free Software Foundation but is freely distributable.
-The same holds for its supporting scripts (config.guess, config.sub,
-ltconfig, ltmain.sh).  Another support script, install-sh, is copyright
-by M.I.T. but is also freely distributable.
-
-It appears that the arithmetic coding option of the JPEG spec is covered by
-patents owned by IBM, AT&T, and Mitsubishi.  Hence arithmetic coding cannot
-legally be used without obtaining one or more licenses.  For this reason,
-support for arithmetic coding has been removed from the free JPEG software.
-(Since arithmetic coding provides only a marginal gain over the unpatented
-Huffman mode, it is unlikely that very many implementations will support it.)
-So far as we are aware, there are no patent restrictions on the remaining
-code.
-
-The IJG distribution formerly included code to read and write GIF files.
-To avoid entanglement with the Unisys LZW patent, GIF reading support has
-been removed altogether, and the GIF writer has been simplified to produce
-"uncompressed GIFs".  This technique does not use the LZW algorithm; the
-resulting GIF files are larger than usual, but are readable by all standard
-GIF decoders.
-
-We are required to state that
-    "The Graphics Interchange Format(c) is the Copyright property of
-    CompuServe Incorporated.  GIF(sm) is a Service Mark property of
-    CompuServe Incorporated."
-
-
-REFERENCES
-==========
-
-We highly recommend reading one or more of these references before trying to
-understand the innards of the JPEG software.
-
-The best short technical introduction to the JPEG compression algorithm is
-	Wallace, Gregory K.  "The JPEG Still Picture Compression Standard",
-	Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
-(Adjacent articles in that issue discuss MPEG motion picture compression,
-applications of JPEG, and related topics.)  If you don't have the CACM issue
-handy, a PostScript file containing a revised version of Wallace's article is
-available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz.  The file (actually
-a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
-omits the sample images that appeared in CACM, but it includes corrections
-and some added material.  Note: the Wallace article is copyright ACM and IEEE,
-and it may not be used for commercial purposes.
-
-A somewhat less technical, more leisurely introduction to JPEG can be found in
-"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
-M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1.  This book provides
-good explanations and example C code for a multitude of compression methods
-including JPEG.  It is an excellent source if you are comfortable reading C
-code but don't know much about data compression in general.  The book's JPEG
-sample code is far from industrial-strength, but when you are ready to look
-at a full implementation, you've got one here...
-
-The best full description of JPEG is the textbook "JPEG Still Image Data
-Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published
-by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1.  Price US$59.95, 638 pp.
-The book includes the complete text of the ISO JPEG standards (DIS 10918-1
-and draft DIS 10918-2).  This is by far the most complete exposition of JPEG
-in existence, and we highly recommend it.
-
-The JPEG standard itself is not available electronically; you must order a
-paper copy through ISO or ITU.  (Unless you feel a need to own a certified
-official copy, we recommend buying the Pennebaker and Mitchell book instead;
-it's much cheaper and includes a great deal of useful explanatory material.)
-In the USA, copies of the standard may be ordered from ANSI Sales at (212)
-642-4900, or from Global Engineering Documents at (800) 854-7179.  (ANSI
-doesn't take credit card orders, but Global does.)  It's not cheap: as of
-1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
-shipping/handling.  The standard is divided into two parts, Part 1 being the
-actual specification, while Part 2 covers compliance testing methods.  Part 1
-is titled "Digital Compression and Coding of Continuous-tone Still Images,
-Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
-10918-1, ITU-T T.81.  Part 2 is titled "Digital Compression and Coding of
-Continuous-tone Still Images, Part 2: Compliance testing" and has document
-numbers ISO/IEC IS 10918-2, ITU-T T.83.
-
-Some extensions to the original JPEG standard are defined in JPEG Part 3,
-a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84.  IJG
-currently does not support any Part 3 extensions.
-
-The JPEG standard does not specify all details of an interchangeable file
-format.  For the omitted details we follow the "JFIF" conventions, revision
-1.02.  A copy of the JFIF spec is available from:
-	Literature Department
-	C-Cube Microsystems, Inc.
-	1778 McCarthy Blvd.
-	Milpitas, CA 95035
-	phone (408) 944-6300,  fax (408) 944-6314
-A PostScript version of this document is available by FTP at
-ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz.  There is also a plain text
-version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing
-the figures.
-
-The TIFF 6.0 file format specification can be obtained by FTP from
-ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz.  The JPEG incorporation scheme
-found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
-IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
-Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
-(Compression tag 7).  Copies of this Note can be obtained from ftp.sgi.com or
-from ftp://ftp.uu.net/graphics/jpeg/.  It is expected that the next revision
-of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
-Although IJG's own code does not support TIFF/JPEG, the free libtiff library
-uses our library to implement TIFF/JPEG per the Note.  libtiff is available
-from ftp://ftp.sgi.com/graphics/tiff/.
-
-
-ARCHIVE LOCATIONS
-=================
-
-The "official" archive site for this software is ftp.uu.net (Internet
-address 192.48.96.9).  The most recent released version can always be found
-there in directory graphics/jpeg.  This particular version will be archived
-as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz.  If you don't have
-direct Internet access, UUNET's archives are also available via UUCP; contact
-help@uunet.uu.net for information on retrieving files that way.
-
-Numerous Internet sites maintain copies of the UUNET files.  However, only
-ftp.uu.net is guaranteed to have the latest official version.
-
-You can also obtain this software in DOS-compatible "zip" archive format from
-the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or
-on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12
-"JPEG Tools".  Again, these versions may sometimes lag behind the ftp.uu.net
-release.
-
-The JPEG FAQ (Frequently Asked Questions) article is a useful source of
-general information about JPEG.  It is updated constantly and therefore is
-not included in this distribution.  The FAQ is posted every two weeks to
-Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
-It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
-and other news.answers archive sites, including the official news.answers
-archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
-If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
-with body
-	send usenet/news.answers/jpeg-faq/part1
-	send usenet/news.answers/jpeg-faq/part2
-
-
-RELATED SOFTWARE
-================
-
-Numerous viewing and image manipulation programs now support JPEG.  (Quite a
-few of them use this library to do so.)  The JPEG FAQ described above lists
-some of the more popular free and shareware viewers, and tells where to
-obtain them on Internet.
-
-If you are on a Unix machine, we highly recommend Jef Poskanzer's free
-PBMPLUS software, which provides many useful operations on PPM-format image
-files.  In particular, it can convert PPM images to and from a wide range of
-other formats, thus making cjpeg/djpeg considerably more useful.  The latest
-version is distributed by the NetPBM group, and is available from numerous
-sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/.
-Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is;
-you are likely to have difficulty making it work on any non-Unix machine.
-
-A different free JPEG implementation, written by the PVRG group at Stanford,
-is available from ftp://havefun.stanford.edu/pub/jpeg/.  This program
-is designed for research and experimentation rather than production use;
-it is slower, harder to use, and less portable than the IJG code, but it
-is easier to read and modify.  Also, the PVRG code supports lossless JPEG,
-which we do not.  (On the other hand, it doesn't do progressive JPEG.)
-
-
-FILE FORMAT WARS
-================
-
-Some JPEG programs produce files that are not compatible with our library.
-The root of the problem is that the ISO JPEG committee failed to specify a
-concrete file format.  Some vendors "filled in the blanks" on their own,
-creating proprietary formats that no one else could read.  (For example, none
-of the early commercial JPEG implementations for the Macintosh were able to
-exchange compressed files.)
-
-The file format we have adopted is called JFIF (see REFERENCES).  This format
-has been agreed to by a number of major commercial JPEG vendors, and it has
-become the de facto standard.  JFIF is a minimal or "low end" representation.
-We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF
-Technical Note #2) for "high end" applications that need to record a lot of
-additional data about an image.  TIFF/JPEG is fairly new and not yet widely
-supported, unfortunately.
-
-The upcoming JPEG Part 3 standard defines a file format called SPIFF.
-SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should
-be able to read the most common variant of SPIFF.  SPIFF has some technical
-advantages over JFIF, but its major claim to fame is simply that it is an
-official standard rather than an informal one.  At this point it is unclear
-whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto
-standard.  IJG intends to support SPIFF once the standard is frozen, but we
-have not decided whether it should become our default output format or not.
-(In any case, our decoder will remain capable of reading JFIF indefinitely.)
-
-Various proprietary file formats incorporating JPEG compression also exist.
-We have little or no sympathy for the existence of these formats.  Indeed,
-one of the original reasons for developing this free software was to help
-force convergence on common, open format standards for JPEG files.  Don't
-use a proprietary file format!
-
-
-TO DO
-=====
-
-The major thrust for v7 will probably be improvement of visual quality.
-The current method for scaling the quantization tables is known not to be
-very good at low Q values.  We also intend to investigate block boundary
-smoothing, "poor man's variable quantization", and other means of improving
-quality-vs-file-size performance without sacrificing compatibility.
-
-In future versions, we are considering supporting some of the upcoming JPEG
-Part 3 extensions --- principally, variable quantization and the SPIFF file
-format.
-
-As always, speeding things up is of great interest.
-
-Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
diff -Nru gthumb-old/src/jpegutils/transupp.c gthumb/src/jpegutils/transupp.c
--- gthumb-old/src/jpegutils/transupp.c	2002-11-28 07:44:00.000000000 -0700
+++ gthumb/src/jpegutils/transupp.c	1969-12-31 17:00:00.000000000 -0700
@@ -1,992 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- *  GThumb
- *
- *  Copyright (C) 2001, 2002 The Free Software Foundation, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- */
-
-/* based upon file transupp.c from the libjpeg package, original copyright 
- * note follows:
-.*
- *
- * transupp.c
- *
- * Copyright (C) 1997, Thomas G. Lane.
- * This file is part of the Independent JPEG Group's software.
- * For conditions of distribution and use, see the accompanying README file.
- *
- * This file contains image transformation routines and other utility code
- * used by the jpegtran sample application.  These are NOT part of the core
- * JPEG library.  But we keep these routines separate from jpegtran.c to
- * ease the task of maintaining jpegtran-like programs that have other user
- * interfaces.
- */
-
-#include <config.h>
-
-#ifdef HAVE_LIBJPEG
-
-#define SAVE_MARKERS_SUPPORTED 1
-
-#include <stdio.h>
-#include <jpeglib.h>
-#include "transupp.h"		/* My own external interface */
-
-#ifndef MAX
-#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
-#endif
-
-enum {
-  JERR_CONVERSION_NOTIMPL
-};
-
-#define ERREXIT(cinfo,code)  \
-  ((cinfo)->err->msg_code = (code), \
-   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
-
-
-static long
-jround_up (long a, long b)
-/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
-/* Assumes a >= 0, b > 0 */
-{
-  a += b - 1L;
-  return a - (a % b);
-}
-
-
-static void
-jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
-		 JDIMENSION num_blocks)
-/* Copy a row of coefficient blocks from one place to another. */
-{
-  register JCOEFPTR inptr, outptr;
-  register long count;
-
-  inptr = (JCOEFPTR) input_row;
-  outptr = (JCOEFPTR) output_row;
-  for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) {
-    *outptr++ = *inptr++;
-  }
-}
-
-
-/*
- * Lossless image transformation routines.  These routines work on DCT
- * coefficient arrays and thus do not require any lossy decompression
- * or recompression of the image.
- * Thanks to Guido Vollbeding for the initial design and code of this feature.
- *
- * Horizontal flipping is done in-place, using a single top-to-bottom
- * pass through the virtual source array.  It will thus be much the
- * fastest option for images larger than main memory.
- *
- * The other routines require a set of destination virtual arrays, so they
- * need twice as much memory as jpegtran normally does.  The destination
- * arrays are always written in normal scan order (top to bottom) because
- * the virtual array manager expects this.  The source arrays will be scanned
- * in the corresponding order, which means multiple passes through the source
- * arrays for most of the transforms.  That could result in much thrashing
- * if the image is larger than main memory.
- *
- * Some notes about the operating environment of the individual transform
- * routines:
- * 1. Both the source and destination virtual arrays are allocated from the
- *    source JPEG object, and therefore should be manipulated by calling the
- *    source's memory manager.
- * 2. The destination's component count should be used.  It may be smaller
- *    than the source's when forcing to grayscale.
- * 3. Likewise the destination's sampling factors should be used.  When
- *    forcing to grayscale the destination's sampling factors will be all 1,
- *    and we may as well take that as the effective iMCU size.
- * 4. When "trim" is in effect, the destination's dimensions will be the
- *    trimmed values but the source's will be untrimmed.
- * 5. All the routines assume that the source and destination buffers are
- *    padded out to a full iMCU boundary.  This is true, although for the
- *    source buffer it is an undocumented property of jdcoefct.c.
- * Notes 2,3,4 boil down to this: generally we should use the destination's
- * dimensions and ignore the source's.
- */
-
-
-static void
-do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
-	   jvirt_barray_ptr *src_coef_arrays)
-/* Horizontal flip; done in-place, so no separate dest array is required */
-{
-  JDIMENSION MCU_cols, comp_width, blk_x, blk_y;
-  int ci, k, offset_y;
-  JBLOCKARRAY buffer;
-  JCOEFPTR ptr1, ptr2;
-  JCOEF temp1, temp2;
-  jpeg_component_info *compptr;
-
-  /* Horizontal mirroring of DCT blocks is accomplished by swapping
-   * pairs of blocks in-place.  Within a DCT block, we perform horizontal
-   * mirroring by changing the signs of odd-numbered columns.
-   * Partial iMCUs at the right edge are left untouched.
-   */
-  MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
-
-  for (ci = 0; ci < dstinfo->num_components; ci++) {
-    compptr = dstinfo->comp_info + ci;
-    comp_width = MCU_cols * compptr->h_samp_factor;
-    for (blk_y = 0; blk_y < compptr->height_in_blocks;
-	 blk_y += compptr->v_samp_factor) {
-      buffer = (*srcinfo->mem->access_virt_barray)
-	((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
-	 (JDIMENSION) compptr->v_samp_factor, TRUE);
-      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
-	for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
-	  ptr1 = buffer[offset_y][blk_x];
-	  ptr2 = buffer[offset_y][comp_width - blk_x - 1];
-	  /* this unrolled loop doesn't need to know which row it's on... */
-	  for (k = 0; k < DCTSIZE2; k += 2) {
-	    temp1 = *ptr1;	/* swap even column */
-	    temp2 = *ptr2;
-	    *ptr1++ = temp2;
-	    *ptr2++ = temp1;
-	    temp1 = *ptr1;	/* swap odd column with sign change */
-	    temp2 = *ptr2;
-	    *ptr1++ = -temp2;
-	    *ptr2++ = -temp1;
-	  }
-	}
-      }
-    }
-  }
-}
-
-
-static void
-do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
-	   jvirt_barray_ptr *src_coef_arrays,
-	   jvirt_barray_ptr *dst_coef_arrays)
-/* Vertical flip */
-{
-  JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
-  int ci, i, j, offset_y;
-  JBLOCKARRAY src_buffer, dst_buffer;
-  JBLOCKROW src_row_ptr, dst_row_ptr;
-  JCOEFPTR src_ptr, dst_ptr;
-  jpeg_component_info *compptr;
-
-  /* We output into a separate array because we can't touch different
-   * rows of the source virtual array simultaneously.  Otherwise, this
-   * is a pretty straightforward analog of horizontal flip.
-   * Within a DCT block, vertical mirroring is done by changing the signs
-   * of odd-numbered rows.
-   * Partial iMCUs at the bottom edge are copied verbatim.
-   */
-  MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
-
-  for (ci = 0; ci < dstinfo->num_components; ci++) {
-    compptr = dstinfo->comp_info + ci;
-    comp_height = MCU_rows * compptr->v_samp_factor;
-    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
-	 dst_blk_y += compptr->v_samp_factor) {
-      dst_buffer = (*srcinfo->mem->access_virt_barray)
-	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
-	 (JDIMENSION) compptr->v_samp_factor, TRUE);
-      if (dst_blk_y < comp_height) {
-	/* Row is within the mirrorable area. */
-	src_buffer = (*srcinfo->mem->access_virt_barray)
-	  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
-	   comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
-	   (JDIMENSION) compptr->v_samp_factor, FALSE);
-      } else {
-	/* Bottom-edge blocks will be copied verbatim. */
-	src_buffer = (*srcinfo->mem->access_virt_barray)
-	  ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
-	   (JDIMENSION) compptr->v_samp_factor, FALSE);
-      }
-      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
-	if (dst_blk_y < comp_height) {
-	  /* Row is within the mirrorable area. */
-	  dst_row_ptr = dst_buffer[offset_y];
-	  src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
-	  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
-	       dst_blk_x++) {
-	    dst_ptr = dst_row_ptr[dst_blk_x];
-	    src_ptr = src_row_ptr[dst_blk_x];
-	    for (i = 0; i < DCTSIZE; i += 2) {
-	      /* copy even row */
-	      for (j = 0; j < DCTSIZE; j++)
-		*dst_ptr++ = *src_ptr++;
-	      /* copy odd row with sign change */
-	      for (j = 0; j < DCTSIZE; j++)
-		*dst_ptr++ = - *src_ptr++;
-	    }
-	  }
-	} else {
-	  /* Just copy row verbatim. */
-	  jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y],
-			  compptr->width_in_blocks);
-	}
-      }
-    }
-  }
-}
-
-
-static void
-do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
-	      jvirt_barray_ptr *src_coef_arrays,
-	      jvirt_barray_ptr *dst_coef_arrays)
-/* Transpose source into destination */
-{
-  JDIMENSION dst_blk_x, dst_blk_y;
-  int ci, i, j, offset_x, offset_y;
-  JBLOCKARRAY src_buffer, dst_buffer;
-  JCOEFPTR src_ptr, dst_ptr;
-  jpeg_component_info *compptr;
-
-  /* Transposing pixels within a block just requires transposing the
-   * DCT coefficients.
-   * Partial iMCUs at the edges require no special treatment; we simply
-   * process all the available DCT blocks for every component.
-   */
-  for (ci = 0; ci < dstinfo->num_components; ci++) {
-    compptr = dstinfo->comp_info + ci;
-    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
-	 dst_blk_y += compptr->v_samp_factor) {
-      dst_buffer = (*srcinfo->mem->access_virt_barray)
-	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
-	 (JDIMENSION) compptr->v_samp_factor, TRUE);
-      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
-	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
-	     dst_blk_x += compptr->h_samp_factor) {
-	  src_buffer = (*srcinfo->mem->access_virt_barray)
-	    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
-	     (JDIMENSION) compptr->h_samp_factor, FALSE);
-	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
-	    src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
-	    dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
-	    for (i = 0; i < DCTSIZE; i++)
-	      for (j = 0; j < DCTSIZE; j++)
-		dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
-	  }
-	}
-      }
-    }
-  }
-}
-
-
-static void
-do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
-	   jvirt_barray_ptr *src_coef_arrays,
-	   jvirt_barray_ptr *dst_coef_arrays)
-/* 90 degree rotation is equivalent to
- *   1. Transposing the image;
- *   2. Horizontal mirroring.
- * These two steps are merged into a single processing routine.
- */
-{
-  JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
-  int ci, i, j, offset_x, offset_y;
-  JBLOCKARRAY src_buffer, dst_buffer;
-  JCOEFPTR src_ptr, dst_ptr;
-  jpeg_component_info *compptr;
-
-  /* Because of the horizontal mirror step, we can't process partial iMCUs
-   * at the (output) right edge properly.  They just get transposed and
-   * not mirrored.
-   */
-  MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
-
-  for (ci = 0; ci < dstinfo->num_components; ci++) {
-    compptr = dstinfo->comp_info + ci;
-    comp_width = MCU_cols * compptr->h_samp_factor;
-    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
-	 dst_blk_y += compptr->v_samp_factor) {
-      dst_buffer = (*srcinfo->mem->access_virt_barray)
-	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
-	 (JDIMENSION) compptr->v_samp_factor, TRUE);
-      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
-	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
-	     dst_blk_x += compptr->h_samp_factor) {
-	  src_buffer = (*srcinfo->mem->access_virt_barray)
-	    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
-	     (JDIMENSION) compptr->h_samp_factor, FALSE);
-	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
-	    src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
-	    if (dst_blk_x < comp_width) {
-	      /* Block is within the mirrorable area. */
-	      dst_ptr = dst_buffer[offset_y]
-		[comp_width - dst_blk_x - offset_x - 1];
-	      for (i = 0; i < DCTSIZE; i++) {
-		for (j = 0; j < DCTSIZE; j++)
-		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
-		i++;
-		for (j = 0; j < DCTSIZE; j++)
-		  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
-	      }
-	    } else {
-	      /* Edge blocks are transposed but not mirrored. */
-	      dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
-	      for (i = 0; i < DCTSIZE; i++)
-		for (j = 0; j < DCTSIZE; j++)
-		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
-	    }
-	  }
-	}
-      }
-    }
-  }
-}
-
-
-static void
-do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
-	    jvirt_barray_ptr *src_coef_arrays,
-	    jvirt_barray_ptr *dst_coef_arrays)
-/* 270 degree rotation is equivalent to
- *   1. Horizontal mirroring;
- *   2. Transposing the image.
- * These two steps are merged into a single processing routine.
- */
-{
-  JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
-  int ci, i, j, offset_x, offset_y;
-  JBLOCKARRAY src_buffer, dst_buffer;
-  JCOEFPTR src_ptr, dst_ptr;
-  jpeg_component_info *compptr;
-
-  /* Because of the horizontal mirror step, we can't process partial iMCUs
-   * at the (output) bottom edge properly.  They just get transposed and
-   * not mirrored.
-   */
-  MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
-
-  for (ci = 0; ci < dstinfo->num_components; ci++) {
-    compptr = dstinfo->comp_info + ci;
-    comp_height = MCU_rows * compptr->v_samp_factor;
-    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
-	 dst_blk_y += compptr->v_samp_factor) {
-      dst_buffer = (*srcinfo->mem->access_virt_barray)
-	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
-	 (JDIMENSION) compptr->v_samp_factor, TRUE);
-      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
-	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
-	     dst_blk_x += compptr->h_samp_factor) {
-	  src_buffer = (*srcinfo->mem->access_virt_barray)
-	    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
-	     (JDIMENSION) compptr->h_samp_factor, FALSE);
-	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
-	    dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
-	    if (dst_blk_y < comp_height) {
-	      /* Block is within the mirrorable area. */
-	      src_ptr = src_buffer[offset_x]
-		[comp_height - dst_blk_y - offset_y - 1];
-	      for (i = 0; i < DCTSIZE; i++) {
-		for (j = 0; j < DCTSIZE; j++) {
-		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
-		  j++;
-		  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
-		}
-	      }
-	    } else {
-	      /* Edge blocks are transposed but not mirrored. */
-	      src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
-	      for (i = 0; i < DCTSIZE; i++)
-		for (j = 0; j < DCTSIZE; j++)
-		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
-	    }
-	  }
-	}
-      }
-    }
-  }
-}
-
-
-static void
-do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
-	    jvirt_barray_ptr *src_coef_arrays,
-	    jvirt_barray_ptr *dst_coef_arrays)
-/* 180 degree rotation is equivalent to
- *   1. Vertical mirroring;
- *   2. Horizontal mirroring.
- * These two steps are merged into a single processing routine.
- */
-{
-  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
-  int ci, i, j, offset_y;
-  JBLOCKARRAY src_buffer, dst_buffer;
-  JBLOCKROW src_row_ptr, dst_row_ptr;
-  JCOEFPTR src_ptr, dst_ptr;
-  jpeg_component_info *compptr;
-
-  MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
-  MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
-
-  for (ci = 0; ci < dstinfo->num_components; ci++) {
-    compptr = dstinfo->comp_info + ci;
-    comp_width = MCU_cols * compptr->h_samp_factor;
-    comp_height = MCU_rows * compptr->v_samp_factor;
-    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
-	 dst_blk_y += compptr->v_samp_factor) {
-      dst_buffer = (*srcinfo->mem->access_virt_barray)
-	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
-	 (JDIMENSION) compptr->v_samp_factor, TRUE);
-      if (dst_blk_y < comp_height) {
-	/* Row is within the vertically mirrorable area. */
-	src_buffer = (*srcinfo->mem->access_virt_barray)
-	  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
-	   comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
-	   (JDIMENSION) compptr->v_samp_factor, FALSE);
-      } else {
-	/* Bottom-edge rows are only mirrored horizontally. */
-	src_buffer = (*srcinfo->mem->access_virt_barray)
-	  ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
-	   (JDIMENSION) compptr->v_samp_factor, FALSE);
-      }
-      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
-	if (dst_blk_y < comp_height) {
-	  /* Row is within the mirrorable area. */
-	  dst_row_ptr = dst_buffer[offset_y];
-	  src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
-	  /* Process the blocks that can be mirrored both ways. */
-	  for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
-	    dst_ptr = dst_row_ptr[dst_blk_x];
-	    src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
-	    for (i = 0; i < DCTSIZE; i += 2) {
-	      /* For even row, negate every odd column. */
-	      for (j = 0; j < DCTSIZE; j += 2) {
-		*dst_ptr++ = *src_ptr++;
-		*dst_ptr++ = - *src_ptr++;
-	      }
-	      /* For odd row, negate every even column. */
-	      for (j = 0; j < DCTSIZE; j += 2) {
-		*dst_ptr++ = - *src_ptr++;
-		*dst_ptr++ = *src_ptr++;
-	      }
-	    }
-	  }
-	  /* Any remaining right-edge blocks are only mirrored vertically. */
-	  for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
-	    dst_ptr = dst_row_ptr[dst_blk_x];
-	    src_ptr = src_row_ptr[dst_blk_x];
-	    for (i = 0; i < DCTSIZE; i += 2) {
-	      for (j = 0; j < DCTSIZE; j++)
-		*dst_ptr++ = *src_ptr++;
-	      for (j = 0; j < DCTSIZE; j++)
-		*dst_ptr++ = - *src_ptr++;
-	    }
-	  }
-	} else {
-	  /* Remaining rows are just mirrored horizontally. */
-	  dst_row_ptr = dst_buffer[offset_y];
-	  src_row_ptr = src_buffer[offset_y];
-	  /* Process the blocks that can be mirrored. */
-	  for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
-	    dst_ptr = dst_row_ptr[dst_blk_x];
-	    src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
-	    for (i = 0; i < DCTSIZE2; i += 2) {
-	      *dst_ptr++ = *src_ptr++;
-	      *dst_ptr++ = - *src_ptr++;
-	    }
-	  }
-	  /* Any remaining right-edge blocks are only copied. */
-	  for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
-	    dst_ptr = dst_row_ptr[dst_blk_x];
-	    src_ptr = src_row_ptr[dst_blk_x];
-	    for (i = 0; i < DCTSIZE2; i++)
-	      *dst_ptr++ = *src_ptr++;
-	  }
-	}
-      }
-    }
-  }
-}
-
-
-static void
-do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
-	       jvirt_barray_ptr *src_coef_arrays,
-	       jvirt_barray_ptr *dst_coef_arrays)
-/* Transverse transpose is equivalent to
- *   1. 180 degree rotation;
- *   2. Transposition;
- * or
- *   1. Horizontal mirroring;
- *   2. Transposition;
- *   3. Horizontal mirroring.
- * These steps are merged into a single processing routine.
- */
-{
-  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
-  int ci, i, j, offset_x, offset_y;
-  JBLOCKARRAY src_buffer, dst_buffer;
-  JCOEFPTR src_ptr, dst_ptr;
-  jpeg_component_info *compptr;
-
-  MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
-  MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
-
-  for (ci = 0; ci < dstinfo->num_components; ci++) {
-    compptr = dstinfo->comp_info + ci;
-    comp_width = MCU_cols * compptr->h_samp_factor;
-    comp_height = MCU_rows * compptr->v_samp_factor;
-    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
-	 dst_blk_y += compptr->v_samp_factor) {
-      dst_buffer = (*srcinfo->mem->access_virt_barray)
-	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
-	 (JDIMENSION) compptr->v_samp_factor, TRUE);
-      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
-	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
-	     dst_blk_x += compptr->h_samp_factor) {
-	  src_buffer = (*srcinfo->mem->access_virt_barray)
-	    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
-	     (JDIMENSION) compptr->h_samp_factor, FALSE);
-	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
-	    if (dst_blk_y < comp_height) {
-	      src_ptr = src_buffer[offset_x]
-		[comp_height - dst_blk_y - offset_y - 1];
-	      if (dst_blk_x < comp_width) {
-		/* Block is within the mirrorable area. */
-		dst_ptr = dst_buffer[offset_y]
-		  [comp_width - dst_blk_x - offset_x - 1];
-		for (i = 0; i < DCTSIZE; i++) {
-		  for (j = 0; j < DCTSIZE; j++) {
-		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
-		    j++;
-		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
-		  }
-		  i++;
-		  for (j = 0; j < DCTSIZE; j++) {
-		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
-		    j++;
-		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
-		  }
-		}
-	      } else {
-		/* Right-edge blocks are mirrored in y only */
-		dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
-		for (i = 0; i < DCTSIZE; i++) {
-		  for (j = 0; j < DCTSIZE; j++) {
-		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
-		    j++;
-		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
-		  }
-		}
-	      }
-	    } else {
-	      src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
-	      if (dst_blk_x < comp_width) {
-		/* Bottom-edge blocks are mirrored in x only */
-		dst_ptr = dst_buffer[offset_y]
-		  [comp_width - dst_blk_x - offset_x - 1];
-		for (i = 0; i < DCTSIZE; i++) {
-		  for (j = 0; j < DCTSIZE; j++)
-		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
-		  i++;
-		  for (j = 0; j < DCTSIZE; j++)
-		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
-		}
-	      } else {
-		/* At lower right corner, just transpose, no mirroring */
-		dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
-		for (i = 0; i < DCTSIZE; i++)
-		  for (j = 0; j < DCTSIZE; j++)
-		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
-	      }
-	    }
-	  }
-	}
-      }
-    }
-  }
-}
-
-
-/* Request any required workspace.
- *
- * We allocate the workspace virtual arrays from the source decompression
- * object, so that all the arrays (both the original data and the workspace)
- * will be taken into account while making memory management decisions.
- * Hence, this routine must be called after jpeg_read_header (which reads
- * the image dimensions) and before jpeg_read_coefficients (which realizes
- * the source's virtual arrays).
- */
-
-void
-jtransform_request_workspace (j_decompress_ptr srcinfo,
-			      jpeg_transform_info *info)
-{
-  jvirt_barray_ptr *coef_arrays = NULL;
-  jpeg_component_info *compptr;
-  int ci;
-
-  if (info->force_grayscale &&
-      srcinfo->jpeg_color_space == JCS_YCbCr &&
-      srcinfo->num_components == 3) {
-    /* We'll only process the first component */
-    info->num_components = 1;
-  } else {
-    /* Process all the components */
-    info->num_components = srcinfo->num_components;
-  }
-
-  switch (info->transform) {
-  case JXFORM_NONE:
-  case JXFORM_FLIP_H:
-    /* Don't need a workspace array */
-    break;
-  case JXFORM_FLIP_V:
-  case JXFORM_ROT_180:
-    /* Need workspace arrays having same dimensions as source image.
-     * Note that we allocate arrays padded out to the next iMCU boundary,
-     * so that transform routines need not worry about missing edge blocks.
-     */
-    coef_arrays = (jvirt_barray_ptr *)
-      (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
-	sizeof(jvirt_barray_ptr) * info->num_components);
-    for (ci = 0; ci < info->num_components; ci++) {
-      compptr = srcinfo->comp_info + ci;
-      coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
-	((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
-	 (JDIMENSION) jround_up((long) compptr->width_in_blocks,
-				(long) compptr->h_samp_factor),
-	 (JDIMENSION) jround_up((long) compptr->height_in_blocks,
-				(long) compptr->v_samp_factor),
-	 (JDIMENSION) compptr->v_samp_factor);
-    }
-    break;
-  case JXFORM_TRANSPOSE:
-  case JXFORM_TRANSVERSE:
-  case JXFORM_ROT_90:
-  case JXFORM_ROT_270:
-    /* Need workspace arrays having transposed dimensions.
-     * Note that we allocate arrays padded out to the next iMCU boundary,
-     * so that transform routines need not worry about missing edge blocks.
-     */
-    coef_arrays = (jvirt_barray_ptr *)
-      (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
-	sizeof(jvirt_barray_ptr) * info->num_components);
-    for (ci = 0; ci < info->num_components; ci++) {
-      compptr = srcinfo->comp_info + ci;
-      coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
-	((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
-	 (JDIMENSION) jround_up((long) compptr->height_in_blocks,
-				(long) compptr->v_samp_factor),
-	 (JDIMENSION) jround_up((long) compptr->width_in_blocks,
-				(long) compptr->h_samp_factor),
-	 (JDIMENSION) compptr->h_samp_factor);
-    }
-    break;
-  }
-  info->workspace_coef_arrays = coef_arrays;
-}
-
-
-/* Transpose destination image parameters */
-
-static void
-transpose_critical_parameters (j_compress_ptr dstinfo)
-{
-  int tblno, i, j, ci, itemp;
-  jpeg_component_info *compptr;
-  JQUANT_TBL *qtblptr;
-  JDIMENSION dtemp;
-  UINT16 qtemp;
-
-  /* Transpose basic image dimensions */
-  dtemp = dstinfo->image_width;
-  dstinfo->image_width = dstinfo->image_height;
-  dstinfo->image_height = dtemp;
-
-  /* Transpose sampling factors */
-  for (ci = 0; ci < dstinfo->num_components; ci++) {
-    compptr = dstinfo->comp_info + ci;
-    itemp = compptr->h_samp_factor;
-    compptr->h_samp_factor = compptr->v_samp_factor;
-    compptr->v_samp_factor = itemp;
-  }
-
-  /* Transpose quantization tables */
-  for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
-    qtblptr = dstinfo->quant_tbl_ptrs[tblno];
-    if (qtblptr != NULL) {
-      for (i = 0; i < DCTSIZE; i++) {
-	for (j = 0; j < i; j++) {
-	  qtemp = qtblptr->quantval[i*DCTSIZE+j];
-	  qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
-	  qtblptr->quantval[j*DCTSIZE+i] = qtemp;
-	}
-      }
-    }
-  }
-}
-
-
-/* Trim off any partial iMCUs on the indicated destination edge */
-
-static void
-trim_right_edge (j_compress_ptr dstinfo)
-{
-  int ci, max_h_samp_factor;
-  JDIMENSION MCU_cols;
-
-  /* We have to compute max_h_samp_factor ourselves,
-   * because it hasn't been set yet in the destination
-   * (and we don't want to use the source's value).
-   */
-  max_h_samp_factor = 1;
-  for (ci = 0; ci < dstinfo->num_components; ci++) {
-    int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor;
-    max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor);
-  }
-  MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE);
-  if (MCU_cols > 0)		/* can't trim to 0 pixels */
-    dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE);
-}
-
-static void
-trim_bottom_edge (j_compress_ptr dstinfo)
-{
-  int ci, max_v_samp_factor;
-  JDIMENSION MCU_rows;
-
-  /* We have to compute max_v_samp_factor ourselves,
-   * because it hasn't been set yet in the destination
-   * (and we don't want to use the source's value).
-   */
-  max_v_samp_factor = 1;
-  for (ci = 0; ci < dstinfo->num_components; ci++) {
-    int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor;
-    max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor);
-  }
-  MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE);
-  if (MCU_rows > 0)		/* can't trim to 0 pixels */
-    dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE);
-}
-
-
-/* Adjust output image parameters as needed.
- *
- * This must be called after jpeg_copy_critical_parameters()
- * and before jpeg_write_coefficients().
- *
- * The return value is the set of virtual coefficient arrays to be written
- * (either the ones allocated by jtransform_request_workspace, or the
- * original source data arrays).  The caller will need to pass this value
- * to jpeg_write_coefficients().
- */
-
-jvirt_barray_ptr *
-jtransform_adjust_parameters (j_decompress_ptr srcinfo,
-			      j_compress_ptr dstinfo,
-			      jvirt_barray_ptr *src_coef_arrays,
-			      jpeg_transform_info *info)
-{
-  /* 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
-     * properly.  Among other things, the target h_samp_factor & v_samp_factor
-     * will get set to 1, which typically won't match the source.
-     * In fact we do this even if the source is already grayscale; that
-     * provides an easy way of coercing a grayscale JPEG with funny sampling
-     * factors to the customary 1,1.  (Some decoders fail on other factors.)
-     */
-    if ((dstinfo->jpeg_color_space == JCS_YCbCr &&
-	 dstinfo->num_components == 3) ||
-	(dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
-	 dstinfo->num_components == 1)) {
-      /* We have to preserve the source's quantization table number. */
-      int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
-      jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
-      dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
-    } else {
-      /* Sorry, can't do it */
-      ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
-    }
-  }
-
-  /* Correct the destination's image dimensions etc if necessary */
-  switch (info->transform) {
-  case JXFORM_NONE:
-    /* Nothing to do */
-    break;
-  case JXFORM_FLIP_H:
-    if (info->trim)
-      trim_right_edge(dstinfo);
-    break;
-  case JXFORM_FLIP_V:
-    if (info->trim)
-      trim_bottom_edge(dstinfo);
-    break;
-  case JXFORM_TRANSPOSE:
-    transpose_critical_parameters(dstinfo);
-    /* transpose does NOT have to trim anything */
-    break;
-  case JXFORM_TRANSVERSE:
-    transpose_critical_parameters(dstinfo);
-    if (info->trim) {
-      trim_right_edge(dstinfo);
-      trim_bottom_edge(dstinfo);
-    }
-    break;
-  case JXFORM_ROT_90:
-    transpose_critical_parameters(dstinfo);
-    if (info->trim)
-      trim_right_edge(dstinfo);
-    break;
-  case JXFORM_ROT_180:
-    if (info->trim) {
-      trim_right_edge(dstinfo);
-      trim_bottom_edge(dstinfo);
-    }
-    break;
-  case JXFORM_ROT_270:
-    transpose_critical_parameters(dstinfo);
-    if (info->trim)
-      trim_bottom_edge(dstinfo);
-    break;
-  }
-
-  /* Return the appropriate output data set */
-  if (info->workspace_coef_arrays != NULL)
-    return info->workspace_coef_arrays;
-  return src_coef_arrays;
-}
-
-
-/* Execute the actual transformation, if any.
- *
- * This must be called *after* jpeg_write_coefficients, because it depends
- * on jpeg_write_coefficients to have computed subsidiary values such as
- * the per-component width and height fields in the destination object.
- *
- * Note that some transformations will modify the source data arrays!
- */
-
-void
-jtransform_execute_transformation (j_decompress_ptr srcinfo,
-				   j_compress_ptr dstinfo,
-				   jvirt_barray_ptr *src_coef_arrays,
-				   jpeg_transform_info *info)
-{
-  jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
-
-  switch (info->transform) {
-  case JXFORM_NONE:
-    break;
-  case JXFORM_FLIP_H:
-    do_flip_h(srcinfo, dstinfo, src_coef_arrays);
-    break;
-  case JXFORM_FLIP_V:
-    do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
-    break;
-  case JXFORM_TRANSPOSE:
-    do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
-    break;
-  case JXFORM_TRANSVERSE:
-    do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
-    break;
-  case JXFORM_ROT_90:
-    do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
-    break;
-  case JXFORM_ROT_180:
-    do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
-    break;
-  case JXFORM_ROT_270:
-    do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
-    break;
-  }
-}
-
-
-/* Setup decompression object to save desired markers in memory.
- * This must be called before jpeg_read_header() to have the desired effect.
- */
-
-void
-jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
-{
-#ifdef SAVE_MARKERS_SUPPORTED
-  int m;
-
-  /* Save comments except under NONE option */
-  if (option != JCOPYOPT_NONE) {
-    jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
-  }
-  /* Save all types of APPn markers iff ALL option */
-  if (option == JCOPYOPT_ALL) {
-    for (m = 0; m < 16; m++)
-      jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
-  }
-#endif /* SAVE_MARKERS_SUPPORTED */
-}
-
-/* Copy markers saved in the given source object to the destination object.
- * This should be called just after jpeg_start_compress() or
- * jpeg_write_coefficients().
- * Note that those routines will have written the SOI, and also the
- * JFIF APP0 or Adobe APP14 markers if selected.
- */
-
-void
-jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
-		       JCOPY_OPTION option)
-{
-  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
-   * if the encoder library already wrote one.
-   */
-  for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
-    if (dstinfo->write_JFIF_header &&
-	marker->marker == JPEG_APP0 &&
-	marker->data_length >= 5 &&
-	GETJOCTET(marker->data[0]) == 0x4A &&
-	GETJOCTET(marker->data[1]) == 0x46 &&
-	GETJOCTET(marker->data[2]) == 0x49 &&
-	GETJOCTET(marker->data[3]) == 0x46 &&
-	GETJOCTET(marker->data[4]) == 0)
-      continue;			/* reject duplicate JFIF */
-    if (dstinfo->write_Adobe_marker &&
-	marker->marker == JPEG_APP0+14 &&
-	marker->data_length >= 5 &&
-	GETJOCTET(marker->data[0]) == 0x41 &&
-	GETJOCTET(marker->data[1]) == 0x64 &&
-	GETJOCTET(marker->data[2]) == 0x6F &&
-	GETJOCTET(marker->data[3]) == 0x62 &&
-	GETJOCTET(marker->data[4]) == 0x65)
-      continue;			/* reject duplicate Adobe */
-
-#ifdef NEED_FAR_POINTERS
-    /* We could use jpeg_write_marker if the data weren't FAR... */
-    {
-      unsigned int i;
-      jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
-      for (i = 0; i < marker->data_length; i++)
-	jpeg_write_m_byte(dstinfo, marker->data[i]);
-    }
-#else
-    jpeg_write_marker(dstinfo, marker->marker,
-		      marker->data, marker->data_length);
-#endif
-  }
-}
-
-
-#endif /* HAVE_LIBJPEG */
diff -Nru gthumb-old/src/jpegutils/transupp.h gthumb/src/jpegutils/transupp.h
--- gthumb-old/src/jpegutils/transupp.h	2003-08-24 09:21:17.000000000 -0600
+++ gthumb/src/jpegutils/transupp.h	1969-12-31 17:00:00.000000000 -0700
@@ -1,157 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- *  GThumb
- *
- *  Copyright (C) 2001, 2002 The Free Software Foundation, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- */
-
-/* based upon file transupp.h from the libjpeg package, original copyright 
- * note follows:
- *
- * transupp.h
- *
- * Copyright (C) 1997, Thomas G. Lane.
- * This file is part of the Independent JPEG Group's software.
- * For conditions of distribution and use, see the accompanying README file.
- *
- * This file contains declarations for image transformation routines and
- * other utility code used by the jpegtran sample application.  These are
- * NOT part of the core JPEG library.  But we keep these routines separate
- * from jpegtran.c to ease the task of maintaining jpegtran-like programs
- * that have other user interfaces.
- *
- * NOTE: all the routines declared here have very specific requirements
- * about when they are to be executed during the reading and writing of the
- * source and destination files.  See the comments in transupp.c, or see
- * jpegtran.c for an example of correct usage.
- */
-
-/*
- * Codes for supported types of image transformations.
- */
-
-#ifdef HAVE_LIBJPEG
-
-
-#ifndef TRANSUPP_H
-#define TRANSUPP_H
-
-#include <jpeglib.h>
-
-
-typedef enum {
-	JXFORM_NONE,		/* no transformation */
-	JXFORM_FLIP_H,		/* horizontal flip */
-	JXFORM_FLIP_V,		/* vertical flip */
-	JXFORM_TRANSPOSE,	/* transpose across UL-to-LR axis */
-	JXFORM_TRANSVERSE,	/* transpose across UR-to-LL axis */
-	JXFORM_ROT_90,		/* 90-degree clockwise rotation */
-	JXFORM_ROT_180,		/* 180-degree rotation */
-	JXFORM_ROT_270		/* 270-degree clockwise (or 90 ccw) */
-} JXFORM_CODE;
-
-/*
- * Although rotating and flipping data expressed as DCT coefficients is not
- * hard, there is an asymmetry in the JPEG format specification for images
- * whose dimensions aren't multiples of the iMCU size.  The right and bottom
- * image edges are padded out to the next iMCU boundary with junk data; but
- * no padding is possible at the top and left edges.  If we were to flip
- * the whole image including the pad data, then pad garbage would become
- * visible at the top and/or left, and real pixels would disappear into the
- * pad margins --- perhaps permanently, since encoders & decoders may not
- * bother to preserve DCT blocks that appear to be completely outside the
- * nominal image area.  So, we have to exclude any partial iMCUs from the
- * basic transformation.
- *
- * Transpose is the only transformation that can handle partial iMCUs at the
- * right and bottom edges completely cleanly.  flip_h can flip partial iMCUs
- * at the bottom, but leaves any partial iMCUs at the right edge untouched.
- * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched.
- * The other transforms are defined as combinations of these basic transforms
- * and process edge blocks in a way that preserves the equivalence.
- *
- * The "trim" option causes untransformable partial iMCUs to be dropped;
- * this is not strictly lossless, but it usually gives the best-looking
- * result for odd-size images.  Note that when this option is active,
- * the expected mathematical equivalences between the transforms may not hold.
- * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim
- * followed by -rot 180 -trim trims both edges.)
- *
- * We also offer a "force to grayscale" option, which simply discards the
- * chrominance channels of a YCbCr image.  This is lossless in the sense that
- * the luminance channel is preserved exactly.  It's not the same kind of
- * thing as the rotate/flip transformations, but it's convenient to handle it
- * as part of this package, mainly because the transformation routines have to
- * be aware of the option to know how many components to work on.
- */
-
-typedef struct {
-  /* Options: set by caller */
-  JXFORM_CODE transform;	/* image transform operator */
-  boolean trim;			/* if TRUE, trim partial MCUs as needed */
-  boolean force_grayscale;	/* if TRUE, convert color image to grayscale */
-
-  /* Internal workspace: caller should not touch these */
-  int num_components;		/* # of components in workspace */
-  jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */
-} jpeg_transform_info;
-
-
-/* Request any required workspace */
-void jtransform_request_workspace   (j_decompress_ptr     srcinfo, 
-				     jpeg_transform_info *info);
-
-/* Adjust output image parameters */
-
-jvirt_barray_ptr * jtransform_adjust_parameters (j_decompress_ptr     srcinfo, 
-						 j_compress_ptr       dstinfo,
-						 jvirt_barray_ptr    *src_coef_arrays,
-						 jpeg_transform_info *info);
-
-/* Execute the actual transformation, if any */
-void jtransform_execute_transformation (j_decompress_ptr     srcinfo, 
-					j_compress_ptr       dstinfo,
-					jvirt_barray_ptr    *src_coef_arrays,
-					jpeg_transform_info *info);
-
-
-/*
- * Support for copying optional markers from source to destination file.
- */
-
-typedef enum {
-	JCOPYOPT_NONE,		/* copy no optional markers */
-	JCOPYOPT_COMMENTS,	/* copy only comment (COM) markers */
-	JCOPYOPT_ALL		/* copy all optional markers */
-} JCOPY_OPTION;
-
-#define JCOPYOPT_DEFAULT  JCOPYOPT_COMMENTS	/* recommended default */
-
-/* Setup decompression object to save desired markers in memory */
-void jcopy_markers_setup (j_decompress_ptr srcinfo, 
-			  JCOPY_OPTION     option);
-
-/* Copy markers saved in the given source object to the destination object */
-void jcopy_markers_execute (j_decompress_ptr srcinfo, 
-			    j_compress_ptr   dstinfo,
-			    JCOPY_OPTION     option);
-
-
-#endif /* TRANSUPP_H */
-
-#endif /* HAVE_LIBJPEG */
diff -Nru gthumb-old/src/Makefile.am gthumb/src/Makefile.am
--- gthumb-old/src/Makefile.am	2006-04-08 14:07:13.000000000 -0600
+++ gthumb/src/Makefile.am	2006-09-29 12:58:02.000000000 -0600
@@ -1,5 +1,5 @@
-SUBDIRS = icons jpegutils
-DIST_SUBDIRS = icons jpegutils 
+SUBDIRS = icons
+DIST_SUBDIRS = icons 
 
 gladedir = $(datadir)/gthumb/glade
 
@@ -97,8 +97,6 @@
 	gth-browser-ui.h			\
 	gth-exif-data-viewer.c			\
 	gth-exif-data-viewer.h			\
-	gth-exif-utils.c			\
-	gth-exif-utils.h			\
 	gth-folder-selection-dialog.c		\
 	gth-folder-selection-dialog.h		\
 	gth-fullscreen.c			\
@@ -147,8 +145,7 @@
 	$(GPHOTO_LIBS)				\
 	$(XF86GAMMA_LIBS)			\
 	$(XTEST_LIBS)				\
-	$(top_builddir)/libgthumb/libgthumb.la	\
-	$(top_builddir)/src/jpegutils/libgthumb-jpegutils.la
+	$(top_builddir)/libgthumb/libgthumb.la
 
 moduledir = $(libdir)/gthumb/modules
 module_LTLIBRARIES = 		\
@@ -164,7 +161,7 @@
 
 libjpegtran_la_SOURCES = dlg-jpegtran.c dlg-jpegtran.h
 libjpegtran_la_LDFLAGS = $(MODULE_LIBTOOL_FLAGS)
-libjpegtran_la_LIBADD  = $(top_builddir)/src/jpegutils/libgthumb-jpegutils.la
+libjpegtran_la_LIBADD  = $(top_builddir)/libgthumb/jpegutils/libgthumb-jpegutils.la
 
 libpngexporter_la_SOURCES = 	\
 	catalog-png-exporter.c	\
@@ -188,7 +185,7 @@
 
 libphotoimporter_la_SOURCES = dlg-photo-importer.c dlg-photo-importer.h
 libphotoimporter_la_LDFLAGS = $(MODULE_LIBTOOL_FLAGS)
-libphotoimporter_la_LIBADD  = $(top_builddir)/src/jpegutils/libgthumb-jpegutils.la
+libphotoimporter_la_LIBADD  = $(top_builddir)/libgthumb/jpegutils/libgthumb-jpegutils.la
 
 EXTRA_DIST = 			\
 	GNOME_GThumb.idl	\
