[f-spot/rubenv-gsoc-2009: 27/86] Split loaders and imaging out into separate assemblies.



commit 36a7f37447a52b503ae6539cb54596042eb30bf2
Author: Ruben Vermeersch <ruben savanne be>
Date:   Tue Jul 28 19:21:37 2009 +0200

    Split loaders and imaging out into separate assemblies.

 configure.ac                                     |    1 +
 extensions/Exporters/FacebookExport/Makefile.am  |    5 +-
 extensions/Exporters/FolderExport/Makefile.am    |    1 +
 extensions/Exporters/PicasaWebExport/Makefile.am |    2 +-
 src/.gitignore                                   |    5 +
 src/FSpot.Loaders.dll.config.in                  |   16 +
 src/Filters/JpegFilter.cs                        |    2 +-
 src/Filters/ResizeFilter.cs                      |    2 +-
 src/Filters/SharpFilter.cs                       |    2 +-
 src/{ => Imaging}/BitConverter.cs                |   22 +-
 src/Imaging/Exif.cs                              |    2 +-
 src/{ => Imaging}/IOChannel.cs                   |   48 +-
 src/Imaging/ImageFile.cs                         |    5 +
 src/{ => Imaging}/InternalProcess.cs             |    6 +-
 src/{ => Imaging}/MetadataStore.cs               |   66 ++--
 src/Imaging/PixbufUtils.cs                       |  622 +++++++++++++++++++++
 src/{ => Imaging}/PixelBuffer.cs                 |   32 +-
 src/Loaders/GdkImageLoader.cs                    |    6 +-
 src/Loaders/LibrawImageLoader.cs                 |    6 +-
 src/MainWindow.cs                                |    2 +-
 src/Makefile.am                                  |  131 ++++--
 src/PhotoImageView.cs                            |    7 +-
 src/PixbufUtils.cs                               |  631 +---------------------
 src/PrintOperation.cs                            |    6 +-
 src/SlideView.cs                                 |  558 +++++++++++++++++++
 src/ThumbnailGenerator.cs                        |    4 +-
 src/UI.Dialog/EditTagIconDialog.cs               |    6 +-
 src/Utils/PixbufExtensions.cs                    |   49 ++
 src/Widgets/Filmstrip.cs                         |    2 +-
 src/Widgets/IconView.cs                          |    3 +-
 src/Widgets/PreviewPopup.cs                      |    2 +-
 src/Widgets/SlideShow.cs                         |    2 +-
 tests/src/Makefile.am                            |    1 +
 33 files changed, 1474 insertions(+), 781 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 265388a..0a23e16 100644
--- a/configure.ac
+++ b/configure.ac
@@ -374,6 +374,7 @@ src/Core/Defines.cs
 src/AssemblyInfo.cs
 src/f-spot.exe.config
 src/Cms.dll.config
+src/FSpot.Loaders.dll.config
 src/FSpot.Widgets.dll.config
 src/Makefile
 extensions/Makefile
diff --git a/extensions/Exporters/FacebookExport/Makefile.am b/extensions/Exporters/FacebookExport/Makefile.am
index 10f4c05..0bfeea3 100644
--- a/extensions/Exporters/FacebookExport/Makefile.am
+++ b/extensions/Exporters/FacebookExport/Makefile.am
@@ -34,8 +34,9 @@ PLUGIN_SOURCES =			\
 
 REFS =							\
 	-r:$(top_builddir)/src/f-spot.exe		\
-	-r:$(top_builddir)/src/FSpot.Core.dll		\
-	-r:$(top_builddir)/src/FSpot.Utils.dll		\
+	-r:$(top_builddir)/src/FSpot.Core.dll	\
+	-r:$(top_builddir)/src/FSpot.Utils.dll	\
+	-r:$(top_builddir)/src/FSpot.Imaging.dll	\
 	-r:$(top_builddir)/src/FSpot.Platform.dll	\
 	-r:$(top_builddir)/src/FSpot.Widgets.dll	\
 	$(LINK_GTKSHARPBEANS)				\
diff --git a/extensions/Exporters/FolderExport/Makefile.am b/extensions/Exporters/FolderExport/Makefile.am
index c4762ca..54143e9 100644
--- a/extensions/Exporters/FolderExport/Makefile.am
+++ b/extensions/Exporters/FolderExport/Makefile.am
@@ -12,6 +12,7 @@ PLUGIN_SOURCES =			\
 REFS =					\
 	-r:$(top_builddir)/src/f-spot.exe		\
 	-r:$(top_builddir)/src/FSpot.Core.dll	\
+	-r:$(top_builddir)/src/FSpot.Imaging.dll	\
 	-r:$(top_builddir)/src/FSpot.Utils.dll	\
 	$(LINK_SEMWEB)				\
 	$(LINK_GPHOTO2)				\
diff --git a/extensions/Exporters/PicasaWebExport/Makefile.am b/extensions/Exporters/PicasaWebExport/Makefile.am
index 2d99f7c..a1fe340 100644
--- a/extensions/Exporters/PicasaWebExport/Makefile.am
+++ b/extensions/Exporters/PicasaWebExport/Makefile.am
@@ -13,9 +13,9 @@ REFS =						\
 	-r:$(top_builddir)/src/f-spot.exe	\
 	-r:$(top_builddir)/src/FSpot.Core.dll	\
 	-r:$(top_builddir)/src/FSpot.Utils.dll	\
+	-r:$(top_builddir)/src/FSpot.Imaging.dll	\
 	$(LINK_SEMWEB)				\
 	-r:google-sharp/Mono.Google.dll		\
-	$(LINK_KEYRING)				\
 	$(LINK_GIOSHARP)			\
 	$(LINK_GPHOTO2)				\
 	$(LINK_UNIQUESHARP)			\
diff --git a/src/.gitignore b/src/.gitignore
index f4fcdfe..dcca615 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -7,6 +7,11 @@
 /FSpot.Core.dll.mdb
 /FSpot.JobScheduler.dll
 /FSpot.JobScheduler.dll.mdb
+/FSpot.Imaging.dll
+/FSpot.Imaging.dll.mdb
+/FSpot.Loaders.dll
+/FSpot.Loaders.dll.mdb
+/FSpot.Loaders.dll.config
 /FSpot.Query.dll
 /FSpot.Query.dll.mdb
 /FSpot.Utils.dll
diff --git a/src/FSpot.Loaders.dll.config.in b/src/FSpot.Loaders.dll.config.in
new file mode 100644
index 0000000..b392442
--- /dev/null
+++ b/src/FSpot.Loaders.dll.config.in
@@ -0,0 +1,16 @@
+<configuration>
+  <dllmap dll="libglib-2.0-0.dll" target="libglib-2.0.so.0"/>
+  <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0"/>
+  <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-x11-2.0.so.0"/>
+  <dllmap dll="libgdk-2.0-0.dll" target="libgdk-x11-2.0.so.0"/>
+  <dllmap dll="libgdk_pixbuf-2.0-0.dll" target="libgdk_pixbuf-2.0.so.0"/>
+  <dllmap dll="libgnomevfs-2-0.dll" target="libgnomevfs-2.so.0"/>
+  <dllmap dll="libgnomeui-2-0.dll" target="libgnomeui-2.so.0"/>
+  <dllmap dll="libfspot" target="@expanded_libdir@/f-spot/libfspot.so.0"/>
+  <dllmap dll="libfspotjpeg" target="@expanded_libdir@/f-spot/libfspotjpg.so.0"/>
+  <dllmap dll="X11" target="libX11.so.6"/>
+  <dllmap dll="GL" target="libGL.so.1"/>
+  <dllmap dll="libXcomposite.dll" target="libXcomposite.so.1"/>
+  <dllmap dll="liblcms-1.0.0.dll" target="liblcms.so.1"/>
+  <dllmap dll="libexif.dll" target="libexif so  EXIF_SOVERSION@"/>
+</configuration>
diff --git a/src/Filters/JpegFilter.cs b/src/Filters/JpegFilter.cs
index 791ed16..8daa0f9 100644
--- a/src/Filters/JpegFilter.cs
+++ b/src/Filters/JpegFilter.cs
@@ -51,7 +51,7 @@ namespace FSpot.Filters {
 				using (IImageLoader loader = ImageLoader.Create (req.Current)) {
 					loader.Load (ImageLoaderItem.Full);
 					using (Pixbuf full = loader.Full)
-						PixbufUtils.SaveJpeg (full, dest, (int) quality, exif_data);
+						FSpotPixbufUtils.SaveJpeg (full, dest, (int) quality, exif_data);
 				}
 			}
 
diff --git a/src/Filters/ResizeFilter.cs b/src/Filters/ResizeFilter.cs
index aa9574e..a9547e0 100644
--- a/src/Filters/ResizeFilter.cs
+++ b/src/Filters/ResizeFilter.cs
@@ -67,7 +67,7 @@ namespace FSpot.Filters {
 	
 						exif_data = new Exif.ExifData (source);
 						
-						PixbufUtils.SaveJpeg (scaled, dest, 95, exif_data);
+						FSpotPixbufUtils.SaveJpeg (scaled, dest, 95, exif_data);
 					} else 
 						throw new NotImplementedException (String.Format (Catalog.GetString ("No way to save files of type \"{0}\""), destination_extension));
 				}
diff --git a/src/Filters/SharpFilter.cs b/src/Filters/SharpFilter.cs
index 64ac496..e6fb135 100644
--- a/src/Filters/SharpFilter.cs
+++ b/src/Filters/SharpFilter.cs
@@ -47,7 +47,7 @@ namespace FSpot.Filters {
 		
 							exif_data = new Exif.ExifData (req.Current.LocalPath);
 							
-							PixbufUtils.SaveJpeg (out_pixbuf, dest_uri.LocalPath, 90, exif_data);
+							FSpotPixbufUtils.SaveJpeg (out_pixbuf, dest_uri.LocalPath, 90, exif_data);
 						} else 
 							throw new NotImplementedException (String.Format (Catalog.GetString ("No way to save files of type \"{0}\""), destination_extension));
 						
