[f-spot/taglib-metadata] Handle creation of derived versions with Taglib#.



commit ebb689cf75d915b6458e55fb45026d0cdfea008d
Author: Ruben Vermeersch <ruben savanne be>
Date:   Fri Jul 2 10:39:37 2010 +0200

    Handle creation of derived versions with Taglib#.
    
    This means copying metadata from one file to another, even if the format
    changes.

 lib/TagLib/TagLib             |    2 +-
 lib/libfspot/f-jpeg-utils.c   |   20 -----
 lib/libfspot/f-pixbuf-utils.c |  153 ----------------------------------
 lib/libfspot/f-pixbuf-utils.h |   11 ---
 src/Core/Photo.cs             |    4 +-
 src/Filters/JpegFilter.cs     |   70 ++++++----------
 src/Filters/ResizeFilter.cs   |   98 +++++++++-------------
 src/Filters/SharpFilter.cs    |   75 +++++++-----------
 src/Imaging/Exif.cs           |   19 -----
 src/Imaging/ImageFile.cs      |    5 -
 src/Imaging/IptcFile.cs       |   24 ------
 src/Imaging/JpegFile.cs       |   64 ---------------
 src/Imaging/PngFile.cs        |  123 ----------------------------
 src/Imaging/PnmFile.cs        |   33 --------
 src/Imaging/XmpFile.cs        |   49 -----------
 src/PixbufUtils.cs            |  180 ++++++++++++++++++-----------------------
 16 files changed, 177 insertions(+), 753 deletions(-)
---
diff --git a/lib/TagLib/TagLib b/lib/TagLib/TagLib
index 2a46d11..600a7b2 160000
--- a/lib/TagLib/TagLib
+++ b/lib/TagLib/TagLib
@@ -1 +1 @@
-Subproject commit 2a46d11248d2d02e8b4bc280093d40b72a2929d8
+Subproject commit 600a7b29dbccbc8d75aa0ddb4a20b1fc816ef285
diff --git a/lib/libfspot/f-jpeg-utils.c b/lib/libfspot/f-jpeg-utils.c
index 0c1fdf8..b83848a 100644
--- a/lib/libfspot/f-jpeg-utils.c
+++ b/lib/libfspot/f-jpeg-utils.c
@@ -315,26 +315,6 @@ f_get_jpeg_size  (const char *path,
 }
 
 
-void
-f_save_jpeg_exif (const char *filename, ExifData *exif_data)
-{
-	JPEGData     *jdata;
-
-	g_warning ("exif = %p", exif_data);
-	jdata = jpeg_data_new_from_file (filename);
-	if (jdata == NULL) {
-		g_warning ("unable to parse jpeg file");
-		return;
-	}
-	if (exif_data == NULL) {
-		g_warning ("missing exif data");
-	}
-	jpeg_data_set_exif_data (jdata, exif_data);
-	jpeg_data_save_file (jdata, filename);
-
-	jpeg_data_unref (jdata);
-}
-
 /* Implementation of non-lossy JPEG file transformations, based on GThumb code
    by Paolo Bacchilega.  */
 
diff --git a/lib/libfspot/f-pixbuf-utils.c b/lib/libfspot/f-pixbuf-utils.c
index d87e01f..32d59d1 100644
--- a/lib/libfspot/f-pixbuf-utils.c
+++ b/lib/libfspot/f-pixbuf-utils.c
@@ -45,64 +45,6 @@
 #include <gdk/gdk.h>
 #include "f-image-surface.h"
 
-
-/* Helper functions.  */
-
-static unsigned char
-apply_brightness_and_contrast (unsigned char u_value,
-			       float brightness,
-			       float contrast)
-{
-	float  nvalue;
-	double power;
-	float  value;
-
-	value = (float) u_value / 255.0;
-
-	/* apply brightness */
-	if (brightness < 0.0)
-		value = value * (1.0 + brightness);
-	else
-		value = value + ((1.0 - value) * brightness);
-	
-	/* apply contrast */
-	if (contrast < 0.0) {
-		if (value > 0.5)
-			nvalue = 1.0 - value;
-		else
-			nvalue = value;
-
-		if (nvalue < 0.0)
-			nvalue = 0.0;
-
-		nvalue = 0.5 * pow (nvalue * 2.0 , (double) (1.0 + contrast));
-
-		if (value > 0.5)
-			value = 1.0 - nvalue;
-		else
-			value = nvalue;
-	} else {
-		if (value > 0.5)
-			nvalue = 1.0 - value;
-		else
-			nvalue = value;
-		
-		if (nvalue < 0.0)
-			nvalue = 0.0;
-		
-		power = (contrast == 1.0) ? 127 : 1.0 / (1.0 - contrast);
-		nvalue = 0.5 * pow (2.0 * nvalue, power);
-		
-		if (value > 0.5)
-			value = 1.0 - nvalue;
-		else
-			value = nvalue;
-	}
-	
-	return (guchar) (value * 255);
-}
-
-
 /* Public functions.  */
 
 int
@@ -146,68 +88,6 @@ f_pixbuf_get_scaled_height (GdkPixbuf *pixbuf,
 		return size;
 }
 
