[gthumb/ext] added ability to specify the file type options when saving images



commit 415a61cd7cb99a37abcc7879f87122aa76fcbc06
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sun Oct 11 21:08:42 2009 +0200

    added ability to specify the file type options when saving images

 configure.ac                                       |   38 ++-
 data/gthumb.schemas.in                             |  110 ----
 data/ui/preferences.ui                             |    2 +-
 extensions/Makefile.am                             |    2 +
 extensions/exiv2/exiv2-utils.cpp                   |    8 +-
 extensions/exiv2/exiv2-utils.h                     |    2 +-
 extensions/exiv2/gth-metadata-provider-exiv2.c     |    2 +-
 extensions/image_rotation/Makefile.am              |   12 -
 .../image_rotation/image_rotation.extension.in.in  |    1 +
 extensions/image_rotation/rotation-utils.c         |    8 +-
 extensions/image_rotation/rotation-utils.h         |    3 +-
 extensions/image_viewer/gth-image-viewer-page.c    |    8 +-
 extensions/jpeg_utils/Makefile.am                  |   38 ++
 .../{image_rotation => jpeg_utils}/jmemorydest.c   |    0
 .../jpeg_utils/jmemorydest.h                       |   22 +-
 .../{image_rotation => jpeg_utils}/jmemorysrc.c    |    0
 .../jpeg_utils/jmemorysrc.h                        |   22 +-
 extensions/jpeg_utils/jpeg_utils.extension.in.in   |    6 +
 .../{image_rotation => jpeg_utils}/jpegtran.c      |   10 +-
 .../{image_rotation => jpeg_utils}/jpegtran.h      |    1 +
 .../gthumb-error.c => extensions/jpeg_utils/main.c |   35 +-
 .../{image_rotation => jpeg_utils}/transupp.c      |    0
 .../{image_rotation => jpeg_utils}/transupp.h      |    0
 extensions/list_tools/gth-script-editor-dialog.c   |    4 +-
 extensions/pixbuf_savers/Makefile.am               |   67 +++
 extensions/pixbuf_savers/data/Makefile.am          |   18 +
 .../data/gthumb-pixbuf-savers.schemas.in           |  143 +++++
 extensions/pixbuf_savers/data/ui/Makefile.am       |   10 +
 extensions/pixbuf_savers/data/ui/jpeg-options.ui   |  120 +++++
 extensions/pixbuf_savers/data/ui/png-options.ui    |   55 ++
 .../data/ui/save-options-preferences.ui            |  167 ++++++
 extensions/pixbuf_savers/data/ui/tga-options.ui    |   26 +
 extensions/pixbuf_savers/data/ui/tiff-options.ui   |  280 ++++++++++
 extensions/pixbuf_savers/gth-jpeg-saver.c          |  512 ++++++++++++++++++
 extensions/pixbuf_savers/gth-jpeg-saver.h          |   57 ++
 extensions/pixbuf_savers/gth-png-saver.c           |  179 +++++++
 extensions/pixbuf_savers/gth-png-saver.h           |   57 ++
 extensions/pixbuf_savers/gth-tga-saver.c           |  414 +++++++++++++++
 extensions/pixbuf_savers/gth-tga-saver.h           |   57 ++
 extensions/pixbuf_savers/gth-tiff-saver.c          |  555 ++++++++++++++++++++
 extensions/pixbuf_savers/gth-tiff-saver.h          |   57 ++
 extensions/pixbuf_savers/main.c                    |   61 +++
 .../pixbuf_savers/pixbuf_savers.extension.in.in    |   11 +
 extensions/pixbuf_savers/preferences.c             |  164 ++++++
 extensions/pixbuf_savers/preferences.h             |   55 ++
 gthumb/Makefile.am                                 |   12 +-
 gthumb/gconf-utils.c                               |    4 +-
 gthumb/gth-browser.c                               |   10 +-
 gthumb/gth-buffer-data.c                           |  161 ++++++
 gthumb/gth-buffer-data.h                           |   51 ++
 gthumb/{gthumb-error.c => gth-error.c}             |    6 +-
 gthumb/{gthumb-error.h => gth-error.h}             |   10 +-
 gthumb/gth-extensions.c                            |    6 +-
 gthumb/gth-image-loader.c                          |    8 +-
 gthumb/gth-main.c                                  |   28 +
 gthumb/gth-main.h                                  |    6 +-
 gthumb/gth-pixbuf-list-task.c                      |    8 +-
 gthumb/gth-pixbuf-saver.c                          |  158 ++++++
 gthumb/gth-pixbuf-saver.h                          |   86 +++
 gthumb/gth-preferences.h                           |   13 -
 gthumb/gth-thumb-loader.c                          |   12 +-
 gthumb/pixbuf-io.c                                 |   34 +-
 gthumb/pixbuf-io.h                                 |    6 +-
 po/POTFILES.in                                     |   89 +++-
 64 files changed, 3835 insertions(+), 272 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 9e2e845..7162a64 100644
--- a/configure.ac
+++ b/configure.ac
@@ -223,17 +223,40 @@ AC_MSG_CHECKING(JPEG Support)
 AC_ARG_ENABLE([jpeg],
 	      [AS_HELP_STRING([--disable-jpeg],[do not compile code that uses the libjpeg library])],,
 	      [enable_jpeg=yes])
-AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
-             [enable_jpeg=yes],
-	     [enable_jpeg=no])
 if test "x$enable_jpeg" = "xyes"; then
-	AC_DEFINE(HAVE_LIBJPEG, 1, [Define to 1 if libjpeg support is included])
-	JPEG_LIBS='-ljpeg -lm -lz'
+	AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
+        	     [enable_jpeg=yes],
+	     	     [enable_jpeg=no])
+	if test "x$enable_jpeg" = "xyes"; then
+		AC_DEFINE(HAVE_LIBJPEG, 1, [Define to 1 if libjpeg support is included])
+		JPEG_LIBS='-ljpeg -lm -lz'
+	fi
 fi
 AC_SUBST(JPEG_LIBS)
 AM_CONDITIONAL(ENABLE_JPEG_TOOLS, test "x$enable_jpeg" = xyes)
 AC_MSG_RESULT($enable_jpeg)
 