diff --git a/src/BitConverter.cs b/src/Imaging/BitConverter.cs
similarity index 88%
rename from src/BitConverter.cs
rename to src/Imaging/BitConverter.cs
index 00f34c5..4e55070 100644
--- a/src/BitConverter.cs
+++ b/src/Imaging/BitConverter.cs
@@ -4,16 +4,16 @@ using System.Runtime.InteropServices;
 namespace FSpot {
 	//[Obsolete ("use Mono.DataConvert instead")]
 	public class BitConverter {
-		public static uint Swap (uint val, bool little) 
+		public static uint Swap (uint val, bool little)
 		{
 			return (little != System.BitConverter.IsLittleEndian) ?
 				((uint) ((((uint) (val) & (uint) 0x000000ffU) << 24) |
-					 (((uint) (val) & (uint) 0x0000ff00U) <<  8) | 
+					 (((uint) (val) & (uint) 0x0000ff00U) <<  8) |
 					 (((uint) (val) & (uint) 0x00ff0000U) >>  8) |
 					 (((uint) (val) & (uint) 0xff000000U) >> 24)))
 				: val;
 		}
-		
+
 		public static ushort Swap (ushort val, bool little)
 		{
 			return (little != System.BitConverter.IsLittleEndian) ?
@@ -25,27 +25,27 @@ namespace FSpot {
 		{
 			return ((ushort) ((ushort)(val >> 8) | (ushort)(val << 8)));
 		}
-		
+
 		public static ulong Swap (ulong val, bool little)
 		{
 		        return (little != System.BitConverter.IsLittleEndian) ?
-			((ulong) ((((ulong) (val) & (ulong) 0x00000000000000ffU) << 56) |     
-				  (((ulong) (val) & (ulong) 0x000000000000ff00U) << 40) |	
+			((ulong) ((((ulong) (val) & (ulong) 0x00000000000000ffU) << 56) |
+				  (((ulong) (val) & (ulong) 0x000000000000ff00U) << 40) |
 				  (((ulong) (val) & (ulong) 0x0000000000ff0000U) << 24) |
 				  (((ulong) (val) & (ulong) 0x00000000ff000000U) <<  8) |
-				  (((ulong) (val) & (ulong) 0x000000ff00000000U) >>  8) |	
+				  (((ulong) (val) & (ulong) 0x000000ff00000000U) >>  8) |
 				  (((ulong) (val) & (ulong) 0x0000ff0000000000U) >> 24) |
 				  (((ulong) (val) & (ulong) 0x00ff000000000000U) >> 40) |
 				  (((ulong) (val) & (ulong) 0xff00000000000000U) >> 56)))
 				: val;
 		}
-		
-		public static byte [] GetBytes (uint val, bool little) 
+
+		public static byte [] GetBytes (uint val, bool little)
 		{
 			val = Swap (val, little);
 			return System.BitConverter.GetBytes (val);
 		}
-		
+
 		public static byte [] GetBytes (ushort val, bool little)
 		{
 			val = Swap (val, little);
@@ -57,7 +57,7 @@ namespace FSpot {
 			val = Swap (val, little);
 			return System.BitConverter.GetBytes (val);
 		}
-		
+
 		public static ushort ToUInt16 (byte [] data, int position, bool little)
 		{
 			ushort val = System.BitConverter.ToUInt16 (data, position);
diff --git a/src/Imaging/Exif.cs b/src/Imaging/Exif.cs
index 2a31444..54684cb 100644
--- a/src/Imaging/Exif.cs
+++ b/src/Imaging/Exif.cs
@@ -156,7 +156,7 @@ namespace Exif {
 		Count
 	}
 	
-	internal class ExifUtil {
+	public class ExifUtil {
 		
 		[DllImport ("libexif.dll")]
 		static extern IntPtr exif_tag_get_name (Tag tag);
diff --git a/src/IOChannel.cs b/src/Imaging/IOChannel.cs
similarity index 95%
rename from src/IOChannel.cs
rename to src/Imaging/IOChannel.cs
index d7e357a..cf5a0f3 100644
--- a/src/IOChannel.cs
+++ b/src/Imaging/IOChannel.cs
@@ -37,7 +37,7 @@ namespace FSpot {
 	public class DataReadEventArgs : EventArgs {
 		public bool Continue;
 		IOCondition condition;
-		
+
 		public IOCondition Condition {
 			get { return condition; }
 		}
@@ -48,29 +48,29 @@ namespace FSpot {
 			Continue = true;
 		}
 	}
-	
+
 	public class IOChannel : System.IO.Stream {
 		private HandleRef handle;
-		
+
 		private delegate bool IOFunc (IntPtr source_channel, IOCondition cond, IntPtr data);
 
 		[DllImport("libglib-2.0-0.dll")]
 		static extern IOFlags g_io_channel_get_flags (HandleRef channel);
 
 		public override bool CanRead {
-			get { 
+			get {
 				IOFlags flags = g_io_channel_get_flags (handle);
 
-				return (flags & IOFlags.Readable) == IOFlags.Readable; 
+				return (flags & IOFlags.Readable) == IOFlags.Readable;
 			}
 		}
 
 		public override bool CanSeek {
 			get {
-#if NOTDONE				
+#if NOTDONE
 				IOFlags flags = g_io_channel_get_flags (handle);
 
-				return (flags & IOFlags.Seekable) == IOFlags.Seekable; 
+				return (flags & IOFlags.Seekable) == IOFlags.Seekable;
 #else
 				return false;
 #endif
@@ -81,16 +81,16 @@ namespace FSpot {
 			get {
 				IOFlags flags = g_io_channel_get_flags (handle);
 
-				return (flags & IOFlags.Writable) == IOFlags.Writable; 
+				return (flags & IOFlags.Writable) == IOFlags.Writable;
 			}
 		}
 
 		public override long Length {
-			get { 
+			get {
 				throw new NotSupportedException ("IOChannel doesn't support seeking");
 			}
 		}
-		
+
 		public override long Position {
 			get {
 				throw new NotSupportedException ("IOChannel doesn't support seeking");
@@ -125,7 +125,7 @@ namespace FSpot {
 		{
 			IOStatus status;
 			IntPtr error;
-			
+
 			status = g_io_channel_flush (handle, out error);
 
 			if (status != IOStatus.Normal && status != IOStatus.Eof)
@@ -137,7 +137,7 @@ namespace FSpot {
 
 		[DllImport("libglib-2.0-0.dll")]
 		static extern unsafe IOStatus g_io_channel_write_chars (HandleRef channel, byte *data, int count, out int bytes_written, out IntPtr error);
-		
+
 		public override void Write (byte [] buffer, int offset, int count)
 		{
 			IOStatus status = IOStatus.Again;
@@ -146,7 +146,7 @@ namespace FSpot {
 
 			if (buffer == null)
 				throw new ArgumentNullException ();
-			
+
 			unsafe {
 				while (status == IOStatus.Again && count > 0) {
 					fixed (byte *data = &buffer [offset]) {
@@ -155,13 +155,13 @@ namespace FSpot {
 
 					if (error != IntPtr.Zero)
 						throw new GException (error);
-					
+
 					offset += written;
 					count -= written;
 				}
 			}
 		}
-		
+
 		[DllImport("libglib-2.0-0.dll")]
 		static unsafe extern IOStatus g_io_channel_read_chars (HandleRef channel, byte *data, int count, out int bytes_read, out IntPtr error);
 
@@ -193,7 +193,7 @@ namespace FSpot {
 		{
 			return g_io_add_watch (handle, condition, func, IntPtr.Zero);
 		}
-		
+
 		// FIXME this should hold more than one source in a table
 		// but I am lazy
 		uint data_ready_source;
@@ -215,9 +215,9 @@ namespace FSpot {
 		private bool DataReadyHandler (IntPtr channel, IOCondition condition, IntPtr data)
 		{
 			DataReadEventArgs args = new DataReadEventArgs (condition);
-			if (data_ready != null) 
+			if (data_ready != null)
 				data_ready (this, args);
-			
+
 			return args.Continue;
 		}
 
@@ -225,7 +225,7 @@ namespace FSpot {
 		{
 			throw new NotSupportedException ();
 		}
-		
+
 		private enum SeekType {
 			Current,
 			Set,
@@ -237,7 +237,7 @@ namespace FSpot {
 
 		public override long Seek (long position, SeekOrigin origin)
 		{
-#if false			
+#if false
 			// GIOChannels have the interesting property of having a seek interface
 			// but no method to retrieve the current position or length.
 			// we could support these actions for unix iochannels with extra work
@@ -246,13 +246,13 @@ namespace FSpot {
 			SeekType type;
 			IntPtr error;
 			long final;
-			
+
 			switch (origin) {
 			case SeekOrigin.Begin:
 				type = SeekType.Set;
 				break;
 			case SeekOrigin.Current:
-				
+
 				break;
 			}
 
@@ -260,7 +260,7 @@ namespace FSpot {
 
 			if (error != IntPtr.Zero)
 				throw new GException (error);
-			
+
 			if (SeekOrigin == SeekOrigin.Begin)
 				return position;
 			else
@@ -284,7 +284,7 @@ namespace FSpot {
 			data_ready_source = 0;
 
 			g_io_channel_shutdown (handle, false, out error);
-			
+
 			base.Close ();
 
 			if (error != IntPtr.Zero)
diff --git a/src/Imaging/ImageFile.cs b/src/Imaging/ImageFile.cs
index cd34063..6ec1238 100644
--- a/src/Imaging/ImageFile.cs
+++ b/src/Imaging/ImageFile.cs
@@ -51,6 +51,11 @@ namespace FSpot {
 			return Open ();
 		}
 
+		public static void AddExtension (string extension, Type type)
+		{
+			name_table [extension] = type;
+		}
+
 		static ImageFile ()
 		{
 			name_table = new Hashtable ();
diff --git a/src/InternalProcess.cs b/src/Imaging/InternalProcess.cs
similarity index 98%
rename from src/InternalProcess.cs
rename to src/Imaging/InternalProcess.cs
index 15d6e43..5ff29b9 100644
--- a/src/InternalProcess.cs
+++ b/src/Imaging/InternalProcess.cs
@@ -54,7 +54,7 @@ namespace FSpot {
 							     IntPtr err,
 							     //ref int stderr,
 							     out IntPtr error);
-		
+
 		public InternalProcess (string path, string [] args)
 		{
 			IntPtr error;
@@ -64,8 +64,8 @@ namespace FSpot {
 				Array.Copy (args, nargs, args.Length);
 				args = nargs;
 			}
-			
-			g_spawn_async_with_pipes (path, args, null, InternalProcessFlags.SearchPath, 
+
+			g_spawn_async_with_pipes (path, args, null, InternalProcessFlags.SearchPath,
 						  IntPtr.Zero, IntPtr.Zero, IntPtr.Zero,
 						  ref stdin, ref stdout, IntPtr.Zero, out error);
 
diff --git a/src/MetadataStore.cs b/src/Imaging/MetadataStore.cs
similarity index 95%
rename from src/MetadataStore.cs
rename to src/Imaging/MetadataStore.cs
index 991b175..f9dac0f 100644
--- a/src/MetadataStore.cs
+++ b/src/Imaging/MetadataStore.cs
@@ -5,12 +5,12 @@ using FSpot.Xmp;
 using FSpot.Utils;
 
 namespace FSpot {
-        internal class Description {
+        public class Description {
 		string predicate;
 		string description;
 		string title;
 		ValueFormat formater;
-		
+
 		static System.Collections.Hashtable table;
 
 		static Description ()
@@ -20,7 +20,7 @@ namespace FSpot {
 				new Description ("dc:title", Catalog.GetString ("Title")),
 				new Description ("dc:rights", Catalog.GetString ("Copyright")),
 				new Description ("dc:subject", Catalog.GetString ("Subject and Keywords")),
-				new Description ("tiff:Compression", Catalog.GetString ("Compression"), 
+				new Description ("tiff:Compression", Catalog.GetString ("Compression"),
 						 typeof (FSpot.Tiff.Compression)),
 						 /* Translators: Planar Configuration is the label for the tiff:PlanarConfiguration tag
 						    "when Planar Configuration=1, this implies that all components must have
@@ -28,19 +28,19 @@ namespace FSpot {
 						    components could have different bit depths." */
 				new Description ("tiff:PlanarConfiguration", Catalog.GetString ("Planar Configuration"), 
 						 typeof (FSpot.Tiff.PlanarConfiguration)),
-				new Description ("tiff:Orientation", Catalog.GetString ("Orientation"), 
+				new Description ("tiff:Orientation", Catalog.GetString ("Orientation"),
 						 typeof (PixbufOrientation)),
-				new Description ("tiff:PhotometricInterpretation", Catalog.GetString ("Photometric Interpretation"), 
+				new Description ("tiff:PhotometricInterpretation", Catalog.GetString ("Photometric Interpretation"),
 						 typeof (FSpot.Tiff.PhotometricInterpretation)),
 				new Description ("tiff:ResolutionUnit", Catalog.GetString ("Resolution Unit"),
 						 typeof (FSpot.Tiff.ResolutionUnit)),
-				new Description ("exif:ExposureProgram", Catalog.GetString ("Exposure Program"), 
+				new Description ("exif:ExposureProgram", Catalog.GetString ("Exposure Program"),
 						 typeof (FSpot.Tiff.ExposureProgram)),
-				new Description ("exif:MeteringMode", Catalog.GetString ("Metering Mode"), 
+				new Description ("exif:MeteringMode", Catalog.GetString ("Metering Mode"),
 						 typeof (FSpot.Tiff.MeteringMode)),
-				new Description ("exif:ExposureMode", Catalog.GetString ("Exposure Mode"), 
+				new Description ("exif:ExposureMode", Catalog.GetString ("Exposure Mode"),
 						 typeof (FSpot.Tiff.ExposureMode)),
-				new Description ("exif:CustomRendered", Catalog.GetString ("Custom Rendered"), 
+				new Description ("exif:CustomRendered", Catalog.GetString ("Custom Rendered"),
 						 typeof (FSpot.Tiff.CustomRendered)),
 				new Description ("exif:ComponentsConfiguration", Catalog.GetString ("Components Configuration"),
 						 typeof (FSpot.Tiff.ComponentsConfiguration)),
@@ -74,18 +74,18 @@ namespace FSpot {
 
 
 			};
-			
+
 			table = new System.Collections.Hashtable ();
 
 			foreach (Description d in preset) {
 				table [MetadataStore.Namespaces.Resolve (d.predicate)] = d;
 			}
 		}
-		
+
 		public Description (string predicate, string title) : this (predicate, title, null, null) {}
 
 		public Description (string predicate, string title, string description) : this (predicate, title, description, null) {}
-		
+
 		public Description (string predicate, string title, System.Type type) : this (predicate, title)
 		{
 			formater = new ValueFormat (type);
@@ -97,7 +97,7 @@ namespace FSpot {
 			this.title = title;
 			this.formater = formater;
 		}
-		
+
 		public static void GetDescription (MemoryStore store, Statement stmt, out string label, out string value)
 		{
 			string predicate = stmt.Predicate.Uri;
@@ -119,7 +119,7 @@ namespace FSpot {
 				Statement sstmt = new Statement (stmt.Predicate,
 								 (Entity)MetadataStore.Namespaces.Resolve ("rdfs:label"),
 								 null);
-				
+
 				foreach (Statement tstmt in MetadataStore.Descriptions.Select (sstmt))
 					if (tstmt.Object is SemWeb.Literal)
 						label = ((SemWeb.Literal)(tstmt.Object)).Value;
@@ -127,11 +127,11 @@ namespace FSpot {
 			return;
 		}
 	}
-	
-        internal class ValueFormat 
+
+    public class ValueFormat
 	{
 		System.Type type;
-		
+
 		public ValueFormat (System.Type type)
 		{
 			this.type = type;
@@ -152,17 +152,17 @@ namespace FSpot {
 			/*
 			else if (type == typeof (Rational)) {
 				object o = FSpot.Tiff.Rational.Parse (obj.Value);
-			} 
+			}
 			*/
 			return result;
 		}
 	}
-	
+
 	public class MetadataStore : MemoryStore
 	{
 		public static NamespaceManager Namespaces;
 		private static MetadataStore descriptions;
-		
+
 		public const string PhotoshopNS = "http://ns.adobe.com/photoshop/1.0/";;
 		public const string Iptc4xmpCoreNS = "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/";;
 		public const string DcNS = "http://purl.org/dc/elements/1.1/";;
@@ -184,7 +184,7 @@ namespace FSpot {
 		static MetadataStore ()
 		{
 			Namespaces = new NamespaceManager ();
-			
+
 			Namespaces.AddNamespace (PhotoshopNS, "photoshop");
 			Namespaces.AddNamespace (Iptc4xmpCoreNS, "Iptc4xmpCore");
 			Namespaces.AddNamespace (DcNS, "dc");
@@ -211,7 +211,7 @@ namespace FSpot {
 						System.Console.WriteLine ("Can't find resource");
 					}
 				}
-				
+
 				return descriptions;
 			}
 		}
@@ -229,8 +229,8 @@ namespace FSpot {
 		{
 			Entity empty = new BNode ();
 			Statement top = new Statement (FSpotXMPBase, (Entity)MetadataStore.Namespaces.Resolve (predicate), empty);
-			Statement desc = new Statement (empty, 
-							(Entity)MetadataStore.Namespaces.Resolve ("rdf:type"), 
+			Statement desc = new Statement (empty,
+							(Entity)MetadataStore.Namespaces.Resolve ("rdf:type"),
 							(Entity)MetadataStore.Namespaces.Resolve (type));
 			sink.Add (desc);
 			Statement literal = new Statement (empty,
@@ -243,7 +243,7 @@ namespace FSpot {
 		public static void AddLiteral (StatementSink sink, string predicate, string value)
 		{
 			Statement stmt = new Statement (FSpotXMPBase,
-							(Entity)MetadataStore.Namespaces.Resolve (predicate), 
+							(Entity)MetadataStore.Namespaces.Resolve (predicate),
 							new SemWeb.Literal (value));
 			sink.Add (stmt);
 		}
@@ -304,7 +304,7 @@ namespace FSpot {
 				Add (this, predicate, type, values);
                         }
 		}
-		
+
 		public static void Add (StatementSink sink, Entity subject, string predicate, string type, string [] values)
 		{
 			if (values == null) {
@@ -314,8 +314,8 @@ namespace FSpot {
 
                         Entity empty = new SemWeb.BNode();
 			Statement top = new Statement (subject, (Entity)MetadataStore.Namespaces.Resolve (predicate), empty);
-			Statement desc = new Statement (empty, 
-							(Entity)MetadataStore.Namespaces.Resolve ("rdf:type"), 
+			Statement desc = new Statement (empty,
+							(Entity)MetadataStore.Namespaces.Resolve ("rdf:type"),
 							(Entity)MetadataStore.Namespaces.Resolve (type));
 			sink.Add (desc);
 			foreach (string value in values) {
@@ -327,7 +327,7 @@ namespace FSpot {
 			sink.Add (top);
 		}
 
-		private class StatementWriter : StatementSink 
+		private class StatementWriter : StatementSink
 		{
 			string name;
 			public StatementWriter (string name)
@@ -355,14 +355,14 @@ namespace FSpot {
 				this.Statement = stmt;
 				return false;
 			}
-		}			
+		}
 
 		public void DumpNode (XPathSemWebNavigator navi, int depth)
 		{
-			do { 
+			do {
 				System.Console.WriteLine ("node [{0}] {1} {2}", depth, navi.Name, navi.Value);
 			} while (navi.MoveToNext ());
 		}
-	       
-	}	       
+
+	}
 }
diff --git a/src/Imaging/PixbufUtils.cs b/src/Imaging/PixbufUtils.cs
new file mode 100644
index 0000000..d073432
--- /dev/null
+++ b/src/Imaging/PixbufUtils.cs
@@ -0,0 +1,622 @@
+//
+// FSpot.PixbufUtils.cs
+//
+// Author(s):
+//	Ettore Perazzoli
+//	Larry Ewing  <lewing novell com>
+//	Stephane Delcroix  <stephane declroix org>
+//
+// This is free softwae. See cOPYING for details
+//
+
+using Gdk;
+using System.Collections;
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using FSpot;
+using FSpot.Utils;
+
+public class PixbufUtils {
+	public static int GetSize (Pixbuf pixbuf)
+	{
+		return Math.Max (pixbuf.Width, pixbuf.Height);
+	}
+
+	public static double Fit (Pixbuf pixbuf,
+				  int dest_width, int dest_height,
+				  bool upscale_smaller,
+				  out int fit_width, out int fit_height)
+	{
+		return Fit (pixbuf.Width, pixbuf.Height,
+			    dest_width, dest_height,
+			    upscale_smaller,
+			    out fit_width, out fit_height);
+	}
+
+	public static double Fit (int orig_width, int orig_height,
+				  int dest_width, int dest_height,
+				  bool upscale_smaller,
+				  out int fit_width, out int fit_height)
+	{
+		if (orig_width == 0 || orig_height == 0) {
+			fit_width = 0;
+			fit_height = 0;
+			return 0.0;
+		}
+
+		double scale = Math.Min (dest_width / (double)orig_width,
+					 dest_height / (double)orig_height);
+
+		if (scale > 1.0 && !upscale_smaller)
+			scale = 1.0;
+
+		fit_width = (int) Math.Round (scale * orig_width);
+		fit_height = (int) Math.Round (scale * orig_height);
+
+		return scale;
+	}
+
+
+	// FIXME: These should be in GTK#.  When my patch is committed, these LoadFrom* methods will
+	// go away.
+
+	public class AspectLoader {
+		Gdk.PixbufLoader loader = new Gdk.PixbufLoader ();
+		int max_width;
+		int max_height;
+		PixbufOrientation orientation;
+
+		public AspectLoader (int max_width, int max_height)
+		{
+			this.max_height = max_height;
+			this.max_width = max_width;
+			loader.SizePrepared += HandleSizePrepared;
+		}
+
+		private void HandleSizePrepared (object obj, SizePreparedArgs args)
+		{
+			switch (orientation) {
+			case PixbufOrientation.LeftTop:
+			case PixbufOrientation.LeftBottom:
+			case PixbufOrientation.RightTop:
+			case PixbufOrientation.RightBottom:
+				int tmp = max_width;
+				max_width = max_height;
+				max_height = tmp;
+				break;
+			default:
+				break;
+			}
+
+			int scale_width = 0;
+			int scale_height = 0;
+
+			double scale = Fit (args.Width, args.Height, max_width, max_height, true, out scale_width, out scale_height);
+
+			if (scale < 1.0)
+				loader.SetSize (scale_width, scale_height);
+		}
+
+		public Pixbuf Load (System.IO.Stream stream, PixbufOrientation orientation)
+		{
+			int count;
+			byte [] data = new byte [8192];
+			while (((count = stream.Read (data, 0, data.Length)) > 0) && loader.Write (data, (ulong)count))
+				;
+
+			loader.Close ();
+			Pixbuf orig = loader.Pixbuf;
+			Gdk.Pixbuf rotated = FSpot.Utils.PixbufUtils.TransformOrientation (orig, orientation);
+
+			if (orig != rotated) {
+				rotated.CopyThumbnailOptionsFrom (orig);
+				orig.Dispose ();
+			}
+			loader.Dispose ();
+			return rotated;
+		}
+
+		public Pixbuf LoadFromFile (string path)
+		{
+			try {
+				orientation = GetOrientation (path);
+				using (FileStream fs = File.OpenRead (path)) {
+					return Load (fs, orientation);
+				}
+			} catch (Exception) {
+				System.Console.WriteLine ("Error loading photo {0}", path);
+				return null;
+			}
+		}
+	}
+
+	[Obsolete ("Use the extension method instead!")]
+	public static Pixbuf ShallowCopy (Pixbuf pixbuf)
+	{
+		if (pixbuf == null)
+			return null;
+		return pixbuf.ShallowCopy ();
+	}
+
+	public static Pixbuf ScaleToMaxSize (Pixbuf pixbuf, int width, int height)
+	{
+		return ScaleToMaxSize (pixbuf, width, height, true);
+	}
+
+	public static Pixbuf ScaleToMaxSize (Pixbuf pixbuf, int width, int height, bool upscale)
+	{
+		int scale_width = 0;
+		int scale_height = 0;
+		double scale = Fit (pixbuf, width, height, upscale, out scale_width, out scale_height);
+
+		Gdk.Pixbuf result;
+		if (upscale || (scale < 1.0))
+			result = pixbuf.ScaleSimple (scale_width, scale_height, (scale_width > 20) ? Gdk.InterpType.Bilinear : Gdk.InterpType.Nearest);
+		else
+			result = pixbuf.Copy ();
+
+		result.CopyThumbnailOptionsFrom (pixbuf);
+
+		return result;
+	}
+
+	static public void GetSize (string path, out int width, out int height)
+	{
+#if true
+		using (Gdk.Pixbuf pixbuf = new Gdk.Pixbuf (path)) {
+			width = pixbuf.Width;
+			height = pixbuf.Height;
+		}
+#else //yes, the pixbuf loader hack is smarter, but it leaks like an old women
+		Gdk.PixbufLoader loader = new Gdk.PixbufLoader ();
+		int orig_width = 0;
+		int orig_height = 0;
+		bool done = false;
+
+		loader.SizePrepared += delegate (object obj, SizePreparedArgs args) {
+			orig_width = args.Width;
+			orig_height = args.Height;
+			done = true;
+		};
+
+		using (Stream stream = File.OpenRead (path)) {
+			byte [] data = new byte [4096];
+			int count;
+
+			while (((count = stream.Read (data, 0, data.Length)) > 0) && loader.Write (data, (ulong)count)) {
+				if (done)
+					break;
+			}
+		}
+
+		width = orig_width;
+		height = orig_height;
+#endif
+	}
+
+	static public Pixbuf LoadAtMaxSize (string path, int max_width, int max_height)
+	{
+#if true
+		AspectLoader loader = new AspectLoader (max_width, max_height);
+		return loader.LoadFromFile (path);
+#else
+		int width, height;
+		JpegUtils.GetSize (path, out width, out height);
+		PixbufUtils.Fit (width, height, max_width, max_height, false, out width, out height);
+		Gdk.Pixbuf image = JpegUtils.LoadScaled (path, width, height);
+
+		return image;
+#endif
+	}
+
+	static public Pixbuf LoadFromStream (System.IO.Stream input)
+	{
+		Gdk.PixbufLoader loader = new Gdk.PixbufLoader ();
+		byte [] buffer = new byte [8192];
+		int n;
+
+		while ((n = input.Read (buffer, 0, 8192)) != 0)
+			loader.Write (buffer, (ulong) n);
+
+		loader.Close ();
+
+		return loader.Pixbuf;
+
+	}
+
+	public static void Save (Gdk.Pixbuf pixbuf, System.IO.Stream stream, string type, string [] options, string [] values)
+	{
+		byte [] data;
+
+		data = Save (pixbuf, type, options, values);
+		stream.Write (data, 0, data.Length);
+	}
+
+	static string [] NullTerminateArray (string [] options)
+	{
+		string [] terminated_options = options;
+
+		if (options != null && options [ options.Length - 1 ] != null) {
+			terminated_options = new string [options.Length + 1];
+			Array.Copy (options, terminated_options, options.Length);
+		}
+
+		return terminated_options;
+	}
+
+	[DllImport("libgdk_pixbuf-2.0-0.dll")]
+	static extern bool gdk_pixbuf_save_to_bufferv (IntPtr raw, out IntPtr data, out IntPtr length,
+						       string type,
+						       string [] keys, string [] values, out IntPtr error);
+
+
+	public static byte [] Save (Gdk.Pixbuf pixbuf, string type, string [] options, string [] values)
+	{
+		IntPtr error = IntPtr.Zero;
+		IntPtr data;
+		IntPtr length;
+
+		bool success = gdk_pixbuf_save_to_bufferv (pixbuf.Handle,
+							   out data,
+							   out length,
+							   type,
+							   NullTerminateArray (options),
+							   NullTerminateArray (values),
+							   out error);
+
+		if (error != IntPtr.Zero)
+			throw new GLib.GException (error);
+
+		if (!success)
+			throw new ApplicationException ("Unknown error while saving file");
+
+		byte [] content = new byte [(int)length];
+		Marshal.Copy (data, content, 0, (int)length);
+
+		GLib.Marshaller.Free (data);
+
+		return content;
+	}
+
+	static public Pixbuf LoadFromScreen (Gdk.Window win) {
+		Gdk.Screen screen = win.Screen;
+		Drawable d = screen.RootWindow;
+		int monitor = screen.GetMonitorAtWindow (win);
+		Gdk.Rectangle geom = screen.GetMonitorGeometry (monitor);
+
+		//
+		// We use the screen width and height because that reflects
+		// the current resolution, the RootWindow can actually be different.
+		//
+
+		Pixbuf buf = new Pixbuf (Colorspace.Rgb, false, 8, geom.Width, geom.Height);
+
+		return buf.GetFromDrawable (d,
+					    d.Colormap, geom.X, geom.Y, 0, 0,
+					    geom.Width, geom.Height);
+	}
+
+	static public Pixbuf LoadFromScreen () {
+		Screen screen = Display.Default.GetScreen (0);
+		Drawable d = screen.RootWindow;
+		int width = screen.Width;
+		int height = screen.Height;
+
+		//
+		// We use the screen width and height because that reflects
+		// the current resolution, the RootWindow can actually be different.
+		//
+
+		Pixbuf buf = new Pixbuf (Colorspace.Rgb, false, 8, width, height);
+
+		return buf.GetFromDrawable (d,
+					    d.Colormap, 0, 0, 0, 0,
+					    width, height);
+	}
+
+	static public Pixbuf LoadFromAssembly (string resource)
+	{
+		try {
+			return new Pixbuf (System.Reflection.Assembly.GetEntryAssembly (), resource);
+		} catch {
+			return null;
+		}
+	}
+
+	[DllImport ("libc")]
+	static extern int rename (string oldpath, string newpath);
+
+	public static void SaveAtomic (Gdk.Pixbuf src, string filename, string type, string [] keys, string [] values)
+	{
+			string tmpname = filename + ".tmp";
+			src.Savev (tmpname, type, NullTerminateArray (keys), NullTerminateArray (values));
+			if (rename (tmpname, filename) < 0)
+				throw new Exception ("Error renaming file");
+	}
+
+	public static Gdk.Pixbuf ScaleToAspect (Gdk.Pixbuf orig, int width, int height)
+	{
+		Gdk.Rectangle pos;
+		double scale = Fit (orig, width, height, false, out pos.Width, out pos.Height);
+		pos.X = (width - pos.Width) / 2;
+		pos.Y = (height - pos.Height) / 2;
+
+		Pixbuf scaled = new Pixbuf (Colorspace.Rgb, false, 8, width, height);
+		scaled.Fill (0x000000);
+
+		orig.Composite (scaled, pos.X, pos.Y,
+				pos.Width, pos.Height,
+				pos.X, pos.Y, scale, scale,
+				Gdk.InterpType.Bilinear,
+				255);
+
+		return scaled;
+	}
+
+	public static Pixbuf Flatten (Pixbuf pixbuf)
+	{
+		if (!pixbuf.HasAlpha)
+			return null;
+
+		Pixbuf flattened = new Pixbuf (Colorspace.Rgb, false, 8, pixbuf.Width, pixbuf.Height);
+		pixbuf.CompositeColor (flattened, 0, 0,
+				       pixbuf.Width, pixbuf.Height,
+				       0, 0, 1, 1,
+				       InterpType.Bilinear,
+				       255, 0, 0, 2000, 0xffffff, 0xffffff);
+
+		return flattened;
+	}
+
+
+
+	[DllImport ("libfspot")]
+	static extern IntPtr f_pixbuf_unsharp_mask (IntPtr src, double radius, double amount, double threshold);
+
+	public static Pixbuf UnsharpMask (Pixbuf src, double radius, double amount, double threshold)
+	{
+		IntPtr raw_ret = f_pixbuf_unsharp_mask (src.Handle, radius, amount, threshold);
+		Gdk.Pixbuf ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret, true);
+		return ret;
+	}
+
+	[DllImport ("libfspot")]
+	static extern IntPtr f_pixbuf_blur (IntPtr src, double radius);
+
+	public static Pixbuf Blur (Pixbuf src, double radius)
+	{
+		IntPtr raw_ret = f_pixbuf_blur (src.Handle, radius);
+		Gdk.Pixbuf ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret, true);
+		return ret;
+	}
+
+	public unsafe static Gdk.Pixbuf RemoveRedeye (Gdk.Pixbuf src, Gdk.Rectangle area)
+	{
+		return RemoveRedeye (src, area, -15);
+	}
+
+	public unsafe static Gdk.Pixbuf RemoveRedeye (Gdk.Pixbuf src, Gdk.Rectangle area, int threshold)
+	//threshold, factors and comparisons borrowed from the gimp plugin 'redeye.c' by Robert Merkel
+	{
+		Gdk.Pixbuf copy = src.Copy ();
+		Gdk.Pixbuf selection = new Gdk.Pixbuf (copy, area.X, area.Y, area.Width, area.Height);
+		byte *spix = (byte *)selection.Pixels;
+		int h = selection.Height;
+		int w = selection.Width;
+		int channels = src.NChannels;
+
+		double RED_FACTOR = 0.5133333;
+		double GREEN_FACTOR = 1;
+		double BLUE_FACTOR = 0.1933333;
+
+		for (int j = 0; j < h; j++) {
+			byte *s = spix;
+			for (int i = 0; i < w; i++) {
+				int adjusted_red = (int)(s[0] * RED_FACTOR);
+				int adjusted_green = (int)(s[1] * GREEN_FACTOR);
+				int adjusted_blue = (int)(s[2] * BLUE_FACTOR);
+
+				if (adjusted_red >= adjusted_green - threshold
+				    && adjusted_red >= adjusted_blue - threshold)
+					s[0] = (byte)(((double)(adjusted_green + adjusted_blue)) / (2.0 * RED_FACTOR));
+				s += channels;
+			}
+			spix += selection.Rowstride;
+		}
+
+		return copy;
+	}
+
+	public static unsafe Pixbuf ColorAdjust (Pixbuf src, double brightness, double contrast,
+					  double hue, double saturation, int src_color, int dest_color)
+	{
+		Pixbuf adjusted = new Pixbuf (Colorspace.Rgb, src.HasAlpha, 8, src.Width, src.Height);
+		ColorAdjust (src, adjusted, brightness, contrast, hue, saturation, src_color, dest_color);
+		return adjusted;
+	}
+
+	public static Cms.Format PixbufCmsFormat (Pixbuf buf)
+	{
+		return buf.HasAlpha ? Cms.Format.Rgba8Planar : Cms.Format.Rgb8;
+	}
+
+	public static unsafe void ColorAdjust (Pixbuf src, Pixbuf dest,
+					       double brightness, double contrast,
+					       double hue, double saturation,
+					       int src_color, int dest_color)
+	{
+		if (src.Width != dest.Width || src.Height != dest.Height)
+			throw new Exception ("Invalid Dimensions");
+
+		//Cms.Profile eos10d = new Cms.Profile ("/home/lewing/ICCProfiles/EOS-10D-True-Color-Non-Linear.icm");
+		Cms.Profile srgb = Cms.Profile.CreateStandardRgb ();
+
+		Cms.Profile bchsw = Cms.Profile.CreateAbstract (256,
+								0.0,
+								brightness, contrast,
+								hue, saturation, src_color,
+								dest_color);
+
+		Cms.Profile [] list = new Cms.Profile [] { srgb, bchsw, srgb };
+		Cms.Transform trans = new Cms.Transform (list,
+							 PixbufCmsFormat (src),
+							 PixbufCmsFormat (dest),
+							 Cms.Intent.Perceptual, 0x0100);
+
+		ColorAdjust (src, dest, trans);
+
+		trans.Dispose ();
+		srgb.Dispose ();
+		bchsw.Dispose ();
+	}
+
+
+	public static unsafe void ColorAdjust (Gdk.Pixbuf src, Gdk.Pixbuf dest, Cms.Transform trans)
+	{
+		int width = src.Width;
+		byte * srcpix  = (byte *) src.Pixels;
+		byte * destpix = (byte *) dest.Pixels;
+
+		for (int row = 0; row < src.Height; row++) {
+			trans.Apply ((IntPtr) (srcpix + row * src.Rowstride),
+				     (IntPtr) (destpix + row * dest.Rowstride),
+				     (uint)width);
+		}
+
+	}
+
+	public static unsafe bool IsGray (Gdk.Pixbuf pixbuf, int max_difference)
+	{
+		int chan = pixbuf.NChannels;
+
+		byte *pix = (byte *)pixbuf.Pixels;
+		int h = pixbuf.Height;
+		int w = pixbuf.Width;
+		int stride = pixbuf.Rowstride;
+
+		for (int j = 0; j < h; j++) {
+			byte *p = pix;
+			for (int i = 0; i < w; i++) {
+				if (Math.Abs (p[0] - p[1]) > max_difference || Math.Abs (p[0] - p [2]) > max_difference) {
+					goto Found;
+				}
+				p += chan;
+			}
+			pix += stride;
+		}
+
+		return true;
+
+	Found:
+		return false;
+	}
+
+	public static unsafe void ReplaceColor (Gdk.Pixbuf src, Gdk.Pixbuf dest)
+	{
+		if (src.HasAlpha || !dest.HasAlpha || (src.Width != dest.Width) || (src.Height != dest.Height))
+			throw new ApplicationException ("invalid pixbufs");
+
+		byte *dpix = (byte *)dest.Pixels;
+		byte *spix = (byte *)src.Pixels;
+		int h = src.Height;
+		int w = src.Width;
+		for (int j = 0; j < h; j++) {
+			byte *d = dpix;
+			byte *s = spix;
+			for (int i = 0; i < w; i++) {
+				d[0] = s[0];
+				d[1] = s[1];
+				d[2] = s[2];
+				d += 4;
+				s += 3;
+			}
+			dpix += dest.Rowstride;
+			spix += src.Rowstride;
+		}
+	}
+
+	public static Gdk.Pixbuf GetThumbnail (Exif.ExifData data)
+	{
+		byte [] thumb_data = data.Data;
+		if (thumb_data.Length > 0) {
+			PixbufOrientation orientation = GetOrientation (data);
+
+			using (MemoryStream mem = new MemoryStream (thumb_data)) {
+				Gdk.Pixbuf thumb = new Gdk.Pixbuf (mem);
+
+				Gdk.Pixbuf rotated = FSpot.Utils.PixbufUtils.TransformOrientation (thumb, orientation);
+
+				if (rotated != thumb)
+					thumb.Dispose ();
+				return rotated;
+			}
+		}
+		return null;
+	}
+
+	public static PixbufOrientation GetOrientation (Exif.ExifData data)
+	{
+		PixbufOrientation orientation = PixbufOrientation.TopLeft;
+
+		Exif.ExifEntry e = data.GetContents (Exif.Ifd.Zero).Lookup (Exif.Tag.Orientation);
+
+		if (e != null) {
+			ushort [] value = e.GetDataUShort ();
+			orientation = (PixbufOrientation) value [0];
+		}
+
+		return orientation;
+	}
+
+	public static PixbufOrientation GetOrientation (System.Uri uri)
+	{
+		using (FSpot.ImageFile img = FSpot.ImageFile.Create (uri)) {
+			return img.Orientation;
+		}
+	}
+
+	[Obsolete ("Use GetOrientation (System.Uri) instead")]
+	public static PixbufOrientation GetOrientation (string path)
+	{
+		using (FSpot.ImageFile img = FSpot.ImageFile.Create (path)) {
+			return img.Orientation;
+		}
+	}
+
+	[DllImport("libgnomeui-2-0.dll")]
+	static extern IntPtr gnome_thumbnail_scale_down_pixbuf(IntPtr pixbuf, int dest_width, int dest_height);
+
+	public static Gdk.Pixbuf ScaleDown (Gdk.Pixbuf src, int width, int height)
+	{
+		IntPtr raw_ret = gnome_thumbnail_scale_down_pixbuf(src.Handle, width, height);
+		Gdk.Pixbuf ret;
+		if (raw_ret == IntPtr.Zero)
+			ret = null;
+		else
+			ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret, true);
+		return ret;
+	}
+
+	// Bindings from libf.
+
+	[DllImport ("libfspot")]
+	static extern IntPtr f_pixbuf_copy_apply_brightness_and_contrast (IntPtr src, float brightness, float contrast);
+
+	public static Pixbuf ApplyBrightnessAndContrast (Pixbuf src, float brightness, float contrast)
+	{
+		return new Pixbuf (f_pixbuf_copy_apply_brightness_and_contrast (src.Handle, brightness, contrast));
+	}
+
+	[DllImport ("libfspot")]
+	static extern bool f_pixbuf_save_jpeg_atomic (IntPtr pixbuf, string filename, int quality, out IntPtr error);
+
+	public static void SaveAsJpegAtomically (Pixbuf pixbuf, string filename, int quality)
+	{
+		IntPtr error = IntPtr.Zero;
+
+		if (! f_pixbuf_save_jpeg_atomic (pixbuf.Handle, filename, quality, out error)) {
+			throw new GLib.GException (error);
+		}
+	}
+}
diff --git a/src/PixelBuffer.cs b/src/Imaging/PixelBuffer.cs
similarity index 98%
rename from src/PixelBuffer.cs
rename to src/Imaging/PixelBuffer.cs
index 544aa94..c1b1d09 100644
--- a/src/PixelBuffer.cs
+++ b/src/Imaging/PixelBuffer.cs
@@ -28,11 +28,11 @@ namespace FSpot.Imaging {
 			width = pixbuf.Width;
 			height = pixbuf.Height;
 			this.nchannels = pixbuf.HasAlpha ? 4 : 3;
-			
+
 			depth = PixelBufferDepth.UInt16;
 
 			data = new ushort [width * height * nchannels];
-			
+
 			unsafe {
 				byte * src_pixels = (byte *) pixbuf.Pixels;
 				int src_stride = pixbuf.Rowstride;
@@ -53,10 +53,10 @@ namespace FSpot.Imaging {
 		public unsafe void Fill8 (int i, int j, byte * src_data, int offset, int count)
 		{
 			ushort * rowpix;
-			
+
 			fixed (ushort * pixels = &data [0]) {
 				rowpix = pixels + i * rowstride + j;
-				
+
 				for (int col = 0; col < count; col++) {
 					int val = src_data [col];
 					rowpix [col] = (ushort) (val << 8 & val);
@@ -80,9 +80,9 @@ namespace FSpot.Imaging {
 			else
 				Fill16Swap (i, j, src_data, offset, count);
 		}
-		
+
 		public void Fill16 (int i, int j, byte [] src_data, int offset, int count)
-		{ 
+		{
 			unsafe {
 				ushort * rowpix;
 
@@ -115,24 +115,24 @@ namespace FSpot.Imaging {
 				}
 			}
 		}
-		
+
 		public override Gdk.Pixbuf ToPixbuf (Cms.Profile destination_profile)
 		{
 #if true //USE_LCMS
 			profile = Cms.Profile.CreateStandardRgb ();
 			Cms.Profile [] list = new Cms.Profile [] { profile, destination_profile };
-			Gdk.Pixbuf pixbuf = new Gdk.Pixbuf (Gdk.Colorspace.Rgb, false, 8, 
+			Gdk.Pixbuf pixbuf = new Gdk.Pixbuf (Gdk.Colorspace.Rgb, false, 8,
 							    width, height);
-			
+
 			Cms.Transform t = new Cms.Transform (list,
 							     Cms.Format.Rgb16,
 							     PixbufUtils.PixbufCmsFormat (pixbuf),
 							     Cms.Intent.Perceptual, 0x0);
-			
+
 			unsafe {
 				fixed (ushort * srcpix  = &data[0]) {
 					byte * destpix = (byte *) pixbuf.Pixels;
-					
+
 					for (int row = 0; row < height; row++)
 						t.Apply ((IntPtr) (srcpix + row * rowstride),
 							 (IntPtr) (destpix + row * pixbuf.Rowstride),
@@ -142,18 +142,18 @@ namespace FSpot.Imaging {
 
 			return pixbuf;
 #else
-			Gdk.Pixbuf pixbuf = new Gdk.Pixbuf (Gdk.Colorspace.Rgb, false, 8, 
+			Gdk.Pixbuf pixbuf = new Gdk.Pixbuf (Gdk.Colorspace.Rgb, false, 8,
 							    width, height);
 
 			unsafe {
 				fixed (ushort * src  = &data[0]) {
 					ushort * srcpix = src;
 					byte * destpix = (byte *) pixbuf.Pixels;
-					
+
 					for (int row = 0; row < height; row++) {
 						for (int col = 0; col < width * nchannels; col++)
 							destpix [col] = (byte) (srcpix [col] >> 8);
-						
+
 						srcpix += rowstride;
 						destpix += pixbuf.Rowstride;
 					}
@@ -168,8 +168,8 @@ namespace FSpot.Imaging {
 #if false
 	public class UInt8Buffer : PixelBuffer {
 		protected ushort [] data;
-		
-		
+
+
 	}
 
 	public class PixbufBuffer : PixelBuffer {
diff --git a/src/Loaders/GdkImageLoader.cs b/src/Loaders/GdkImageLoader.cs
index 58fcd30..4ace520 100644
--- a/src/Loaders/GdkImageLoader.cs
+++ b/src/Loaders/GdkImageLoader.cs
@@ -28,13 +28,13 @@ namespace FSpot.Loaders {
 
 		Pixbuf thumbnail;
 		public Pixbuf Thumbnail {
-			get { return PixbufUtils.ShallowCopy (thumbnail); }
+			get { return thumbnail.ShallowCopy (); }
 			private set { thumbnail = value; }
 		}
 		public PixbufOrientation ThumbnailOrientation { get; private set; }
 
 		public Pixbuf Large {
-			get { return PixbufUtils.ShallowCopy (Pixbuf); }
+			get { return Pixbuf.ShallowCopy (); }
 		}
 		public PixbufOrientation LargeOrientation { get; private set; }
 
@@ -204,8 +204,8 @@ namespace FSpot.Loaders {
 			if (is_disposed)
 				return;
 
+			image_stream = new GLib.GioStream (GLib.FileFactory.NewForUri (uri).Read (null));
 			using (ImageFile image_file = ImageFile.Create (uri)) {
-				image_stream = image_file.PixbufStream ();
 				LargeOrientation = image_file.Orientation;
 			}
 
diff --git a/src/Loaders/LibrawImageLoader.cs b/src/Loaders/LibrawImageLoader.cs
index 64517ba..2f8bbdb 100644
--- a/src/Loaders/LibrawImageLoader.cs
+++ b/src/Loaders/LibrawImageLoader.cs
@@ -30,20 +30,20 @@ namespace FSpot.Loaders {
 
 		Pixbuf thumbnail;
 		public Pixbuf Thumbnail {
-			get { return PixbufUtils.ShallowCopy (thumbnail); }
+			get { return thumbnail.ShallowCopy (); }
 			private set { thumbnail = value; }
 		}
 		public PixbufOrientation ThumbnailOrientation { get; private set; }
 
 		Pixbuf large;
 		public Pixbuf Large {
-			get { return PixbufUtils.ShallowCopy (large); }
+			get { return large.ShallowCopy (); }
 		}
 		public PixbufOrientation LargeOrientation { get; private set; }
 
 		Pixbuf full;
 		public Pixbuf Full {
-			get { return PixbufUtils.ShallowCopy (full); }
+			get { return full.ShallowCopy (); }
 		}
 		public PixbufOrientation FullOrientation { get; private set; }
 
diff --git a/src/MainWindow.cs b/src/MainWindow.cs
index 44574c3..af253a1 100644
--- a/src/MainWindow.cs
+++ b/src/MainWindow.cs
@@ -943,7 +943,7 @@ namespace FSpot
 				Pixbuf icon = null;
 				try {
 					Pixbuf tmp = FSpot.PhotoLoader.LoadAtMaxSize (query [nums[0]], 128, 128);
-					icon = PixbufUtils.TagIconFromPixbuf (tmp);
+					icon = FSpotPixbufUtils.TagIconFromPixbuf (tmp);
 					tmp.Dispose ();
 				} catch {
 					icon = null;
diff --git a/src/Makefile.am b/src/Makefile.am
index 875edcd..7f98254 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -40,6 +40,46 @@ CORE_CSDISTFILES =				\
 	$(srcdir)/Core/PhotosChanges.cs		\
 	$(srcdir)/Core/Roll.cs
 
+IMAGING_CSDISTFILES =						\
+	$(srcdir)/Imaging/PixbufUtils.cs		\
+	$(srcdir)/Imaging/DCRawFile.cs			\
+	$(srcdir)/Imaging/BitConverter.cs		\
+	$(srcdir)/Imaging/Bim.cs				\
+	$(srcdir)/Imaging/Ciff.cs				\
+	$(srcdir)/Imaging/Exif.cs				\
+	$(srcdir)/Imaging/ImageFile.cs			\
+	$(srcdir)/Imaging/IptcFile.cs			\
+	$(srcdir)/Imaging/InternalProcess.cs	\
+	$(srcdir)/Imaging/IOChannel.cs			\
+	$(srcdir)/Imaging/IRawFile.cs			\
+	$(srcdir)/Imaging/JpegFile.cs			\
+	$(srcdir)/Imaging/JpegHeader.cs			\
+	$(srcdir)/Imaging/JpegUtils.cs			\
+	$(srcdir)/Imaging/MetadataStore.cs		\
+	$(srcdir)/Imaging/MrwFile.cs			\
+	$(srcdir)/Imaging/OrderedWriter.cs		\
+	$(srcdir)/Imaging/PixelBuffer.cs		\
+	$(srcdir)/Imaging/PngFile.cs			\
+	$(srcdir)/Imaging/PnmFile.cs			\
+	$(srcdir)/Imaging/RafFile.cs			\
+	$(srcdir)/Imaging/SvgFile.cs			\
+	$(srcdir)/Imaging/X3fFile.cs			\
+	$(srcdir)/Imaging/XmpFile.cs			\
+	$(srcdir)/Imaging/Tiff.cs
+
+LOADERS_CSDISTFILES =								\
+	$(srcdir)/Loaders/AreaPreparedEventArgs.cs		\
+	$(srcdir)/Loaders/AreaUpdatedEventArgs.cs		\
+	$(srcdir)/Loaders/GdkImageLoader.cs				\
+	$(srcdir)/Loaders/IImageLoader.cs				\
+	$(srcdir)/Loaders/IImageLoaderExtensions.cs		\
+	$(srcdir)/Loaders/ImageLoader.cs				\
+	$(srcdir)/Loaders/ImageLoaderItem.cs			\
+	$(srcdir)/Loaders/ImageLoaderItemExtensions.cs	\
+	$(srcdir)/Loaders/ItemCompletedEventArgs.cs		\
+	$(srcdir)/Loaders/LibrawImageLoader.cs			\
+	$(srcdir)/Loaders/ProgressHintEventArgs.cs
+
 QUERY_CSDISTFILES =				\
 	$(srcdir)/Query/DateRange.cs		\
 	$(srcdir)/Query/FolderSet.cs		\
@@ -61,6 +101,7 @@ UTILS_CSDISTFILES =				\
 	$(srcdir)/Utils/GdkUtils.cs		\
 	$(srcdir)/Utils/GtkUtil.cs		\
 	$(srcdir)/Utils/Log.cs			\
+	$(srcdir)/Utils/PixbufExtensions.cs		\
 	$(srcdir)/Utils/PixbufOrientation.cs	\
 	$(srcdir)/Utils/PixbufUtils.cs		\
 	$(srcdir)/Utils/RecursiveFileEnumerator.cs		\
@@ -127,7 +168,6 @@ NULL_PLATFORM_CSDISTFILES =				\
 
 F_SPOT_CSDISTFILES =				\
 	$(srcdir)/BlockProcessor.cs		\
-	$(srcdir)/BitConverter.cs		\
 	$(srcdir)/PhotoList.cs 		\
 	$(srcdir)/ColorAdjustment/Adjustment.cs		\
 	$(srcdir)/ColorAdjustment/AutoStretch.cs		\
@@ -186,43 +226,11 @@ F_SPOT_CSDISTFILES =				\
 	$(srcdir)/GroupSelector.cs		\
 	$(srcdir)/Accelerometer.cs		\
 	$(srcdir)/Histogram.cs			\
-	$(srcdir)/Loaders/AreaPreparedEventArgs.cs		\
-	$(srcdir)/Loaders/AreaUpdatedEventArgs.cs		\
-	$(srcdir)/Loaders/GdkImageLoader.cs		\
-	$(srcdir)/Loaders/IImageLoader.cs		\
-	$(srcdir)/Loaders/IImageLoaderExtensions.cs		\
-	$(srcdir)/Loaders/ImageLoader.cs		\
-	$(srcdir)/Loaders/ImageLoaderItem.cs		\
-	$(srcdir)/Loaders/ImageLoaderItemExtensions.cs		\
-	$(srcdir)/Loaders/ItemCompletedEventArgs.cs		\
-	$(srcdir)/Loaders/LibrawImageLoader.cs		\
-	$(srcdir)/Loaders/ProgressHintEventArgs.cs		\
 	$(srcdir)/ImageLoaderThread.cs		\
 	$(srcdir)/ImportBackend.cs		\
 	$(srcdir)/ImportCommand.cs		\
 	$(srcdir)/InfoOverlay.cs		\
-	$(srcdir)/InternalProcess.cs		\
-	$(srcdir)/IOChannel.cs			\
 	$(srcdir)/ItemAction.cs			\
-	$(srcdir)/Imaging/DCRawFile.cs		\
-	$(srcdir)/Imaging/Bim.cs		\
-	$(srcdir)/Imaging/Ciff.cs		\
-	$(srcdir)/Imaging/Exif.cs		\
-	$(srcdir)/Imaging/ImageFile.cs		\
-	$(srcdir)/Imaging/IptcFile.cs		\
-	$(srcdir)/Imaging/IRawFile.cs		\
-	$(srcdir)/Imaging/JpegFile.cs		\
-	$(srcdir)/Imaging/JpegHeader.cs		\
-	$(srcdir)/Imaging/JpegUtils.cs		\
-	$(srcdir)/Imaging/MrwFile.cs		\
-	$(srcdir)/Imaging/OrderedWriter.cs	\
-	$(srcdir)/Imaging/PngFile.cs		\
-	$(srcdir)/Imaging/PnmFile.cs		\
-	$(srcdir)/Imaging/RafFile.cs		\
-	$(srcdir)/Imaging/SvgFile.cs		\
-	$(srcdir)/Imaging/X3fFile.cs		\
-	$(srcdir)/Imaging/XmpFile.cs		\
-	$(srcdir)/Imaging/Tiff.cs		\
 	$(srcdir)/JobStore.cs			\
 	$(srcdir)/Jobs/SyncMetadataJob.cs	\
 	$(srcdir)/Jobs/CalculateHashJob.cs	\
@@ -230,7 +238,6 @@ F_SPOT_CSDISTFILES =				\
 	$(srcdir)/MainWindow.cs			\
 	$(srcdir)/MemorySurface.cs		\
 	$(srcdir)/MetaStore.cs			\
-	$(srcdir)/MetadataStore.cs		\
 	$(srcdir)/PhotoEventArgs.cs		\
 	$(srcdir)/PhotoImageView.cs		\
 	$(srcdir)/PhotoLoader.cs		\
@@ -241,9 +248,8 @@ F_SPOT_CSDISTFILES =				\
 	$(srcdir)/PhotoVersionCommands.cs	\
 	$(srcdir)/PhotoVersionMenu.cs		\
 	$(srcdir)/PhotoView.cs			\
-	$(srcdir)/PixbufUtils.cs		\
 	$(srcdir)/PixbufCache.cs		\
-	$(srcdir)/PixelBuffer.cs		\
+	$(srcdir)/PixbufUtils.cs		\
 	$(srcdir)/Preferences.cs 		\
 	$(srcdir)/PrintOperation.cs		\
 	$(srcdir)/ProgressItem.cs		\
@@ -343,6 +349,28 @@ CORE_ASSEMBLIES =				\
 	-r:Mono.Posix				\
 	-r:FSpot.Utils.dll
 
+IMAGING_ASSEMBLIES =			\
+	$(LINK_SEMWEB)				\
+	$(LINK_GIOSHARP)			\
+	$(LINK_GTKSHARPBEANS)		\
+	-pkg:gnome-sharp-2.0		\
+	-pkg:gtk-sharp-2.0			\
+	-r:ICSharpCode.SharpZipLib	\
+	-r:Cms.dll					\
+	-r:Mono.Posix				\
+	-r:FSpot.Core.dll			\
+	-r:FSpot.Utils.dll
+
+LOADERS_ASSEMBLIES =			\
+	$(LINK_GIOSHARP)			\
+	$(LINK_GTKSHARPBEANS)		\
+	$(LINK_FSPOTRAWSHARP)		\
+	-pkg:gtk-sharp-2.0			\
+	-r:Mono.Posix				\
+	-r:FSpot.Imaging.dll		\
+	-r:FSpot.Platform.dll		\
+	-r:FSpot.Utils.dll
+
 QUERY_ASSEMBLIES =				\
 	$(LINK_GIOSHARP)			\
 	-r:FSpot.Core.dll			\
@@ -396,18 +424,19 @@ F_SPOT_ASSEMBLIES = 				\
 	$(LINK_KEYRING)				\
 	$(LINK_SMUGMUG)				\
 	$(LINK_SEMWEB)				\
+	$(LINK_FSPOTRAWSHARP)		\
 	$(LINK_GTKSHARPBEANS)			\
 	$(LINK_GIOSHARP)			\
 	$(LINK_UNIQUESHARP)			\
-	$(LINK_FSPOTRAWSHARP)		\
 	-r:System.Data				\
 	-r:System.Web				\
 	-r:Mono.Data.SqliteClient		\
 	-r:Mono.Posix				\
 	-r:Mono.Security			\
 	-r:Mono.Cairo				\
-	-r:ICSharpCode.SharpZipLib		\
 	-r:FSpot.Core.dll			\
+	-r:FSpot.Imaging.dll			\
+	-r:FSpot.Loaders.dll			\
 	-r:FSpot.Query.dll			\
 	-r:FSpot.Utils.dll			\
 	-r:FSpot.JobScheduler.dll		\
@@ -456,6 +485,10 @@ fspotlib_DATA = f-spot.exe.config	\
 		FSpot.Utils.dll		\
 		FSpot.Utils.dll.mdb	\
 		FSpot.Utils.dll.config	\
+		FSpot.Imaging.dll		\
+		FSpot.Imaging.dll.mdb	\
+		FSpot.Loaders.dll		\
+		FSpot.Loaders.dll.mdb	\
 		FSpot.Query.dll		\
 		FSpot.Query.dll.mdb	\
 		FSpot.Core.dll		\
@@ -477,6 +510,10 @@ CMS_CSFILES = $(CMS_CSDISTFILES)
 CORE_CSFILES = $(CORE_CSDISTFILES)	\
 	Core/Defines.cs	
 
+IMAGING_CSFILES = $(IMAGING_CSDISTFILES)
+
+LOADERS_CSFILES = $(LOADERS_CSDISTFILES)
+
 QUERY_CSFILES = $(QUERY_CSDISTFILES)
 
 UTILS_CSFILES = $(UTILS_CSDISTFILES)
@@ -504,6 +541,16 @@ FSpot.Core.dll.mdb: FSpot.Core.dll
 FSpot.Core.dll: $(CORE_CSFILES) FSpot.Utils.dll Cms.dll
 	$(CSC_LIB) -warnaserror -out:$@ $(EXTRAFLAGS) $(CORE_CSFILES) $(CORE_ASSEMBLIES)
 
+FSpot.Imaging.dll.mdb: FSpot.Imaging.dll
+
+FSpot.Imaging.dll: $(IMAGING_CSFILES) FSpot.Utils.dll FSpot.Core.dll
+	$(CSC_LIB) -out:$@ $(EXTRAFLAGS) $(UNSAFE) $(IMAGING_CSFILES) $(IMAGING_ASSEMBLIES)
+
+FSpot.Loaders.dll.mdb: FSpot.Loaders.dll
+
+FSpot.Loaders.dll: $(LOADERS_CSFILES) FSpot.Platform.dll FSpot.Utils.dll FSpot.Imaging.dll
+	$(CSC_LIB) -out:$@ $(EXTRAFLAGS) $(LOADERS_CSFILES) $(LOADERS_ASSEMBLIES)
+
 FSpot.Query.dll.mdb: FSpot.Query.dll
 
 FSpot.Query.dll: $(QUERY_CSFILES) FSpot.Utils.dll FSpot.Core.dll
@@ -539,7 +586,7 @@ FSpot.Platform.dll: $(PLATFORM_CSFILES) FSpot.Utils.dll
 
 f-spot.exe.mdb: f-spot.exe
 
-f-spot.exe: $(F_SPOT_CSFILES) FSpot.Utils.dll FSpot.Core.dll FSpot.Query.dll FSpot.JobScheduler.dll FSpot.Bling.dll FSpot.Widgets.dll Cms.dll FSpot.Platform.dll $(F_SPOT_RESOURCES)
+f-spot.exe: $(F_SPOT_CSFILES) FSpot.Utils.dll FSpot.Core.dll FSpot.Imaging.dll FSpot.Loaders.dll FSpot.Query.dll FSpot.JobScheduler.dll FSpot.Bling.dll FSpot.Widgets.dll Cms.dll FSpot.Platform.dll $(F_SPOT_RESOURCES)
 	$(CSC) -target:winexe -out:$@ $(EXTRAFLAGS) $(UNSAFE) $(NOWARN) $(NUNIT_DEFINES) $(F_SPOT_CSFILES) $(F_SPOT_ASSEMBLIES) $(RESOURCES)
 
 all: f-spot.exe
@@ -548,6 +595,8 @@ EXTRA_DIST =					\
 	$(UTILS_CSDISTFILES)			\
 	$(CMS_CSDISTFILES)			\
 	$(CORE_CSDISTFILES)			\
+	$(IMAGING_CSDISTFILES)			\
+	$(LOADERS_CSDISTFILES)			\
 	$(QUERY_CSDISTFILES)			\
 	$(JOBSCHEDULER_CSDISTFILES)		\
 	$(BLING_CSDISTFILES)			\
@@ -571,6 +620,10 @@ CLEANFILES =					\
 	Cms.dll					\
 	FSpot.Utils.dll.mdb			\
 	FSpot.Utils.dll				\
+	FSpot.Imaging.dll				\
+	FSpot.Imaging.dll.mdb			\
+	FSpot.Loaders.dll				\
+	FSpot.Loaders.dll.mdb			\
 	FSpot.Query.dll				\
 	FSpot.Query.dll.mdb			\
 	FSpot.Core.dll.mdb			\
diff --git a/src/PhotoImageView.cs b/src/PhotoImageView.cs
index eaa9e3e..5d75ec8 100644
--- a/src/PhotoImageView.cs
+++ b/src/PhotoImageView.cs
@@ -346,9 +346,10 @@ namespace FSpot.Widgets {
 			// like offer the user a chance to locate the moved file and
 			// update the db entry, but for now just set the error pixbuf	
 			Pixbuf old = Pixbuf;
-			Pixbuf = new Pixbuf (PixbufUtils.ErrorPixbuf, 0, 0, 
-					     PixbufUtils.ErrorPixbuf.Width, 
-					     PixbufUtils.ErrorPixbuf.Height);
+			Pixbuf err = new Pixbuf (FSpotPixbufUtils.ErrorPixbuf, 0, 0,
+									 FSpotPixbufUtils.ErrorPixbuf.Width,
+									 FSpotPixbufUtils.ErrorPixbuf.Height);
+			ChangeImage (err, PixbufOrientation.TopLeft, true, false);
 			if (old != null)
 				old.Dispose ();
 
diff --git a/src/PixbufUtils.cs b/src/PixbufUtils.cs
index 87baa26..7a05028 100644
--- a/src/PixbufUtils.cs
+++ b/src/PixbufUtils.cs
@@ -11,13 +11,13 @@
 
 using Gdk;
 using System.Collections;
-using System.Runtime.InteropServices;
 using System;
 using System.IO;
+using System.Runtime.InteropServices;
 using FSpot;
 using FSpot.Utils;
 
-public class PixbufUtils {
+public class FSpotPixbufUtils {
 	static Pixbuf error_pixbuf = null;
 	public static Pixbuf ErrorPixbuf {
 		get {
@@ -27,270 +27,6 @@ public class PixbufUtils {
 		}
 	}
 	public static Pixbuf LoadingPixbuf = PixbufUtils.LoadFromAssembly ("f-spot-loading.png");
-
-	public static int GetSize (Pixbuf pixbuf)
-	{
-		return Math.Max (pixbuf.Width, pixbuf.Height);
-	}
-
-	public static double Fit (Pixbuf pixbuf,
-				  int dest_width, int dest_height,
-				  bool upscale_smaller,
-				  out int fit_width, out int fit_height)
-	{
-		return Fit (pixbuf.Width, pixbuf.Height, 
-			    dest_width, dest_height, 
-			    upscale_smaller, 
-			    out fit_width, out fit_height);
-	}
-
-	public static double Fit (int orig_width, int orig_height,
-				  int dest_width, int dest_height,
-				  bool upscale_smaller,
-				  out int fit_width, out int fit_height)
-	{
-		if (orig_width == 0 || orig_height == 0) {
-			fit_width = 0;
-			fit_height = 0;
-			return 0.0;
-		}
-
-		double scale = Math.Min (dest_width / (double)orig_width,
-					 dest_height / (double)orig_height);
-		
-		if (scale > 1.0 && !upscale_smaller)
-			scale = 1.0;
-
-		fit_width = (int) Math.Round (scale * orig_width);
-		fit_height = (int) Math.Round (scale * orig_height);
-		
-		return scale;
-	}
-
-
-	// FIXME: These should be in GTK#.  When my patch is committed, these LoadFrom* methods will
-	// go away.
-
-	public class AspectLoader {
-		Gdk.PixbufLoader loader = new Gdk.PixbufLoader ();
-		int max_width;
-		int max_height;
-		PixbufOrientation orientation;
-		int orig_width;
-
-		public AspectLoader (int max_width, int max_height) 
-		{
-			this.max_height = max_height;
-			this.max_width = max_width;
-			loader.SizePrepared += HandleSizePrepared;
-		}
-
-		private void HandleSizePrepared (object obj, SizePreparedArgs args)
-		{
-			switch (orientation) {
-			case PixbufOrientation.LeftTop:
-			case PixbufOrientation.LeftBottom:
-			case PixbufOrientation.RightTop:
-			case PixbufOrientation.RightBottom:	
-				int tmp = max_width;
-				max_width = max_height;
-				max_height = tmp;
-				break;
-			default:
-				break;
-			}
-
-			int scale_width = 0;
-			int scale_height = 0;
-
-			double scale = Fit (args.Width, args.Height, max_width, max_height, true, out scale_width, out scale_height);
-
-			if (scale < 1.0)
-				loader.SetSize (scale_width, scale_height);
-		}
-
-		public Pixbuf Load (System.IO.Stream stream, PixbufOrientation orientation)
-		{
-			int count;
-			byte [] data = new byte [8192];
-			while (((count = stream.Read (data, 0, data.Length)) > 0) && loader.Write (data, (ulong)count))
-				;
-			
-			loader.Close ();
-			Pixbuf orig = loader.Pixbuf;
-			Gdk.Pixbuf rotated = FSpot.Utils.PixbufUtils.TransformOrientation (orig, orientation);
-			
-			if (orig != rotated) {
-				FSpot.Utils.PixbufUtils.CopyThumbnailOptions (orig, rotated);
-				orig.Dispose ();
-			}
-			loader.Dispose ();
-			return rotated;
-		}
-		
-		public Pixbuf LoadFromFile (string path)
-		{
-			try {
-				orientation = GetOrientation (path);
-				using (FileStream fs = File.OpenRead (path)) {
-					return Load (fs, orientation);
-				}
-			} catch (Exception) {
-				System.Console.WriteLine ("Error loading photo {0}", path);
-				return null;
-			} 
-		}
-	}
-
-	public static Pixbuf ShallowCopy (Pixbuf pixbuf)
-	{
-		if (pixbuf == null)
-			return null;
-		Pixbuf result = new Pixbuf (pixbuf, 0, 0, pixbuf.Width, pixbuf.Height);
-		FSpot.Utils.PixbufUtils.CopyThumbnailOptions (pixbuf, result);
-		return result;
-	}
-
-	public static Pixbuf ScaleToMaxSize (Pixbuf pixbuf, int width, int height)
-	{
-		return ScaleToMaxSize (pixbuf, width, height, true);
-	}	
-
-	public static Pixbuf ScaleToMaxSize (Pixbuf pixbuf, int width, int height, bool upscale)
-	{
-		int scale_width = 0;
-		int scale_height = 0;
-		double scale = Fit (pixbuf, width, height, upscale, out scale_width, out scale_height);
-
-		Gdk.Pixbuf result;
-		if (upscale || (scale < 1.0))
-			result = pixbuf.ScaleSimple (scale_width, scale_height, (scale_width > 20) ? Gdk.InterpType.Bilinear : Gdk.InterpType.Nearest);
-		else
-			result = pixbuf.Copy ();
-
-		FSpot.Utils.PixbufUtils.CopyThumbnailOptions (pixbuf, result);
-
-		return result;
-	}
-		
-	static public void GetSize (string path, out int width, out int height)
-	{
-#if true
-		using (Gdk.Pixbuf pixbuf = new Gdk.Pixbuf (path)) {
-			width = pixbuf.Width;
-			height = pixbuf.Height;
-		}
-#else //yes, the pixbuf loader hack is smarter, but it leaks like an old women
-		Gdk.PixbufLoader loader = new Gdk.PixbufLoader ();
-		int orig_width = 0;
-		int orig_height = 0;
-		bool done = false;
-
-		loader.SizePrepared += delegate (object obj, SizePreparedArgs args) {
-			orig_width = args.Width;
-			orig_height = args.Height;
-			done = true;
-		};
-		
-		using (Stream stream = File.OpenRead (path)) {
-			byte [] data = new byte [4096];
-			int count;
-
-			while (((count = stream.Read (data, 0, data.Length)) > 0) && loader.Write (data, (ulong)count)) {
-				if (done)
-					break;
-			}
-		}
-		
-		width = orig_width;
-		height = orig_height;
-#endif
-	}
-
-	static public Pixbuf LoadAtMaxSize (string path, int max_width, int max_height)
-	{
-#if true
-		PixbufUtils.AspectLoader loader = new AspectLoader (max_width, max_height);
-		return loader.LoadFromFile (path);
-#else
-		int width, height;
-		JpegUtils.GetSize (path, out width, out height);
-		PixbufUtils.Fit (width, height, max_width, max_height, false, out width, out height);
-		Gdk.Pixbuf image = JpegUtils.LoadScaled (path, width, height);
-		
-		return image;
-#endif
-	}
-
-	static public Pixbuf LoadFromStream (System.IO.Stream input)
-	{
-		Gdk.PixbufLoader loader = new Gdk.PixbufLoader ();
-		byte [] buffer = new byte [8192];
-		int n;
-
-		while ((n = input.Read (buffer, 0, 8192)) != 0)
-			loader.Write (buffer, (ulong) n);
-		
-		loader.Close ();
-		
-		return loader.Pixbuf;
-		
-	}
-	
-
-	public static void Save (Gdk.Pixbuf pixbuf, System.IO.Stream stream, string type, string [] options, string [] values)
-	{
-		byte [] data;
-
-		data = PixbufUtils.Save (pixbuf, type, options, values);
-		stream.Write (data, 0, data.Length);
-	}
-
-	static string [] NullTerminateArray (string [] options)
-	{
-		string [] terminated_options = options;
-
-		if (options != null && options [ options.Length - 1 ] != null) {
-			terminated_options = new string [options.Length + 1];
-			Array.Copy (options, terminated_options, options.Length);
-		}
-		
-		return terminated_options;
-	}
-
-	[DllImport("libgdk_pixbuf-2.0-0.dll")]
-	static extern bool gdk_pixbuf_save_to_bufferv (IntPtr raw, out IntPtr data, out IntPtr length, 
-						       string type, 
-						       string [] keys, string [] values, out IntPtr error);
-
-					
-	public static byte [] Save (Gdk.Pixbuf pixbuf, string type, string [] options, string [] values)
-	{
-		IntPtr error = IntPtr.Zero;
-		IntPtr data;
-		IntPtr length;
-
-		bool success = gdk_pixbuf_save_to_bufferv (pixbuf.Handle, 
-							   out data, 
-							   out length, 
-							   type,
-							   NullTerminateArray (options),
-							   NullTerminateArray (values),
-							   out error);
-		
-		if (error != IntPtr.Zero) 
-			throw new GLib.GException (error);
-
-		if (!success)
-			throw new ApplicationException ("Unknown error while saving file");
-
-		byte [] content = new byte [(int)length];
-		Marshal.Copy (data, content, 0, (int)length);
-
-		GLib.Marshaller.Free (data);
-
-		return content;
-	}
 	
 	public static Pixbuf TagIconFromPixbuf (Pixbuf source)
 	{
@@ -317,96 +53,6 @@ public class PixbufUtils {
 		
 		return icon;
 	}
-		
-	static public Pixbuf LoadFromScreen (Gdk.Window win) {
-		Gdk.Screen screen = win.Screen;
-		Drawable d = screen.RootWindow;
-		int monitor = screen.GetMonitorAtWindow (win);
-		Gdk.Rectangle geom = screen.GetMonitorGeometry (monitor);
-		
-		//
-		// We use the screen width and height because that reflects
-		// the current resolution, the RootWindow can actually be different.
-		//
-
-		Pixbuf buf = new Pixbuf (Colorspace.Rgb, false, 8, geom.Width, geom.Height);
-		
-		return buf.GetFromDrawable (d,
-					    d.Colormap, geom.X, geom.Y, 0, 0, 
-					    geom.Width, geom.Height);
-	}
-
-	static public Pixbuf LoadFromScreen () {
-		Screen screen = Display.Default.GetScreen (0);
-		Drawable d = screen.RootWindow;
-		int width = screen.Width;
-		int height = screen.Height;
-		
-		//
-		// We use the screen width and height because that reflects
-		// the current resolution, the RootWindow can actually be different.
-		//
-
-		Pixbuf buf = new Pixbuf (Colorspace.Rgb, false, 8, width, height);
-		
-		return buf.GetFromDrawable (d,
-					    d.Colormap, 0, 0, 0, 0, 
-					    width, height);
-	}
-
-	static public Pixbuf LoadFromAssembly (string resource)
-	{
-		try {
-			return new Pixbuf (System.Reflection.Assembly.GetEntryAssembly (), resource);
-		} catch {
-			return null;
-		}
-	}
-
-	[DllImport ("libc")]
-	static extern int rename (string oldpath, string newpath);
-
-	public static void SaveAtomic (Gdk.Pixbuf src, string filename, string type, string [] keys, string [] values)
-	{
-			string tmpname = filename + ".tmp";
-			src.Savev (tmpname, type, NullTerminateArray (keys), NullTerminateArray (values));
-			if (rename (tmpname, filename) < 0)
-				throw new Exception ("Error renaming file");
-	}
-
-	public static Gdk.Pixbuf ScaleToAspect (Gdk.Pixbuf orig, int width, int height)
-	{
-		Gdk.Rectangle pos;
-		double scale = Fit (orig, width, height, false, out pos.Width, out pos.Height);
-		pos.X = (width - pos.Width) / 2;
-		pos.Y = (height - pos.Height) / 2;
-
-		Pixbuf scaled = new Pixbuf (Colorspace.Rgb, false, 8, width, height);
-		scaled.Fill (0x000000); 
-
-		orig.Composite (scaled, pos.X, pos.Y, 
-				pos.Width, pos.Height,
-				pos.X, pos.Y, scale, scale,
-				Gdk.InterpType.Bilinear,
-				255);
-
-		return scaled;
-	}
-
-	public static Pixbuf Flatten (Pixbuf pixbuf)
-	{
-		if (!pixbuf.HasAlpha)
-			return null;
-
-		Pixbuf flattened = new Pixbuf (Colorspace.Rgb, false, 8, pixbuf.Width, pixbuf.Height);
-		pixbuf.CompositeColor (flattened, 0, 0, 
-				       pixbuf.Width, pixbuf.Height, 
-				       0, 0, 1, 1, 
-				       InterpType.Bilinear,
-				       255, 0, 0, 2000, 0xffffff, 0xffffff);
-
-		return flattened;
-	}
 
 	[StructLayout(LayoutKind.Sequential)]
 	public unsafe struct FPixbufJpegMarker {
@@ -422,13 +68,13 @@ public class PixbufUtils {
 	{
 		Pixbuf temp = null;
 		if (pixbuf.HasAlpha) {
-			temp = Flatten (pixbuf);
+			temp = PixbufUtils.Flatten (pixbuf);
 			pixbuf = temp;
 		}
 
 		// The DCF spec says thumbnails should be 160x120 always
-		Pixbuf thumbnail = ScaleToAspect (pixbuf, 160, 120);
-		byte [] thumb_data = Save (thumbnail, "jpeg", null, null);
+		Pixbuf thumbnail = PixbufUtils.ScaleToAspect (pixbuf, 160, 120);
+		byte [] thumb_data = PixbufUtils.Save (thumbnail, "jpeg", null, null);
 		thumbnail.Dispose ();
 
 		byte [] data = new byte [0]; 
@@ -475,271 +121,4 @@ public class PixbufUtils {
 		if (result == false)
 			throw new System.Exception ("Error Saving File");
 	}
-
-
-	[DllImport ("libfspot")]
-	static extern IntPtr f_pixbuf_unsharp_mask (IntPtr src, double radius, double amount, double threshold);
-
-	public static Pixbuf UnsharpMask (Pixbuf src, double radius, double amount, double threshold)
-	{
-		IntPtr raw_ret = f_pixbuf_unsharp_mask (src.Handle, radius, amount, threshold);
- 		Gdk.Pixbuf ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret, true);
-		return ret;
-	}	
-	
-	[DllImport ("libfspot")]
-	static extern IntPtr f_pixbuf_blur (IntPtr src, double radius);
-
-	public static Pixbuf Blur (Pixbuf src, double radius)
-	{
-		IntPtr raw_ret = f_pixbuf_blur (src.Handle, radius);
- 		Gdk.Pixbuf ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret, true);
-		return ret;
-	}	
-
-	public unsafe static Gdk.Pixbuf RemoveRedeye (Gdk.Pixbuf src, Gdk.Rectangle area)
-	{
-		return RemoveRedeye (src, area, -15);
-	}
-
-	public unsafe static Gdk.Pixbuf RemoveRedeye (Gdk.Pixbuf src, Gdk.Rectangle area, int threshold)
-	//threshold, factors and comparisons borrowed from the gimp plugin 'redeye.c' by Robert Merkel
-	{
-		Gdk.Pixbuf copy = src.Copy ();
-		Gdk.Pixbuf selection = new Gdk.Pixbuf (copy, area.X, area.Y, area.Width, area.Height);
-		byte *spix = (byte *)selection.Pixels;
-		int h = selection.Height;
-		int w = selection.Width;
-		int channels = src.NChannels;
-
-		double RED_FACTOR = 0.5133333;
-		double GREEN_FACTOR = 1;
-		double BLUE_FACTOR = 0.1933333;
-
-		for (int j = 0; j < h; j++) {
-			byte *s = spix;
-			for (int i = 0; i < w; i++) {
-				int adjusted_red = (int)(s[0] * RED_FACTOR);
-				int adjusted_green = (int)(s[1] * GREEN_FACTOR);
-				int adjusted_blue = (int)(s[2] * BLUE_FACTOR);
-
-				if (adjusted_red >= adjusted_green - threshold
-				    && adjusted_red >= adjusted_blue - threshold)
-					s[0] = (byte)(((double)(adjusted_green + adjusted_blue)) / (2.0 * RED_FACTOR));
-				s += channels;
-			}
-			spix += selection.Rowstride;
-		}
-
-		return copy;
-	}
-
-	public static unsafe Pixbuf ColorAdjust (Pixbuf src, double brightness, double contrast,
-					  double hue, double saturation, int src_color, int dest_color)
-	{
-		Pixbuf adjusted = new Pixbuf (Colorspace.Rgb, src.HasAlpha, 8, src.Width, src.Height);
-		PixbufUtils.ColorAdjust (src, adjusted, brightness, contrast, hue, saturation, src_color, dest_color);
-		return adjusted;
-	}
-
-	public static Cms.Format PixbufCmsFormat (Pixbuf buf)
-	{
-		return buf.HasAlpha ? Cms.Format.Rgba8Planar : Cms.Format.Rgb8;
-	}
-
-	public static unsafe void ColorAdjust (Pixbuf src, Pixbuf dest, 
-					       double brightness, double contrast,
-					       double hue, double saturation, 
-					       int src_color, int dest_color)
-	{
-		if (src.Width != dest.Width || src.Height != dest.Height)
-			throw new Exception ("Invalid Dimensions");
-
-		//Cms.Profile eos10d = new Cms.Profile ("/home/lewing/ICCProfiles/EOS-10D-True-Color-Non-Linear.icm");
-		Cms.Profile srgb = Cms.Profile.CreateStandardRgb ();
-
-		Cms.Profile bchsw = Cms.Profile.CreateAbstract (256, 
-								0.0, 
-								brightness, contrast,
-								hue, saturation, src_color, 
-								dest_color);
-
-		Cms.Profile [] list = new Cms.Profile [] { srgb, bchsw, srgb };
-		Cms.Transform trans = new Cms.Transform (list, 
-							 PixbufCmsFormat (src),
-							 PixbufCmsFormat (dest),
-							 Cms.Intent.Perceptual, 0x0100);
-
-		ColorAdjust (src, dest, trans);
-
-		trans.Dispose ();
-		srgb.Dispose ();
-		bchsw.Dispose ();
-	}
-
-
-	public static unsafe void ColorAdjust (Gdk.Pixbuf src, Gdk.Pixbuf dest, Cms.Transform trans)
-	{
-		int width = src.Width;
-		byte * srcpix  = (byte *) src.Pixels;
-		byte * destpix = (byte *) dest.Pixels;
-
-		for (int row = 0; row < src.Height; row++) {
-			trans.Apply ((IntPtr) (srcpix + row * src.Rowstride),
-				     (IntPtr) (destpix + row * dest.Rowstride), 
-				     (uint)width);
-		}
-		
-	}
-
-	public static unsafe bool IsGray (Gdk.Pixbuf pixbuf, int max_difference)
-	{
-		int chan = pixbuf.NChannels;
-
-		byte *pix = (byte *)pixbuf.Pixels;
-		int h = pixbuf.Height;
-		int w = pixbuf.Width;
-		int stride = pixbuf.Rowstride;
-
-		for (int j = 0; j < h; j++) {
-			byte *p = pix;
-			for (int i = 0; i < w; i++) {
-				if (Math.Abs (p[0] - p[1]) > max_difference || Math.Abs (p[0] - p [2]) > max_difference) {
-					goto Found;
-				}
-				p += chan;
-			}
-			pix += stride;
-		}
-
-		return true;
-
-	Found:
-		return false;
-	}
-
-	public static unsafe void ReplaceColor (Gdk.Pixbuf src, Gdk.Pixbuf dest)
-	{
-		if (src.HasAlpha || !dest.HasAlpha || (src.Width != dest.Width) || (src.Height != dest.Height))
-			throw new ApplicationException ("invalid pixbufs");
-
-		byte *dpix = (byte *)dest.Pixels;
-		byte *spix = (byte *)src.Pixels;
-		int h = src.Height;
-		int w = src.Width;
-		for (int j = 0; j < h; j++) {
-			byte *d = dpix;
-			byte *s = spix;
-			for (int i = 0; i < w; i++) {
-				d[0] = s[0];
-				d[1] = s[1];
-				d[2] = s[2];
-				d += 4;
-				s += 3;
-			}
-			dpix += dest.Rowstride;
-			spix += src.Rowstride;
-		}
-	}
-
-	public static Gdk.Pixbuf GetThumbnail (Exif.ExifData data)
-	{
-		byte [] thumb_data = data.Data;
-		if (thumb_data.Length > 0) {
-			PixbufOrientation orientation = GetOrientation (data);
-			
-			using (MemoryStream mem = new MemoryStream (thumb_data)) {
-				Gdk.Pixbuf thumb = new Gdk.Pixbuf (mem);
-				Gdk.Pixbuf rotated;
-
-				using (thumb)
-					rotated = FSpot.Utils.PixbufUtils.TransformOrientation (thumb, orientation);
-				
-				return rotated;
-			}			
-		}
-		return null;
-	}
-
-	public static PixbufOrientation GetOrientation (Exif.ExifData data)
-	{
-		PixbufOrientation orientation = PixbufOrientation.TopLeft;
-		
-		Exif.ExifEntry e = data.GetContents (Exif.Ifd.Zero).Lookup (Exif.Tag.Orientation);
-
-		if (e != null) {
-			ushort [] value = e.GetDataUShort ();
-			orientation = (PixbufOrientation) value [0];
-		}
-
-		return orientation;
-	}
-
-	public static PixbufOrientation GetOrientation (System.Uri uri)
-	{
-		using (FSpot.ImageFile img = FSpot.ImageFile.Create (uri)) {
-			return img.Orientation;
-		}	
-	}
-	
-	[Obsolete ("Use GetOrientation (System.Uri) instead")]
-	public static PixbufOrientation GetOrientation (string path)
-	{
-		using (FSpot.ImageFile img = FSpot.ImageFile.Create (path)) {
-			return img.Orientation;
-		}
-	}
-
-	[DllImport("libgnomeui-2-0.dll")]
-	static extern IntPtr gnome_thumbnail_scale_down_pixbuf(IntPtr pixbuf, int dest_width, int dest_height);
-
-	public static Gdk.Pixbuf ScaleDown (Gdk.Pixbuf src, int width, int height)
-	{
-		IntPtr raw_ret = gnome_thumbnail_scale_down_pixbuf(src.Handle, width, height);
-		Gdk.Pixbuf ret;
-		if (raw_ret == IntPtr.Zero)
-			ret = null;
-		else
-			ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret, true);
-		return ret;
-	}
-
-	// Bindings from libf.
-
-	[DllImport ("libfspot")]
-	static extern IntPtr f_pixbuf_copy_apply_brightness_and_contrast (IntPtr src, float brightness, float contrast);
-
-	public static Pixbuf ApplyBrightnessAndContrast (Pixbuf src, float brightness, float contrast)
-	{
-		return new Pixbuf (f_pixbuf_copy_apply_brightness_and_contrast (src.Handle, brightness, contrast));
-	}
-
-	[DllImport ("libfspot")]
-	static extern bool f_pixbuf_save_jpeg_atomic (IntPtr pixbuf, string filename, int quality, out IntPtr error);
-
-	public static void SaveAsJpegAtomically (Pixbuf pixbuf, string filename, int quality)
-	{
-		IntPtr error = IntPtr.Zero;
-
-		if (! f_pixbuf_save_jpeg_atomic (pixbuf.Handle, filename, quality, out error)) {
-			throw new GLib.GException (error);
-		}
-	}
-
-//	[DllImport ("libfspot")]
-//	static extern void f_pixbuf_copy_with_orientation (IntPtr src, IntPtr dest, int orientation);
-//
-//	public static void CopyWithOrientation (Gdk.Pixbuf src, Gdk.Pixbuf dest, PixbufOrientation orientation)
-//	{
-//		f_pixbuf_copy_with_orientation (src.Handle, dest.Handle, (int)orientation);
-//	}
-
-#if false
-	[DllImport("glibsharpglue")]
-	static extern int gtksharp_object_get_ref_count (IntPtr obj);
-	
-	public static int RefCount (GLib.Object obj) {
-		return gtksharp_object_get_ref_count (obj.Handle);
-	}
-#endif
 }
diff --git a/src/PrintOperation.cs b/src/PrintOperation.cs
index 4be9d4a..83d6b75 100644
--- a/src/PrintOperation.cs
+++ b/src/PrintOperation.cs
@@ -121,9 +121,9 @@ namespace FSpot
 						} catch (Exception e) {
 							Log.Exception ("Unable to load image " + selected_photos[p_index].DefaultVersion.Uri + "\n", e);
 							// If the image is not found load error pixbuf
-							pixbuf = new Gdk.Pixbuf (PixbufUtils.ErrorPixbuf, 0, 0, 
-										      PixbufUtils.ErrorPixbuf.Width, 
-										      PixbufUtils.ErrorPixbuf.Height);
+							pixbuf = new Gdk.Pixbuf (FSpotPixbufUtils.ErrorPixbuf, 0, 0,
+										      FSpotPixbufUtils.ErrorPixbuf.Width,
+										      FSpotPixbufUtils.ErrorPixbuf.Height);
 						}
 						//Gdk.Pixbuf pixbuf = img.Load (100, 100);
 						bool rotated = false;
diff --git a/src/SlideView.cs b/src/SlideView.cs
new file mode 100644
index 0000000..03bdea2
--- /dev/null
+++ b/src/SlideView.cs
@@ -0,0 +1,558 @@
+using Gtk;
+using Gdk;
+using System;
+using GLib;
+using System.Runtime.InteropServices;
+using FSpot;
+using FSpot.Utils;
+
+namespace FSpot {
+	public class XScreenSaverSlide : Gtk.Window {
+		public const string ScreenSaverEnviroment = "XSCREENSAVER_WINDOW";
+
+		public XScreenSaverSlide () : base (String.Empty)
+		{
+		}
+	       
+		protected override void OnRealized ()
+		{
+			string env = Environment.GetEnvironmentVariable (ScreenSaverEnviroment);
+			
+			if (env != null) {
+				try {
+					env = env.ToLower ();
+					
+					if (env.StartsWith ("0x"))
+						env = env.Substring (2);
+
+					uint xid = UInt32.Parse (env, System.Globalization.NumberStyles.HexNumber);
+					
+					GdkWindow = Gdk.Window.ForeignNew (xid);
+					Style.Attach (GdkWindow);
+					GdkWindow.Events = EventMask.ExposureMask 
+						| EventMask.StructureMask 
+						| EventMask.EnterNotifyMask 
+						| EventMask.LeaveNotifyMask 
+						| EventMask.FocusChangeMask;
+					
+					Style.SetBackground (GdkWindow, Gtk.StateType.Normal);
+					GdkWindow.SetDecorations ((Gdk.WMDecoration) 0);
+					GdkWindow.UserData = this.Handle;
+					SetFlag (WidgetFlags.Realized);
+					SizeRequest ();
+					Gdk.Rectangle geom;
+					int depth;
+					GdkWindow.GetGeometry (out geom.X, out geom.Y, out geom.Width, out geom.Height, out depth);
+					SizeAllocate (new Gdk.Rectangle (geom.X, geom.Y, geom.Width, geom.Height));
+					Resize (geom.Width, geom.Height);
+					return;
+				} catch (System.Exception e) {
+					System.Console.WriteLine (e);
+				}
+			} else {
+				System.Console.WriteLine ("{0} not set, falling back to window", ScreenSaverEnviroment);
+			}
+
+			SetSizeRequest (640, 480);
+			base.OnRealized ();
+		}
+	}
+
+	public class FullSlide : Gtk.Window {
+		private SlideView slideview;
+		private Gdk.Pixbuf screenshot;
+		private Delay hide;
+		private Gdk.Cursor busy;
+		private Gdk.Cursor none;
+		
+		public FullSlide (Gtk.Window parent, IBrowsableItem [] items) : base ("Slideshow")
+		{
+			screenshot =  PixbufUtils.LoadFromScreen (parent.GdkWindow);
+			
+			this.Destroyed += HandleDestroyed;
+
+			this.TransientFor = parent;
+
+			this.ButtonPressEvent += HandleSlideViewButtonPressEvent;
+			this.KeyPressEvent += HandleSlideViewKeyPressEvent;
+			this.AddEvents ((int) (EventMask.ButtonPressMask | EventMask.KeyPressMask | EventMask.PointerMotionMask));
+			slideview = new SlideView (screenshot, items, 2.0);
+			this.Add (slideview);
+			this.Decorated = false;
+			this.Fullscreen();
+			this.Realize ();
+
+			busy = new Gdk.Cursor (Gdk.CursorType.Watch);
+			this.GdkWindow.Cursor = busy;
+			none = GdkUtils.CreateEmptyCursor (GdkWindow.Display);
+
+			hide = new Delay (2000, new GLib.IdleHandler (HideCursor));
+		}
+
+		public void Play ()
+		{
+			Gdk.GCValues values = new Gdk.GCValues ();
+			values.SubwindowMode = SubwindowMode.IncludeInferiors;
+			Gdk.GC fillgc = new Gdk.GC (this.GdkWindow, values, Gdk.GCValuesMask.Subwindow);
+			
+			slideview.Show ();
+			this.GdkWindow.SetBackPixmap (null, false);
+			this.Show ();
+			screenshot.RenderToDrawable (this.GdkWindow, fillgc, 
+						     0, 0, 0, 0, -1, -1, RgbDither.Normal, 0, 0);
+			
+			slideview.Play ();
+			hide.Start ();
+		}
+		
+		[GLib.ConnectBefore]
+		private void HandleSlideViewKeyPressEvent (object sender, KeyPressEventArgs args)
+		{
+			this.Destroy ();
+			args.RetVal = true;
+		}
+
+		protected override bool OnMotionNotifyEvent (Gdk.EventMotion args)
+		{
+			base.OnMotionNotifyEvent (args);
+			this.GdkWindow.Cursor = busy;
+			hide.Start ();
+			return true;
+		}
+		
+		private bool HideCursor ()
+		{
+			this.GdkWindow.Cursor = none;
+			return false;
+		}
+		
+		private void HandleDestroyed (object sender, System.EventArgs args)
+		{
+			hide.Stop ();
+		}
+
+		private void HandleSlideViewButtonPressEvent (object sender, ButtonPressEventArgs args)
+		{
+			this.Destroy ();
+			args.RetVal = true;
+		}
+	}
+	
+	public class SlideView : Gtk.Image {
+		IBrowsableItem [] photos;
+		Pixbuf last;
+		Pixbuf next;
+		
+		
+		Pixbuf [] tweens = new Pixbuf [10];	
+		int current_tween;
+		uint tween_idle;
+		uint resize_idle;
+		
+		int current_idx = 0;	
+		int next_idx = 0;
+		
+		uint flip_timer = 0;
+		uint transition_timer = 0;
+		
+		uint fail_count = 0;
+		bool animate = true;
+		uint animate_max = 200;
+		
+		bool black = false;
+		uint flip_interval = 2000;
+		uint transition_interval = 75;
+		
+		public bool Running {
+			get {
+				return flip_timer != 0 || transition_timer != 0;
+			}
+		}
+		
+		public bool Animate {
+			get { return animate; }
+			set { animate = value; }
+		}
+		
+		public void Play () 
+		{
+			if (photos.Length < 1)
+				return;
+
+			StopTweenIdle ();
+			if (current_idx >= 0) {
+				Pixbuf frame = GetScaled (photos[current_idx]);
+				this.Pixbuf = frame;
+				frame.Dispose ();
+			} 
+			
+			if (PreloadNextImage (current_idx + 1))
+				StartFlipTimer ();
+		}
+		
+		public void Pause () 
+		{
+			StopTranstionTimer ();
+			StopFlipTimer ();
+		}
+		
+		public void Stop ()
+		{
+			StopTweenIdle ();
+			StopTranstionTimer ();
+			StopFlipTimer ();
+		}
+		
+		public void Forward ()
+		{
+			if (PreloadNextImage (current_idx + 1))
+				ShowNext ();
+		}
+		
+		public void Back ()
+		{
+			if (PreloadNextImage (current_idx - 1))
+				ShowNext ();
+		}	
+		
+		private void ShowNext ()
+		{
+			StopTweenIdle ();
+			
+			if (current_idx != next_idx && next != null)
+				this.Pixbuf = next;
+			
+			current_idx = next_idx;
+			
+			black = false;
+		}
+		
+		private bool PreloadNextImage (int idx)
+		{
+			try {
+				if (idx < photos.Length && idx >= 0) {
+					if (next != null)
+						next.Dispose ();
+					
+					next = GetScaled (photos [idx]);
+					if (next == null)
+						next = GetScaled (PixbufUtils.ShallowCopy (FSpotPixbufUtils.ErrorPixbuf));
+					
+					next_idx = idx;
+					StartTweenIdle ();
+					
+					return true;
+				} else {
+					if (next != null)
+						next.Dispose ();
+
+					next = GetScaled (photos [0]);
+					if (next == null)
+						next = GetScaled (PixbufUtils.ShallowCopy (FSpotPixbufUtils.ErrorPixbuf));
+					next_idx = 0;
+					StartTweenIdle ();
+					
+					return false;
+				}
+			} catch (GLib.GException e) {
+				System.Console.WriteLine (e);
+				idx = (idx + 1) % photos.Length;
+				return PreloadNextImage (idx);
+			}
+		}
+		
+		private Pixbuf CrossFade (Pixbuf current, Pixbuf prev, Pixbuf next, double percent)
+		{ 
+			Rectangle area = new Rectangle (0, 0, Allocation.Width, Allocation.Height);
+			BlockProcessor proc = new BlockProcessor (area, 256);
+			Rectangle subarea;
+
+			while (proc.Step (out subarea)) {
+				if (IsRealized)
+					GdkWindow.ProcessUpdates (false);
+				
+				prev.CopyArea (subarea.X, subarea.Y, subarea.Width, subarea.Height, current, subarea.X, subarea.Y);
+				next.Composite (current, subarea.X, subarea.Y, subarea.Width, subarea.Height, 0, 0, 1, 1,
+						Gdk.InterpType.Nearest, (int) System.Math.Round (255 * percent));
+			}
+			return current;
+		}
+		
+		private Pixbuf BlackFade (Pixbuf current, Pixbuf prev, Pixbuf next, double percent)
+		{ 
+			int width = Allocation.Width;
+			int height = Allocation.Height;
+			
+			current.Fill (0);		
+			
+			if (percent < 0.5)
+				prev.Composite (current, 0,0, width, height, 0, 0, 1, 1,
+						Gdk.InterpType.Nearest, (int)System.Math.Round (255  * (1 - percent * 2)));
+			else
+				next.Composite (current, 0,0, width, height, 0, 0, 1, 1,
+						Gdk.InterpType.Nearest, (int)System.Math.Round (255 * (percent * 2 - 1)));
+			return current;
+		}
+		
+		private Pixbuf Blend (Pixbuf current, Pixbuf prev, Pixbuf next, double percent)
+		{
+			if (black) {
+				return BlackFade (current, prev, next, percent);
+			} else {
+				return CrossFade (current, prev, next, percent);
+			}
+		}
+		
+		private Pixbuf GetScaled (Pixbuf orig)
+		{
+			Gdk.Rectangle pos;
+			int width = Allocation.Width;
+			int height = Allocation.Height;
+			double scale = PixbufUtils.Fit (orig, width, height, false, out pos.Width, out pos.Height);
+			pos.X = (width - pos.Width) / 2;
+			pos.Y = (height - pos.Height) / 2;
+			
+			Pixbuf scaled = new Pixbuf (Colorspace.Rgb, false, 8, width, height);
+			scaled.Fill (0x000000); 
+			
+			Rectangle rect = new Rectangle (pos.X, pos.Y, 256, 256);
+			Rectangle subarea;
+			
+			while (rect.Top < pos.Bottom) {
+				while (rect.X < pos.Right) {
+					if (IsRealized) 
+						GdkWindow.ProcessUpdates (false);
+
+					rect.Intersect (pos, out subarea);
+					orig.Composite (scaled, subarea.X, subarea.Y, 
+							subarea.Width, subarea.Height,
+							pos.X, pos.Y, scale, scale,
+							Gdk.InterpType.Bilinear,
+							255);
+					rect.X += rect.Width;
+				}
+				rect.X = pos.X;
+				rect.Y += rect.Height;
+			}
+			
+			orig.Dispose ();
+			return scaled;
+		}
+		
+		private Pixbuf GetScaled (IBrowsableItem photo)
+		{
+			Pixbuf orig;
+			try { 
+				orig = FSpot.PhotoLoader.LoadAtMaxSize (photo, Allocation.Width, Allocation.Height);
+			} catch {
+				orig = null;
+			}
+
+			if (orig == null)
+				return null;
+
+			Pixbuf result = GetScaled (orig);
+			if (orig != result)
+				orig.Dispose ();
+			
+			return result;
+		}
+		
+		private bool HandleFlipTimer ()
+		{	
+			StopTweenIdle ();
+			
+			StartTransitionTimer ();
+			
+			flip_timer = 0;
+			return false;
+		}
+		
+		private bool HandleTransitionTimer ()
+		{			
+			System.DateTime start_time = System.DateTime.Now;
+			transition_timer = 0;
+			if (current_tween--  > 0) {
+				StartTransitionTimer ();
+				this.Pixbuf = tweens[current_tween];
+				GdkWindow.ProcessUpdates (false);
+				System.TimeSpan span = System.DateTime.Now  - start_time;
+				
+				if (Animate) { 
+					if (span.TotalMilliseconds > animate_max) {
+						fail_count++;
+						
+						if (fail_count > 3) {
+							Animate = false;
+							System.Console.WriteLine ("Disabling slide animation due to 3 consecutive excessive frame intervals {0}ms", 
+										  span.TotalMilliseconds);
+							current_tween = 0;
+						}
+					} else {
+						fail_count = 0;
+					}
+				} 
+			} else {
+				ShowNext ();
+
+				PreloadNextImage (current_idx + 1);
+				StartFlipTimer ();
+			}
+			
+			return false;			
+		}
+
+		
+		private bool HandleTweenIdle ()
+		{
+			using (Pixbuf prev = this.Pixbuf) {	
+				if (!Animate) {
+					ClearTweens ();
+					return false;
+				}
+				
+				if (photos.Length < 2) { // Only one photo. Nothing to do
+					ClearTweens ();
+					return false;
+				}
+				
+				if (current_tween >= tweens.Length) {
+					tween_idle = 0;
+					return false;
+				}
+
+				if (current_tween < tweens.Length && tweens[current_tween] == null) {
+					tweens[current_tween] = new Pixbuf (Colorspace.Rgb, false, 8, 
+									    Allocation.Width, Allocation.Height);
+				}
+
+				double blend_val;
+#if USE_EXP
+				double blend_t = (-10 * current_tween) / ((double)tweens.Length - 1);
+				blend_val = 1.0 - (.01 / (.01 + (.99 * Math.Exp(blend_t))));
+#else
+				double [] blends = new double [] { .99, .97, .9, .8, .7, .6, .5, .4, .3, .15};
+				blend_val = blends [current_tween];
+#endif
+				tweens[current_tween] = Blend (tweens[current_tween], prev, next, blend_val);
+				current_tween++;
+				return true;
+			}
+		}	
+		
+		private void StartTweenIdle () 
+		{
+			if (tween_idle == 0) {
+				current_tween = 0;	
+				tween_idle = GLib.Idle.Add (new GLib.IdleHandler (HandleTweenIdle));
+			}
+		}
+		
+		private void StopTweenIdle ()
+		{
+			if (tween_idle != 0) {
+				GLib.Source.Remove (tween_idle);
+			}
+			tween_idle = 0;
+	
+		}
+		
+		private void StartTransitionTimer ()
+		{
+			if (transition_timer == 0)
+				transition_timer = GLib.Timeout.Add (transition_interval, 
+								     new TimeoutHandler (HandleTransitionTimer));
+		}
+		
+		private void StopTranstionTimer ()
+		{
+			if (transition_timer != 0)
+				GLib.Source.Remove (transition_timer);
+
+			transition_timer = 0;
+		}
+		
+		private void StartFlipTimer ()
+		{
+			if (flip_timer == 0)
+				flip_timer = GLib.Timeout.Add (flip_interval, 
+							       new TimeoutHandler (HandleFlipTimer));
+		}
+		
+		private void StopFlipTimer ()
+		{	
+			if (flip_timer != 0)
+				GLib.Source.Remove (flip_timer);
+
+			flip_timer = 0;
+		}
+
+		
+		private void HandleSizeAllocate (object sender, SizeAllocatedArgs args)
+		{	
+			Pixbuf current = this.Pixbuf;
+
+			if (current == null)
+				return;
+
+			//
+			// The size has changed so we need to reload the images.
+			//
+			if (current.Width != Allocation.Width || current.Height != Allocation.Height) {
+				bool playing = (flip_timer != 0 || transition_timer != 0);
+				
+				if (current_idx < 0) {
+					using (Gdk.Pixbuf old = this.Pixbuf) {
+						this.Pixbuf = GetScaled (old);
+						current.Dispose ();
+					}
+				} else {
+					using (Pixbuf frame =  GetScaled (photos[current_idx])) {
+						this.Pixbuf =  frame;
+						current.Dispose ();
+					}
+				}
+				
+				Stop ();
+				
+				ClearTweens ();
+				
+				if (playing && current_idx != next_idx)
+					Play ();
+				
+				
+			}
+		}
+
+		private void ClearTweens () {
+			for (int i = 0; i < tweens.Length; i++) {
+				if (tweens[i] != null) 
+					tweens[i].Dispose ();
+				tweens[i] = null;
+			}
+		}
+		
+		private void HandleDestroyed (object sender, EventArgs args)
+		{
+			ClearTweens ();
+			Stop ();
+		}
+
+		public SlideView (Pixbuf background, IBrowsableItem [] photos, double delay) : base ()
+		{
+			this.photos = photos;
+
+			if (background != null) {
+				this.Pixbuf = background;
+				background.Dispose ();
+				
+				current_idx = -1;
+				black = true;
+				flip_interval = (uint)(delay * 1000);
+			}
+			
+			SizeAllocated += new SizeAllocatedHandler (HandleSizeAllocate);
+			Destroyed += new EventHandler (HandleDestroyed);
+		}
+	}
+}		
diff --git a/src/ThumbnailGenerator.cs b/src/ThumbnailGenerator.cs
index ae4d408..e4d87a4 100644
--- a/src/ThumbnailGenerator.cs
+++ b/src/ThumbnailGenerator.cs
@@ -41,8 +41,8 @@ namespace FSpot {
 					GFileInfo info = GLib.FileFactory.NewForUri (uri).QueryInfo ("time::modified", GLib.FileQueryInfoFlags.None, null);
 					DateTime mtime = NativeConvert.ToDateTime ((long)info.GetAttributeULong ("time::modified"));
 
-					FSpot.Utils.PixbufUtils.SetOption (thumb, ThumbUri, UriUtils.UriToStringEscaped (uri));
-					FSpot.Utils.PixbufUtils.SetOption (thumb, ThumbMTime, ((uint)GLib.Marshaller.DateTimeTotime_t (mtime)).ToString ());
+					thumb.SetOption (ThumbUri, UriUtils.UriToStringEscaped (uri));
+					thumb.SetOption (ThumbMTime, ((uint)GLib.Marshaller.DateTimeTotime_t (mtime)).ToString ());
 				} catch (System.Exception e) {
 					Log.Exception (e);
 				}
diff --git a/src/UI.Dialog/EditTagIconDialog.cs b/src/UI.Dialog/EditTagIconDialog.cs
index 954586d..cdcd683 100644
--- a/src/UI.Dialog/EditTagIconDialog.cs
+++ b/src/UI.Dialog/EditTagIconDialog.cs
@@ -161,7 +161,7 @@ namespace FSpot.UI.Dialog
 			try {
 				using (FSpot.ImageFile img = FSpot.ImageFile.Create (new Uri(external_photo_chooser.Uri))) {
 					using (Gdk.Pixbuf external_image = img.Load ()) {
-						PreviewPixbuf = PixbufUtils.TagIconFromPixbuf (external_image);
+						PreviewPixbuf = FSpotPixbufUtils.TagIconFromPixbuf (external_image);
 					}
 				}
 			} catch (Exception) {
@@ -190,12 +190,12 @@ namespace FSpot.UI.Dialog
 				if (image_view.Selection != Gdk.Rectangle.Zero) {
 					using (var tmp = new Gdk.Pixbuf (image_view.Pixbuf, x, y, width, height)) {
 						Gdk.Pixbuf transformed = FSpot.Utils.PixbufUtils.TransformOrientation (tmp, image_view.PixbufOrientation);
-						PreviewPixbuf = PixbufUtils.TagIconFromPixbuf (transformed);
+						PreviewPixbuf = FSpotPixbufUtils.TagIconFromPixbuf (transformed);
 						transformed.Dispose ();
 					}
 				} else {
 					Gdk.Pixbuf transformed = FSpot.Utils.PixbufUtils.TransformOrientation (image_view.Pixbuf, image_view.PixbufOrientation);
-					PreviewPixbuf = PixbufUtils.TagIconFromPixbuf (transformed);
+					PreviewPixbuf = FSpotPixbufUtils.TagIconFromPixbuf (transformed);
 					transformed.Dispose ();
 				}
 			}
diff --git a/src/Utils/PixbufExtensions.cs b/src/Utils/PixbufExtensions.cs
new file mode 100644
index 0000000..408c50d
--- /dev/null
+++ b/src/Utils/PixbufExtensions.cs
@@ -0,0 +1,49 @@
+//
+// FSpot.Utils.PixbufExtensions.cs
+//
+// Author(s)
+// 	Ruben Vermeersch <ruben savanne be>
+//
+// This is free software. See COPYING for details.
+//
+
+using Gdk;
+using System;
+using System.Runtime.InteropServices;
+
+namespace FSpot.Utils
+{
+	public static class PixbufExtensions
+	{
+		public static Pixbuf ShallowCopy (this Pixbuf pixbuf)
+		{
+			Pixbuf result = new Pixbuf (pixbuf, 0, 0, pixbuf.Width, pixbuf.Height);
+			result.CopyThumbnailOptionsFrom (pixbuf);
+			return result;
+		}
+
+		//
+		// FIXME this is actually not public api and we should do a verison check,
+		// but frankly I'm irritated that it isn't public so I don't much care.
+		//
+		[DllImport("libgdk_pixbuf-2.0-0.dll")]
+		static extern bool gdk_pixbuf_set_option(IntPtr raw, string key, string value);
+
+		public static bool SetOption(this Gdk.Pixbuf pixbuf, string key, string value)
+		{
+
+			if (value != null)
+				return gdk_pixbuf_set_option(pixbuf.Handle, key, value);
+			else
+				return false;
+		}
+
+		public static void CopyThumbnailOptionsFrom (this Gdk.Pixbuf dest, Gdk.Pixbuf src)
+		{
+			if (src != null && dest != null) {
+				dest.SetOption ("tEXt::Thumb::URI", src.GetOption ("tEXt::Thumb::URI"));
+				dest.SetOption ("tEXt::Thumb::MTime", src.GetOption ("tEXt::Thumb::MTime"));
+			}
+		}
+	}
+}
diff --git a/src/Widgets/Filmstrip.cs b/src/Widgets/Filmstrip.cs
index acf322d..464b121 100644
--- a/src/Widgets/Filmstrip.cs
+++ b/src/Widgets/Filmstrip.cs
@@ -625,7 +625,7 @@ namespace FSpot.Widgets
 
 					if (SquaredThumbs) {
 						using (Pixbuf p = ThumbnailFactory.LoadThumbnail (uri)) {
-							current = PixbufUtils.IconFromPixbuf (p, ThumbSize);
+							current = FSpotPixbufUtils.IconFromPixbuf (p, ThumbSize);
 						}
 					} else 
 						current = ThumbnailFactory.LoadThumbnail (uri, -1, ThumbSize);
diff --git a/src/Widgets/IconView.cs b/src/Widgets/IconView.cs
index a934624..7eb3a86 100644
--- a/src/Widgets/IconView.cs
+++ b/src/Widgets/IconView.cs
@@ -16,6 +16,7 @@ using System.Reflection;
 using System.Collections;
 using System.IO;
 using FSpot.Platform;
+using FSpot.Utils;
 
 namespace FSpot.Widgets
 {
@@ -928,7 +929,7 @@ namespace FSpot.Widgets
 								InterpType.Bilinear);
 					}
 
-					FSpot.Utils.PixbufUtils.CopyThumbnailOptions (thumbnail, temp_thumbnail);
+					temp_thumbnail.CopyThumbnailOptionsFrom (thumbnail);
 				} else
 					temp_thumbnail = thumbnail;
 
diff --git a/src/Widgets/PreviewPopup.cs b/src/Widgets/PreviewPopup.cs
index 25a965a..be5fefb 100644
--- a/src/Widgets/PreviewPopup.cs
+++ b/src/Widgets/PreviewPopup.cs
@@ -126,7 +126,7 @@ namespace FSpot {
 					AddHistogram (pixbuf);
 					image.Pixbuf = pixbuf;
 				} else {
-					image.Pixbuf = PixbufUtils.ErrorPixbuf;
+					image.Pixbuf = FSpotPixbufUtils.ErrorPixbuf;
 				}
 			} else {
 				image.Pixbuf = pixbuf;
diff --git a/src/Widgets/SlideShow.cs b/src/Widgets/SlideShow.cs
index f6d9d22..2a6430d 100644
--- a/src/Widgets/SlideShow.cs
+++ b/src/Widgets/SlideShow.cs
@@ -128,7 +128,7 @@ namespace FSpot.Widgets
 							FSpot.ColorManagement.ApplyProfile (next, screen_profile);
 						loadRetries = 0;
 					} catch (Exception) {
-						next = PixbufUtils.ErrorPixbuf;
+						next = FSpotPixbufUtils.ErrorPixbuf;
 						if (++loadRetries < 10)
 							item.MoveNext (true);
 						else
diff --git a/tests/src/Makefile.am b/tests/src/Makefile.am
index 81fe2a4..bea91f5 100644
--- a/tests/src/Makefile.am
+++ b/tests/src/Makefile.am
@@ -30,6 +30,7 @@ REFS =							\
 	-r:$(top_builddir)/src/FSpot.Query.dll		\
 	-r:$(top_builddir)/src/FSpot.Utils.dll		\
 	-r:$(top_builddir)/src/FSpot.Platform.dll	\
+	-r:$(top_builddir)/src/FSpot.Imaging.dll	\
 	-r:$(top_builddir)/src/Cms.dll			\
 	-r:$(top_builddir)/lib/semweb/SemWeb.dll
 



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