-/* Return a new GdkPixbuf enhancing/reducing brightness and contrast according
-   to the specified values (from -1.0 to +1.0).  */
-GdkPixbuf *
-f_pixbuf_copy_apply_brightness_and_contrast (GdkPixbuf *src,
-					     float brightness,
-					     float contrast)
-{
-	GdkPixbuf *result_pixbuf;
-	char *sp, *dp;
-	int width, height;
-	int line;
-	int result_rowstride, src_rowstride;
-	int bytes_per_pixel;
-
-	g_return_val_if_fail ((brightness > -1.0 || F_DOUBLE_EQUAL (brightness, -1.0))
-			       && (brightness < 1.0 || F_DOUBLE_EQUAL (brightness, 1.0)),
-			      NULL);
-	g_return_val_if_fail ((contrast > -1.0 || F_DOUBLE_EQUAL (contrast, -1.0))
-			       && (contrast < 1.0 || F_DOUBLE_EQUAL (contrast, 1.0)),
-			      NULL);
-
-	if (F_DOUBLE_EQUAL (brightness, 0.0) && F_DOUBLE_EQUAL (contrast, 0.0))
-		return gdk_pixbuf_copy (src);
-
-	result_pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src),
-					gdk_pixbuf_get_has_alpha (src),
-					gdk_pixbuf_get_bits_per_sample (src),
-					gdk_pixbuf_get_width (src),
-					gdk_pixbuf_get_height (src));
-
-	width = gdk_pixbuf_get_width (result_pixbuf);
-	height = gdk_pixbuf_get_height (result_pixbuf);
-
-	result_rowstride = gdk_pixbuf_get_rowstride (result_pixbuf);
-	src_rowstride = gdk_pixbuf_get_rowstride (src);
-
-	bytes_per_pixel = gdk_pixbuf_get_has_alpha (result_pixbuf) ? 4 : 3;
-
-	sp = gdk_pixbuf_get_pixels (src);
-	dp = gdk_pixbuf_get_pixels (result_pixbuf);
-
-	for (line = 0; line < height; line ++) {
-		char *sq = sp;
-		char *dq = dp;
-		int i;
-
-		for (i = 0; i < width; i ++) {
-			dq[0] = apply_brightness_and_contrast (sq[0], brightness, contrast);
-			dq[1] = apply_brightness_and_contrast (sq[1], brightness, contrast);
-			dq[2] = apply_brightness_and_contrast (sq[2], brightness, contrast);
-
-			dq += bytes_per_pixel;
-			sq += bytes_per_pixel;
-		}
-
-		sp += src_rowstride;
-		dp += result_rowstride;
-	}
-
-	return result_pixbuf;
-}
-
 cairo_surface_t *
 f_pixbuf_to_cairo_surface (GdkPixbuf *pixbuf)
 {
@@ -347,36 +227,3 @@ f_pixbuf_from_cairo_surface (cairo_surface_t *source)
   cairo_surface_destroy (surface);
   return pixbuf;
 }
-
-gboolean
-f_pixbuf_save_jpeg_atomic  (GdkPixbuf   *pixbuf,
-			    const char  *file_name,
-			    int          quality,
-			    GError     **error)
-{
-	char *tmp_file_name = g_strconcat (file_name, ".tmp", NULL);
-	char *quality_string = g_strdup_printf ("%d", quality);
-	gboolean success;
-
-	if (! gdk_pixbuf_save (pixbuf, tmp_file_name, "jpeg", error,
-			       "quality", quality_string, NULL)) {
-		success = FALSE;
-		goto end;
-	}
-
-	if (rename (tmp_file_name, file_name) != 0) {
-		char *error_message = g_strdup_printf ("Atomic rename failed: %s", g_strerror (errno));
-		g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, error_message);
-		g_free (error_message);
-
-		success = FALSE;
-		goto end;
-	}
-
-	success = TRUE;
-
- end:
-	g_free (quality_string);
-	g_free (tmp_file_name);
-	return TRUE;
-}
diff --git a/lib/libfspot/f-pixbuf-utils.h b/lib/libfspot/f-pixbuf-utils.h
index 443be87..a0ae7dd 100644
--- a/lib/libfspot/f-pixbuf-utils.h
+++ b/lib/libfspot/f-pixbuf-utils.h
@@ -38,15 +38,4 @@ int f_pixbuf_get_scaled_width (GdkPixbuf *pixbuf, int size);
    thumbnail SIZE.  */
 int f_pixbuf_get_scaled_height (GdkPixbuf *pixbuf, int size);
 
-
-/* Picture ops.  */
-GdkPixbuf *f_pixbuf_copy_apply_brightness_and_contrast (GdkPixbuf *src,
-							float brightness,
-							float contrast);
-
-gboolean  f_pixbuf_save_jpeg_atomic  (GdkPixbuf   *pixbuf,
-				      const char  *filename,
-				      int          quality,
-				      GError     **error);
-
 #endif