+
+dnl ===========================================================================
+
+AC_MSG_CHECKING(TIFF Support)
+AC_ARG_ENABLE([tiff],
+	      [AC_HELP_STRING([--disable-tiff],[do not compile code that uses the libtiff library])],,
+	      [enable_tiff=yes])
+if test x$enable_tiff = xyes ; then
+	AC_CHECK_LIB(tiff, TIFFWriteScanline,
+		     [AC_CHECK_HEADER(tiffio.h,				    
+				      [enable_tiff=yes],
+				      [enable_tiff=no])],
+		     [enable_tiff=no])
+	if test "x$enable_tiff" = "xyes"; then
+		AC_DEFINE(HAVE_LIBTIFF, 1, [Define to 1 if libtiff support is included])
+		TIFF_LIBS='-ltiff -lm -lz'
+	fi
+fi
+AC_SUBST(TIFF_LIBS)
+AC_MSG_RESULT($enable_tiff)
+
 dnl ===========================================================================
 
 AC_CONFIG_FILES([
@@ -272,12 +295,16 @@ extensions/image_rotation/Makefile
 extensions/image_viewer/Makefile
 extensions/image_viewer/data/Makefile
 extensions/image_viewer/data/ui/Makefile
+extensions/jpeg_utils/Makefile
 extensions/list_tools/Makefile
 extensions/list_tools/data/Makefile
 extensions/list_tools/data/ui/Makefile
 extensions/photo_importer/Makefile
 extensions/photo_importer/data/Makefile
 extensions/photo_importer/data/ui/Makefile
+extensions/pixbuf_savers/Makefile
+extensions/pixbuf_savers/data/Makefile
+extensions/pixbuf_savers/data/ui/Makefile
 extensions/red_eye_removal/Makefile
 extensions/red_eye_removal/data/Makefile
 extensions/red_eye_removal/data/ui/Makefile
@@ -313,5 +340,6 @@ Configuration:
 	Build tests          : $ENABLE_TEST_SUITE
 	Exiv2 support        : ${enable_exiv2}
 	JPEG tools           : ${enable_jpeg}
+	TIFF tools           : ${enable_tiff}
 	Clutter support      : ${enable_clutter}
 "
diff --git a/data/gthumb.schemas.in b/data/gthumb.schemas.in
index 3964c4c..855ab05 100644
--- a/data/gthumb.schemas.in
+++ b/data/gthumb.schemas.in
@@ -492,116 +492,6 @@
 	</locale>
       </schema>
 
-      <!-- JPEG Saver -->
-
-      <schema>
-	<key>/schemas/apps/gthumb/dialogs/jpeg_saver/quality</key>
-	<applyto>/apps/gthumb/dialogs/jpeg_saver/quality</applyto>
-	<owner>gthumb</owner>
-	<type>int</type>
-	<default>85</default>
-	<locale name="C">
-	  <short></short>
-	  <long>
-	  </long>
-	</locale>
-      </schema>
-
-      <schema>
-	<key>/schemas/apps/gthumb/dialogs/jpeg_saver/smoothing</key>
-	<applyto>/apps/gthumb/dialogs/jpeg_saver/smoothing</applyto>
-	<owner>gthumb</owner>
-	<type>int</type>
-	<default>0</default>
-	<locale name="C">
-	  <short></short>
-	  <long>
-	  </long>
-	</locale>
-      </schema>
-
-      <schema>
-	<key>/schemas/apps/gthumb/dialogs/jpeg_saver/optimize</key>
-	<applyto>/apps/gthumb/dialogs/jpeg_saver/optimize</applyto>
-	<owner>gthumb</owner>
-	<type>bool</type>
-	<default>true</default>
-	<locale name="C">
-	  <short></short>
-	  <long>
-	  </long>
-	</locale>
-      </schema>
-
-      <schema>
-	<key>/schemas/apps/gthumb/dialogs/jpeg_saver/pregressive</key>
-	<applyto>/apps/gthumb/dialogs/jpeg_saver/pregressive</applyto>
-	<owner>gthumb</owner>
-	<type>bool</type>
-	<default>false</default>
-	<locale name="C">
-	  <short></short>
-	  <long>
-	  </long>
-	</locale>
-      </schema>
-
-      <!-- TGA Saver -->
-
-      <schema>
-	<key>/schemas/apps/gthumb/dialogs/tga_saver/rle_compression</key>
-	<applyto>/apps/gthumb/dialogs/tga_saver/rle_compression</applyto>
-	<owner>gthumb</owner>
-	<type>bool</type>
-	<default>true</default>
-	<locale name="C">
-	  <short></short>
-	  <long>
-	  </long>
-	</locale>
-      </schema>
-
-      <!-- TIFF Saver -->
-
-      <schema>
-	<key>/schemas/apps/gthumb/dialogs/tiff_saver/compression</key>
-	<applyto>/apps/gthumb/dialogs/tiff_saver/compression</applyto>
-	<owner>gthumb</owner>
-	<type>string</type>
-	<default>deflate</default>
-	<locale name="C">
-	  <short></short>
-	  <long> Possible values are: none, deflate, jpeg.
-	  </long>
-	</locale>
-      </schema>
-
-      <schema>
-	<key>/schemas/apps/gthumb/dialogs/tiff_saver/horizontal_resolution</key>
-	<applyto>/apps/gthumb/dialogs/tiff_saver/horizontal_resolution</applyto>
-	<owner>gthumb</owner>
-	<type>int</type>
-	<default>72</default>
-	<locale name="C">
-	  <short></short>
-	  <long>
-	  </long>
-	</locale>
-      </schema>
-
-      <schema>
-	<key>/schemas/apps/gthumb/dialogs/tiff_saver/vertical_resolution</key>
-	<applyto>/apps/gthumb/dialogs/tiff_saver/vertical_resolution</applyto>
-	<owner>gthumb</owner>
-	<type>int</type>
-	<default>72</default>
-	<locale name="C">
-	  <short></short>
-	  <long>
-	  </long>
-	</locale>
-      </schema>
-
       <!-- Messages -->
 
       <schema>
diff --git a/data/ui/preferences.ui b/data/ui/preferences.ui
index 837d7ab..37bfe3d 100644
--- a/data/ui/preferences.ui
+++ b/data/ui/preferences.ui
@@ -185,8 +185,8 @@
                                 <child>
                                   <object class="GtkFileChooserButton" id="startup_dir_filechooserbutton">
                                     <property name="visible">True</property>
-                                    <property name="action">select-folder</property>
                                     <property name="local_only">False</property>
+                                    <property name="action">select-folder</property>
                                     <property name="title" translatable="yes">Choose startup folder</property>
                                   </object>
                                   <packing>
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index aa92000..9d4c532 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -7,8 +7,10 @@ SUBDIRS = 		\
 	file_viewer	\
 	image_rotation	\
 	image_viewer	\
+	jpeg_utils	\
 	list_tools	\
 	photo_importer	\
+	pixbuf_savers	\
 	red_eye_removal	\
 	rename_series 	\
 	resize_images	\
diff --git a/extensions/exiv2/exiv2-utils.cpp b/extensions/exiv2/exiv2-utils.cpp
index 74b0fa7..739f15c 100644
--- a/extensions/exiv2/exiv2-utils.cpp
+++ b/extensions/exiv2/exiv2-utils.cpp
@@ -669,10 +669,10 @@ exiv2_write_metadata_private (Exiv2::Image::AutoPtr  image,
 
 extern "C"
 gboolean
-exiv2_supports_writes (GthFileData *file_data)
+exiv2_supports_writes (const char *mime_type)
 {
-	return (g_content_type_equals (gth_file_data_get_mime_type (file_data), "image/jpeg") ||
-		g_content_type_equals (gth_file_data_get_mime_type (file_data), "image/png"));
+	return (g_content_type_equals (mime_type, "image/jpeg") ||
+		g_content_type_equals (mime_type, "image/png"));
 }
 
 
@@ -680,7 +680,7 @@ extern "C"
 gboolean
 exiv2_write_metadata (SavePixbufData *data)
 {
-	if (exiv2_supports_writes (data->file_data)) {
+	if (exiv2_supports_writes (data->mime_type)) {
 		try {
 			Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open ((Exiv2::byte*) data->buffer, data->buffer_size);
 			g_assert (image.get() != 0);
diff --git a/extensions/exiv2/exiv2-utils.h b/extensions/exiv2/exiv2-utils.h
index c21dbf5..083e739 100644
--- a/extensions/exiv2/exiv2-utils.h
+++ b/extensions/exiv2/exiv2-utils.h
@@ -44,7 +44,7 @@ gboolean  exiv2_write_metadata_to_buffer   (void           **buffer,
 					    GFileInfo       *info,
 					    GdkPixbuf       *pixbuf, /* optional */
 					    GError         **error);
-gboolean  exiv2_supports_writes            (GthFileData     *file_data);
+gboolean  exiv2_supports_writes            (const char      *mime_type);
 
 G_END_DECLS
 
diff --git a/extensions/exiv2/gth-metadata-provider-exiv2.c b/extensions/exiv2/gth-metadata-provider-exiv2.c
index 86c694f..f611cd1 100644
--- a/extensions/exiv2/gth-metadata-provider-exiv2.c
+++ b/extensions/exiv2/gth-metadata-provider-exiv2.c
@@ -87,7 +87,7 @@ gth_metadata_provider_exiv2_write (GthMetadataProvider *self,
 	GError  *error = NULL;
 	GObject *metadata;
 
-	if (! exiv2_supports_writes (file_data))
+	if (! exiv2_supports_writes (gth_file_data_get_mime_type (file_data)))
 		return;
 
 	if (! g_load_file_in_buffer (file_data->file, &buffer, &size, &error))
diff --git a/extensions/image_rotation/Makefile.am b/extensions/image_rotation/Makefile.am
index c3b739b..7370a81 100644
--- a/extensions/image_rotation/Makefile.am
+++ b/extensions/image_rotation/Makefile.am
@@ -1,18 +1,6 @@
 extensiondir = $(libdir)/gthumb-2.0/extensions
 extension_LTLIBRARIES = libimage_rotation.la
 
-if ENABLE_JPEG_TOOLS
-JPEG_FILES =				\
-	jmemorydest.c			\
-	jmemorysrc.c			\
-	jpegtran.c			\
-	jpegtran.h			\
-	transupp.c			\
-	transupp.h
-else
-JPEG_FILES =
-endif
-
 libimage_rotation_la_SOURCES = 		\
 	$(JPEG_FILES)			\
 	actions.c			\
diff --git a/extensions/image_rotation/image_rotation.extension.in.in b/extensions/image_rotation/image_rotation.extension.in.in
index 422caba..827c2d4 100644
--- a/extensions/image_rotation/image_rotation.extension.in.in
+++ b/extensions/image_rotation/image_rotation.extension.in.in
@@ -8,3 +8,4 @@ Version=1.0
 [Loader]
 Type=module
 File=%LIBRARY%
+Requires=jpeg_utils
diff --git a/extensions/image_rotation/rotation-utils.c b/extensions/image_rotation/rotation-utils.c
index 8c691e3..17569b5 100644
--- a/extensions/image_rotation/rotation-utils.c
+++ b/extensions/image_rotation/rotation-utils.c
@@ -25,6 +25,7 @@
 #include <sys/types.h>
 #include <glib/gi18n.h>
 #include <gio/gio.h>
+#include <extensions/jpeg_utils/jpegtran.h>
 #include "rotation-utils.h"
 
 
@@ -303,7 +304,6 @@ file_buffer_ready_cb (void     *buffer,
 		GInputStream *istream;
 		GdkPixbuf    *original_pixbuf;
 		GdkPixbuf    *transformed_pixbuf;
-		char         *pixbuf_type;
 
 		istream = g_memory_input_stream_new_from_data (buffer, count, NULL);
 		original_pixbuf = gdk_pixbuf_new_from_stream (istream, tdata->cancellable, &error);
@@ -314,16 +314,12 @@ file_buffer_ready_cb (void     *buffer,
 		}
 
 		transformed_pixbuf = _gdk_pixbuf_transform (original_pixbuf, tdata->transform);
-		pixbuf_type = get_pixbuf_type_from_mime_type (gth_file_data_get_mime_type (tdata->file_data));
 		_gdk_pixbuf_save_async (transformed_pixbuf,
 					tdata->file_data,
-					pixbuf_type,
-					NULL,
-					NULL,
+					gth_file_data_get_mime_type (tdata->file_data),
 					pixbuf_saved_cb,
 					tdata);
 
-		g_free (pixbuf_type);
 		g_object_unref (transformed_pixbuf);
 		g_object_unref (original_pixbuf);
 		g_object_unref (istream);
diff --git a/extensions/image_rotation/rotation-utils.h b/extensions/image_rotation/rotation-utils.h
index 0f153d9..a25efe0 100644
--- a/extensions/image_rotation/rotation-utils.h
+++ b/extensions/image_rotation/rotation-utils.h
@@ -26,7 +26,8 @@
 #include <config.h>
 #include <gtk/gtk.h>
 #include <gthumb.h>
-#include "jpegtran.h"
+#include <extensions/jpeg_utils/jpegtran.h>
+
 
 typedef void (*TrimResponseFunc) (JpegMcuAction action, gpointer user_data);
 
diff --git a/extensions/image_viewer/gth-image-viewer-page.c b/extensions/image_viewer/gth-image-viewer-page.c
index 6fe64a6..06f5f98 100644
--- a/extensions/image_viewer/gth-image-viewer-page.c
+++ b/extensions/image_viewer/gth-image-viewer-page.c
@@ -736,7 +736,6 @@ _gth_image_viewer_page_real_save (GthViewerPage *base,
 {
 	GthImageViewerPage *self;
 	SaveData           *data;
-	char               *pixbuf_type;
 	GthFileData        *current_file;
 
 	self = (GthImageViewerPage *) base;
@@ -748,7 +747,6 @@ _gth_image_viewer_page_real_save (GthViewerPage *base,
 
 	if (mime_type == NULL)
 		mime_type = gth_file_data_get_mime_type (self->priv->file_data);
-	pixbuf_type = get_pixbuf_type_from_mime_type (mime_type);
 
 	current_file = gth_browser_get_current_file (self->priv->browser);
 	data->original_file = gth_file_data_dup (current_file);
@@ -758,13 +756,9 @@ _gth_image_viewer_page_real_save (GthViewerPage *base,
 
 	_gdk_pixbuf_save_async (gth_image_viewer_get_current_pixbuf (GTH_IMAGE_VIEWER (self->priv->viewer)),
 			        current_file,
-				pixbuf_type,
-				NULL,
-				NULL,
+			        mime_type,
 				image_saved_cb,
 				data);
-
-	g_free (pixbuf_type);
 }
 
 
diff --git a/extensions/jpeg_utils/Makefile.am b/extensions/jpeg_utils/Makefile.am
new file mode 100644
index 0000000..a6a447a
--- /dev/null
+++ b/extensions/jpeg_utils/Makefile.am
@@ -0,0 +1,38 @@
+extensiondir = $(libdir)/gthumb-2.0/extensions
+extension_LTLIBRARIES = libjpeg_utils.la
+
+if ENABLE_JPEG_TOOLS
+libjpeg_utils_la_SOURCES = 		\
+	jmemorydest.c			\
+	jmemorydest.h			\
+	jmemorysrc.c			\
+	jmemorysrc.h			\
+	jpegtran.c			\
+	jpegtran.h			\
+	main.c				\
+	transupp.c			\
+	transupp.h
+else
+libjpeg_utils_la_SOURCES =
+endif
+
+libjpeg_utils_la_CFLAGS = $(GTHUMB_CFLAGS) $(DISABLE_DEPRECATED) $(WARNINGS) -I$(top_srcdir) -I$(top_builddir)/gthumb 
+libjpeg_utils_la_LDFLAGS = $(EXTENSION_LIBTOOL_FLAGS)
+libjpeg_utils_la_LIBADD = $(GTHUMB_LIBS) $(JPEG_LIBS)
+libjpeg_utils_la_DEPENDENCIES = $(top_builddir)/gthumb/gthumb$(EXEEXT)
+
+extensioninidir = $(extensiondir)
+extensionini_in_files = jpeg_utils.extension.in.in
+extensionini_DATA = $(extensionini_in_files:.extension.in.in=.extension)
+
+%.extension.in: %.extension.in.in $(extension_LTLIBRARIES)
+	sed -e "s|%LIBRARY%|`. ./$(extension_LTLIBRARIES) && echo $$dlname`|" \
+	$< > $@
+
+%.extension: %.extension.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+
+EXTRA_DIST = $(extensionini_in_files) 
+
+DISTCLEANFILES = $(extensionini_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/extensions/image_rotation/jmemorydest.c b/extensions/jpeg_utils/jmemorydest.c
similarity index 100%
rename from extensions/image_rotation/jmemorydest.c
rename to extensions/jpeg_utils/jmemorydest.c
diff --git a/gthumb/gthumb-error.c b/extensions/jpeg_utils/jmemorydest.h
similarity index 73%
copy from gthumb/gthumb-error.c
copy to extensions/jpeg_utils/jmemorydest.h
index 18e5578..00354cc 100644
--- a/gthumb/gthumb-error.c
+++ b/extensions/jpeg_utils/jmemorydest.h
@@ -3,7 +3,7 @@
 /*
  *  GThumb
  *
- *  Copyright (C) 2001 The Free Software Foundation, Inc.
+ *  Copyright (C) 2001-2009 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
@@ -20,16 +20,14 @@
  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
  */
 
-#include "gthumb-error.h"
+#ifndef JMEMORYDEST_H
+#define JMEMORYDEST_H
 
+#include <jpeglib.h>
+#include <glib.h>
 
-GQuark 
-gthumb_error_quark (void)
-{
-	static GQuark quark;
-        
-        if (!quark)
-                quark = g_quark_from_static_string ("gthumb_error");
-	
-        return quark;
-}
+void _jpeg_memory_dest (j_compress_ptr     cinfo,
+			void             **out_buffer,
+			gsize             *out_buffer_size);
+
+#endif /* JMEMORYDEST_H */
diff --git a/extensions/image_rotation/jmemorysrc.c b/extensions/jpeg_utils/jmemorysrc.c
similarity index 100%
rename from extensions/image_rotation/jmemorysrc.c
rename to extensions/jpeg_utils/jmemorysrc.c
diff --git a/gthumb/gthumb-error.c b/extensions/jpeg_utils/jmemorysrc.h
similarity index 72%
copy from gthumb/gthumb-error.c
copy to extensions/jpeg_utils/jmemorysrc.h
index 18e5578..ba0fd69 100644
--- a/gthumb/gthumb-error.c
+++ b/extensions/jpeg_utils/jmemorysrc.h
@@ -3,7 +3,7 @@
 /*
  *  GThumb
  *
- *  Copyright (C) 2001 The Free Software Foundation, Inc.
+ *  Copyright (C) 2001-2009 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
@@ -20,16 +20,14 @@
  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
  */
 
-#include "gthumb-error.h"
+#ifndef JMEMORYSRC_H
+#define JMEMORYSRC_H
 
+#include <jpeglib.h>
+#include <glib.h>
 
-GQuark 
-gthumb_error_quark (void)
-{
-	static GQuark quark;
-        
-        if (!quark)
-                quark = g_quark_from_static_string ("gthumb_error");
-	
-        return quark;
-}
+void _jpeg_memory_src  (j_decompress_ptr   cinfo,
+		        void              *in_buffer,
+		        gsize              in_buffer_size);
+
+#endif /* JMEMORYSRC_H */
diff --git a/extensions/jpeg_utils/jpeg_utils.extension.in.in b/extensions/jpeg_utils/jpeg_utils.extension.in.in
new file mode 100644
index 0000000..9a557a4
--- /dev/null
+++ b/extensions/jpeg_utils/jpeg_utils.extension.in.in
@@ -0,0 +1,6 @@
+[Extension]
+Mandatory=true
+
+[Loader]
+Type=module
+File=%LIBRARY%
diff --git a/extensions/image_rotation/jpegtran.c b/extensions/jpeg_utils/jpegtran.c
similarity index 97%
rename from extensions/image_rotation/jpegtran.c
rename to extensions/jpeg_utils/jpegtran.c
index a71c370..5fc6350 100644
--- a/extensions/image_rotation/jpegtran.c
+++ b/extensions/jpeg_utils/jpegtran.c
@@ -49,6 +49,8 @@
 #include <glib.h>
 #include <gthumb.h>
 #include "transupp.h"
+#include "jmemorydest.h"
+#include "jmemorysrc.h"
 #include "jpegtran.h"
 
 
@@ -257,14 +259,6 @@ jpegtran_internal (struct jpeg_decompress_struct  *srcinfo,
 }
 
 
-void _jpeg_memory_src  (j_decompress_ptr   cinfo,
-		        void              *in_buffer,
-		        gsize              in_buffer_size);
-void _jpeg_memory_dest (j_compress_ptr     cinfo,
-			void             **out_buffer,
-			gsize             *out_buffer_size);
-
-
 gboolean
 jpegtran (void           *in_buffer,
 	  gsize           in_buffer_size,
diff --git a/extensions/image_rotation/jpegtran.h b/extensions/jpeg_utils/jpegtran.h
similarity index 98%
rename from extensions/image_rotation/jpegtran.h
rename to extensions/jpeg_utils/jpegtran.h
index ec62a5f..6c26139 100644
--- a/extensions/image_rotation/jpegtran.h
+++ b/extensions/jpeg_utils/jpegtran.h
@@ -25,6 +25,7 @@
 
 #include <config.h>
 #include <glib.h>
+#include <gthumb.h>
 #include "transupp.h"
 
 
diff --git a/gthumb/gthumb-error.c b/extensions/jpeg_utils/main.c
similarity index 68%
copy from gthumb/gthumb-error.c
copy to extensions/jpeg_utils/main.c
index 18e5578..a30b86f 100644
--- a/gthumb/gthumb-error.c
+++ b/extensions/jpeg_utils/main.c
@@ -3,7 +3,7 @@
 /*
  *  GThumb
  *
- *  Copyright (C) 2001 The Free Software Foundation, Inc.
+ *  Copyright (C) 2009 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
@@ -20,16 +20,31 @@
  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
  */
 
-#include "gthumb-error.h"
 
+#include <config.h>
+#include <gtk/gtk.h>
 
-GQuark 
-gthumb_error_quark (void)
+
+G_MODULE_EXPORT void
+gthumb_extension_activate (void)
+{
+}
+
+
+G_MODULE_EXPORT void
+gthumb_extension_deactivate (void)
+{
+}
+
+
+G_MODULE_EXPORT gboolean
+gthumb_extension_is_configurable (void)
+{
+	return FALSE;
+}
+
+
+G_MODULE_EXPORT void
+gthumb_extension_configure (GtkWindow *parent)
 {
-	static GQuark quark;
-        
-        if (!quark)
-                quark = g_quark_from_static_string ("gthumb_error");
-	
-        return quark;
 }
diff --git a/extensions/image_rotation/transupp.c b/extensions/jpeg_utils/transupp.c
similarity index 100%
rename from extensions/image_rotation/transupp.c
rename to extensions/jpeg_utils/transupp.c
diff --git a/extensions/image_rotation/transupp.h b/extensions/jpeg_utils/transupp.h
similarity index 100%
rename from extensions/image_rotation/transupp.h
rename to extensions/jpeg_utils/transupp.h
diff --git a/extensions/list_tools/gth-script-editor-dialog.c b/extensions/list_tools/gth-script-editor-dialog.c
index ab6eb1c..b2f1be0 100644
--- a/extensions/list_tools/gth-script-editor-dialog.c
+++ b/extensions/list_tools/gth-script-editor-dialog.c
@@ -238,13 +238,13 @@ gth_script_editor_dialog_get_script (GthScriptEditorDialog  *self,
 		      NULL);
 
 	if (g_strcmp0 (gth_script_get_display_name (script), "") == 0) {
-		*error = g_error_new (GTHUMB_ERROR, 0, _("No name specified"));
+		*error = g_error_new (GTH_ERROR, 0, _("No name specified"));
 		g_object_unref (script);
 		return NULL;
 	}
 
 	if (g_strcmp0 (gth_script_get_command (script), "") == 0) {
-		*error = g_error_new (GTHUMB_ERROR, 0, _("No command specified"));
+		*error = g_error_new (GTH_ERROR, 0, _("No command specified"));
 		g_object_unref (script);
 		return NULL;
 	}
diff --git a/extensions/pixbuf_savers/Makefile.am b/extensions/pixbuf_savers/Makefile.am
new file mode 100644
index 0000000..fac5059
--- /dev/null
+++ b/extensions/pixbuf_savers/Makefile.am
@@ -0,0 +1,67 @@
+SUBDIRS = data
+
+extensiondir = $(libdir)/gthumb-2.0/extensions
+extension_LTLIBRARIES = libpixbuf_savers.la
+
+ENUM_TYPES =				\
+	enum-types.h			\
+	enum-types.c
+
+HEADER_FILES = 				\
+	preferences.h
+
+enum-types.h: $(HEADER_FILES) $(GLIB_MKENUMS)
+	$(GLIB_MKENUMS) \
+		--fhead "#ifndef ENUM_TYPES_H\n#define ENUM_TYPES_H\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
+		--fprod "/* enumerations from \"@filename \" */\n" \
+		--vhead "GType @enum_name _get_type (void);\n#define GTH_TYPE_ ENUMSHORT@ (@enum_name _get_type())\n" \
+		--ftail "G_END_DECLS\n\n#endif /* ENUM_TYPES_H */" \
+		$^> xgen-$(@F) \
+	&& (cmp -s xgen-$(@F) enum-types.h || cp xgen-$(@F) enum-types.h ) \
+	&& rm -f xgen-$(@F)
+
+enum-types.c: $(HEADER_FILES) enum-types.h
+	$(GLIB_MKENUMS) \
+		--fhead "#include <glib-object.h>\n" \
+		--fprod "\n/* enumerations from \"@filename \" */\n#include \"@filename \"" \
+		--vhead "GType\n enum_name@_get_type (void)\n{\n  static GType etype = 0;\n  if (etype == 0) {\n    static const G Type@Value values[] = {" \
+		--vprod "      { @VALUENAME@, \"@VALUENAME \", \"@valuenick \" }," \
+		--vtail "      { 0, NULL, NULL }\n    };\n    etype = g_ type@_register_static (\"@EnumName \", values);\n  }\n  return etype;\n}\n" \
+		$^> xgen-$(@F) \
+	&& (cmp -s xgen-$(@F) enum-types.c || cp xgen-$(@F) enum-types.c ) \
+	&& rm -f xgen-$(@F)
+
+libpixbuf_savers_la_SOURCES = 	\
+	$(ENUM_TYPES)		\
+	$(HEADER_FILES)		\
+	gth-jpeg-saver.c	\
+	gth-jpeg-saver.h	\
+	gth-png-saver.c		\
+	gth-png-saver.h		\
+	gth-tga-saver.c		\
+	gth-tga-saver.h		\
+	gth-tiff-saver.c	\
+	gth-tiff-saver.h	\
+	main.c			\
+	preferences.c
+
+libpixbuf_savers_la_CFLAGS = $(GTHUMB_CFLAGS) $(CLUTTER_CFLAGS) $(DISABLE_DEPRECATED) $(WARNINGS) -I$(top_srcdir) -I$(top_builddir)/gthumb 
+libpixbuf_savers_la_LDFLAGS = $(EXTENSION_LIBTOOL_FLAGS)
+libpixbuf_savers_la_LIBADD = $(GTHUMB_LIBS) $(TIFF_LIBS)
+libpixbuf_savers_la_DEPENDENCIES = $(top_builddir)/gthumb/gthumb$(EXEEXT)
+
+extensioninidir = $(extensiondir)
+extensionini_in_files = pixbuf_savers.extension.in.in
+extensionini_DATA = $(extensionini_in_files:.extension.in.in=.extension)
+
+%.extension.in: %.extension.in.in $(extension_LTLIBRARIES)
+	sed -e "s|%LIBRARY%|`. ./$(extension_LTLIBRARIES) && echo $$dlname`|" \
+	$< > $@
+
+%.extension: %.extension.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+
+EXTRA_DIST = $(extensionini_in_files) 
+
+DISTCLEANFILES = $(extensionini_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/extensions/pixbuf_savers/data/Makefile.am b/extensions/pixbuf_savers/data/Makefile.am
new file mode 100644
index 0000000..5b8c51c
--- /dev/null
+++ b/extensions/pixbuf_savers/data/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = ui
+
+schemadir = @GCONF_SCHEMA_FILE_DIR@
+schema_in_files = gthumb-pixbuf-savers.schemas.in
+schema_DATA = $(schema_in_files:.schemas.in=.schemas)
+
+ INTLTOOL_SCHEMAS_RULE@
+
+if GCONF_SCHEMAS_INSTALL
+install-data-local:
+	GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(top_builddir)/extensions/pixbuf_savers/data/$(schema_DATA)
+endif
+
+EXTRA_DIST = $(schema_in_files)
+
+CLEANFILES = $(schema_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/extensions/pixbuf_savers/data/gthumb-pixbuf-savers.schemas.in b/extensions/pixbuf_savers/data/gthumb-pixbuf-savers.schemas.in
new file mode 100644
index 0000000..3e4fb41
--- /dev/null
+++ b/extensions/pixbuf_savers/data/gthumb-pixbuf-savers.schemas.in
@@ -0,0 +1,143 @@
+<gconfschemafile>
+    <schemalist>
+
+      <schema>
+        <key>/schemas/apps/gthumb/ext/save_options/ask_options</key>
+        <applyto>/apps/gthumb/ext/save_options/ask_options</applyto>
+        <owner>gthumb</owner>
+        <type>bool</type>
+        <default>true</default>
+        <locale name="C">
+          <short></short>
+          <long>
+          </long>
+        </locale>
+      </schema>
+
+      <!-- JPEG Options -->
+
+      <schema>
+	<key>/schemas/apps/gthumb/save_options/jpeg/quality</key>
+	<applyto>/apps/gthumb/save_options/jpeg/quality</applyto>
+	<owner>gthumb</owner>
+	<type>int</type>
+	<default>85</default>
+	<locale name="C">
+	  <short></short>
+	  <long>
+	  </long>
+	</locale>
+      </schema>
+
+      <schema>
+	<key>/schemas/apps/gthumb/save_options/jpeg/smoothing</key>
+	<applyto>/apps/gthumb/save_options/jpeg/smoothing</applyto>
+	<owner>gthumb</owner>
+	<type>int</type>
+	<default>0</default>
+	<locale name="C">
+	  <short></short>
+	  <long>
+	  </long>
+	</locale>
+      </schema>
+
+      <schema>
+	<key>/schemas/apps/gthumb/save_options/jpeg/optimize</key>
+	<applyto>/apps/gthumb/save_options/jpeg/optimize</applyto>
+	<owner>gthumb</owner>
+	<type>bool</type>
+	<default>true</default>
+	<locale name="C">
+	  <short></short>
+	  <long>
+	  </long>
+	</locale>
+      </schema>
+
+      <schema>
+	<key>/schemas/apps/gthumb/save_options/jpeg/pregressive</key>
+	<applyto>/apps/gthumb/save_options/jpeg/pregressive</applyto>
+	<owner>gthumb</owner>
+	<type>bool</type>
+	<default>false</default>
+	<locale name="C">
+	  <short></short>
+	  <long>
+	  </long>
+	</locale>
+      </schema>
+
+      <!-- PNG Options -->
+
+      <schema>
+	<key>/schemas/apps/gthumb/save_options/png/compression_level</key>
+	<applyto>/apps/gthumb/save_options/png/compression_level</applyto>
+	<owner>gthumb</owner>
+	<type>int</type>
+	<default>6</default>
+	<locale name="C">
+	  <short></short>
+	  <long>
+	  </long>
+	</locale>
+      </schema>
+
+      <!-- TGA Options -->
+
+      <schema>
+	<key>/schemas/apps/gthumb/save_options/tga/rle_compression</key>
+	<applyto>/apps/gthumb/save_options/tga/rle_compression</applyto>
+	<owner>gthumb</owner>
+	<type>bool</type>
+	<default>true</default>
+	<locale name="C">
+	  <short></short>
+	  <long>
+	  </long>
+	</locale>
+      </schema>
+
+      <!-- TIFF Options -->
+
+      <schema>
+	<key>/schemas/apps/gthumb/save_options/tiff/compression</key>
+	<applyto>/apps/gthumb/save_options/tiff/compression</applyto>
+	<owner>gthumb</owner>
+	<type>string</type>
+	<default>deflate</default>
+	<locale name="C">
+	  <short></short>
+	  <long> Possible values are: none, deflate, jpeg.
+	  </long>
+	</locale>
+      </schema>
+
+      <schema>
+	<key>/schemas/apps/gthumb/save_options/tiff/horizontal_resolution</key>
+	<applyto>/apps/gthumb/save_options/tiff/horizontal_resolution</applyto>
+	<owner>gthumb</owner>
+	<type>int</type>
+	<default>72</default>
+	<locale name="C">
+	  <short></short>
+	  <long>
+	  </long>
+	</locale>
+      </schema>
+
+      <schema>
+	<key>/schemas/apps/gthumb/save_options/tiff/vertical_resolution</key>
+	<applyto>/apps/gthumb/save_options/tiff/vertical_resolution</applyto>
+	<owner>gthumb</owner>
+	<type>int</type>
+	<default>72</default>
+	<locale name="C">
+	  <short></short>
+	  <long>
+	  </long>
+	</locale>
+      </schema>
+
+    </schemalist>
+</gconfschemafile>
diff --git a/extensions/pixbuf_savers/data/ui/Makefile.am b/extensions/pixbuf_savers/data/ui/Makefile.am
new file mode 100644
index 0000000..cf1d274
--- /dev/null
+++ b/extensions/pixbuf_savers/data/ui/Makefile.am
@@ -0,0 +1,10 @@
+uidir = $(datadir)/gthumb-2.0/ui
+ui_DATA = 				\
+	jpeg-options.ui 		\
+	png-options.ui			\
+	save-options-preferences.ui	\
+	tga-options.ui			\
+	tiff-options.ui
+EXTRA_DIST = $(ui_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/extensions/pixbuf_savers/data/ui/jpeg-options.ui b/extensions/pixbuf_savers/data/ui/jpeg-options.ui
new file mode 100644
index 0000000..cb0c07c
--- /dev/null
+++ b/extensions/pixbuf_savers/data/ui/jpeg-options.ui
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires gtk+ 2.12 -->
+  <!-- interface-naming-policy toplevel-contextual -->
+  <object class="GtkAdjustment" id="jpeg_quality_adjustment">
+    <property name="value">75</property>
+    <property name="upper">100</property>
+    <property name="step_increment">0.5</property>
+    <property name="page_increment">1</property>
+  </object>
+  <object class="GtkAdjustment" id="jpeg_smooth_adjustment">
+    <property name="upper">100</property>
+    <property name="step_increment">0.5</property>
+    <property name="page_increment">1</property>
+  </object>
+  <object class="GtkTable" id="jpeg_options">
+    <property name="visible">True</property>
+    <property name="border_width">6</property>
+    <property name="n_rows">4</property>
+    <property name="n_columns">2</property>
+    <property name="column_spacing">12</property>
+    <property name="row_spacing">6</property>
+    <child>
+      <object class="GtkCheckButton" id="jpeg_optimize_checkbutton">
+        <property name="label" translatable="yes">Opti_mize</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">False</property>
+        <property name="use_underline">True</property>
+        <property name="active">True</property>
+        <property name="draw_indicator">True</property>
+      </object>
+      <packing>
+        <property name="right_attach">2</property>
+        <property name="top_attach">2</property>
+        <property name="bottom_attach">3</property>
+        <property name="x_options">GTK_FILL</property>
+        <property name="y_options"></property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkCheckButton" id="jpeg_progressive_checkbutton">
+        <property name="label" translatable="yes">_Progressive</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">False</property>
+        <property name="use_underline">True</property>
+        <property name="draw_indicator">True</property>
+      </object>
+      <packing>
+        <property name="right_attach">2</property>
+        <property name="top_attach">3</property>
+        <property name="bottom_attach">4</property>
+        <property name="x_options">GTK_FILL</property>
+        <property name="y_options"></property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="label127">
+        <property name="visible">True</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">_Quality:</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">jpeg_quality_hscale</property>
+      </object>
+      <packing>
+        <property name="x_options">GTK_FILL</property>
+        <property name="y_options">GTK_FILL</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkHScale" id="jpeg_quality_hscale">
+        <property name="width_request">150</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="adjustment">jpeg_quality_adjustment</property>
+        <property name="digits">0</property>
+        <property name="value_pos">left</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="right_attach">2</property>
+        <property name="y_options">GTK_FILL</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkHScale" id="jpeg_smooth_hscale">
+        <property name="width_request">150</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="adjustment">jpeg_smooth_adjustment</property>
+        <property name="digits">0</property>
+        <property name="value_pos">left</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="right_attach">2</property>
+        <property name="top_attach">1</property>
+        <property name="bottom_attach">2</property>
+        <property name="x_options">GTK_FILL</property>
+        <property name="y_options">GTK_FILL</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="label130">
+        <property name="visible">True</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">_Smoothing:</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">jpeg_smooth_hscale</property>
+      </object>
+      <packing>
+        <property name="top_attach">1</property>
+        <property name="bottom_attach">2</property>
+        <property name="x_options">GTK_FILL</property>
+        <property name="y_options">GTK_FILL</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/extensions/pixbuf_savers/data/ui/png-options.ui b/extensions/pixbuf_savers/data/ui/png-options.ui
new file mode 100644
index 0000000..96dcde0
--- /dev/null
+++ b/extensions/pixbuf_savers/data/ui/png-options.ui
@@ -0,0 +1,55 @@
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires gtk+ 2.12 -->
+  <!-- interface-naming-policy toplevel-contextual -->
+  <object class="GtkAdjustment" id="png_compression_adjustment">
+    <property name="value">6</property>
+    <property name="upper">9</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">1</property>
+  </object>
+  <object class="GtkVBox" id="png_options">
+    <property name="visible">True</property>
+    <property name="border_width">6</property>
+    <property name="orientation">vertical</property>
+    <child>
+      <object class="GtkHBox" id="hbox64">
+        <property name="visible">True</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkLabel" id="label126">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="yalign">0.89999997615814209</property>
+            <property name="label" translatable="yes">Compression _level:</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">png_compression_hscale</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHScale" id="png_compression_hscale">
+            <property name="width_request">100</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="adjustment">png_compression_adjustment</property>
+            <property name="digits">0</property>
+            <property name="value_pos">left</property>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">False</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/extensions/pixbuf_savers/data/ui/save-options-preferences.ui b/extensions/pixbuf_savers/data/ui/save-options-preferences.ui
new file mode 100644
index 0000000..65c6bd2
--- /dev/null
+++ b/extensions/pixbuf_savers/data/ui/save-options-preferences.ui
@@ -0,0 +1,167 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkListStore" id="file_type_liststore">
+    <columns>
+      <!-- column-name gint1 -->
+      <column type="gint"/>
+      <!-- column-name GObject1 -->
+      <column type="GObject"/>
+      <!-- column-name gchararray1 -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkVBox" id="preferences_page">
+    <property name="visible">True</property>
+    <property name="border_width">12</property>
+    <property name="orientation">vertical</property>
+    <property name="spacing">12</property>
+    <child>
+      <object class="GtkCheckButton" id="ask_options_checkbutton">
+        <property name="label" translatable="yes">_Ask the options before saving a file</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">False</property>
+        <property name="use_underline">True</property>
+        <property name="draw_indicator">True</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="vbox2">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="label1">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">Default options:</property>
+            <attributes>
+              <attribute name="weight" value="bold"/>
+            </attributes>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHPaned" id="hpaned1">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="position">100</property>
+            <property name="position_set">True</property>
+            <child>
+              <object class="GtkScrolledWindow" id="scrolledwindow1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">automatic</property>
+                <property name="vscrollbar_policy">automatic</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="file_type_treeview">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="model">file_type_liststore</property>
+                    <property name="headers_visible">False</property>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+                        <child>
+                          <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                          <attributes>
+                            <attribute name="text">2</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="resize">False</property>
+                <property name="shrink">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkVBox" id="file_type_options_box">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkLabel" id="file_type_label">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                      <attribute name="size" value="10000"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHSeparator" id="hseparator1">
+                    <property name="visible">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="padding">6</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkNotebook" id="options_notebook">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="show_tabs">False</property>
+                    <property name="show_border">False</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child type="tab">
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child type="tab">
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child type="tab">
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="resize">True</property>
+                <property name="shrink">True</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+  <object class="GtkTreeViewColumn" id="file_type_treeviewcolumn"/>
+</interface>
diff --git a/extensions/pixbuf_savers/data/ui/tga-options.ui b/extensions/pixbuf_savers/data/ui/tga-options.ui
new file mode 100644
index 0000000..993e8f1
--- /dev/null
+++ b/extensions/pixbuf_savers/data/ui/tga-options.ui
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires gtk+ 2.12 -->
+  <!-- interface-naming-policy toplevel-contextual -->
+  <object class="GtkVBox" id="tga_options">
+    <property name="visible">True</property>
+    <property name="border_width">6</property>
+    <property name="orientation">vertical</property>
+    <child>
+      <object class="GtkCheckButton" id="tga_rle_compression_checkbutton">
+        <property name="label" translatable="yes">_RLE compression</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">False</property>
+        <property name="use_underline">True</property>
+        <property name="active">True</property>
+        <property name="draw_indicator">True</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">False</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/extensions/pixbuf_savers/data/ui/tiff-options.ui b/extensions/pixbuf_savers/data/ui/tiff-options.ui
new file mode 100644
index 0000000..a5151b6
--- /dev/null
+++ b/extensions/pixbuf_savers/data/ui/tiff-options.ui
@@ -0,0 +1,280 @@
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires gtk+ 2.12 -->
+  <!-- interface-naming-policy toplevel-contextual -->
+  <object class="GtkAdjustment" id="tiff_hdpi_adjustment">
+    <property name="value">72</property>
+    <property name="lower">1</property>
+    <property name="upper">10000</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="tiff_vdpi_adjustment">
+    <property name="value">72</property>
+    <property name="lower">1</property>
+    <property name="upper">10000</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkVBox" id="tiff_options">
+    <property name="visible">True</property>
+    <property name="border_width">6</property>
+    <property name="orientation">vertical</property>
+    <property name="spacing">12</property>
+    <child>
+      <object class="GtkVBox" id="vbox43">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="label128">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">&lt;b&gt;Compression&lt;/b&gt;</property>
+            <property name="use_markup">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox65">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkLabel" id="label129">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">    </property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkVBox" id="vbox44">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">6</property>
+                <child>
+                  <object class="GtkRadioButton" id="tiff_comp_none_radiobutton">
+                    <property name="label" translatable="yes">_No compression</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_underline">True</property>
+                    <property name="active">True</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkRadioButton" id="tiff_comp_deflate_radiobutton">
+                    <property name="label" translatable="yes">No_rmal (Deflate)</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_underline">True</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">tiff_comp_none_radiobutton</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkRadioButton" id="tiff_comp_jpeg_radiobutton">
+                    <property name="label" translatable="yes">_Loss compression (JPEG)</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_underline">True</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">tiff_comp_none_radiobutton</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="vbox48">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="label132">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">&lt;b&gt;Resolution&lt;/b&gt;</property>
+            <property name="use_markup">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox66">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkLabel" id="label131">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">    </property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkTable" id="table12">
+                <property name="visible">True</property>
+                <property name="n_rows">2</property>
+                <property name="n_columns">2</property>
+                <property name="column_spacing">12</property>
+                <property name="row_spacing">6</property>
+                <child>
+                  <object class="GtkLabel" id="label133">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">_Horizontal:</property>
+                    <property name="use_underline">True</property>
+                  </object>
+                  <packing>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label134">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">_Vertical:</property>
+                    <property name="use_underline">True</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHBox" id="hbox67">
+                    <property name="visible">True</property>
+                    <property name="spacing">6</property>
+                    <child>
+                      <object class="GtkSpinButton" id="tiff_hdpi_spinbutton">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="invisible_char">&#x25CF;</property>
+                        <property name="adjustment">tiff_hdpi_adjustment</property>
+                        <property name="climb_rate">1</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label135">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">dpi</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHBox" id="hbox68">
+                    <property name="visible">True</property>
+                    <property name="spacing">6</property>
+                    <child>
+                      <object class="GtkSpinButton" id="tiff_vdpi_spinbutton">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="invisible_char">&#x25CF;</property>
+                        <property name="adjustment">tiff_vdpi_adjustment</property>
+                        <property name="climb_rate">1</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label136">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">dpi</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/extensions/pixbuf_savers/gth-jpeg-saver.c b/extensions/pixbuf_savers/gth-jpeg-saver.c
new file mode 100644
index 0000000..3ccef70
--- /dev/null
+++ b/extensions/pixbuf_savers/gth-jpeg-saver.c
@@ -0,0 +1,512 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <string.h>
+#include <jpeglib.h>
+#include <extensions/jpeg_utils/jmemorydest.h>
+#endif /* HAVE_LIBJPEG */
+#include <glib/gi18n.h>
+#include <gthumb.h>
+#include "gth-jpeg-saver.h"
+#include "preferences.h"
+
+
+struct _GthJpegSaverPrivate {
+	GtkBuilder *builder;
+};
+
+
+static gpointer parent_class = NULL;
+
+
+static void
+gth_jpeg_saver_init (GthJpegSaver *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_JPEG_SAVER, GthJpegSaverPrivate);
+}
+
+
+static void
+gth_jpeg_saver_finalize (GObject *object)
+{
+	GthJpegSaver *self = GTH_JPEG_SAVER (object);
+
+	_g_object_unref (self->priv->builder);
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static GtkWidget *
+gth_jpeg_saver_get_control (GthPixbufSaver *base)
+{
+	GthJpegSaver *self = GTH_JPEG_SAVER (base);
+
+	if (self->priv->builder == NULL)
+		self->priv->builder = _gtk_builder_new_from_file ("jpeg-options.ui", "pixbuf_savers");
+
+	gtk_adjustment_set_value (GTK_ADJUSTMENT (_gtk_builder_get_widget (self->priv->builder, "jpeg_quality_adjustment")),
+				  eel_gconf_get_integer (PREF_JPEG_QUALITY, 85));
+	gtk_adjustment_set_value (GTK_ADJUSTMENT (_gtk_builder_get_widget (self->priv->builder, "jpeg_smooth_adjustment")),
+				  eel_gconf_get_integer (PREF_JPEG_SMOOTHING, 0));
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "jpeg_optimize_checkbutton")),
+				      eel_gconf_get_boolean (PREF_JPEG_OPTIMIZE, TRUE));
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "jpeg_progressive_checkbutton")),
+				      eel_gconf_get_boolean (PREF_JPEG_PROGRESSIVE, FALSE));
+
+	return _gtk_builder_get_widget (self->priv->builder, "jpeg_options");
+}
+
+
+static void
+gth_jpeg_saver_save_options (GthPixbufSaver *base)
+{
+	GthJpegSaver *self = GTH_JPEG_SAVER (base);
+
+	eel_gconf_set_integer (PREF_JPEG_QUALITY, (int) gtk_adjustment_get_value (GTK_ADJUSTMENT (_gtk_builder_get_widget (self->priv->builder, "jpeg_quality_adjustment"))));
+	eel_gconf_set_integer (PREF_JPEG_SMOOTHING, (int) gtk_adjustment_get_value (GTK_ADJUSTMENT (_gtk_builder_get_widget (self->priv->builder, "jpeg_smooth_adjustment"))));
+	eel_gconf_set_boolean (PREF_JPEG_OPTIMIZE, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "jpeg_optimize_checkbutton"))));
+	eel_gconf_set_boolean (PREF_JPEG_PROGRESSIVE, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "jpeg_progressive_checkbutton"))));
+}
+
+
+static gboolean
+gth_jpeg_saver_can_save (GthPixbufSaver *self,
+			 const char     *mime_type)
+{
+#ifdef HAVE_LIBJPEG
+
+	return g_content_type_equals (mime_type, "image/jpeg");
+
+#else /* ! HAVE_LIBJPEG */
+
+	GSList          *formats;
+	GSList          *scan;
+	GdkPixbufFormat *jpeg_format;
+
+	if (! g_content_type_equals (mime_type, "image/jpeg"))
+		return FALSE;
+
+	formats = gdk_pixbuf_get_formats ();
+	jpeg_format = NULL;
+	for (scan = formats; (jpeg_format == NULL) && (scan != NULL); scan = g_slist_next (scan)) {
+		GdkPixbufFormat  *format = scan->data;
+		char            **mime_types;
+		int               i;
+
+		mime_types = gdk_pixbuf_format_get_mime_types (format);
+		for (i = 0; mime_types[i] != NULL; i++)
+			if (g_content_type_equals (mime_types[i], "image/jpeg"))
+				break;
+
+		if (mime_types[i] == NULL)
+			continue;
+
+		if (! gdk_pixbuf_format_is_writable (format))
+			continue;
+
+		jpeg_format = format;
+	}
+
+	return jpeg_format != NULL;
+
+#endif /* HAVE_LIBJPEG */
+}
+
+
+#ifdef HAVE_LIBJPEG
+
+
+/* error handler data */
+
+struct error_handler_data {
+	struct jpeg_error_mgr   pub;
+	sigjmp_buf              setjmp_buffer;
+        GError                **error;
+};
+
+
+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,
+                             GDK_PIXBUF_ERROR,
+                             GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+			     "Error interpreting JPEG image file (%s)",
+                             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 */
+}
+
+
+static gboolean
+_gdk_pixbuf_save_as_jpeg (GdkPixbuf   *pixbuf,
+			  char       **buffer,
+			  gsize       *buffer_size,
+			  char       **keys,
+			  char       **values,
+			  GError     **error)
+{
+	struct jpeg_compress_struct cinfo;
+	struct error_handler_data jerr;
+	guchar            *buf = NULL;
+	guchar            *ptr;
+	guchar            *pixels = NULL;
+	volatile int       quality = 85; /* default; must be between 0 and 100 */
+	volatile int       smoothing = 0;
+	volatile gboolean  optimize = FALSE;
+	volatile gboolean  progressive = FALSE;
+	int                i, j;
+	int                w, h = 0;
+	int                rowstride = 0;
+	volatile int       bpp;
+
+	if (keys && *keys) {
+		char **kiter = keys;
+		char **viter = values;
+
+		while (*kiter) {
+			if (strcmp (*kiter, "quality") == 0) {
+				char *endptr = NULL;
+				quality = strtol (*viter, &endptr, 10);
+
+				if (endptr == *viter) {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "JPEG quality must be a value between 0 and 100; value '%s' could not be parsed.",
+						     *viter);
+
+					return FALSE;
+				}
+
+				if (quality < 0 || quality > 100) {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "JPEG quality must be a value between 0 and 100; value '%d' is not allowed.",
+						     quality);
+
+					return FALSE;
+				}
+			}
+			else if (strcmp (*kiter, "smooth") == 0) {
+				char *endptr = NULL;
+				smoothing = strtol (*viter, &endptr, 10);
+
+				if (endptr == *viter) {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "JPEG smoothing must be a value between 0 and 100; value '%s' could not be parsed.",
+						     *viter);
+
+					return FALSE;
+				}
+
+				if (smoothing < 0 || smoothing > 100) {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "JPEG smoothing must be a value between 0 and 100; value '%d' is not allowed.",
+						     smoothing);
+
+					return FALSE;
+				}
+			}
+			else if (strcmp (*kiter, "optimize") == 0) {
+				if (strcmp (*viter, "yes") == 0)
+					optimize = TRUE;
+				else if (strcmp (*viter, "no") == 0)
+					optimize = FALSE;
+				else {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "JPEG optimize option must be 'yes' or 'no', value is: %s", *viter);
+
+					return FALSE;
+				}
+			}
+			else if (strcmp (*kiter, "progressive") == 0) {
+				if (strcmp (*viter, "yes") == 0)
+					progressive = TRUE;
+				else if (strcmp (*viter, "no") == 0)
+					progressive = FALSE;
+				else {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "JPEG progressive option must be 'yes' or 'no', value is: %s", *viter);
+
+					return FALSE;
+				}
+			}
+			else {
+				g_warning ("Bad option name '%s' passed to JPEG saver", *kiter);
+				return FALSE;
+			}
+
+			++kiter;
+			++viter;
+		}
+	}
+
+	rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+	w = gdk_pixbuf_get_width (pixbuf);
+	h = gdk_pixbuf_get_height (pixbuf);
+	if (gdk_pixbuf_get_has_alpha (pixbuf))
+		bpp = 4;
+	else
+		bpp = 3;
+	pixels = gdk_pixbuf_get_pixels (pixbuf);
+	g_return_val_if_fail (pixels != NULL, FALSE);
+
+	/* allocate a small buffer to convert image data */
+
+	buf = g_try_malloc (w * bpp * sizeof (guchar));
+	if (! buf) {
+		g_set_error (error,
+			     GDK_PIXBUF_ERROR,
+			     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+			     "Couldn't allocate memory for loading JPEG file");
+		return FALSE;
+	}
+
+	/* set up error handling */
+
+	cinfo.err = jpeg_std_error (&(jerr.pub));
+	jerr.pub.error_exit = fatal_error_handler;
+	jerr.pub.output_message = output_message_handler;
+	jerr.error = error;
+	if (sigsetjmp (jerr.setjmp_buffer, 1)) {
+		jpeg_destroy_compress (&cinfo);
+		g_free (buf);
+		return FALSE;
+	}
+
+	/* setup compress params */
+
+	jpeg_create_compress (&cinfo);
+	_jpeg_memory_dest (&cinfo, (void **)buffer, buffer_size);
+
+	cinfo.image_width      = w;
+	cinfo.image_height     = h;
+	cinfo.input_components = 3;
+	cinfo.in_color_space   = JCS_RGB;
+
+	/* set up jepg compression parameters */
+
+	jpeg_set_defaults (&cinfo);
+	jpeg_set_quality (&cinfo, quality, TRUE);
+	cinfo.smoothing_factor = smoothing;
+	cinfo.optimize_coding = optimize;
+
+#ifdef HAVE_PROGRESSIVE_JPEG
+	if (progressive)
+		jpeg_simple_progression (&cinfo);
+#endif /* HAVE_PROGRESSIVE_JPEG */
+
+	jpeg_start_compress (&cinfo, TRUE);
+	/* get the start pointer */
+	ptr = pixels;
+	/* go one scanline at a time... and save */
+	i = 0;
+	while (cinfo.next_scanline < cinfo.image_height) {
+		JSAMPROW *jbuf;
+
+		/* convert scanline from ARGB to RGB packed */
+		for (j = 0; j < w; j++)
+			memcpy (&(buf[j * 3]),
+				&(ptr[i * rowstride + j * bpp]),
+				3);
+
+		/* write scanline */
+		jbuf = (JSAMPROW *)(&buf);
+		jpeg_write_scanlines (&cinfo, jbuf, 1);
+		i++;
+	}
+
+	/* finish off */
+
+	jpeg_finish_compress (&cinfo);
+	jpeg_destroy_compress(&cinfo);
+	g_free (buf);
+
+	return TRUE;
+}
+
+
+#endif /* HAVE_LIBJPEG */
+
+
+static gboolean
+gth_jpeg_saver_save_pixbuf (GthPixbufSaver  *self,
+			    GdkPixbuf       *pixbuf,
+			    char           **buffer,
+			    gsize           *buffer_size,
+			    const char      *mime_type,
+			    GError         **error)
+{
+#ifdef HAVE_LIBJPEG
+
+	char     **option_keys;
+	char     **option_values;
+	int        i = -1;
+	int        i_value;
+	gboolean   result;
+
+	option_keys = g_malloc (sizeof (char *) * 5);
+	option_values = g_malloc (sizeof (char *) * 5);
+
+	i++;
+	i_value = eel_gconf_get_integer (PREF_JPEG_QUALITY, 85);
+	option_keys[i] = g_strdup ("quality");
+	option_values[i] = g_strdup_printf ("%d", i_value);
+
+	i++;
+	i_value = eel_gconf_get_integer (PREF_JPEG_SMOOTHING, 0);
+	option_keys[i] = g_strdup ("smooth");
+	option_values[i] = g_strdup_printf ("%d", i_value);
+
+	i++;
+	i_value = eel_gconf_get_boolean (PREF_JPEG_OPTIMIZE, TRUE);
+	option_keys[i] = g_strdup ("optimize");
+	option_values[i] = g_strdup (i_value != 0 ? "yes" : "no");
+
+	i++;
+	i_value = eel_gconf_get_boolean (PREF_JPEG_PROGRESSIVE, TRUE);
+	option_keys[i] = g_strdup ("progressive");
+	option_values[i] = g_strdup (i_value != 0 ? "yes" : "no");
+
+	i++;
+	option_keys[i] = NULL;
+	option_values[i] = NULL;
+
+	result = _gdk_pixbuf_save_as_jpeg (pixbuf,
+					   buffer,
+					   buffer_size,
+					   option_keys,
+					   option_values,
+					   error);
+
+	g_strfreev (option_keys);
+	g_strfreev (option_values);
+
+#else /* ! HAVE_LIBJPEG */
+
+	char     *pixbuf_type;
+	gboolean  result;
+
+	pixbuf_type = get_pixbuf_type_from_mime_type (mime_type);
+	result = gdk_pixbuf_save_to_bufferv (pixbuf,
+					     buffer,
+					     buffer_size,
+					     pixbuf_type,
+					     NULL,
+					     NULL,
+					     error);
+
+	g_free (pixbuf_type);
+
+#endif /* HAVE_LIBJPEG */
+
+	return result;
+}
+
+
+static void
+gth_jpeg_saver_class_init (GthJpegSaverClass *klass)
+{
+	GObjectClass        *object_class;
+	GthPixbufSaverClass *pixbuf_saver_class;
+
+	parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GthJpegSaverPrivate));
+
+	object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = gth_jpeg_saver_finalize;
+
+	pixbuf_saver_class = GTH_PIXBUF_SAVER_CLASS (klass);
+	pixbuf_saver_class->id = "jpeg";
+	pixbuf_saver_class->display_name = _("JPEG");
+	pixbuf_saver_class->get_control = gth_jpeg_saver_get_control;
+	pixbuf_saver_class->save_options = gth_jpeg_saver_save_options;
+	pixbuf_saver_class->can_save = gth_jpeg_saver_can_save;
+	pixbuf_saver_class->save_pixbuf = gth_jpeg_saver_save_pixbuf;
+}
+
+
+GType
+gth_jpeg_saver_get_type (void)
+{
+	static GType type = 0;
+
+	if (! type) {
+		GTypeInfo type_info = {
+			sizeof (GthJpegSaverClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) gth_jpeg_saver_class_init,
+			NULL,
+			NULL,
+			sizeof (GthJpegSaver),
+			0,
+			(GInstanceInitFunc) gth_jpeg_saver_init
+		};
+
+		type = g_type_register_static (GTH_TYPE_PIXBUF_SAVER,
+					       "GthJpegSaver",
+					       &type_info,
+					       0);
+	}
+
+	return type;
+}
diff --git a/extensions/pixbuf_savers/gth-jpeg-saver.h b/extensions/pixbuf_savers/gth-jpeg-saver.h
new file mode 100644
index 0000000..0592a4f
--- /dev/null
+++ b/extensions/pixbuf_savers/gth-jpeg-saver.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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 GTH_JPEG_SAVER_H
+#define GTH_JPEG_SAVER_H
+
+#include <gtk/gtk.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_JPEG_SAVER              (gth_jpeg_saver_get_type ())
+#define GTH_JPEG_SAVER(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_JPEG_SAVER, GthJpegSaver))
+#define GTH_JPEG_SAVER_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_JPEG_SAVER_TYPE, GthJpegSaverClass))
+#define GTH_IS_JPEG_SAVER(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_JPEG_SAVER))
+#define GTH_IS_JPEG_SAVER_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_JPEG_SAVER))
+#define GTH_JPEG_SAVER_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_JPEG_SAVER, GthJpegSaverClass))
+
+typedef struct _GthJpegSaver         GthJpegSaver;
+typedef struct _GthJpegSaverClass    GthJpegSaverClass;
+typedef struct _GthJpegSaverPrivate  GthJpegSaverPrivate;
+
+struct _GthJpegSaver
+{
+	GthPixbufSaver __parent;
+	GthJpegSaverPrivate *priv;
+};
+
+struct _GthJpegSaverClass
+{
+	GthPixbufSaverClass __parent_class;
+};
+
+GType  gth_jpeg_saver_get_type (void);
+
+G_END_DECLS
+
+#endif /* GTH_JPEG_SAVER_H */
diff --git a/extensions/pixbuf_savers/gth-png-saver.c b/extensions/pixbuf_savers/gth-png-saver.c
new file mode 100644
index 0000000..ce6996c
--- /dev/null
+++ b/extensions/pixbuf_savers/gth-png-saver.c
@@ -0,0 +1,179 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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>
+#include <glib/gi18n.h>
+#include <gthumb.h>
+#include "gth-png-saver.h"
+#include "preferences.h"
+
+
+struct _GthPngSaverPrivate {
+	GtkBuilder *builder;
+};
+
+
+static gpointer parent_class = NULL;
+
+
+static void
+gth_png_saver_init (GthPngSaver *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_PNG_SAVER, GthPngSaverPrivate);
+}
+
+
+static void
+gth_png_saver_finalize (GObject *object)
+{
+	GthPngSaver *self = GTH_PNG_SAVER (object);
+
+	_g_object_unref (self->priv->builder);
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static GtkWidget *
+gth_png_saver_get_control (GthPixbufSaver *base)
+{
+	GthPngSaver *self = GTH_PNG_SAVER (base);
+
+	if (self->priv->builder == NULL)
+		self->priv->builder = _gtk_builder_new_from_file ("png-options.ui", "pixbuf_savers");
+
+	gtk_adjustment_set_value (GTK_ADJUSTMENT (_gtk_builder_get_widget (self->priv->builder, "png_compression_adjustment")),
+				  eel_gconf_get_integer (PREF_PNG_COMPRESSION_LEVEL, 6));
+
+	return _gtk_builder_get_widget (self->priv->builder, "png_options");
+}
+
+
+static void
+gth_png_saver_save_options (GthPixbufSaver *base)
+{
+	GthPngSaver *self = GTH_PNG_SAVER (base);
+
+	eel_gconf_set_integer (PREF_PNG_COMPRESSION_LEVEL, (int) gtk_adjustment_get_value (GTK_ADJUSTMENT (_gtk_builder_get_widget (self->priv->builder, "png_compression_adjustment"))));
+}
+
+
+static gboolean
+gth_png_saver_can_save (GthPixbufSaver *self,
+			const char     *mime_type)
+{
+	return g_content_type_equals (mime_type, "image/png");
+}
+
+
+static gboolean
+gth_png_saver_save_pixbuf (GthPixbufSaver  *self,
+			   GdkPixbuf       *pixbuf,
+			   char           **buffer,
+			   gsize           *buffer_size,
+			   const char      *mime_type,
+			   GError         **error)
+{
+	char      *pixbuf_type;
+	char     **option_keys;
+	char     **option_values;
+	int        i = -1;
+	int        i_value;
+	gboolean   result;
+
+	pixbuf_type = get_pixbuf_type_from_mime_type (mime_type);
+
+	option_keys = g_malloc (sizeof (char *) * 2);
+	option_values = g_malloc (sizeof (char *) * 2);
+
+	i++;
+	i_value = eel_gconf_get_integer (PREF_PNG_COMPRESSION_LEVEL, 6);
+	option_keys[i] = g_strdup ("compression");;
+	option_values[i] = g_strdup_printf ("%d", i_value);
+
+	i++;
+	option_keys[i] = NULL;
+	option_values[i] = NULL;
+
+	result = gdk_pixbuf_save_to_bufferv (pixbuf,
+					     buffer,
+					     buffer_size,
+					     pixbuf_type,
+					     option_keys,
+					     option_values,
+					     error);
+
+	g_strfreev (option_keys);
+	g_strfreev (option_values);
+	g_free (pixbuf_type);
+
+	return result;
+}
+
+
+static void
+gth_png_saver_class_init (GthPngSaverClass *klass)
+{
+	GObjectClass        *object_class;
+	GthPixbufSaverClass *pixbuf_saver_class;
+
+	parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GthPngSaverPrivate));
+
+	object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = gth_png_saver_finalize;
+
+	pixbuf_saver_class = GTH_PIXBUF_SAVER_CLASS (klass);
+	pixbuf_saver_class->id = "png";
+	pixbuf_saver_class->display_name = _("PNG");
+	pixbuf_saver_class->get_control = gth_png_saver_get_control;
+	pixbuf_saver_class->save_options = gth_png_saver_save_options;
+	pixbuf_saver_class->can_save = gth_png_saver_can_save;
+	pixbuf_saver_class->save_pixbuf = gth_png_saver_save_pixbuf;
+}
+
+
+GType
+gth_png_saver_get_type (void)
+{
+	static GType type = 0;
+
+	if (! type) {
+		GTypeInfo type_info = {
+			sizeof (GthPngSaverClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) gth_png_saver_class_init,
+			NULL,
+			NULL,
+			sizeof (GthPngSaver),
+			0,
+			(GInstanceInitFunc) gth_png_saver_init
+		};
+
+		type = g_type_register_static (GTH_TYPE_PIXBUF_SAVER,
+					       "GthPngSaver",
+					       &type_info,
+					       0);
+	}
+
+	return type;
+}
diff --git a/extensions/pixbuf_savers/gth-png-saver.h b/extensions/pixbuf_savers/gth-png-saver.h
new file mode 100644
index 0000000..a871fa6
--- /dev/null
+++ b/extensions/pixbuf_savers/gth-png-saver.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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 GTH_PNG_SAVER_H
+#define GTH_PNG_SAVER_H
+
+#include <gtk/gtk.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_PNG_SAVER              (gth_png_saver_get_type ())
+#define GTH_PNG_SAVER(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_PNG_SAVER, GthPngSaver))
+#define GTH_PNG_SAVER_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_PNG_SAVER_TYPE, GthPngSaverClass))
+#define GTH_IS_PNG_SAVER(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_PNG_SAVER))
+#define GTH_IS_PNG_SAVER_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_PNG_SAVER))
+#define GTH_PNG_SAVER_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_PNG_SAVER, GthPngSaverClass))
+
+typedef struct _GthPngSaver         GthPngSaver;
+typedef struct _GthPngSaverClass    GthPngSaverClass;
+typedef struct _GthPngSaverPrivate  GthPngSaverPrivate;
+
+struct _GthPngSaver
+{
+	GthPixbufSaver __parent;
+	GthPngSaverPrivate *priv;
+};
+
+struct _GthPngSaverClass
+{
+	GthPixbufSaverClass __parent_class;
+};
+
+GType  gth_png_saver_get_type  (void);
+
+G_END_DECLS
+
+#endif /* GTH_PNG_SAVER_H */
diff --git a/extensions/pixbuf_savers/gth-tga-saver.c b/extensions/pixbuf_savers/gth-tga-saver.c
new file mode 100644
index 0000000..7fdc941
--- /dev/null
+++ b/extensions/pixbuf_savers/gth-tga-saver.c
@@ -0,0 +1,414 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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>
+#include <glib/gi18n.h>
+#include <gthumb.h>
+#include "gth-tga-saver.h"
+#include "preferences.h"
+
+
+struct _GthTgaSaverPrivate {
+	GtkBuilder *builder;
+};
+
+
+static gpointer parent_class = NULL;
+
+
+static void
+gth_tga_saver_init (GthTgaSaver *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_TGA_SAVER, GthTgaSaverPrivate);
+}
+
+
+static void
+gth_tga_saver_finalize (GObject *object)
+{
+	GthTgaSaver *self = GTH_TGA_SAVER (object);
+
+	_g_object_unref (self->priv->builder);
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static GtkWidget *
+gth_tga_saver_get_control (GthPixbufSaver *base)
+{
+	GthTgaSaver *self = GTH_TGA_SAVER (base);
+
+	if (self->priv->builder == NULL)
+		self->priv->builder = _gtk_builder_new_from_file ("tga-options.ui", "pixbuf_savers");
+
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tga_rle_compression_checkbutton")),
+				      eel_gconf_get_boolean (PREF_TGA_RLE_COMPRESSION, TRUE));
+
+	return _gtk_builder_get_widget (self->priv->builder, "tga_options");
+}
+
+
+static void
+gth_tga_saver_save_options (GthPixbufSaver *base)
+{
+	GthTgaSaver *self = GTH_TGA_SAVER (base);
+
+	eel_gconf_set_boolean (PREF_TGA_RLE_COMPRESSION, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tga_rle_compression_checkbutton"))));
+}
+
+
+static gboolean
+gth_tga_saver_can_save (GthPixbufSaver *self,
+			const char     *mime_type)
+{
+	return g_content_type_equals (mime_type, "image/tga") || g_content_type_equals (mime_type, "image/x-tga");
+}
+
+
+/* -- _gdk_pixbuf_save_as_tga -- */
+
+
+/* TRUEVISION-XFILE magic signature string */
+static guchar magic[18] = {
+	0x54, 0x52, 0x55, 0x45, 0x56, 0x49, 0x53, 0x49, 0x4f,
+	0x4e, 0x2d, 0x58, 0x46, 0x49, 0x4c, 0x45, 0x2e, 0x0
+};
+
+
+static gboolean
+rle_write (GthBufferData  *buffer_data,
+	   guchar         *buffer,
+	   guint           width,
+	   guint           bytes,
+	   GError        **error)
+{
+	int     repeat = 0;
+	int     direct = 0;
+	guchar *from = buffer;
+	guint   x;
+
+	for (x = 1; x < width; ++x) {
+		if (memcmp (buffer, buffer + bytes, bytes)) {
+			/* next pixel is different */
+			if (repeat) {
+				gth_buffer_data_putc (buffer_data, 128 + repeat, error);
+				gth_buffer_data_write (buffer_data, from, bytes, error);
+				from = buffer + bytes; /* point to first different pixel */
+				repeat = 0;
+				direct = 0;
+			}
+			else
+				direct += 1;
+		}
+		else {
+			/* next pixel is the same */
+			if (direct) {
+				gth_buffer_data_putc (buffer_data, direct - 1, error);
+				gth_buffer_data_write (buffer_data, from, bytes * direct, error);
+				from = buffer; /* point to first identical pixel */
+				direct = 0;
+				repeat = 1;
+			}
+			else
+				repeat += 1;
+		}
+
+		if (repeat == 128) {
+			gth_buffer_data_putc (buffer_data, 255, error);
+			gth_buffer_data_write (buffer_data, from, bytes, error);
+			from = buffer + bytes;
+			direct = 0;
+			repeat = 0;
+		}
+		else if (direct == 128) {
+			gth_buffer_data_putc (buffer_data, 127, error);
+			gth_buffer_data_write (buffer_data, from, bytes * direct, error);
+			from = buffer + bytes;
+			direct = 0;
+			repeat = 0;
+		}
+
+		buffer += bytes;
+	}
+
+	if (repeat > 0) {
+		gth_buffer_data_putc (buffer_data, 128 + repeat, error);
+		gth_buffer_data_write (buffer_data, from, bytes, error);
+	}
+	else {
+		gth_buffer_data_putc (buffer_data, direct, error);
+		gth_buffer_data_write (buffer_data, from, bytes * (direct + 1), error);
+	}
+
+	return TRUE;
+}
+
+
+static void
+bgr2rgb (guchar *dest,
+	 guchar *src,
+	 guint   width,
+	 guint   bytes,
+	 guint   alpha)
+{
+	guint x;
+
+	if (alpha)
+		for (x = 0; x < width; x++) {
+			*(dest++) = src[2];
+			*(dest++) = src[1];
+			*(dest++) = src[0];
+			*(dest++) = src[3];
+
+			src += bytes;
+		}
+	else
+		for (x = 0; x < width; x++) {
+			*(dest++) = src[2];
+			*(dest++) = src[1];
+			*(dest++) = src[0];
+
+			src += bytes;
+		}
+}
+
+
+static gboolean
+_gdk_pixbuf_save_as_tga (GdkPixbuf   *pixbuf,
+			 char       **buffer,
+			 gsize       *buffer_size,
+			 char       **keys,
+			 char       **values,
+			 GError     **error)
+{
+	GthBufferData *buffer_data;
+	int            out_bpp = 0;
+	int            row;
+	guchar         header[18];
+	guchar         footer[26];
+	gboolean       rle_compression;
+	gboolean       alpha;
+	guchar        *pixels, *ptr, *buf;
+	int            width, height;
+	int            rowstride;
+
+	rle_compression = TRUE;
+
+	if (keys && *keys) {
+		char **kiter = keys;
+		char **viter = values;
+
+		while (*kiter) {
+			if (strcmp (*kiter, "compression") == 0) {
+				if (*viter == NULL) {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "Must specify a compression type");
+					return FALSE;
+				}
+
+				if (strcmp (*viter, "none") == 0)
+					rle_compression = FALSE;
+
+				else if (strcmp (*viter, "rle") == 0)
+					rle_compression = TRUE;
+
+				else {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "Unsupported compression type passed to the TGA saver");
+					return FALSE;
+				}
+			}
+			else {
+				g_warning ("Bad option name '%s' passed to the TGA saver", *kiter);
+				return FALSE;
+			}
+
+			++kiter;
+			++viter;
+		}
+	}
+
+	width     = gdk_pixbuf_get_width (pixbuf);
+	height    = gdk_pixbuf_get_height (pixbuf);
+	alpha     = gdk_pixbuf_get_has_alpha (pixbuf);
+	pixels    = gdk_pixbuf_get_pixels (pixbuf);
+	rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+
+	buffer_data = gth_buffer_data_new ();
+
+	/* write the header */
+
+	header[0] = 0; /* No image identifier / description */
+	header[1] = 0;
+	header[2] = rle_compression ? 10 : 2;
+	header[3] = header[4] = header[5] = header[6] = header[7] = 0;
+	header[8]  = header[9]  = 0; /* xorigin */
+	header[10] = header[11] = 0; /* yorigin */
+	header[12] = width % 256;
+	header[13] = width / 256;
+	header[14] = height % 256;
+	header[15] = height / 256;
+	if (alpha) {
+		out_bpp = 4;
+		header[16] = 32; /* bpp */
+		header[17] = 0x28; /* alpha + orientation */
+	}
+	else {
+		out_bpp = 3;
+		header[16] = 24; /* bpp */
+		header[17] = 0x20; /* alpha + orientation */
+	}
+	gth_buffer_data_write (buffer_data, header, sizeof (header), error);
+
+	/* allocate a small buffer to convert image data */
+	buf = g_try_malloc (width * out_bpp * sizeof (guchar));
+	if (! buf) {
+		g_set_error_literal (error,
+				     GDK_PIXBUF_ERROR,
+				     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+				     _("Insufficient memory"));
+		return FALSE;
+	}
+
+	ptr = pixels;
+	for (row = 0; row < height; ++row) {
+		bgr2rgb (buf, ptr, width, out_bpp, alpha);
+
+		if (rle_compression)
+			rle_write (buffer_data, buf, width, out_bpp, error);
+		else
+			gth_buffer_data_write (buffer_data, buf, width * out_bpp, error);
+
+		ptr += rowstride;
+	}
+
+	g_free (buf);
+
+	/* write the footer  */
+
+	memset (footer, 0, 8); /* No extensions, no developer directory */
+	memcpy (footer + 8, magic, sizeof (magic)); /* magic signature */
+	gth_buffer_data_write (buffer_data, footer, sizeof (footer), error);
+
+	gth_buffer_data_get (buffer_data, buffer, buffer_size);
+	gth_buffer_data_free (buffer_data, FALSE);
+
+	return TRUE;
+}
+
+
+static gboolean
+gth_tga_saver_save_pixbuf (GthPixbufSaver  *self,
+			   GdkPixbuf       *pixbuf,
+			   char           **buffer,
+			   gsize           *buffer_size,
+			   const char      *mime_type,
+			   GError         **error)
+{
+	char      *pixbuf_type;
+	char     **option_keys;
+	char     **option_values;
+	int        i = -1;
+	int        i_value;
+	gboolean   result;
+
+	pixbuf_type = get_pixbuf_type_from_mime_type (mime_type);
+
+	option_keys = g_malloc (sizeof (char *) * 2);
+	option_values = g_malloc (sizeof (char *) * 2);
+
+	i++;
+	i_value = eel_gconf_get_integer (PREF_PNG_COMPRESSION_LEVEL, 6);
+	option_keys[i] = g_strdup ("compression");;
+	option_values[i] = g_strdup_printf ("%d", i_value);
+
+	i++;
+	option_keys[i] = NULL;
+	option_values[i] = NULL;
+
+	result = _gdk_pixbuf_save_as_tga (pixbuf,
+					  buffer,
+					  buffer_size,
+					  option_keys,
+					  option_values,
+					  error);
+
+	g_strfreev (option_keys);
+	g_strfreev (option_values);
+	g_free (pixbuf_type);
+
+	return result;
+}
+
+
+static void
+gth_tga_saver_class_init (GthTgaSaverClass *klass)
+{
+	GObjectClass        *object_class;
+	GthPixbufSaverClass *pixbuf_saver_class;
+
+	parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GthTgaSaverPrivate));
+
+	object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = gth_tga_saver_finalize;
+
+	pixbuf_saver_class = GTH_PIXBUF_SAVER_CLASS (klass);
+	pixbuf_saver_class->id = "tga";
+	pixbuf_saver_class->display_name = _("TGA");
+	pixbuf_saver_class->get_control = gth_tga_saver_get_control;
+	pixbuf_saver_class->save_options = gth_tga_saver_save_options;
+	pixbuf_saver_class->can_save = gth_tga_saver_can_save;
+	pixbuf_saver_class->save_pixbuf = gth_tga_saver_save_pixbuf;
+}
+
+
+GType
+gth_tga_saver_get_type (void)
+{
+	static GType type = 0;
+
+	if (! type) {
+		GTypeInfo type_info = {
+			sizeof (GthTgaSaverClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) gth_tga_saver_class_init,
+			NULL,
+			NULL,
+			sizeof (GthTgaSaver),
+			0,
+			(GInstanceInitFunc) gth_tga_saver_init
+		};
+
+		type = g_type_register_static (GTH_TYPE_PIXBUF_SAVER,
+					       "GthTgaSaver",
+					       &type_info,
+					       0);
+	}
+
+	return type;
+}
diff --git a/extensions/pixbuf_savers/gth-tga-saver.h b/extensions/pixbuf_savers/gth-tga-saver.h
new file mode 100644
index 0000000..11f61a6
--- /dev/null
+++ b/extensions/pixbuf_savers/gth-tga-saver.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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 GTH_TGA_SAVER_H
+#define GTH_TGA_SAVER_H
+
+#include <gtk/gtk.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_TGA_SAVER              (gth_tga_saver_get_type ())
+#define GTH_TGA_SAVER(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_TGA_SAVER, GthTgaSaver))
+#define GTH_TGA_SAVER_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_TGA_SAVER, GthTgaSaverClass))
+#define GTH_IS_TGA_SAVER(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_TGA_SAVER))
+#define GTH_IS_TGA_SAVER_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_TGA_SAVER))
+#define GTH_TGA_SAVER_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_TGA_SAVER, GthTgaSaverClass))
+
+typedef struct _GthTgaSaver         GthTgaSaver;
+typedef struct _GthTgaSaverClass    GthTgaSaverClass;
+typedef struct _GthTgaSaverPrivate  GthTgaSaverPrivate;
+
+struct _GthTgaSaver
+{
+	GthPixbufSaver __parent;
+	GthTgaSaverPrivate *priv;
+};
+
+struct _GthTgaSaverClass
+{
+	GthPixbufSaverClass __parent_class;
+};
+
+GType  gth_tga_saver_get_type (void);
+
+G_END_DECLS
+
+#endif /* GTH_TGA_SAVER_H */
diff --git a/extensions/pixbuf_savers/gth-tiff-saver.c b/extensions/pixbuf_savers/gth-tiff-saver.c
new file mode 100644
index 0000000..933c96c
--- /dev/null
+++ b/extensions/pixbuf_savers/gth-tiff-saver.c
@@ -0,0 +1,555 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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_LIBTIFF
+#include <tiffio.h>
+#endif /* HAVE_LIBTIFF */
+#include <glib/gi18n.h>
+#include <gthumb.h>
+#include "enum-types.h"
+#include "gth-tiff-saver.h"
+#include "preferences.h"
+
+
+struct _GthTiffSaverPrivate {
+	GtkBuilder *builder;
+};
+
+
+static gpointer parent_class = NULL;
+
+
+static void
+gth_tiff_saver_init (GthTiffSaver *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_TIFF_SAVER, GthTiffSaverPrivate);
+}
+
+
+static void
+gth_tiff_saver_finalize (GObject *object)
+{
+	GthTiffSaver *self = GTH_TIFF_SAVER (object);
+
+	_g_object_unref (self->priv->builder);
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static GtkWidget *
+gth_tiff_saver_get_control (GthPixbufSaver *base)
+{
+#ifdef HAVE_LIBTIFF
+
+	GthTiffSaver       *self = GTH_TIFF_SAVER (base);
+	GthTiffCompression  compression_type;
+
+	if (self->priv->builder == NULL)
+		self->priv->builder = _gtk_builder_new_from_file ("tiff-options.ui", "pixbuf_savers");
+
+	compression_type = eel_gconf_get_enum (PREF_TIFF_COMPRESSION, GTH_TYPE_TIFF_COMPRESSION, GTH_TIFF_COMPRESSION_DEFLATE);
+	switch (compression_type) {
+	case GTH_TIFF_COMPRESSION_NONE:
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_comp_none_radiobutton")), TRUE);
+		break;
+	case GTH_TIFF_COMPRESSION_DEFLATE:
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_comp_deflate_radiobutton")), TRUE);
+		break;
+	case GTH_TIFF_COMPRESSION_JPEG:
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_comp_jpeg_radiobutton")), TRUE);
+		break;
+	}
+
+	gtk_spin_button_set_value (GTK_SPIN_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_hdpi_spinbutton")), eel_gconf_get_integer (PREF_TIFF_HORIZONTAL_RES, 72));
+	gtk_spin_button_set_value (GTK_SPIN_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_vdpi_spinbutton")), eel_gconf_get_integer (PREF_TIFF_VERTICAL_RES, 72));
+
+	return _gtk_builder_get_widget (self->priv->builder, "tiff_options");
+
+#else /* ! HAVE_LIBTIFF */
+
+	return GTH_PIXBUF_SAVER_CLASS (parent_class)->get_control (base);
+
+#endif /* HAVE_LIBTIFF */
+}
+
+
+static void
+gth_tiff_saver_save_options (GthPixbufSaver *base)
+{
+#ifdef HAVE_LIBTIFF
+
+	GthTiffSaver     *self = GTH_TIFF_SAVER (base);
+	GthTiffCompression  compression_type;
+
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_comp_none_radiobutton"))))
+		compression_type = GTH_TIFF_COMPRESSION_NONE;
+	else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_comp_deflate_radiobutton"))))
+		compression_type = GTH_TIFF_COMPRESSION_DEFLATE;
+	else
+		compression_type = GTH_TIFF_COMPRESSION_JPEG;
+	eel_gconf_set_enum (PREF_TIFF_COMPRESSION, GTH_TYPE_TIFF_COMPRESSION, compression_type);
+
+	eel_gconf_set_integer (PREF_TIFF_HORIZONTAL_RES, (int) gtk_spin_button_get_value (GTK_SPIN_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_hdpi_spinbutton"))));
+	eel_gconf_set_integer (PREF_TIFF_VERTICAL_RES, (int) gtk_spin_button_get_value (GTK_SPIN_BUTTON (_gtk_builder_get_widget (self->priv->builder, "tiff_vdpi_spinbutton"))));
+
+#endif /* HAVE_LIBTIFF */
+}
+
+
+static gboolean
+gth_tiff_saver_can_save (GthPixbufSaver *self,
+			 const char     *mime_type)
+{
+#ifdef HAVE_LIBTIFF
+
+	return g_content_type_equals (mime_type, "image/tiff");
+
+#else /* ! HAVE_LIBTIFF */
+
+	GSList          *formats;
+	GSList          *scan;
+	GdkPixbufFormat *tiff_format;
+
+	if (! g_content_type_equals (mime_type, "image/tiff"))
+		return FALSE;
+
+	formats = gdk_pixbuf_get_formats ();
+	tiff_format = NULL;
+	for (scan = formats; (tiff_format == NULL) && (scan != NULL); scan = g_slist_next (scan)) {
+		GdkPixbufFormat  *format = scan->data;
+		char            **mime_types;
+		int               i;
+
+		mime_types = gdk_pixbuf_format_get_mime_types (format);
+		for (i = 0; mime_types[i] != NULL; i++)
+			if (g_content_type_equals (mime_types[i], "image/tiff"))
+				break;
+
+		if (mime_types[i] == NULL)
+			continue;
+
+		if (! gdk_pixbuf_format_is_writable (format))
+			continue;
+
+		tiff_format = format;
+	}
+
+	return tiff_format != NULL;
+
+#endif /* HAVE_LIBTIFF */
+}
+
+
+#ifdef HAVE_LIBTIFF
+
+
+/* -- gth_tiff_saver_save_pixbuf -- */
+
+
+#define TILE_HEIGHT 40   /* FIXME */
+
+
+static tsize_t
+tiff_save_read (thandle_t handle, tdata_t buf, tsize_t size)
+{
+	return -1;
+}
+
+
+static tsize_t
+tiff_save_write (thandle_t handle, tdata_t buf, tsize_t size)
+{
+        GthBufferData *buffer_data = (GthBufferData *)handle;
+
+        gth_buffer_data_write (buffer_data, buf, size, NULL);
+        return size;
+}
+
+
+static toff_t
+tiff_save_seek (thandle_t handle, toff_t offset, int whence)
+{
+	GthBufferData *buffer_data = (GthBufferData *)handle;
+
+	return gth_buffer_data_seek (buffer_data, offset, whence);
+}
+
+
+static int
+tiff_save_close (thandle_t context)
+{
+        return 0;
+}
+
+
+static toff_t
+tiff_save_size (thandle_t handle)
+{
+        return -1;
+}
+
+
+static gboolean
+_gdk_pixbuf_save_as_tiff (GdkPixbuf   *pixbuf,
+			  char       **buffer,
+			  gsize       *buffer_size,
+			  char       **keys,
+			  char       **values,
+			  GError     **error)
+{
+	GthBufferData *buffer_data;
+	TIFF          *tif;
+	int            cols, col, rows, row;
+	glong          rowsperstrip;
+	gushort        compression;
+	int            alpha;
+	gshort         predictor;
+	gshort         photometric;
+	gshort         samplesperpixel;
+	gshort         bitspersample;
+	int            rowstride;
+	guchar        *pixels, *buf, *ptr;
+	int            success;
+	int            horizontal_dpi = 72, vertical_dpi = 72;
+	gboolean       save_resolution = FALSE;
+
+	compression = COMPRESSION_DEFLATE;
+
+	if (keys && *keys) {
+		char **kiter = keys;
+		char **viter = values;
+
+		while (*kiter) {
+			if (strcmp (*kiter, "compression") == 0) {
+				if (*viter == NULL) {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "Must specify a compression type");
+					return FALSE;
+				}
+
+				if (strcmp (*viter, "none") == 0)
+					compression = COMPRESSION_NONE;
+				else if (strcmp (*viter, "pack bits") == 0)
+					compression = COMPRESSION_PACKBITS;
+				else if (strcmp (*viter, "lzw") == 0)
+					compression = COMPRESSION_LZW;
+				else if (strcmp (*viter, "deflate") == 0)
+					compression = COMPRESSION_DEFLATE;
+				else if (strcmp (*viter, "jpeg") == 0)
+					compression = COMPRESSION_JPEG;
+				else {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "Unsupported compression type passed to the TIFF saver");
+					return FALSE;
+				}
+			}
+			else if (strcmp (*kiter, "vertical dpi") == 0) {
+				char *endptr = NULL;
+				vertical_dpi = strtol (*viter, &endptr, 10);
+				save_resolution = TRUE;
+
+				if (endptr == *viter) {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "TIFF vertical dpi must be a value greater than 0; value '%s' could not be parsed.",
+						     *viter);
+					return FALSE;
+				}
+
+				if (vertical_dpi < 0) {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "TIFF vertical dpi must be a value greater than 0; value '%d' is not allowed.",
+						     vertical_dpi);
+					return FALSE;
+				}
+			}
+			else if (strcmp (*kiter, "horizontal dpi") == 0) {
+				char *endptr = NULL;
+				horizontal_dpi = strtol (*viter, &endptr, 10);
+				save_resolution = TRUE;
+
+				if (endptr == *viter) {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "TIFF horizontal dpi must be a value greater than 0; value '%s' could not be parsed.",
+						     *viter);
+					return FALSE;
+				}
+
+				if (horizontal_dpi < 0) {
+					g_set_error (error,
+						     GDK_PIXBUF_ERROR,
+						     GDK_PIXBUF_ERROR_BAD_OPTION,
+						     "TIFF horizontal dpi must be a value greater than 0; value '%d' is not allowed.",
+						     horizontal_dpi);
+					return FALSE;
+				}
+			}
+			else {
+				g_warning ("Bad option name '%s' passed to the TIFF saver", *kiter);
+				return FALSE;
+			}
+
+			++kiter;
+			++viter;
+		}
+	}
+
+	predictor    = 0;
+	rowsperstrip = TILE_HEIGHT;
+
+	buffer_data = gth_buffer_data_new ();
+	tif = TIFFClientOpen ("gth-tiff-writer", "w", buffer_data,
+	                      tiff_save_read, tiff_save_write,
+	                      tiff_save_seek, tiff_save_close,
+	                      tiff_save_size,
+	                      NULL, NULL);
+	if (tif == NULL) {
+		g_set_error_literal (error,
+				     GDK_PIXBUF_ERROR,
+				     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+				     "Couldn't allocate memory for writing TIFF file");
+		return FALSE;
+	}
+
+	cols      = gdk_pixbuf_get_width (pixbuf);
+	rows      = gdk_pixbuf_get_height (pixbuf);
+	alpha     = gdk_pixbuf_get_has_alpha (pixbuf);
+	pixels    = gdk_pixbuf_get_pixels (pixbuf);
+	rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+
+	predictor       = 2;
+	bitspersample   = 8;
+	photometric     = PHOTOMETRIC_RGB;
+
+	if (alpha)
+		samplesperpixel = 4;
+	else
+		samplesperpixel = 3;
+
+	/* Set TIFF parameters. */
+
+	TIFFSetField (tif, TIFFTAG_SUBFILETYPE,   0);
+	TIFFSetField (tif, TIFFTAG_IMAGEWIDTH,    cols);
+	TIFFSetField (tif, TIFFTAG_IMAGELENGTH,   rows);
+	TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, bitspersample);
+	TIFFSetField (tif, TIFFTAG_ORIENTATION,   ORIENTATION_TOPLEFT);
+	TIFFSetField (tif, TIFFTAG_COMPRESSION,   compression);
+
+	if ((compression == COMPRESSION_LZW || compression == COMPRESSION_DEFLATE)
+	    && (predictor != 0))
+	{
+		TIFFSetField (tif, TIFFTAG_PREDICTOR, predictor);
+	}
+
+	if (alpha) {
+		gushort extra_samples[1];
+
+		extra_samples [0] = EXTRASAMPLE_ASSOCALPHA;
+		TIFFSetField (tif, TIFFTAG_EXTRASAMPLES, 1, extra_samples);
+	}
+
+	TIFFSetField (tif, TIFFTAG_PHOTOMETRIC,     photometric);
+	/*TIFFSetField (tif, TIFFTAG_DOCUMENTNAME,    filename);*/
+	TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
+	TIFFSetField (tif, TIFFTAG_ROWSPERSTRIP,    rowsperstrip);
+	TIFFSetField (tif, TIFFTAG_PLANARCONFIG,    PLANARCONFIG_CONTIG);
+
+	if (save_resolution) {
+		TIFFSetField (tif, TIFFTAG_XRESOLUTION, (double) horizontal_dpi);
+		TIFFSetField (tif, TIFFTAG_YRESOLUTION, (double) vertical_dpi);
+		TIFFSetField (tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
+	}
+
+	/* allocate a small buffer to convert image data */
+	buf = g_try_malloc (cols * samplesperpixel * sizeof (guchar));
+	if (! buf) {
+		g_set_error_literal (error,
+				     GDK_PIXBUF_ERROR,
+				     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+				     "Couldn't allocate memory for writing TIFF file");
+		return FALSE;
+	}
+
+	ptr = pixels;
+
+	/* Now write the TIFF data. */
+	for (row = 0; row < rows; row++) {
+		/* convert scanline from ARGB to RGB packed */
+		for (col = 0; col < cols; col++)
+			memcpy (&(buf[col * 3]), &(ptr[col * samplesperpixel]), 3);
+
+		success = TIFFWriteScanline (tif, buf, row, 0) >= 0;
+
+		if (! success) {
+			g_set_error (error,
+				     GDK_PIXBUF_ERROR,
+				     GDK_PIXBUF_ERROR_FAILED,
+				     "TIFF Failed a scanline write on row %d",
+				     row);
+			return FALSE;
+		}
+
+		ptr += rowstride;
+	}
+
+	TIFFFlushData (tif);
+	TIFFClose (tif);
+
+	g_free (buf);
+
+	gth_buffer_data_get (buffer_data, buffer, buffer_size);
+	gth_buffer_data_free (buffer_data, FALSE);
+
+	return TRUE;
+}
+
+
+#endif /* HAVE_LIBTIFF */
+
+
+static gboolean
+gth_tiff_saver_save_pixbuf (GthPixbufSaver  *self,
+			    GdkPixbuf       *pixbuf,
+			    char           **buffer,
+			    gsize           *buffer_size,
+			    const char      *mime_type,
+			    GError         **error)
+{
+#ifdef HAVE_LIBTIFF
+
+	char     **option_keys;
+	char     **option_values;
+	int        i = -1;
+	int        i_value;
+	gboolean   result;
+
+	option_keys = g_malloc (sizeof (char *) * 4);
+	option_values = g_malloc (sizeof (char *) * 4);
+
+	i++;
+	option_keys[i] = g_strdup ("compression");;
+	option_values[i] = eel_gconf_get_string (PREF_TIFF_COMPRESSION, "deflate");
+
+	i++;
+	i_value = eel_gconf_get_integer (PREF_TIFF_VERTICAL_RES, 72);
+	option_keys[i] = g_strdup ("vertical dpi");;
+	option_values[i] = g_strdup_printf ("%d", i_value);
+
+	i++;
+	i_value = eel_gconf_get_integer (PREF_TIFF_HORIZONTAL_RES, 72);
+	option_keys[i] = g_strdup ("horizontal dpi");;
+	option_values[i] = g_strdup_printf ("%d", i_value);
+
+	i++;
+	option_keys[i] = NULL;
+	option_values[i] = NULL;
+
+	result = _gdk_pixbuf_save_as_tiff (pixbuf,
+					   buffer,
+					   buffer_size,
+					   option_keys,
+					   option_values,
+					   error);
+
+	g_strfreev (option_keys);
+	g_strfreev (option_values);
+
+#else /* ! HAVE_LIBTIFF */
+
+	char     *pixbuf_type;
+	gboolean  result;
+
+	pixbuf_type = get_pixbuf_type_from_mime_type (mime_type);
+	result = gdk_pixbuf_save_to_bufferv (pixbuf,
+					     buffer,
+					     buffer_size,
+					     pixbuf_type,
+					     NULL,
+					     NULL,
+					     error);
+
+	g_free (pixbuf_type);
+
+#endif /* HAVE_LIBTIFF */
+
+	return result;
+}
+
+
+static void
+gth_tiff_saver_class_init (GthTiffSaverClass *klass)
+{
+	GObjectClass        *object_class;
+	GthPixbufSaverClass *pixbuf_saver_class;
+
+	parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GthTiffSaverPrivate));
+
+	object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = gth_tiff_saver_finalize;
+
+	pixbuf_saver_class = GTH_PIXBUF_SAVER_CLASS (klass);
+	pixbuf_saver_class->id = "tiff";
+	pixbuf_saver_class->display_name = _("TIFF");
+	pixbuf_saver_class->get_control = gth_tiff_saver_get_control;
+	pixbuf_saver_class->save_options = gth_tiff_saver_save_options;
+	pixbuf_saver_class->can_save = gth_tiff_saver_can_save;
+	pixbuf_saver_class->save_pixbuf = gth_tiff_saver_save_pixbuf;
+}
+
+
+GType
+gth_tiff_saver_get_type (void)
+{
+	static GType type = 0;
+
+	if (! type) {
+		GTypeInfo type_info = {
+			sizeof (GthTiffSaverClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) gth_tiff_saver_class_init,
+			NULL,
+			NULL,
+			sizeof (GthTiffSaver),
+			0,
+			(GInstanceInitFunc) gth_tiff_saver_init
+		};
+
+		type = g_type_register_static (GTH_TYPE_PIXBUF_SAVER,
+					       "GthTiffSaver",
+					       &type_info,
+					       0);
+	}
+
+	return type;
+}
diff --git a/extensions/pixbuf_savers/gth-tiff-saver.h b/extensions/pixbuf_savers/gth-tiff-saver.h
new file mode 100644
index 0000000..fd818c4
--- /dev/null
+++ b/extensions/pixbuf_savers/gth-tiff-saver.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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 GTH_TIFF_SAVER_H
+#define GTH_TIFF_SAVER_H
+
+#include <gtk/gtk.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_TIFF_SAVER              (gth_tiff_saver_get_type ())
+#define GTH_TIFF_SAVER(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_TIFF_SAVER, GthTiffSaver))
+#define GTH_TIFF_SAVER_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TIFF_SAVER_TYPE, GthTiffSaverClass))
+#define GTH_IS_TIFF_SAVER(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_TIFF_SAVER))
+#define GTH_IS_TIFF_SAVER_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_TIFF_SAVER))
+#define GTH_TIFF_SAVER_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_TIFF_SAVER, GthTiffSaverClass))
+
+typedef struct _GthTiffSaver         GthTiffSaver;
+typedef struct _GthTiffSaverClass    GthTiffSaverClass;
+typedef struct _GthTiffSaverPrivate  GthTiffSaverPrivate;
+
+struct _GthTiffSaver
+{
+	GthPixbufSaver __parent;
+	GthTiffSaverPrivate *priv;
+};
+
+struct _GthTiffSaverClass
+{
+	GthPixbufSaverClass __parent_class;
+};
+
+GType  gth_tiff_saver_get_type  (void);
+
+G_END_DECLS
+
+#endif /* GTH_TIFF_SAVER_H */
diff --git a/extensions/pixbuf_savers/main.c b/extensions/pixbuf_savers/main.c
new file mode 100644
index 0000000..f29741c
--- /dev/null
+++ b/extensions/pixbuf_savers/main.c
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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>
+#include <gthumb.h>
+#include "gth-jpeg-saver.h"
+#include "gth-png-saver.h"
+#include "gth-tga-saver.h"
+#include "gth-tiff-saver.h"
+#include "preferences.h"
+
+
+G_MODULE_EXPORT void
+gthumb_extension_activate (void)
+{
+	gth_main_register_type ("pixbuf-saver", GTH_TYPE_JPEG_SAVER);
+	gth_main_register_type ("pixbuf-saver", GTH_TYPE_PNG_SAVER);
+	gth_main_register_type ("pixbuf-saver", GTH_TYPE_TGA_SAVER);
+	gth_main_register_type ("pixbuf-saver", GTH_TYPE_TIFF_SAVER);
+	gth_hook_add_callback ("dlg-preferences-construct", 30, G_CALLBACK (so__dlg_preferences_construct_cb), NULL);
+	gth_hook_add_callback ("dlg-preferences-apply", 10, G_CALLBACK (so__dlg_preferences_apply_cb), NULL);
+}
+
+
+G_MODULE_EXPORT void
+gthumb_extension_deactivate (void)
+{
+}
+
+
+G_MODULE_EXPORT gboolean
+gthumb_extension_is_configurable (void)
+{
+	return FALSE;
+}
+
+
+G_MODULE_EXPORT void
+gthumb_extension_configure (GtkWindow *parent)
+{
+}
diff --git a/extensions/pixbuf_savers/pixbuf_savers.extension.in.in b/extensions/pixbuf_savers/pixbuf_savers.extension.in.in
new file mode 100644
index 0000000..032c973
--- /dev/null
+++ b/extensions/pixbuf_savers/pixbuf_savers.extension.in.in
@@ -0,0 +1,11 @@
+[Extension]
+_Name=Save images
+_Description=Save images in common file formats such as JPEG, PNG and TIFF
+_Authors=gthumb development team
+Copyright=Copyright © 2009 The Free Software Foundation, Inc.
+Version=1.0
+
+[Loader]
+Type=module
+File=%LIBRARY%
+Requires=jpeg_utils
diff --git a/extensions/pixbuf_savers/preferences.c b/extensions/pixbuf_savers/preferences.c
new file mode 100644
index 0000000..c78311a
--- /dev/null
+++ b/extensions/pixbuf_savers/preferences.c
@@ -0,0 +1,164 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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>
+#include <glib/gi18n.h>
+#include <gthumb.h>
+#include "preferences.h"
+
+
+#define GET_WIDGET(name) _gtk_builder_get_widget (data->builder, (name))
+#define BROWSER_DATA_KEY "save-options-preference-data"
+
+
+enum {
+	FILE_TYPE_COLUMN_N,
+	FILE_TYPE_COLUMN_OBJ,
+	FILE_TYPE_COLUMN_DISPLAY_NAME
+};
+
+
+typedef struct {
+	GtkBuilder *builder;
+	GList      *pixbuf_saver;
+} BrowserData;
+
+
+static void
+browser_data_free (BrowserData *data)
+{
+	_g_object_list_unref (data->pixbuf_saver);
+	g_object_unref (data->builder);
+	g_free (data);
+}
+
+
+static void
+treeselection_changed_cb (GtkTreeSelection *treeselection,
+			  gpointer          user_data)
+{
+	GtkWidget      *dialog = user_data;
+	BrowserData    *data;
+	GtkTreeIter     iter;
+	int             page_n;
+	GthPixbufSaver *pixbuf_saver;
+
+	data = g_object_get_data (G_OBJECT (dialog), BROWSER_DATA_KEY);
+	g_return_if_fail (data != NULL);
+
+	if (! gtk_tree_selection_get_selected (treeselection, NULL, &iter))
+		return;
+
+	gtk_tree_model_get (GTK_TREE_MODEL (gtk_builder_get_object (data->builder, "file_type_liststore")), &iter,
+			    FILE_TYPE_COLUMN_N, &page_n,
+			    FILE_TYPE_COLUMN_OBJ, &pixbuf_saver,
+			    -1);
+	gtk_notebook_set_current_page (GTK_NOTEBOOK (_gtk_builder_get_widget (data->builder, "options_notebook")), page_n);
+	gtk_label_set_text (GTK_LABEL (_gtk_builder_get_widget (data->builder, "file_type_label")), gth_pixbuf_saver_get_display_name (pixbuf_saver));
+
+	g_object_unref (pixbuf_saver);
+}
+
+
+void
+so__dlg_preferences_construct_cb (GtkWidget  *dialog,
+				  GthBrowser *browser,
+				  GtkBuilder *dialog_builder)
+{
+	BrowserData      *data;
+	GtkWidget        *notebook;
+	GtkWidget        *page;
+	GtkListStore     *model;
+	GArray           *pixbuf_saver_types;
+	int               i;
+	GtkTreeSelection *treeselection;
+	GtkTreePath      *path;
+	GtkWidget        *label;
+
+	data = g_new0 (BrowserData, 1);
+	data->builder = _gtk_builder_new_from_file ("save-options-preferences.ui", "pixbuf_savers");
+
+	notebook = _gtk_builder_get_widget (dialog_builder, "notebook");
+
+	page = _gtk_builder_get_widget (data->builder, "preferences_page");
+	gtk_widget_show (page);
+
+	model = (GtkListStore *) gtk_builder_get_object (data->builder, "file_type_liststore");
+	pixbuf_saver_types = gth_main_get_type_set ("pixbuf-saver");
+	for (i = 0; (pixbuf_saver_types != NULL) && (i < pixbuf_saver_types->len); i++) {
+		GthPixbufSaver *pixbuf_saver;
+		GtkTreeIter     iter;
+		GtkWidget      *options;
+
+		pixbuf_saver = g_object_new (g_array_index (pixbuf_saver_types, GType, i), NULL);
+
+		gtk_list_store_append (model, &iter);
+		gtk_list_store_set (model, &iter,
+				    FILE_TYPE_COLUMN_N, i,
+				    FILE_TYPE_COLUMN_OBJ, pixbuf_saver,
+				    FILE_TYPE_COLUMN_DISPLAY_NAME, gth_pixbuf_saver_get_display_name (pixbuf_saver),
+				    -1);
+
+		options = gth_pixbuf_saver_get_control (pixbuf_saver);
+		gtk_widget_show (options);
+		gtk_notebook_append_page (GTK_NOTEBOOK (_gtk_builder_get_widget (data->builder, "options_notebook")), options, NULL);
+
+		data->pixbuf_saver = g_list_prepend (data->pixbuf_saver, pixbuf_saver);
+	}
+
+	treeselection = gtk_tree_view_get_selection (GTK_TREE_VIEW (_gtk_builder_get_widget (data->builder, "file_type_treeview")));
+	gtk_tree_selection_set_mode (treeselection, GTK_SELECTION_BROWSE);
+	g_signal_connect (treeselection,
+			  "changed",
+			  G_CALLBACK (treeselection_changed_cb),
+			  dialog);
+
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("ask_options_checkbutton")), eel_gconf_get_boolean (PREF_SAVE_OPTIONS_ASK_OPTIONS, TRUE));
+
+	label = gtk_label_new (_("Saving"));
+	gtk_widget_show (label);
+
+	gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, label);
+	g_object_set_data_full (G_OBJECT (dialog), BROWSER_DATA_KEY, data, (GDestroyNotify) browser_data_free);
+
+	path = gtk_tree_path_new_first ();
+	gtk_tree_selection_select_path (treeselection, path);
+	gtk_tree_path_free (path);
+}
+
+
+void
+so__dlg_preferences_apply_cb (GtkWidget  *dialog,
+			      GthBrowser *browser,
+			      GtkBuilder *builder)
+{
+	BrowserData *data;
+	GList       *scan;
+
+	data = g_object_get_data (G_OBJECT (dialog), BROWSER_DATA_KEY);
+	g_return_if_fail (data != NULL);
+
+	for (scan = data->pixbuf_saver; scan; scan = scan->next) {
+		GthPixbufSaver *pixbuf_saver = scan->data;
+		gth_pixbuf_saver_save_options (pixbuf_saver);
+	}
+}
diff --git a/extensions/pixbuf_savers/preferences.h b/extensions/pixbuf_savers/preferences.h
new file mode 100644
index 0000000..da2d013
--- /dev/null
+++ b/extensions/pixbuf_savers/preferences.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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 PREFERENCES_H
+#define PREFERENCES_H
+
+#include <gthumb.h>
+
+
+typedef enum {
+	GTH_TIFF_COMPRESSION_NONE,
+	GTH_TIFF_COMPRESSION_DEFLATE,
+	GTH_TIFF_COMPRESSION_JPEG
+} GthTiffCompression;
+
+
+#define  PREF_SAVE_OPTIONS_ASK_OPTIONS  "/apps/gthumb/ext/save_options/ask_options"
+#define  PREF_JPEG_QUALITY              "/apps/gthumb/save_options/jpeg/quality"
+#define  PREF_JPEG_SMOOTHING            "/apps/gthumb/save_options/jpeg/smoothing"
+#define  PREF_JPEG_OPTIMIZE             "/apps/gthumb/save_options/jpeg/optimize"
+#define  PREF_JPEG_PROGRESSIVE          "/apps/gthumb/save_options/jpeg/progressive"
+#define  PREF_PNG_COMPRESSION_LEVEL     "/apps/gthumb/save_options/png/compression_level"
+#define  PREF_TGA_RLE_COMPRESSION       "/apps/gthumb/save_options/tga/rle_compression"
+#define  PREF_TIFF_COMPRESSION          "/apps/gthumb/save_options/tiff/compression"
+#define  PREF_TIFF_HORIZONTAL_RES       "/apps/gthumb/save_options/tiff/horizontal_resolution"
+#define  PREF_TIFF_VERTICAL_RES         "/apps/gthumb/save_options/tiff/vertical_resolution"
+
+
+void so__dlg_preferences_construct_cb (GtkWidget  *dialog,
+				       GthBrowser *browser,
+				       GtkBuilder *builder);
+void so__dlg_preferences_apply_cb     (GtkWidget  *dialog,
+				       GthBrowser *browser,
+				       GtkBuilder *builder);
+
+#endif /* PREFERENCES_H */
diff --git a/gthumb/Makefile.am b/gthumb/Makefile.am
index d4d1281..fa36212 100644
--- a/gthumb/Makefile.am
+++ b/gthumb/Makefile.am
@@ -30,6 +30,7 @@ PUBLIC_HEADER_FILES = 					\
 	glib-utils.h					\
 	gnome-desktop-thumbnail.h			\
 	gth-async-task.h				\