diff --git a/src/Core/Photo.cs b/src/Core/Photo.cs
index 6c56316..3980df8 100644
--- a/src/Core/Photo.cs
+++ b/src/Core/Photo.cs
@@ -231,9 +231,7 @@ namespace FSpot
 				try {
 					var versionUri = VersionUri (version);
 
-					using (Stream stream = System.IO.File.OpenWrite (versionUri.LocalPath)) {
-						img.Save (buffer, stream);
-					}
+					PixbufUtils.CreateDerivedVersion (DefaultVersion.Uri, versionUri, 95, buffer);
 					(GetVersion (version) as PhotoVersion).ImportMD5 = HashUtils.GenerateMD5 (VersionUri (version));
 					DefaultVersionId = version;
 				} catch (System.Exception e) {
diff --git a/src/Filters/JpegFilter.cs b/src/Filters/JpegFilter.cs
index d315d1f..6c2b48e 100644
--- a/src/Filters/JpegFilter.cs
+++ b/src/Filters/JpegFilter.cs
@@ -9,50 +9,34 @@
  */
 
 using System;
+using FSpot.Utils;
 using FSpot.Imaging;
-using FSpot.Imaging.Exif;
 
 namespace FSpot.Filters {
-	public class JpegFilter : IFilter {
-		private uint quality = 95;
-		public uint Quality {
-			get { return quality; }
-			set { quality = value; }
-		}
-		
-		public JpegFilter (uint quality)
-		{
-			this.quality = quality;
-		}
-
-		public JpegFilter()
-		{
-		}
-			
-		public bool Convert (FilterRequest req)
-		{
-			// FIXME this should copy metadata from the original
-			// even when the source is not a jpeg
-			string source = req.Current.LocalPath;
-
-			using (ImageFile img = ImageFile.Create (req.Current)) {
-				if (img is Imaging.JpegFile)
-					return false;
-
-				req.Current = req.TempUri ("jpg");
-				string dest = req.Current.LocalPath;
-
-				ExifData exif_data;
-				try {
-					exif_data = new ExifData (source);
-				} catch (Exception) {
-					exif_data = new ExifData();
-				}
-
-				PixbufUtils.SaveJpeg (img.Load(), dest, (int) quality, exif_data);
-			}
-
-			return true;
-		}
-	}
+    public class JpegFilter : IFilter {
+        private uint quality = 95;
+        public uint Quality {
+            get { return quality; }
+            set { quality = value; }
+        }
+
+        public JpegFilter (uint quality)
+        {
+            this.quality = quality;
+        }
+
+        public JpegFilter()
+        {
+        }
+
+        public bool Convert (FilterRequest req)
+        {
+            var source = req.Current;
+            req.Current = req.TempUri ("jpg");
+
+            PixbufUtils.CreateDerivedVersion (source, req.Current, quality);
+
+            return true;
+        }
+    }
 }
diff --git a/src/Filters/ResizeFilter.cs b/src/Filters/ResizeFilter.cs
index ea8dbc4..050c977 100644
--- a/src/Filters/ResizeFilter.cs
+++ b/src/Filters/ResizeFilter.cs
@@ -12,69 +12,51 @@
 using System;
 using System.IO;
 
+using FSpot.Utils;
 using FSpot.Imaging;
-using FSpot.Imaging.Exif;
 
 using Mono.Unix;
 
 using Gdk;
 
 namespace FSpot.Filters {
-	public class ResizeFilter : IFilter
-	{
-		public ResizeFilter ()
-		{
-		}
-
-		public ResizeFilter (uint size)
-		{
-			this.size = size;
-		}
-
-		private uint size = 600;
-
-		public uint Size {
-			get { return size; }
-			set { size = value; }
-		}
-
-		public bool Convert (FilterRequest req)
-		{
-			string source = req.Current.LocalPath;
-			var dest_uri = req.TempUri (System.IO.Path.GetExtension (source));
-			string dest = dest_uri.LocalPath;
-
-			using (ImageFile img = ImageFile.Create (req.Current)) {
-
-				using (Pixbuf pixbuf = img.Load ()) {
-					if (pixbuf.Width < size && pixbuf.Height < size)
-						return false;
-				}
-	
-				using (Pixbuf pixbuf = img.Load ((int)size, (int)size)) {
-					string destination_extension = Path.GetExtension (dest);
-	
-					if (Path.GetExtension (source).ToLower () == Path.GetExtension (dest).ToLower ()) {
-						using (Stream output = File.OpenWrite (dest)) {
-							img.Save (pixbuf, output);
-						}
-					} else if (destination_extension == ".jpg") {
-						// FIXME this is a bit of a nasty hack to work around
-						// the lack of being able to change the path in this filter
-						// and the lack of proper metadata copying yuck
-						ExifData exif_data;
-	
-						exif_data = new ExifData (source);
-						
-						PixbufUtils.SaveJpeg (pixbuf, dest, 95, exif_data);
-					} else 
-						throw new NotImplementedException (String.Format (Catalog.GetString ("No way to save files of type \"{0}\""), destination_extension));
-				}
-			}
-
-			req.Current = dest_uri;
-			return true;
-		}
-	}
+    public class ResizeFilter : IFilter
+    {
+        public ResizeFilter ()
+        {
+        }
+
+        public ResizeFilter (uint size)
+        {
+            this.size = size;
+        }
+
+        private uint size = 600;
+
+        public uint Size {
+            get { return size; }
+            set { size = value; }
+        }
+
+        public bool Convert (FilterRequest req)
+        {
+            string source = req.Current.LocalPath;
+            var dest_uri = req.TempUri (System.IO.Path.GetExtension (source));
+
+            using (ImageFile img = ImageFile.Create (req.Current)) {
+
+                using (Pixbuf pixbuf = img.Load ()) {
+                    if (pixbuf.Width < size && pixbuf.Height < size)
+                        return false;
+                }
+
+                using (Pixbuf pixbuf = img.Load ((int)size, (int)size)) {
+                    PixbufUtils.CreateDerivedVersion (req.Current, dest_uri, 95, pixbuf);
+                }
+            }
+
+            req.Current = dest_uri;
+            return true;
+        }
+    }
 }
-
diff --git a/src/Filters/SharpFilter.cs b/src/Filters/SharpFilter.cs
index 2959738..a90591a 100644
--- a/src/Filters/SharpFilter.cs
+++ b/src/Filters/SharpFilter.cs
@@ -14,54 +14,35 @@ using Gdk;
 
 using Mono.Unix;
 
+using FSpot.Utils;
 using FSpot.Imaging;
-using FSpot.Imaging.Exif;
 
 namespace FSpot.Filters {
-	public class SharpFilter : IFilter 
-	{	
-		double radius, amount, threshold;
-
-		public SharpFilter (double radius, double amount, double threshold)
-		{
-			this.radius = radius;
-			this.amount = amount;
-			this.threshold = threshold;
-		}
-
-		public bool Convert (FilterRequest req)
-		{
-			var dest_uri = req.TempUri (System.IO.Path.GetExtension (req.Current.LocalPath));
-
-			using (ImageFile img = ImageFile.Create (req.Current)) {
-				using (Pixbuf in_pixbuf = img.Load ()) {
-					using (Pixbuf out_pixbuf = PixbufUtils.UnsharpMask (in_pixbuf, radius, amount, threshold)) {
-						string destination_extension = Path.GetExtension (dest_uri.LocalPath);
-		
-						if (Path.GetExtension (req.Current.LocalPath).ToLower () == Path.GetExtension (dest_uri.LocalPath).ToLower ()) {
-							using (Stream output = File.OpenWrite (dest_uri.LocalPath)) {
-								img.Save (out_pixbuf, output);
-							}
-						} else if (destination_extension == ".jpg") {
-							// FIXME this is a bit of a nasty hack to work around
-							// the lack of being able to change the path in this filter
-							// and the lack of proper metadata copying yuck
-							ExifData exif_data;
-		
-							exif_data = new ExifData (req.Current.LocalPath);
-							
-							PixbufUtils.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));
-						
-					}
-				}
-			}
-
-			req.Current = dest_uri;
-			return true;
-		}
-
-	}
+    public class SharpFilter : IFilter 
+    {
+        double radius, amount, threshold;
+
+        public SharpFilter (double radius, double amount, double threshold)
+        {
+            this.radius = radius;
+            this.amount = amount;
+            this.threshold = threshold;
+        }
+
+        public bool Convert (FilterRequest req)
+        {
+            var dest_uri = req.TempUri (req.Current.GetExtension ());
+
+            using (ImageFile img = ImageFile.Create (req.Current)) {
+                using (Pixbuf in_pixbuf = img.Load ()) {
+                    using (Pixbuf out_pixbuf = PixbufUtils.UnsharpMask (in_pixbuf, radius, amount, threshold)) {
+                        PixbufUtils.CreateDerivedVersion (req.Current, dest_uri, 95, out_pixbuf);
+                    }
+                }
+            }
+
+            req.Current = dest_uri;
+            return true;
+        }
+    }
 }
-
diff --git a/src/Imaging/Exif.cs b/src/Imaging/Exif.cs
index 76c754f..b11c1f2 100644
--- a/src/Imaging/Exif.cs
+++ b/src/Imaging/Exif.cs
@@ -789,25 +789,6 @@ namespace FSpot.Imaging.Exif {
 		internal static extern IntPtr malloc (uint size);
 		
 		[DllImport ("libexif.dll")]
-		private static extern void exif_data_save_data (HandleRef handle, out IntPtr content, out uint size);		
-		public byte [] Save ()
-		{
-			Byte [] content = null;
-			uint size;
-			IntPtr data;
-			unsafe {
-				exif_data_save_data (handle, out data, out size);
-				
-				content = new byte [size];
-				Marshal.Copy (data, content, 0, (int)size);
-				free (data);
-			}
-				
-			Log.DebugFormat ("Saved {0} bytes", content.Length);
-			return content;
-		}
-		
-		[DllImport ("libexif.dll")]
 		internal static extern void exif_data_unref (HandleRef data);
 		
 		[DllImport ("libexif.dll")]
diff --git a/src/Imaging/ImageFile.cs b/src/Imaging/ImageFile.cs
index 2990a90..bffa1a2 100644
--- a/src/Imaging/ImageFile.cs
+++ b/src/Imaging/ImageFile.cs
@@ -111,11 +111,6 @@ namespace FSpot.Imaging {
 			get { return GetOrientation (); }
 		}
 
-		public virtual void Save (Gdk.Pixbuf pixbuf, System.IO.Stream stream)
-		{
-			throw new NotImplementedException (Catalog.GetString ("Writing to this file format is not supported"));
-		}
-
 		protected Gdk.Pixbuf TransformAndDispose (Gdk.Pixbuf orig)
 		{
 			if (orig == null)
diff --git a/src/Imaging/IptcFile.cs b/src/Imaging/IptcFile.cs
index 3058d71..b53dd75 100644
--- a/src/Imaging/IptcFile.cs
+++ b/src/Imaging/IptcFile.cs
@@ -314,23 +314,6 @@ namespace FSpot.Imaging.Iptc {
 			}
 		}
 
-		public void Save (System.IO.Stream stream)
-		{
-			stream.WriteByte (TagMarker);
-			stream.WriteByte (RecordNumber);
-			stream.WriteByte (DataSetNumber);
-			if (Data.Length < LengthMask) {
-				byte [] len = FSpot.BitConverter.GetBytes ((ushort)Data.Length, false);
-				stream.Write (len, 0, len.Length);
-			} else {
-				byte [] len =  FSpot.BitConverter.GetBytes ((ushort)LengthMask & 8, false);
-				stream.Write (len, 0, len.Length);
-				len = FSpot.BitConverter.GetBytes ((ulong) Data.Length, false);
-				stream.Write (len, 0, len.Length);
-			}
-			stream.Write (Data, 0, Data.Length);
-		}
-
 		public string XmpObject 
 		{
 			get {
@@ -419,12 +402,5 @@ namespace FSpot.Imaging.Iptc {
 				sets.Add (data);
 			}
 		}
-
-		public void Save (System.IO.Stream stream) 
-		{
-			foreach (DataSet data in sets) {
-				data.Save (stream);
-			}
-		}
 	}
 }