+	gth-buffer-data.h				\
 	gth-browser.h					\
 	gth-cell-renderer-thumbnail.h			\
 	gth-cursors.h					\
@@ -38,8 +39,8 @@ PUBLIC_HEADER_FILES = 					\
 	gth-edit-metadata-dialog.h			\
 	gth-embedded-dialog.h				\
 	gth-empty-list.h				\
-	gth-enum-types.h                                \
 	gth-extensions.h				\
+	gth-error.h					\
 	gth-file-data.h					\
 	gth-file-list.h					\
 	gth-file-properties.h				\
@@ -76,6 +77,7 @@ PUBLIC_HEADER_FILES = 					\
 	gth-overwrite-dialog.h				\
 	gth-pixbuf-task.h				\
 	gth-pixbuf-list-task.h				\
+	gth-pixbuf-saver.h				\
 	gth-preferences.h				\
 	gth-progress-dialog.h				\
 	gth-sidebar.h					\
@@ -98,7 +100,6 @@ PUBLIC_HEADER_FILES = 					\
 	gth-user-dir.h					\
 	gth-viewer-page.h				\
 	gth-window.h					\
-	gthumb-error.h					\
 	gtk-utils.h					\
 	main.h						\
 	pixbuf-cache.h					\
@@ -142,6 +143,7 @@ gthumb_SOURCES = 					\
 	gth-async-task.c				\
 	gth-browser.c					\
 	gth-browser-actions-callbacks.c			\