diff --git a/src/Imaging/JpegFile.cs b/src/Imaging/JpegFile.cs
index 097a4e4..2b6e948 100644
--- a/src/Imaging/JpegFile.cs
+++ b/src/Imaging/JpegFile.cs
@@ -31,70 +31,6 @@ namespace FSpot.Imaging {
 			return null;
 		}
 
-		public void SetThumbnail (Gdk.Pixbuf source)
-		{
-			/*// Then create the thumbnail
-			// The DCF spec says thumbnails should be 160x120 always
-			Gdk.Pixbuf thumbnail = PixbufUtils.ScaleToAspect (source, 160, 120);
-			byte [] thumb_data = PixbufUtils.Save (thumbnail, "jpeg", null, null);
-			
-			// System.Console.WriteLine ("saving thumbnail");				
-
-			// now update the exif data
-			ExifData.Data = thumb_data;*/
-            // FIXME: needs to be readded https://bugzilla.gnome.org/show_bug.cgi?id=618769
-		}
-
-		public void SetDimensions (int width, int height)
-		{
-			/* FIXME: disabled, related to metadata copying
-             * https://bugzilla.gnome.org/show_bug.cgi?id=618770
-             * Exif.ExifEntry e;
-			Exif.ExifContent thumb_content;
-			
-			// update the thumbnail related image fields if they exist.
-			thumb_content = this.ExifData.GetContents (Exif.Ifd.One);
-			e = thumb_content.Lookup (Exif.Tag.RelatedImageWidth);
-			if (e != null)
-				e.SetData ((uint)width);
-
-			e = thumb_content.Lookup (Exif.Tag.RelatedImageHeight);
-			if (e != null)
-				e.SetData ((uint)height);
-			
-			Exif.ExifContent image_content;
-			image_content = this.ExifData.GetContents (Exif.Ifd.Zero);
-			image_content.GetEntry (Exif.Tag.Orientation).SetData ((ushort)PixbufOrientation.TopLeft);
-			//image_content.GetEntry (Exif.Tag.ImageWidth).SetData ((uint)pixbuf.Width);
-			//image_content.GetEntry (Exif.Tag.ImageHeight).SetData ((uint)pixbuf.Height);
-			image_content.GetEntry (Exif.Tag.PixelXDimension).SetData ((uint)width);
-			image_content.GetEntry (Exif.Tag.PixelYDimension).SetData ((uint)height);*/
-		}
-
-		public override void Save (Gdk.Pixbuf pixbuf, System.IO.Stream stream)
-		{
-
-			// Console.WriteLine ("starting save");
-			// First save the imagedata
-			int quality = metadata_file.Properties.PhotoQuality;
-			quality = quality == 0 ? 75 : quality;
-			byte [] image_data = PixbufUtils.Save (pixbuf, "jpeg", new string [] {"quality" }, new string [] { quality.ToString () });
-			System.IO.MemoryStream buffer = new System.IO.MemoryStream ();
-			buffer.Write (image_data, 0, image_data.Length);
-/*			FIXME: Metadata copying doesn't work yet https://bugzilla.gnome.org/show_bug.cgi?id=618770
-			buffer.Position = 0;
-			
-			// Console.WriteLine ("setting thumbnail");
-			SetThumbnail (pixbuf);
-			SetDimensions (pixbuf.Width, pixbuf.Height);
-			pixbuf.Dispose ();
-			
-			// Console.WriteLine ("saving metatdata");
-			SaveMetaData (buffer, stream);
-			// Console.WriteLine ("done");*/
-			buffer.Close ();
-		}
-		
 		public Gdk.Pixbuf GetEmbeddedThumbnail ()
 		{
 			/*if (this.ExifData.Data.Length > 0) {
diff --git a/src/Imaging/PngFile.cs b/src/Imaging/PngFile.cs
index 1f37b97..eb2a0c2 100644
--- a/src/Imaging/PngFile.cs
+++ b/src/Imaging/PngFile.cs
@@ -294,9 +294,6 @@ namespace FSpot.Imaging.Png {
 		public class ItxtChunk : ZtxtChunk{
 			//public static string Name = "zTXt";
 
-			string Language;
-			string LocalizedKeyword;
-
 			public override void Load (byte [] data)
 			{
 				int i = 0;
@@ -304,9 +301,7 @@ namespace FSpot.Imaging.Png {
 				i++;
 				compressed = (data [i++] != 0);
 				i++;
-				Language = GetString (ref i);
 				i++;
-				LocalizedKeyword = GetString (ref i, System.Text.Encoding.UTF8);
 				i++;
 
 				if (Compressed) {
@@ -318,48 +313,6 @@ namespace FSpot.Imaging.Png {
 				}
 			}
 
-			public override void SetText (string text)
-			{
-				byte [] raw = System.Text.Encoding.UTF8.GetBytes (text);
-				SetText (raw);
-			}
-
-			public void SetText (byte [] raw)
-			{
-				using (MemoryStream stream = new MemoryStream ()) {
-					byte [] tmp;
-					
-					text_data = raw;
-
-					tmp = Latin1.GetBytes (keyword);
-					stream.Write (tmp, 0, tmp.Length);
-					stream.WriteByte (0);
-					
-					stream.WriteByte ((byte)(compressed ? 1 : 0));
-					stream.WriteByte (0);
-					
-					if (Language != null && Language != System.String.Empty) {
-						tmp = Latin1.GetBytes (Language);
-						stream.Write (tmp, 0, tmp.Length);
-					}
-					stream.WriteByte (0);
-					
-					if (LocalizedKeyword != null && LocalizedKeyword != System.String.Empty) {
-						tmp = System.Text.Encoding.UTF8.GetBytes (LocalizedKeyword);
-						stream.Write (tmp, 0, tmp.Length);
-					}
-					stream.WriteByte (0);
-				
-					if (compressed) {
-						tmp = Deflate (text_data, 0, text_data.Length);
-						stream.Write (tmp, 0, tmp.Length);
-					} else {
-						stream.Write (text_data, 0, text_data.Length);
-					}
-					this.data = stream.ToArray ();
-				}
-			}
-
 			public ItxtChunk (string name, byte [] data) : base (name, data) 
 			{
 				this.Name = name;
@@ -371,8 +324,6 @@ namespace FSpot.Imaging.Png {
 				encoding = System.Text.Encoding.UTF8;
 				this.Name = "iTXt";
 				this.keyword = keyword;
-				this.Language = language;
-				this.LocalizedKeyword = System.String.Empty;
 				this.compressed = compressed;
 			}
 		}
@@ -698,17 +649,6 @@ namespace FSpot.Imaging.Png {
 				
 			}
 			
-			public virtual void Save (System.IO.Stream stream)
-			{
-				byte [] name_bytes = System.Text.Encoding.ASCII.GetBytes (Name);
-				byte [] length_bytes = BitConverter.GetBytes ((uint)data.Length, false);
-				stream.Write (length_bytes, 0, length_bytes.Length);
-				Crc crc = new Crc (stream);
-				crc.Write (name_bytes);
-				crc.Write (data);
-				crc.WriteSum ();
-			}
-
 			public bool Critical {
 				get {
 					return !System.Char.IsLower (Name, 0);
@@ -1217,49 +1157,6 @@ namespace FSpot.Imaging.Png {
 				else
 					throw new System.Exception ("Uknown ordering for chunk");
 			}
-			
-			public void Save (System.IO.Stream stream)
-			{
-				stream.Write (magic, 0, magic.Length);
-				foreach (Chunk chunk in Chunks) {
-					chunk.Save (stream);
-				}
-			}
-		}
-
-
-		public void Save (System.IO.Stream stream)
-		{
-			Header.Save (stream);
-		}
-
-		public void Save (string path)
-		{
-			string  temp_path = path + ".tmp.png";
-			using (System.IO.Stream output = System.IO.File.OpenWrite (temp_path)) {
-				Save (output);
-			}
-			if (FSpot.Utils.Unix.Rename (temp_path, path) < 0) {
-				System.IO.File.Delete (temp_path);
-				throw new System.Exception (System.String.Format ("Unable to rename {0} to {1}", temp_path, path));
-			}
-		}
-
-		public override void Save (Gdk.Pixbuf pixbuf, System.IO.Stream stream)
-		{
-			byte [] buffer = PixbufUtils.Save (pixbuf, "png", null, null);
-			using (MemoryStream mem = new MemoryStream (buffer)) {
-				PngHeader converted = new PngHeader (mem);
-				
-				/* FIXME we need to update the XMP metadata here */
-				foreach (Chunk c in Chunks) {
-					if (c is TextChunk) {
-						converted.Insert (c);
-					}
-				}
-				
-				converted.Save (stream);
-			}
 		}
 
 		public override Cms.Profile GetProfile ()
@@ -1333,25 +1230,5 @@ namespace FSpot.Imaging.Png {
 				return new XmpFile (stream);
 			}
 		}
-
-		public void SetXmp (XmpFile xmp)
-		{
-			TextChunk text = null;
-
-			text = Header.LookupTextChunk ("XML:com.adobe.xmp");
-			if (text != null)
-				Chunks.Remove (text);
-			
-			text = Header.LookupTextChunk ("XMP");
-			if (text != null)
-				Chunks.Remove (text);
-
-			ItxtChunk itext = new ItxtChunk ("XML:com.adobe.xmp", "en", false);
-			using (MemoryStream stream = new MemoryStream ()) {
-				xmp.Save (stream);
-				itext.SetText (stream.ToArray ());
-			}
-			Header.Insert (itext);
-		}
 	}
 }
diff --git a/src/Imaging/PnmFile.cs b/src/Imaging/PnmFile.cs
index b2d2275..231e7a0 100644
--- a/src/Imaging/PnmFile.cs
+++ b/src/Imaging/PnmFile.cs
@@ -199,39 +199,6 @@ namespace FSpot.Imaging.Pnm {
 			return PixbufUtils.ScaleToMaxSize (this.Load (), width, height);
 		}
 
-		public override void Save (Gdk.Pixbuf pixbuf, System.IO.Stream stream)
-		{
-			if (pixbuf.HasAlpha)
-				throw new NotImplementedException ();
-
-			// FIXME this should be part of the header class
-			string header = String.Format ("P6\n"
-						       + "#Software: {0} {1}\n"
-						       + "{2} {3}  #Width and Height\n"
-						       + "255\n", 
-						       FSpot.Defines.PACKAGE,
-						       FSpot.Defines.VERSION,
-						       pixbuf.Width, 
-						       pixbuf.Height);
-						       
-			byte [] header_bytes = System.Text.Encoding.UTF8.GetBytes (header);
-			stream.Write (header_bytes, 0, header.Length);
-										 
-			unsafe {
-				byte * src_pixels = (byte *) pixbuf.Pixels;
-				int src_stride = pixbuf.Rowstride;
-				int count = pixbuf.Width * pixbuf.NChannels;
-				int height = pixbuf.Height;
-
-				for (int y = 0; y < height; y++) {
-					for (int x = 0; x < count; x++) {
-						stream.WriteByte (* (src_pixels + x));
-					}
-					src_pixels += src_stride;
-				}
-			}
-		}
-
 		public static Gdk.Pixbuf Load (Stream stream)
 		{
 			Header header = new Header (stream);
diff --git a/src/Imaging/XmpFile.cs b/src/Imaging/XmpFile.cs
index ff20334..42b8015 100644
--- a/src/Imaging/XmpFile.cs
+++ b/src/Imaging/XmpFile.cs
@@ -62,40 +62,6 @@ namespace FSpot.Imaging.Xmp {
 			}
 		}
 