+	gth-buffer-data.c				\
 	gth-cell-renderer-thumbnail.c			\
 	gth-cursors.c					\
 	gth-dumb-notebook.c				\
@@ -149,6 +151,7 @@ gthumb_SOURCES = 					\
 	gth-edit-metadata-dialog.c			\
 	gth-embedded-dialog.c				\
 	gth-empty-list.c				\
+	gth-error.c					\
 	gth-extensions.c				\
 	gth-file-data.c					\
 	gth-file-list.c					\
@@ -192,6 +195,7 @@ gthumb_SOURCES = 					\
 	gth-overwrite-dialog.c				\
 	gth-pixbuf-task.c				\
 	gth-pixbuf-list-task.c				\
+	gth-pixbuf-saver.c				\
 	gth-preferences.c				\
 	gth-progress-dialog.c				\
 	gth-sidebar.c					\
@@ -214,7 +218,6 @@ gthumb_SOURCES = 					\
 	gth-viewer-page.c				\
 	gth-window.c					\
 	gth-window-actions-callbacks.c			\
-	gthumb-error.c					\
 	gtk-utils.c					\
 	main.c						\
 	pixbuf-cache.c					\
@@ -232,6 +235,7 @@ gthumb_LDADD =						\
 	$(GTHUMB_LIBS)					\
 	$(EXIV2_LIBS)					\
 	$(JPEG_LIBS)					\