-		public void Save (System.IO.Stream stream)
-		{
-			try {
-				XmlTextWriter text;
-				RdfXmlWriter writer;
-                                XmlDocument rdfdoc = new XmlDocument();
-
-                                // first, construct the rdf guts, semweb style
-                                writer = new XmpWriter (rdfdoc);
-				//writer.Namespaces.Parent = MetadataStore.Namespaces;
-				writer.Write (store);
-				writer.Close ();
-			       
-                                // now construct the xmp wrapper packet
-				text = new XmlTextWriter (stream, System.Text.Encoding.UTF8);
- 				text.Formatting = Formatting.Indented;
-                        
-                                text.WriteProcessingInstruction ("xpacket", "begin=\"\ufeff\" id=\"W5M0MpCehiHzreSzNTczkc9d\"");
-                                text.WriteStartElement ("x:xmpmeta");
-                                text.WriteAttributeString ("xmlns", "x", null, "adobe:ns:meta/");
-
-				((XmlElement)rdfdoc.ChildNodes[1]).RemoveAttribute ("xml:base");
-				rdfdoc.ChildNodes[1].WriteTo (text);
-
-                                // now close off the xmp packet
-                                text.WriteEndElement ();
-                                text.WriteProcessingInstruction ("xpacket", "end=\"r\"");
-				text.Close ();
-				
-			} catch (System.Exception e) {
-				Log.Exception (e);
-			}
-		}
-
 		public bool Add (Statement stmt)
 		{
 			return ((SemWeb.StatementSink)store).Add (stmt);
@@ -112,20 +78,5 @@ namespace FSpot.Imaging.Xmp {
 				Log.Debug(stmt.ToString());
 			}
 		}
-
-#if TEST_XMP
-		static void Main (string [] args)
-		{
-			XmpFile xmp = new XmpFile (System.IO.File.OpenRead (args [0]));
-			//xmp.Store.Dump ();
-#if false
-			System.IO.StreamReader stream = new System.IO.StreamReader (System.IO.File.OpenRead (args [0]));
-
-			while (stream.BaseStream.Position < stream.BaseStream.Length) {
-				System.Console.WriteLine (stream.ReadLine ());
-			}
-#endif
-		}
-#endif
 	}
 }
diff --git a/src/PixbufUtils.cs b/src/PixbufUtils.cs
index 7b44a92..1d3dc62 100644
--- a/src/PixbufUtils.cs
+++ b/src/PixbufUtils.cs
@@ -21,7 +21,7 @@ using FSpot.Imaging.Exif;
 using Hyena;
 using TagLib.Image;
 
-public class PixbufUtils {
+public static class PixbufUtils {
 	static Pixbuf error_pixbuf = null;
 	public static Pixbuf ErrorPixbuf {
 		get {
@@ -407,75 +407,6 @@ public class PixbufUtils {
 		return flattened;
 	}
 
-	[StructLayout(LayoutKind.Sequential)]
-	public unsafe struct FPixbufJpegMarker {
-		public int type;
-		public byte *data;
-		public int length;
-	}
-
-	[DllImport ("libfspot")]
-	static extern bool f_pixbuf_save_jpeg (IntPtr src, string path, int quality, FPixbufJpegMarker [] markers, int num_markers);
-
-	public static void SaveJpeg (Pixbuf pixbuf, string path, int quality, ExifData exif_data)
-	{
-		Pixbuf temp = null;
-		if (pixbuf.HasAlpha) {
-			temp = 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);
-		thumbnail.Dispose ();
-
-		byte [] data = new byte [0]; 
-		FPixbufJpegMarker [] marker = new FPixbufJpegMarker [0];
-		bool result = false;
-
-		if (exif_data != null && exif_data.Handle.Handle != IntPtr.Zero) {
-			exif_data.Data = thumb_data;
-
-			// Most of the things we will set will be in the 0th ifd
-			var content = exif_data.GetContents (FSpot.Imaging.Exif.Ifd.Zero);
-
-			// reset the orientation tag the default is top/left
-			content.GetEntry (FSpot.Imaging.Exif.Tag.Orientation).Reset ();
-
-			// set the write time in the datetime tag
-			content.GetEntry (FSpot.Imaging.Exif.Tag.DateTime).Reset ();
-
-			// set the software tag
-			content.GetEntry (FSpot.Imaging.Exif.Tag.Software).SetData (FSpot.Defines.PACKAGE + " version " + FSpot.Defines.VERSION);
-
-			data = exif_data.Save ();
-		}
-
-		unsafe {
-			if (data.Length > 0) {
-				
-				fixed (byte *p = data) {
-					marker = new FPixbufJpegMarker [1];
-					marker [0].type = 0xe1; // APP1 marker
-					marker [0].data = p;
-					marker [0].length = data.Length;
-					
-					result = f_pixbuf_save_jpeg (pixbuf.Handle, path, quality, marker, marker.Length);
-				}					
-			} else
-				result = f_pixbuf_save_jpeg (pixbuf.Handle, path, quality, marker, marker.Length);
-			
-		}
-
-		if (temp != null)
-			temp.Dispose ();
-		
-		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);
 
@@ -484,7 +415,7 @@ public class PixbufUtils {
 		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);
@@ -701,33 +632,82 @@ public class PixbufUtils {
 		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);
-//	}
+    public static void CreateDerivedVersion (SafeUri source, SafeUri destination)
+    {
+        CreateDerivedVersion (source, destination, 95);
+    }
+
+    public static void CreateDerivedVersion (SafeUri source, SafeUri destination, uint jpeg_quality)
+    {
+        if (source.GetExtension () == destination.GetExtension ()) {
+            // Simple copy will do!
+            var file_from = GLib.FileFactory.NewForUri (source);
+            var file_to = GLib.FileFactory.NewForUri (destination);
+            file_from.Copy (file_to, GLib.FileCopyFlags.AllMetadata | GLib.FileCopyFlags.Overwrite, null, null);
+            return;
+        }
+
+        // Else make a derived copy with metadata copied
+        using (ImageFile img = ImageFile.Create (source)) {
+            using (var pixbuf = img.Load ()) {
+                CreateDerivedVersion (source, destination, jpeg_quality, pixbuf);
+            }
+        }
+    }
+
+    public static void CreateDerivedVersion (SafeUri source, SafeUri destination, uint jpeg_quality, Pixbuf pixbuf)
+    {
+        SaveToSuitableFormat (destination, pixbuf, jpeg_quality);
+
+        var res_from = new GIOTagLibFileAbstraction () { Uri = source };
+        var res_to = new GIOTagLibFileAbstraction () { Uri = destination };
+        using (var metadata_from = TagLib.File.Create (res_from) as TagLib.Image.File) {
+            using (var metadata_to = TagLib.File.Create (res_to) as TagLib.Image.File) {
+                metadata_to.CopyFrom (metadata_from);
+                metadata_to.Save ();
+            }
+        }
+    }
+
+    private static void SaveToSuitableFormat (SafeUri destination, Pixbuf pixbuf, uint jpeg_quality)
+    {
+        // FIXME: this needs to work on streams rather than filenames. Do that when we switch to
+        // newer GDK.
+        var extension = destination.GetExtension ().ToLower ();
+        if (extension == ".png") {
+            pixbuf.Save (destination.LocalPath, "png");
+        } else if (extension == ".jpg" || extension == ".jpeg") {
+            pixbuf.Save (destination.LocalPath, "jpeg", jpeg_quality);
+        } else {
+            throw new NotImplementedException ("Saving this file format is not supported");
+        }
+    }
+
+#region Gdk hackery
+
+    // This hack below is needed because there is no wrapped version of
+    // Save which allows specifying the variable arguments (it's not
+    // possible with p/invoke).
+
+    [DllImport("libgdk_pixbuf-2.0-0.dll")]
+    static extern bool gdk_pixbuf_save(IntPtr raw, IntPtr filename, IntPtr type, out IntPtr error,
+            IntPtr optlabel1, IntPtr optvalue1, IntPtr dummy);
+
+    private static bool Save (this Pixbuf pixbuf, string filename, string type, uint jpeg_quality)
+    {
+        IntPtr error = IntPtr.Zero;
+        IntPtr nfilename = GLib.Marshaller.StringToPtrGStrdup (filename);
+        IntPtr ntype = GLib.Marshaller.StringToPtrGStrdup (type);
+        IntPtr optlabel1 = GLib.Marshaller.StringToPtrGStrdup ("quality");
+        IntPtr optvalue1 = GLib.Marshaller.StringToPtrGStrdup (jpeg_quality.ToString ());
+        bool ret = gdk_pixbuf_save(pixbuf.Handle, nfilename, ntype, out error, optlabel1, optvalue1, IntPtr.Zero);
+        GLib.Marshaller.Free (nfilename);
+        GLib.Marshaller.Free (ntype);
+        GLib.Marshaller.Free (optlabel1);
+        GLib.Marshaller.Free (optvalue1);
+        if (error != IntPtr.Zero) throw new GLib.GException (error);
+        return ret;
+    }
+
+#endregion
 }



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