+	$(TIFF_LIBS)					\
 	$(CLUTTER_LIBS)					\
 	$(NULL)	
 
@@ -292,7 +296,7 @@ gth-marshal.c: gth-marshal.h gth-marshal.list $(GLIB_GENMARSHAL)
 	&& $(GLIB_GENMARSHAL) $(srcdir)/gth-marshal.list --body --prefix=gth_marshal >> $@ 
 
 gthumb.h: make-header.sh gthumb.h.template Makefile.am
-	$(srcdir)/make-header.sh $(srcdir)/gthumb.h.template  $(PUBLIC_HEADER_FILES) > xgen-$(@F) \
+	$(srcdir)/make-header.sh $(srcdir)/gthumb.h.template  $(PUBLIC_HEADER_FILES) gth-enum-types.h > xgen-$(@F) \
 	&& (cmp -s xgen-$(@F) gthumb.h || cp xgen-$(@F) gthumb.h ) \
 	&& rm -f xgen-$(@F)
 
diff --git a/gthumb/gconf-utils.c b/gthumb/gconf-utils.c
index 65c1e07..4541ce8 100644
--- a/gthumb/gconf-utils.c
+++ b/gthumb/gconf-utils.c
@@ -51,7 +51,7 @@
 #include <gconf/gconf.h>
 #include "gconf-utils.h"
 #include "gtk-utils.h"
-#include "gthumb-error.h"
+#include "gth-error.h"
 #include "glib-utils.h"
 
 #define HOME_DIR "~"
@@ -129,7 +129,7 @@ check_type (const char      *key,
 {
 	if (val->type != t) {
 		g_set_error (err,
-			     GTHUMB_ERROR,
+			     GTH_ERROR,
 			     errno,
 			     "Type mismatch for key %s",
 			     key);
diff --git a/gthumb/gth-browser.c b/gthumb/gth-browser.c
index 0370ea4..65b9942 100644
--- a/gthumb/gth-browser.c
+++ b/gthumb/gth-browser.c
@@ -33,6 +33,7 @@
 #include "gth-browser-ui.h"
 #include "gth-duplicable.h"
 #include "gth-enum-types.h"
+#include "gth-error.h"
 #include "gth-file-list.h"
 #include "gth-file-view.h"
 #include "gth-file-selection.h"
@@ -54,7 +55,6 @@
 #include "gth-window.h"
 #include "gth-window-actions-callbacks.h"
 #include "gth-window-actions-entries.h"
-#include "gthumb-error.h"
 #include "main.h"
 
 #define GTH_BROWSER_CALLBACK(f) ((GthBrowserCallback) (f))
@@ -1617,7 +1617,7 @@ _gth_browser_load (GthBrowser *browser,
 		char   *uri;
 
 		uri = g_file_get_uri (location);
-		error = g_error_new (GTHUMB_ERROR, 0, _("No suitable module found for %s"), uri);
+		error = g_error_new (GTH_ERROR, 0, _("No suitable module found for %s"), uri);
 		load_data_ready (load_data, NULL, error);
 
 		g_free (uri);
@@ -1644,7 +1644,7 @@ _gth_browser_load (GthBrowser *browser,
 		char   *uri;
 
 		uri = g_file_get_uri (load_data->requested_folder->file);
-		error = g_error_new (GTHUMB_ERROR, 0, _("No suitable module found for %s"), uri);
+		error = g_error_new (GTH_ERROR, 0, _("No suitable module found for %s"), uri);
 		load_data_ready (load_data, NULL, error);
 
 		g_free (uri);
@@ -4574,7 +4574,7 @@ load_file_attributes_ready_cb (GthFileSource *file_source,
 			char   *uri;
 
 			uri = g_file_get_uri (data->location);
-			error = g_error_new (GTHUMB_ERROR, 0, _("File type not supported %s"), uri);
+			error = g_error_new (GTH_ERROR, 0, _("File type not supported %s"), uri);
 			_gtk_error_dialog_from_gerror_show (GTK_WINDOW (browser), _("Could not load the position"), &error);
 
 			g_free (uri);
@@ -4612,7 +4612,7 @@ gth_browser_load_location (GthBrowser *browser,
 		char   *uri;
 
 		uri = g_file_get_uri (data->location);
-		error = g_error_new (GTHUMB_ERROR, 0, _("No suitable module found for %s"), uri);
+		error = g_error_new (GTH_ERROR, 0, _("No suitable module found for %s"), uri);
 		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (browser), _("Could not load the position"), &error);
 
 		g_free (uri);
diff --git a/gthumb/gth-buffer-data.c b/gthumb/gth-buffer-data.c
new file mode 100644
index 0000000..00b5f0b
--- /dev/null
+++ b/gthumb/gth-buffer-data.c
@@ -0,0 +1,161 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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>
+#include <string.h>
+#include <stdio.h>
+#include <glib/gi18n.h>
+#include "gth-buffer-data.h"
+#include "gth-error.h"
+
+
+#define INITIAL_ALLOCATED_SIZE 1024
+
+
+struct _GthBufferData {
+	char    *buffer;
+	gsize    buffer_size;
+	gsize    allocated_size;
+	goffset  current_pos;
+};
+
+
+GthBufferData *
+gth_buffer_data_new (void)
+{
+	GthBufferData *buffer_data;
+
+	buffer_data = g_new (GthBufferData, 1);
+	buffer_data->buffer = g_try_malloc (INITIAL_ALLOCATED_SIZE);
+	buffer_data->buffer_size = 0;
+	buffer_data->allocated_size = INITIAL_ALLOCATED_SIZE;
+	buffer_data->current_pos = 0;
+
+	return buffer_data;
+}
+
+
+void
+gth_buffer_data_free (GthBufferData *buffer_data,
+		      gboolean       free_segment)
+{
+	if (free_segment)
+		g_free (buffer_data->buffer);
+	g_free (buffer_data);
+}
+
+
+static gboolean
+gth_buffer_data_alloc_new_space (GthBufferData  *buffer_data,
+				 gsize           len,
+				 GError        **error)
+{
+	if (buffer_data->current_pos + len > buffer_data->buffer_size)
+		buffer_data->buffer_size = buffer_data->current_pos + len;
+
+	if (buffer_data->buffer_size > buffer_data->allocated_size) {
+		gsize  new_allocated_size;
+		char  *new_buffer;
+
+		new_allocated_size = MAX (buffer_data->allocated_size * 2, buffer_data->buffer_size + len);
+		new_buffer = g_try_realloc (buffer_data->buffer, new_allocated_size);
+		if (new_buffer == NULL) {
+			g_set_error_literal (error,
+					     GTH_ERROR,
+					     GTH_ERROR_GENERIC,
+                                             _("Insufficient memory"));
+			return FALSE;
+		}
+
+		buffer_data->buffer = new_buffer;
+		buffer_data->allocated_size = new_allocated_size;
+	}
+
+	return TRUE;
+}
+
+
+gboolean
+gth_buffer_data_write (GthBufferData  *buffer_data,
+		       void           *buffer,
+		       gsize           len,
+		       GError        **error)
+{
+	if (len <= 0)
+		return TRUE;
+
+	if (! gth_buffer_data_alloc_new_space (buffer_data, len, error))
+		return FALSE;
+
+	memcpy (buffer_data->buffer + buffer_data->current_pos, buffer, len);
+	buffer_data->current_pos += len;
+
+	return TRUE;
+}
+
+
+gboolean
+gth_buffer_data_putc (GthBufferData  *buffer_data,
+		      int             c,
+		      GError        **error)
+{
+	if (! gth_buffer_data_alloc_new_space (buffer_data, 1, error))
+		return FALSE;
+
+	buffer_data->buffer[buffer_data->current_pos] = (char) c;
+	buffer_data->current_pos += 1;
+
+	return TRUE;
+}
+
+
+goffset
+gth_buffer_data_seek (GthBufferData *buffer_data,
+		      goffset        offset,
+		      int            whence)
+{
+        switch (whence) {
+        case SEEK_SET:
+        	buffer_data->current_pos = offset;
+                break;
+        case SEEK_CUR:
+        	buffer_data->current_pos += offset;
+                break;
+        case SEEK_END:
+        	buffer_data->current_pos = buffer_data->buffer_size + offset;
+                break;
+        default:
+                return -1;
+        }
+
+        return buffer_data->current_pos;
+}
+
+
+void
+gth_buffer_data_get (GthBufferData  *buffer_data,
+		     char          **buffer,
+		     gsize          *buffer_size)
+{
+	*buffer = buffer_data->buffer;
+	*buffer_size = buffer_data->buffer_size;
+}
diff --git a/gthumb/gth-buffer-data.h b/gthumb/gth-buffer-data.h
new file mode 100644
index 0000000..f10b3b4
--- /dev/null
+++ b/gthumb/gth-buffer-data.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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 GTH_BUFFER_DATA_H
+#define GTH_BUFFER_DATA_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GthBufferData GthBufferData;
+
+GthBufferData * gth_buffer_data_new   (void);
+void            gth_buffer_data_free  (GthBufferData  *buffer_data,
+				       gboolean        free_segment);
+gboolean        gth_buffer_data_write (GthBufferData  *buffer_data,
+				       void           *buffer,
+				       gsize           len,
+				       GError        **error);
+gboolean        gth_buffer_data_putc  (GthBufferData  *buffer_data,
+				       int             c,
+				       GError        **error);
+goffset         gth_buffer_data_seek  (GthBufferData  *buffer_data,
+				       goffset         offset,
+				       int             whence);
+void            gth_buffer_data_get   (GthBufferData  *buffer_data,
+				       char          **buffer,
+				       gsize          *buffer_size);
+
+G_END_DECLS
+
+#endif /* GTH_BUFFER_DATA_H */
diff --git a/gthumb/gthumb-error.c b/gthumb/gth-error.c
similarity index 88%
rename from gthumb/gthumb-error.c
rename to gthumb/gth-error.c
index 18e5578..a338faa 100644
--- a/gthumb/gthumb-error.c
+++ b/gthumb/gth-error.c
@@ -20,16 +20,16 @@
  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
  */
 
-#include "gthumb-error.h"
+#include "gth-error.h"
 
 
 GQuark 
-gthumb_error_quark (void)
+gth_error_quark (void)
 {
 	static GQuark quark;
         
         if (!quark)
-                quark = g_quark_from_static_string ("gthumb_error");
+                quark = g_quark_from_static_string ("gth_error");
 	
         return quark;
 }
diff --git a/gthumb/gthumb-error.h b/gthumb/gth-error.h
similarity index 86%
rename from gthumb/gthumb-error.h
rename to gthumb/gth-error.h
index 894230d..203d225 100644
--- a/gthumb/gthumb-error.h
+++ b/gthumb/gth-error.h
@@ -20,8 +20,8 @@
  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
  */
 
-#ifndef __GTHUMB_ERROR_H__
-#define __GTHUMB_ERROR_H__
+#ifndef GTH_ERROR_H
+#define GTH_ERROR_H
 
 #include <glib.h>
 
@@ -33,9 +33,9 @@ typedef enum {
 	GTH_ERROR_EXTENSION_DEPENDENCY
 } GthErrorCode;
 
-#define GTHUMB_ERROR gthumb_error_quark ()
-GQuark gthumb_error_quark (void);
+#define GTH_ERROR gth_error_quark ()
+GQuark gth_error_quark (void);
 
 G_END_DECLS
 
-#endif /* __GTHUMB_ERROR_H__ */
+#endif /* GTH_ERROR_H */
diff --git a/gthumb/gth-extensions.c b/gthumb/gth-extensions.c
index bee2e8c..e05c156 100644
--- a/gthumb/gth-extensions.c
+++ b/gthumb/gth-extensions.c
@@ -23,8 +23,8 @@
 #include <config.h>
 #include <glib/gi18n.h>
 #include "glib-utils.h"
+#include "gth-error.h"
 #include "gth-extensions.h"
-#include "gthumb-error.h"
 
 
 #define EXTENSION_SUFFIX ".extension"
@@ -267,7 +267,7 @@ gth_extension_module_exec_generic_func (GthExtensionModule   *self,
 	if (g_module_symbol (self->priv->module, function_name, (gpointer *)&func))
 		func();
 	else
-		*error = g_error_new_literal (GTHUMB_ERROR, GTH_ERROR_GENERIC, g_module_error ());
+		*error = g_error_new_literal (GTH_ERROR, GTH_ERROR_GENERIC, g_module_error ());
 
 	g_free (function_name);
 
@@ -811,7 +811,7 @@ gth_extension_manager_deactivate (GthExtensionManager  *manager,
 		GthExtensionDescription *child_description = scan->data;
 
 		if (gth_extension_description_is_active (child_description)) {
-			*error = g_error_new (GTHUMB_ERROR, GTH_ERROR_EXTENSION_DEPENDENCY, _("The extension '%s' is required by the extension '%s'"), description->name, child_description->name);
+			*error = g_error_new (GTH_ERROR, GTH_ERROR_EXTENSION_DEPENDENCY, _("The extension '%s' is required by the extension '%s'"), description->name, child_description->name);
 			break;
 		}
 	}
diff --git a/gthumb/gth-image-loader.c b/gthumb/gth-image-loader.c
index e0b0702..61839e4 100644
--- a/gthumb/gth-image-loader.c
+++ b/gthumb/gth-image-loader.c
@@ -27,9 +27,9 @@
 #include <gtk/gtk.h>
 #include "gth-file-data.h"
 #include "glib-utils.h"
+#include "gth-error.h"
 #include "gth-image-loader.h"
 #include "gth-main.h"
-#include "gthumb-error.h"
 
 /*
 #include "file-utils.h"
@@ -774,7 +774,7 @@ gth_image_loader_cancel_with_error (GthImageLoader *iloader,
 				    gpointer        done_func_data)
 {
 	g_mutex_lock (iloader->priv->data_mutex);
-	iloader->priv->error = g_error_new_literal (GTHUMB_ERROR, 0, "cancelled");
+	iloader->priv->error = g_error_new_literal (GTH_ERROR, 0, "cancelled");
 	g_mutex_unlock (iloader->priv->data_mutex);
 
 	_gth_image_loader_stop (iloader, done_func, done_func_data, TRUE, TRUE);
@@ -826,7 +826,7 @@ gth_image_loader_load_from_pixbuf_loader (GthImageLoader  *iloader,
 
 	g_mutex_lock (iloader->priv->data_mutex);
 	if ((iloader->priv->pixbuf == NULL) && (iloader->priv->animation == NULL))
-		error = g_error_new_literal (GTHUMB_ERROR, 0, "No image available");
+		error = g_error_new_literal (GTH_ERROR, 0, "No image available");
 	g_mutex_unlock (iloader->priv->data_mutex);
 
 	g_signal_emit (G_OBJECT (iloader), gth_image_loader_signals[READY], 0, error);
@@ -873,7 +873,7 @@ gth_image_loader_load_from_image_loader (GthImageLoader *to,
 	}
 
 	if ((to->priv->pixbuf == NULL) && (to->priv->animation == NULL))
-		error = g_error_new_literal (GTHUMB_ERROR, 0, "No image available");
+		error = g_error_new_literal (GTH_ERROR, 0, "No image available");
 
 	g_mutex_unlock (to->priv->data_mutex);
 	g_mutex_unlock (from->priv->data_mutex);
diff --git a/gthumb/gth-main.c b/gthumb/gth-main.c
index 1e1a3b8..7e2f3b2 100644
--- a/gthumb/gth-main.c
+++ b/gthumb/gth-main.c
@@ -690,6 +690,32 @@ gth_main_get_file_loader (const char *mime_type)
 }
 
 
+GthPixbufSaver *
+gth_main_get_pixbuf_saver (const char *mime_type)
+{
+	GArray *savers;
+	int     i;
+
+	savers = gth_main_get_type_set ("pixbuf-saver");
+	if (savers == NULL)
+		return NULL;
+
+	for (i = 0; i < savers->len; i++) {
+		GType           saver_type;
+		GthPixbufSaver *saver;
+
+		saver_type = g_array_index (savers, GType, i);
+		saver = g_object_new (saver_type, NULL);
+		if (gth_pixbuf_saver_can_save (saver, mime_type))
+			return saver;
+
+		g_object_unref (saver);
+	}
+
+	return NULL;
+}
+
+
 GthTest *
 gth_main_get_general_filter (void)
 {
@@ -1123,6 +1149,7 @@ void
 gth_main_activate_extensions (void)
 {
 	const char *mandatory_extensions[] = {	"file_viewer",
+						"jpeg_utils",
 						NULL };
 	const char *default_extensions[] = {	"catalogs",
 						"comments",
@@ -1133,6 +1160,7 @@ gth_main_activate_extensions (void)
 						"image_viewer",
 						"list_tools",
 						"photo_importer",
+						"pixbuf_savers",
 						"red_eye_removal",
 						"rename_series",
 						"resize_images",
diff --git a/gthumb/gth-main.h b/gthumb/gth-main.h
index 79f21cb..6c3592a 100644
--- a/gthumb/gth-main.h
+++ b/gthumb/gth-main.h
@@ -3,7 +3,7 @@
 /*
  *  GThumb
  *
- *  Copyright (C) 2008 Free Software Foundation, Inc.
+ *  Copyright (C) 2008-2009 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
@@ -26,13 +26,14 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
-#include "gth-file-data.h"
 #include "gth-extensions.h"
+#include "gth-file-data.h"
 #include "gth-file-source.h"
 #include "gth-filter-file.h"
 #include "gth-hook.h"
 #include "gth-metadata-provider.h"
 #include "gth-monitor.h"
+#include "gth-pixbuf-saver.h"
 #include "gth-tags-file.h"
 #include "gth-test.h"
 
@@ -90,6 +91,7 @@ void                   gth_main_register_file_loader          (FileLoader
 						               const char           *first_mime_type,
 						               ...);
 FileLoader             gth_main_get_file_loader               (const char           *mime_type);
+GthPixbufSaver *       gth_main_get_pixbuf_saver              (const char           *mime_type);
 GthTest *              gth_main_get_general_filter            (void);
 GthTest *              gth_main_add_general_filter            (GthTest              *filter);
 void		       gth_main_register_object               (GType                 superclass_type,
diff --git a/gthumb/gth-pixbuf-list-task.c b/gthumb/gth-pixbuf-list-task.c
index d3425c1..a27ac98 100644
--- a/gthumb/gth-pixbuf-list-task.c
+++ b/gthumb/gth-pixbuf-list-task.c
@@ -133,7 +133,6 @@ pixbuf_task_completed_cb (GthTask  *task,
 {
 	GthPixbufListTask *self = user_data;
 	GthFileData       *file_data;
-	char              *pixbuf_type;
 
 	if (g_error_matches (error, GTH_TASK_ERROR, GTH_TASK_ERROR_SKIP_TO_NEXT_FILE)) {
 		process_next_file (self);
@@ -146,17 +145,12 @@ pixbuf_task_completed_cb (GthTask  *task,
 	}
 
 	file_data = self->priv->current->data;
-	pixbuf_type = get_pixbuf_type_from_mime_type (gth_file_data_get_mime_type (file_data));
 	self->priv->new_pixbuf = g_object_ref (GTH_PIXBUF_TASK (task)->dest);
 	_gdk_pixbuf_save_async (self->priv->new_pixbuf,
 				file_data,
-				pixbuf_type,
-				NULL,
-				NULL,
+				gth_file_data_get_mime_type (file_data),
 				pixbuf_saved_cb,
 				self);
-
-	g_free (pixbuf_type);
 }
 
 
diff --git a/gthumb/gth-pixbuf-saver.c b/gthumb/gth-pixbuf-saver.c
new file mode 100644
index 0000000..deac3ab
--- /dev/null
+++ b/gthumb/gth-pixbuf-saver.c
@@ -0,0 +1,158 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include "gth-pixbuf-saver.h"
+
+
+static gpointer parent_class = NULL;
+
+
+static GtkWidget *
+base_get_control (GthPixbufSaver *self)
+{
+	return gtk_label_new (_("No options available for this file type"));
+}
+
+
+static void
+base_save_options (GthPixbufSaver *self)
+{
+	/* void */
+}
+
+
+static gboolean
+base_can_save (GthPixbufSaver *self,
+	       const char     *mime_type)
+{
+	return FALSE;
+}
+
+
+static gboolean
+base_save_pixbuf (GthPixbufSaver  *self,
+	          GdkPixbuf       *pixbuf,
+	          char           **buffer,
+	          gsize           *buffer_size,
+	          const char      *mime_type,
+	          GError         **error)
+{
+	return FALSE;
+}
+
+
+static void
+gth_pixbuf_saver_class_init (GthPixbufSaverClass *klass)
+{
+	parent_class = g_type_class_peek_parent (klass);
+
+	klass->id = "";
+	klass->display_name = "";
+	klass->get_control = base_get_control;
+	klass->save_options = base_save_options;
+	klass->can_save = base_can_save;
+	klass->save_pixbuf = base_save_pixbuf;
+}
+
+
+GType
+gth_pixbuf_saver_get_type (void)
+{
+	static GType type = 0;
+
+	if (! type) {
+		GTypeInfo type_info = {
+			sizeof (GthPixbufSaverClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) gth_pixbuf_saver_class_init,
+			NULL,
+			NULL,
+			sizeof (GthPixbufSaver),
+			0,
+			(GInstanceInitFunc) NULL
+		};
+
+		type = g_type_register_static (G_TYPE_OBJECT,
+					       "GthPixbufSaver",
+					       &type_info,
+					       0);
+	}
+
+	return type;
+}
+
+
+const char *
+gth_pixbuf_saver_get_id (GthPixbufSaver *self)
+{
+	return GTH_PIXBUF_SAVER_GET_CLASS (self)->id;
+}
+
+
+const char *
+gth_pixbuf_saver_get_display_name (GthPixbufSaver *self)
+{
+	return GTH_PIXBUF_SAVER_GET_CLASS (self)->display_name;
+}
+
+
+GtkWidget *
+gth_pixbuf_saver_get_control (GthPixbufSaver *self)
+{
+	return GTH_PIXBUF_SAVER_GET_CLASS (self)->get_control (self);
+}
+
+
+void
+gth_pixbuf_saver_save_options (GthPixbufSaver *self)
+{
+	GTH_PIXBUF_SAVER_GET_CLASS (self)->save_options (self);
+}
+
+
+gboolean
+gth_pixbuf_saver_can_save (GthPixbufSaver *self,
+			   const char     *mime_type)
+{
+	return GTH_PIXBUF_SAVER_GET_CLASS (self)->can_save (self, mime_type);
+}
+
+
+gboolean
+gth_pixbuf_saver_save_pixbuf (GthPixbufSaver   *self,
+			      GdkPixbuf        *pixbuf,
+			      char            **buffer,
+			      gsize            *buffer_size,
+			      const char       *mime_type,
+			      GError          **error)
+{
+	return GTH_PIXBUF_SAVER_GET_CLASS (self)->save_pixbuf (self,
+							       pixbuf,
+							       buffer,
+							       buffer_size,
+							       mime_type,
+							       error);
+}
diff --git a/gthumb/gth-pixbuf-saver.h b/gthumb/gth-pixbuf-saver.h
new file mode 100644
index 0000000..d64c569
--- /dev/null
+++ b/gthumb/gth-pixbuf-saver.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 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 GTH_PIXBUF_SAVER_H
+#define GTH_PIXBUF_SAVER_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_PIXBUF_SAVER              (gth_pixbuf_saver_get_type ())
+#define GTH_PIXBUF_SAVER(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_PIXBUF_SAVER, GthPixbufSaver))
+#define GTH_PIXBUF_SAVER_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_PIXBUF_SAVER, GthPixbufSaverClass))
+#define GTH_IS_PIXBUF_SAVER(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_PIXBUF_SAVER))
+#define GTH_IS_PIXBUF_SAVER_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_PIXBUF_SAVER))
+#define GTH_PIXBUF_SAVER_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_PIXBUF_SAVER, GthPixbufSaverClass))
+
+typedef struct _GthPixbufSaver         GthPixbufSaver;
+typedef struct _GthPixbufSaverClass    GthPixbufSaverClass;
+typedef struct _GthPixbufSaverPrivate  GthPixbufSaverPrivate;
+
+struct _GthPixbufSaver
+{
+	GObject __parent;
+	GthPixbufSaverPrivate *priv;
+};
+
+struct _GthPixbufSaverClass
+{
+	GObjectClass __parent_class;
+
+	/*< class attributes >*/
+
+	const char *id;
+	const char *display_name;
+
+	/*< virtual functions >*/
+
+	GtkWidget *  (*get_control)   (GthPixbufSaver   *self);
+	void         (*save_options)  (GthPixbufSaver   *self);
+	gboolean     (*can_save)      (GthPixbufSaver   *self,
+				       const char       *mime_type);
+	gboolean     (*save_pixbuf)   (GthPixbufSaver   *self,
+				       GdkPixbuf        *pixbuf,
+				       char            **buffer,
+				       gsize            *buffer_size,
+				       const char       *mime_type,
+				       GError          **error);
+};
+
+GType         gth_pixbuf_saver_get_type          (void);
+const char *  gth_pixbuf_saver_get_id            (GthPixbufSaver  *self);
+const char *  gth_pixbuf_saver_get_display_name  (GthPixbufSaver  *self);
+GtkWidget *   gth_pixbuf_saver_get_control       (GthPixbufSaver  *self);
+void          gth_pixbuf_saver_save_options      (GthPixbufSaver  *self);
+gboolean      gth_pixbuf_saver_can_save          (GthPixbufSaver  *self,
+					          const char      *mime_type);
+gboolean      gth_pixbuf_saver_save_pixbuf       (GthPixbufSaver  *self,
+						  GdkPixbuf       *pixbuf,
+						  char           **buffer,
+						  gsize           *buffer_size,
+						  const char      *mime_type,
+						  GError         **error);
+
+G_END_DECLS
+
+#endif /* GTH_PIXBUF_SAVER_H */
diff --git a/gthumb/gth-preferences.h b/gthumb/gth-preferences.h
index 08f962c..da2dcd4 100644
--- a/gthumb/gth-preferences.h
+++ b/gthumb/gth-preferences.h
@@ -72,19 +72,6 @@ G_BEGIN_DECLS
 #define PREF_UI_PROPERTIES_HEIGHT     "/apps/gthumb/ui/properties_height"
 #define PREF_UI_COMMENT_HEIGHT        "/apps/gthumb/ui/comment_height"
 
-#define PREF_PNG_COMPRESSION_LEVEL  "/apps/gthumb/dialogs/png_saver/compression_level"
-
-#define PREF_JPEG_QUALITY           "/apps/gthumb/dialogs/jpeg_saver/quality"
-#define PREF_JPEG_SMOOTHING         "/apps/gthumb/dialogs/jpeg_saver/smoothing"
-#define PREF_JPEG_OPTIMIZE          "/apps/gthumb/dialogs/jpeg_saver/optimize"
-#define PREF_JPEG_PROGRESSIVE       "/apps/gthumb/dialogs/jpeg_saver/progressive"
-
-#define PREF_TGA_RLE_COMPRESSION    "/apps/gthumb/dialogs/tga_saver/rle_compression"
-
-#define PREF_TIFF_COMPRESSION       "/apps/gthumb/dialogs/tiff_saver/compression"
-#define PREF_TIFF_HORIZONTAL_RES    "/apps/gthumb/dialogs/tiff_saver/horizontal_resolution"
-#define PREF_TIFF_VERTICAL_RES      "/apps/gthumb/dialogs/tiff_saver/vertical_resolution"
-
 #define PREF_ADD_TO_CATALOG_LAST_CATALOG "/apps/gthumb/dialogs/add_to_catalog/last_catalog"
 #define PREF_ADD_TO_CATALOG_VIEW    "/apps/gthumb/dialogs/add_to_catalog/view"
 
diff --git a/gthumb/gth-thumb-loader.c b/gthumb/gth-thumb-loader.c
index 206889b..84bc227 100644
--- a/gthumb/gth-thumb-loader.c
+++ b/gthumb/gth-thumb-loader.c
@@ -33,10 +33,10 @@
 #include "glib-utils.h"
 #define GNOME_DESKTOP_USE_UNSTABLE_API
 #include "gnome-desktop-thumbnail.h"
+#include "gth-error.h"
 #include "gth-image-loader.h"
 #include "gth-main.h"
 #include "gth-thumb-loader.h"
-#include "gthumb-error.h"
 #include "pixbuf-io.h"
 #include "pixbuf-utils.h"
 #include "typedefs.h"
@@ -416,7 +416,7 @@ watch_thumbnailer_cb (GPid     pid,
 	tloader->priv->thumbnailer_watch = 0;
 
 	if (status != 0) {
-		error = g_error_new_literal (GTHUMB_ERROR, 0, "cannot generate the thumbnail");
+		error = g_error_new_literal (GTH_ERROR, 0, "cannot generate the thumbnail");
 		image_loader_error (NULL, error, data);
 		return;
 	}
@@ -428,7 +428,7 @@ watch_thumbnailer_cb (GPid     pid,
 		g_object_unref (pixbuf);
 	}
 	else {
-		error = g_error_new_literal (GTHUMB_ERROR, 0, "cannot generate the thumbnail");
+		error = g_error_new_literal (GTH_ERROR, 0, "cannot generate the thumbnail");
 		image_loader_error (NULL, error, data);
 	}
 }
@@ -474,7 +474,7 @@ image_loader_ready_cb (GthImageLoader *iloader,
 	}
 	else {
 		if (error == NULL)
-			error = g_error_new_literal (GTHUMB_ERROR, 0, "cannot generate the thumbnail");
+			error = g_error_new_literal (GTH_ERROR, 0, "cannot generate the thumbnail");
 		image_loader_error (iloader, error, data);
 	}
 
@@ -515,7 +515,7 @@ thumb_loader (GthFileData  *file,
 		g_object_unref (pixbuf);
 	}
 	else
-		*error = g_error_new_literal (GTHUMB_ERROR, 0, "cannot generate the thumbnail");
+		*error = g_error_new_literal (GTH_ERROR, 0, "cannot generate the thumbnail");
 
 	return animation;
 }
@@ -684,7 +684,7 @@ gth_thumb_loader_load__step2 (GthThumbLoader *tloader)
 			g_signal_emit (G_OBJECT (tloader),
 				       gth_thumb_loader_signals[READY],
 				       0,
-				       g_error_new_literal (GTHUMB_ERROR, 0, "failed thumbnail"));
+				       g_error_new_literal (GTH_ERROR, 0, "failed thumbnail"));
 			g_free (uri);
 			return;
 		}
diff --git a/gthumb/pixbuf-io.c b/gthumb/pixbuf-io.c
index 8698d28..fd7a201 100644
--- a/gthumb/pixbuf-io.c
+++ b/gthumb/pixbuf-io.c
@@ -22,10 +22,14 @@
 
 #include <config.h>
 #include <string.h>
+#include <glib/gi18n.h>
 #define GDK_PIXBUF_ENABLE_BACKEND 1
 #include "gio-utils.h"
 #include "glib-utils.h"
+#include "gth-error.h"
 #include "gth-hook.h"
+#include "gth-main.h"
+#include "gth-pixbuf-saver.h"
 #include "pixbuf-io.h"
 
 
@@ -147,24 +151,29 @@ save_files (SavePixbufData  *data,
 void
 _gdk_pixbuf_save_async (GdkPixbuf        *pixbuf,
 			GthFileData      *file_data,
-			const char       *type,
-			char            **keys,
-			char            **values,
+			const char       *mime_type,
 			GthFileDataFunc   ready_func,
 			gpointer          ready_data)
 {
+	GthPixbufSaver *saver;
+	GError         *error = NULL;
 	void           *buffer;
 	gsize           buffer_size;
-	GError         *error = NULL;
 	SavePixbufData *data;
 
-	if (! gdk_pixbuf_save_to_bufferv (pixbuf,
-					  (char **)&buffer,
-					  &buffer_size,
-					  type,
-					  keys,
-					  values,
-					  &error))
+	saver = gth_main_get_pixbuf_saver (mime_type);
+	if (saver == NULL) {
+		error = g_error_new (GTH_ERROR, GTH_ERROR_GENERIC, _("Could not find a suitable module to save the image as \"%s\""), mime_type);
+		gth_file_data_ready_with_error (file_data, ready_func, ready_data, error);
+		return;
+	}
+
+	if (! gth_pixbuf_saver_save_pixbuf (saver,
+					    pixbuf,
+					    (char **)&buffer,
+					    &buffer_size,
+					    mime_type,
+					    &error))
 	{
 		gth_file_data_ready_with_error (file_data, ready_func, ready_data, error);
 		return;
@@ -173,12 +182,11 @@ _gdk_pixbuf_save_async (GdkPixbuf        *pixbuf,
 	data = g_new0 (SavePixbufData, 1);
 	data->file_data = g_object_ref (file_data);
 	data->pixbuf = g_object_ref (pixbuf);
-	data->type = type;
+	data->mime_type = mime_type;
 	data->buffer = buffer;
 	data->buffer_size = buffer_size;
 	data->files = NULL;
 	data->error = NULL;
-
 	gth_hook_invoke ("save-pixbuf", data);
 
 	if (data->error == NULL) {
diff --git a/gthumb/pixbuf-io.h b/gthumb/pixbuf-io.h
index 63667d6..9f19945 100644
--- a/gthumb/pixbuf-io.h
+++ b/gthumb/pixbuf-io.h
@@ -42,7 +42,7 @@ typedef struct {
 typedef struct {
 	GthFileData  *file_data;
 	GdkPixbuf    *pixbuf;
-	const char   *type;
+	const char   *mime_type;
 	void         *buffer;
 	gsize         buffer_size;
 	GList        *files; 		/* SavePixbufFile list */
@@ -52,9 +52,7 @@ typedef struct {
 char *      get_pixbuf_type_from_mime_type     (const char       *mime_type);
 void        _gdk_pixbuf_save_async             (GdkPixbuf        *pixbuf,
 						GthFileData      *file_data,
-						const char       *type,
-						char            **keys,
-						char            **values,
+						const char       *mime_type,
 						GthFileDataFunc   ready_func,
 						gpointer          data);
 GdkPixbuf * gth_pixbuf_new_from_file           (GthFileData      *file,
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9b44f5a..ff22581 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -8,8 +8,8 @@ copy-n-paste/eggsmclient.h
 copy-n-paste/eggsmclient-private.h
 copy-n-paste/eggsmclient-xsmp.c
 data/gthumb.desktop.in.in
-data/gthumb.schemas.in
 data/gthumb-import.desktop.in.in
+data/gthumb.schemas.in
 [type: gettext/glade]data/ui/bookmarks.ui
 [type: gettext/glade]data/ui/extensions.ui
 [type: gettext/glade]data/ui/filter-editor.ui
@@ -61,14 +61,33 @@ extensions/file_manager/gth-duplicate-task.h
 extensions/file_manager/gth-reorder-task.c
 extensions/file_manager/gth-reorder-task.h
 extensions/file_manager/main.c
+[type: gettext/glade]extensions/file_tools/data/ui/adjust-colors-options.ui
 [type: gettext/glade]extensions/file_tools/data/ui/crop-options.ui
 extensions/file_tools/file_tools.extension.in.in
+extensions/file_tools/gth-file-tool-adjust-colors.c
+extensions/file_tools/gth-file-tool-adjust-colors.h
 extensions/file_tools/gth-file-tool-crop.c
 extensions/file_tools/gth-file-tool-crop.h
 extensions/file_tools/gth-file-tool-desaturate.c
 extensions/file_tools/gth-file-tool-desaturate.h
+extensions/file_tools/gth-file-tool-enhance.c
+extensions/file_tools/gth-file-tool-enhance.h
+extensions/file_tools/gth-file-tool-equalize.c
+extensions/file_tools/gth-file-tool-equalize.h
+extensions/file_tools/gth-file-tool-flip.c
+extensions/file_tools/gth-file-tool-flip.h
+extensions/file_tools/gth-file-tool-mirror.c
+extensions/file_tools/gth-file-tool-mirror.h
+extensions/file_tools/gth-file-tool-negative.c
+extensions/file_tools/gth-file-tool-negative.h
 extensions/file_tools/gth-file-tool-redo.c
 extensions/file_tools/gth-file-tool-redo.h
+extensions/file_tools/gth-file-tool-rotate-left.c
+extensions/file_tools/gth-file-tool-rotate-left.h
+extensions/file_tools/gth-file-tool-rotate-right.c
+extensions/file_tools/gth-file-tool-rotate-right.h
+extensions/file_tools/gth-file-tool-save-as.c
+extensions/file_tools/gth-file-tool-save-as.h
 extensions/file_tools/gth-file-tool-save.c
 extensions/file_tools/gth-file-tool-save.h
 extensions/file_tools/gth-file-tool-undo.c
@@ -85,15 +104,9 @@ extensions/image_rotation/callbacks.h
 extensions/image_rotation/gth-transform-task.c
 extensions/image_rotation/gth-transform-task.h
 extensions/image_rotation/image_rotation.extension.in.in
-extensions/image_rotation/jmemorydest.c
-extensions/image_rotation/jmemorysrc.c
-extensions/image_rotation/jpegtran.c
-extensions/image_rotation/jpegtran.h
 extensions/image_rotation/main.c
 extensions/image_rotation/rotation-utils.c
 extensions/image_rotation/rotation-utils.h
-extensions/image_rotation/transupp.c
-extensions/image_rotation/transupp.h
 extensions/image_viewer/data/gthumb-image-viewer.schemas.in
 [type: gettext/glade]extensions/image_viewer/data/ui/image-viewer-preferences.ui
 extensions/image_viewer/gth-image-viewer-page.c
@@ -104,6 +117,16 @@ extensions/image_viewer/image_viewer.extension.in.in
 extensions/image_viewer/main.c
 extensions/image_viewer/preferences.c
 extensions/image_viewer/preferences.h
+extensions/jpeg_utils/jmemorydest.c
+extensions/jpeg_utils/jmemorydest.h
+extensions/jpeg_utils/jmemorysrc.c
+extensions/jpeg_utils/jmemorysrc.h
+extensions/jpeg_utils/jpegtran.c
+extensions/jpeg_utils/jpegtran.h
+extensions/jpeg_utils/jpeg_utils.extension.in.in
+extensions/jpeg_utils/main.c
+extensions/jpeg_utils/transupp.c
+extensions/jpeg_utils/transupp.h
 extensions/list_tools/actions.c
 extensions/list_tools/actions.h
 extensions/list_tools/callbacks.c
@@ -136,6 +159,29 @@ extensions/photo_importer/gth-import-task.h
 extensions/photo_importer/main.c
 extensions/photo_importer/photo_importer.extension.in.in
 extensions/photo_importer/preferences.h
+extensions/pixbuf_savers/data/gthumb-pixbuf-savers.schemas.in
+[type: gettext/glade]extensions/pixbuf_savers/data/ui/jpeg-options.ui
+[type: gettext/glade]extensions/pixbuf_savers/data/ui/png-options.ui
+[type: gettext/glade]extensions/pixbuf_savers/data/ui/save-options-preferences.ui
+[type: gettext/glade]extensions/pixbuf_savers/data/ui/tga-options.ui
+[type: gettext/glade]extensions/pixbuf_savers/data/ui/tiff-options.ui
+extensions/pixbuf_savers/gth-jpeg-saver.c
+extensions/pixbuf_savers/gth-jpeg-saver.h
+extensions/pixbuf_savers/gth-png-saver.c
+extensions/pixbuf_savers/gth-png-saver.h
+extensions/pixbuf_savers/gth-tga-saver.c
+extensions/pixbuf_savers/gth-tga-saver.h
+extensions/pixbuf_savers/gth-tiff-saver.c
+extensions/pixbuf_savers/gth-tiff-saver.h
+extensions/pixbuf_savers/main.c
+extensions/pixbuf_savers/pixbuf_savers.extension.in.in
+extensions/pixbuf_savers/preferences.c
+extensions/pixbuf_savers/preferences.h
+[type: gettext/glade]extensions/red_eye_removal/data/ui/red-eye-removal-options.ui
+extensions/red_eye_removal/gth-file-tool-red-eye.c
+extensions/red_eye_removal/gth-file-tool-red-eye.h
+extensions/red_eye_removal/main.c
+extensions/red_eye_removal/red_eye_removal.extension.in.in
 extensions/rename_series/actions.c
 extensions/rename_series/actions.h
 extensions/rename_series/callbacks.c
@@ -147,6 +193,17 @@ extensions/rename_series/gth-rename-task.c
 extensions/rename_series/gth-rename-task.h
 extensions/rename_series/main.c
 extensions/rename_series/rename_series.extension.in.in
+extensions/resize_images/actions.c
+extensions/resize_images/actions.h
+extensions/resize_images/callbacks.c
+extensions/resize_images/callbacks.h
+extensions/resize_images/data/gthumb_resize_images.schemas.in
+[type: gettext/glade]extensions/resize_images/data/ui/resize-images.ui
+extensions/resize_images/dlg-resize-images.c
+extensions/resize_images/dlg-resize-images.h
+extensions/resize_images/main.c
+extensions/resize_images/preferences.h
+extensions/resize_images/resize_images.extension.in.in
 extensions/search/actions.c
 extensions/search/actions.h
 extensions/search/callbacks.c
@@ -202,12 +259,16 @@ gthumb/glib-utils.h
 gthumb/gnome-desktop-thumbnail.c
 gthumb/gnome-desktop-thumbnail.h
 gthumb/gnome-thumbnail-pixbuf-utils.c
+gthumb/gth-async-task.c
+gthumb/gth-async-task.h
 gthumb/gth-browser-actions-callbacks.c
 gthumb/gth-browser-actions-callbacks.h
 gthumb/gth-browser-actions-entries.h
 gthumb/gth-browser.c
 gthumb/gth-browser.h
 gthumb/gth-browser-ui.h
+gthumb/gth-buffer-data.c
+gthumb/gth-buffer-data.h
 gthumb/gth-cell-renderer-thumbnail.c
 gthumb/gth-cell-renderer-thumbnail.h
 gthumb/gth-cursors.c
@@ -222,6 +283,8 @@ gthumb/gth-embedded-dialog.c
 gthumb/gth-embedded-dialog.h
 gthumb/gth-empty-list.c
 gthumb/gth-empty-list.h
+gthumb/gth-error.c
+gthumb/gth-error.h
 gthumb/gth-extensions.c
 gthumb/gth-extensions.h
 gthumb/gth-file-data.c
@@ -252,6 +315,10 @@ gthumb/gth-filter-file.h
 gthumb/gth-filter.h
 gthumb/gth-folder-tree.c
 gthumb/gth-folder-tree.h
+gthumb/gth-histogram.c
+gthumb/gth-histogram.h
+gthumb/gth-histogram-view.c
+gthumb/gth-histogram-view.h
 gthumb/gth-hook.c
 gthumb/gth-hook.h
 gthumb/gth-icon-cache.c
@@ -295,6 +362,10 @@ gthumb/gth-nav-window.c
 gthumb/gth-nav-window.h
 gthumb/gth-overwrite-dialog.c
 gthumb/gth-overwrite-dialog.h
+gthumb/gth-pixbuf-list-task.c
+gthumb/gth-pixbuf-list-task.h
+gthumb/gth-pixbuf-saver.c
+gthumb/gth-pixbuf-saver.h
 gthumb/gth-pixbuf-task.c
 gthumb/gth-pixbuf-task.h
 gthumb/gth-preferences.c
@@ -332,8 +403,6 @@ gthumb/gth-toggle-menu-tool-button.c
 gthumb/gth-toggle-menu-tool-button.h
 gthumb/gth-toolbox.c
 gthumb/gth-toolbox.h
-gthumb/gthumb-error.c
-gthumb/gthumb-error.h
 gthumb/gth-uri-list.c
 gthumb/gth-uri-list.h
 gthumb/gth-user-dir.c
@@ -349,6 +418,8 @@ gthumb/gtk-utils.c
 gthumb/gtk-utils.h
 gthumb/main.c
 gthumb/main.h
+gthumb/pixbuf-cache.c
+gthumb/pixbuf-cache.h
 gthumb/pixbuf-io.c
 gthumb/pixbuf-io.h
 gthumb/pixbuf-utils.c



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]