[f-spot/taglib-metadata: 2/5] Initial replacement of libexif usage by Taglib#.



commit f02ed0ce864ef9481169bac17ce8b60aaed5a5e0
Author: Ruben Vermeersch <ruben savanne be>
Date:   Sun May 16 11:33:13 2010 +0200

    Initial replacement of libexif usage by Taglib#.

 lib/libfspot/f-jpeg-utils.c           |   10 --
 lib/libfspot/f-jpeg-utils.h           |    6 -
 src/Imaging/JpegFile.cs               |  267 ++++++---------------------------
 src/Imaging/JpegUtils.cs              |   33 ----
 src/Imaging/RafFile.cs                |   13 +--
 src/Jobs/SyncMetadataJob.cs           |   14 ++-
 src/Utils/GIOTagLibFileAbstraction.cs |   33 ++++
 src/Utils/Unix.cs                     |   19 ---
 8 files changed, 97 insertions(+), 298 deletions(-)
---
diff --git a/lib/libfspot/f-jpeg-utils.c b/lib/libfspot/f-jpeg-utils.c
index a237bd8..0c1fdf8 100644
--- a/lib/libfspot/f-jpeg-utils.c
+++ b/lib/libfspot/f-jpeg-utils.c
@@ -304,16 +304,6 @@ do_load_internal (const char *path,
 
 /* Public API.  */
 
-//GdkPixbuf *
-//f_load_scaled_jpeg  (const char *path,
-//		     int target_width,
-//		     int target_height,
-//		     int *original_width_return,
-//		     int *original_height_return)
-//{
-//	return do_load_internal (path, target_width, target_height, original_width_return, original_height_return);
-//}
-
 
 /* FIXME: Error reporting in this function sucks...  */
 void
diff --git a/lib/libfspot/f-jpeg-utils.h b/lib/libfspot/f-jpeg-utils.h
index 35dd596..74fef89 100644
--- a/lib/libfspot/f-jpeg-utils.h
+++ b/lib/libfspot/f-jpeg-utils.h
@@ -31,12 +31,6 @@
 
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
-//GdkPixbuf *f_load_scaled_jpeg  (const char *path,
-//				int         target_width,
-//				int         target_heigh,
-//				int        *original_width_return,
-//				int        *original_height_return);
-//
 void  f_get_jpeg_size  (const char *path,
 			int        *width_return,
 			int        *height_return);
diff --git a/src/Imaging/JpegFile.cs b/src/Imaging/JpegFile.cs
index f341ee0..2a65937 100644
--- a/src/Imaging/JpegFile.cs
+++ b/src/Imaging/JpegFile.cs
@@ -5,133 +5,49 @@ using FSpot.Xmp;
 using FSpot.Tiff;
 using FSpot.Utils;
 using Hyena;
+using TagLib;
 
 namespace FSpot {
 	public interface IThumbnailContainer {
 		Gdk.Pixbuf GetEmbeddedThumbnail ();
 	}
 
-	public class JpegFile : ImageFile, IThumbnailContainer, SemWeb.StatementSource {
-		private Exif.ExifData exif_data;
-		private XmpFile xmp;
-		private JpegHeader header;
-		private FSpot.Tiff.Header exif_header;
+	public class JpegFile : ImageFile, IThumbnailContainer {
+        public Image.File Metadata {
+            get { return metadata_file; }
+        }
 
-                // False seems a safe default
-                public bool Distinct {
-                        get { return false; }
-                }
+        private Image.File metadata_file;
 		
 		public JpegFile (SafeUri uri) : base (uri)
 		{
-			try {
-				// Console.WriteLine ("approximate quality = {0}", Header.GuessQuality ());
-			} catch (Exception e) {
-				Log.Exception (e);
-			}
+            metadata_file = TagLib.File.Create (new GIOTagLibFileAbstraction () { Uri = uri }) as Image.File;
 		}
 		
-		public JpegHeader Header {
-			get {
-				if (header == null) {
-					using (Stream stream = this.Open ()) {
-						header = new JpegHeader (stream, true);
-					}
-				}
-				return header;
-			}
-		}
-
-		public FSpot.Tiff.Header ExifHeader {
-			get {
-				if (exif_header == null) {
-					exif_header = Header.GetExifHeader ();
-				}
-				return exif_header;
-			}
-		}
-
-		public override Stream PixbufStream ()
-		{
-			if (header != null)
-				return Open ();
-
-			Stream s = Open ();
-			if (s.CanSeek) {
-				header = new JpegHeader (s, true);
-				s.Position = 0;
-			} else
-				Log.DebugFormat ("{0} can not seek :(", s);
-			return s;
-		}
-
-		public void Select (SemWeb.StatementSink sink)
-		{
-			Header.Select (sink);
-		}
-
 		public override Cms.Profile GetProfile ()
 		{
-			return Header.GetProfile ();
+			return null;
 		}
 
 		public override string Description {
 			get {
-#if USE_TIFF
-				try {
-					SubdirectoryEntry sub = (SubdirectoryEntry) ExifHeader.Directory.Lookup (TagId.ExifIfdPointer);
-					if (sub != null) {
-						DirectoryEntry entry = sub.Directory [0].Lookup (TagId.UserComment);
-						if (entry != null)
-							return entry.ValueAsString [0];
-					}
-				} catch (System.Exception e) {
-					Log.Exception (e);
-				}
-				return null;
-#else
-				try {
-					Exif.ExifContent exif_content = this.ExifData.GetContents (Exif.Ifd.Exif);
-					Exif.ExifEntry entry = exif_content.Lookup (Exif.Tag.UserComment);
-					
-					if (entry == null)
-						return null;
-					
-					UserComment comment = new UserComment (entry.Data, entry.ByteOrder == Exif.ByteOrder.Intel);
-					return comment.Value;
-				} catch (Exception e) {
-					// errors here shouldn't be fatal
-					return null;
-				}
-#endif				
+                return metadata_file.ImageTag.Comment;
 			}
 		}
 
 		public void SetDescription (string value)
 		{
-			Exif.ExifContent exif_content = this.ExifData.GetContents (Exif.Ifd.Exif);			
-			Exif.ExifEntry entry = exif_content.GetEntry (Exif.Tag.UserComment);
-
-			UserComment comment = new UserComment (value);
-			byte [] data = comment.GetBytes (entry.ByteOrder == Exif.ByteOrder.Intel);
-			entry.SetData (data);
-		}
-		
-		public void SetXmp (XmpFile xmp)
-		{
-			this.xmp = xmp;
+            metadata_file.GetTag (TagTypes.XMP, true); // Ensure XMP tag
+            metadata_file.ImageTag.Comment = value;
 		}
 
 		private void UpdateMeta ()
 		{
-			Exif.ExifContent image_content = this.ExifData.GetContents (Exif.Ifd.Zero);
-			image_content.GetEntry (Exif.Tag.Software).SetData (FSpot.Defines.PACKAGE + " version " + FSpot.Defines.VERSION);
-
-			// set the write time in the datetime tag
-			image_content.GetEntry (Exif.Tag.DateTime).Reset ();
+            metadata_file.GetTag (TagTypes.XMP, true); // Ensure XMP tag
+            metadata_file.ImageTag.Software = FSpot.Defines.PACKAGE + " version " + FSpot.Defines.VERSION;
 		}
 
-		private void SaveMetaData (System.IO.Stream input, System.IO.Stream output)
+		/*private void SaveMetaData (System.IO.Stream input, System.IO.Stream output)
 		{
 			JpegHeader header = new JpegHeader (input);
 			UpdateMeta ();
@@ -144,44 +60,34 @@ namespace FSpot {
 			// Console.WriteLine ("set xmp");
 			header.Save (output);
 			// Console.WriteLine ("saved");
-		}
+		}*/
 		
 		public void SaveMetaData (string path)
 		{
-			UpdateMeta ();
-
-			//Get file permissions... (mkstemp does not keep permissions or ownership)
-			Mono.Unix.Native.Stat stat;
-			int stat_err = Mono.Unix.Native.Syscall.stat (path, out stat);
+            // FIXME: This currently copies the file out to a tmp file, overwrites it
+            // and restores the tmp file in case of failure. Should obviously be the
+            // other way around, but Taglib# doesn't have an interface to do this.
+            // https://bugzilla.gnome.org/show_bug.cgi?id=618768
 
-			string  temp_path = path;
-			using (System.IO.FileStream stream = System.IO.File.OpenRead (path)) {
-				using (System.IO.Stream output = FSpot.Utils.Unix.MakeSafeTemp (ref temp_path)) {
-					SaveMetaData (stream, output);
-				}
-			}
+            var uri = UriUtils.PathToFileUri (path);
+            var tmp = System.IO.Path.GetTempFileName ();
+            var tmp_uri = UriUtils.PathToFileUri (tmp);
 
-			File.SetAttributes (temp_path, File.GetAttributes (path));
+            var orig_file = GLib.FileFactory.NewForUri (uri);
+            var tmp_file = GLib.FileFactory.NewForUri (tmp_uri);
 
-			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));
-			}
+            orig_file.Copy (tmp_file, GLib.FileCopyFlags.AllMetadata, null, null);
 
-			//Set file permissions and gid...
-			if (stat_err == 0) 
-				try {
-					Mono.Unix.Native.Syscall.chmod (path, stat.st_mode |
-									      Mono.Unix.Native.FilePermissions.S_IRUSR | 
-									      Mono.Unix.Native.FilePermissions.S_IWUSR);
-					Mono.Unix.Native.Syscall.chown(path, Mono.Unix.Native.Syscall.getuid (), stat.st_gid);
-				} catch (Exception) {}
+            try {
+                metadata_file.Save ();
+            } catch (Exception) {
+                tmp_file.Copy (orig_file, GLib.FileCopyFlags.AllMetadata, null, null);
+            }
 		}
 
 		public void SetThumbnail (Gdk.Pixbuf source)
 		{
-			// Then create the thumbnail
+			/*// 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);
@@ -189,12 +95,15 @@ namespace FSpot {
 			// System.Console.WriteLine ("saving thumbnail");				
 
 			// now update the exif data
-			ExifData.Data = thumb_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)
 		{
-			Exif.ExifEntry e;
+			/* 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.
@@ -213,7 +122,7 @@ namespace FSpot {
 			//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);
+			image_content.GetEntry (Exif.Tag.PixelYDimension).SetData ((uint)height);*/
 		}
 
 		public override void Save (Gdk.Pixbuf pixbuf, System.IO.Stream stream)
@@ -221,11 +130,12 @@ namespace FSpot {
 
 			// Console.WriteLine ("starting save");
 			// First save the imagedata
-			int quality = Header.GuessQuality ();
+			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");
@@ -235,13 +145,13 @@ namespace FSpot {
 			
 			// Console.WriteLine ("saving metatdata");
 			SaveMetaData (buffer, stream);
-			// Console.WriteLine ("done");
+			// Console.WriteLine ("done");*/
 			buffer.Close ();
 		}
 		
 		public Gdk.Pixbuf GetEmbeddedThumbnail ()
 		{
-			if (this.ExifData.Data.Length > 0) {
+			/*if (this.ExifData.Data.Length > 0) {
 				MemoryStream mem = new MemoryStream (this.ExifData.Data);
 				Gdk.Pixbuf thumb = new Gdk.Pixbuf (mem);
 				Gdk.Pixbuf rotated = FSpot.Utils.PixbufUtils.TransformOrientation (thumb, this.Orientation);
@@ -249,110 +159,31 @@ namespace FSpot {
 				
 				mem.Close ();
 				return rotated;
-			}
+			}*/
+            // FIXME: No thumbnail support in TagLib# https://bugzilla.gnome.org/show_bug.cgi?id=618769
 			return null;
 		}
 		
-		public Exif.ExifData ExifData {
-			get {
-				if (exif_data == null) {
-					exif_data = Header.Exif;
-
-					if (exif_data == null || exif_data.Handle.Handle == System.IntPtr.Zero)
-						exif_data = new Exif.ExifData ();
-				}
-				// System.Console.WriteLine ("loading exif data");
-				return exif_data;
-			}
-			set {
-				this.exif_data = value;
-			}
-		}
-
 		public override PixbufOrientation GetOrientation () 
 		{
-			PixbufOrientation orientation = PixbufOrientation.TopLeft;
-#if USE_TIFF
-			try {
-				DirectoryEntry e = ExifHeader.Directory.Lookup (TagId.Orientation);
-				orientation = (PixbufOrientation)e.ValueAsLong [0];
-			} catch {
-				Log.Warning ("Error checking orientation", uri);
-			}
-#else						     
-Log.Debug (">>>");
-			Exif.ExifEntry e = this.ExifData.GetContents (Exif.Ifd.Zero).Lookup (Exif.Tag.Orientation);
-Log.Debug ("<<<");
-			
-			if (e != null) {
-				ushort [] value = e.GetDataUShort ();
-				orientation = (PixbufOrientation) value [0];
-			}
-#endif			
-			if (orientation < PixbufOrientation.TopLeft || orientation > PixbufOrientation.LeftBottom)
-				orientation = PixbufOrientation.TopLeft;
-
-			return orientation;
+            var orientation = metadata_file.ImageTag.Orientation;
+			return (PixbufOrientation) orientation;
 		}
 		
 		public void SetOrientation (PixbufOrientation orientation)
 		{
-			Exif.ExifEntry e = this.ExifData.GetContents (Exif.Ifd.Zero).GetEntry (Exif.Tag.Orientation);
-			// System.Console.WriteLine ("Saving orientation as {0}", orientation);
-			e.SetData ((ushort)orientation);
-		       
-			e = this.ExifData.GetContents (Exif.Ifd.One).Lookup (Exif.Tag.Orientation);
-			if (e != null)
-				e.SetData ((ushort)orientation);
+            metadata_file.ImageTag.Orientation = (Image.ImageOrientation) orientation;
 		}
 		
 		public void SetDateTimeOriginal (DateTime time)
 		{
-			Exif.ExifEntry e = ExifData.LookupFirst (Exif.Tag.DateTimeOriginal);
-			if (e != null)
-				e.SetData (time);
-			else {
-				Exif.ExifContent exif_content = this.ExifData.GetContents (Exif.Ifd.Exif);
-				Exif.ExifEntry entry = exif_content.GetEntry (Exif.Tag.DateTimeOriginal);
-				entry.SetData (time);
-			}		
+            metadata_file.ImageTag.DateTime = time;
 		}
 
 		public override System.DateTime Date {
 			get {
-				System.DateTime time;
-				try {
-#if USE_TIFF
-					SubdirectoryEntry sub = (SubdirectoryEntry) ExifHeader.Directory.Lookup (TagId.ExifIfdPointer);
-					DirectoryEntry e;
-					
-					if (sub != null) {
-						e = sub.Directory [0].Lookup (TagId.DateTimeOriginal);
-						
-						if (e != null)
-							return DirectoryEntry.DateTimeFromString (e.StringValue);
-					}
-					
-					e = ExifHeader.Directory.Lookup (TagId.DateTime);
-					
-					if (e != null)
-						return DirectoryEntry.DateTimeFromString (e.StringValue);
-					
-					return base.Date;
-#else
-					string time_str = "";				
-					time_str = ExifData.LookupFirstValue (Exif.Tag.DateTimeOriginal);
-					
-					if (time_str == null || time_str == "") 
-						time_str = ExifData.LookupFirstValue (Exif.Tag.DateTime);
-					
-					time = Exif.ExifUtil.DateTimeFromString (time_str); 
-#endif
-				} catch (System.Exception e) {
-					Log.Exception (e);
-					time = base.Date;
-				}
-				return time;
+                var date = metadata_file.ImageTag.DateTime;
+                return date.HasValue ? date.Value : base.Date;
 			}
 		}
 
diff --git a/src/Imaging/JpegUtils.cs b/src/Imaging/JpegUtils.cs
index e6a1f72..981b1e9 100644
--- a/src/Imaging/JpegUtils.cs
+++ b/src/Imaging/JpegUtils.cs
@@ -3,39 +3,6 @@ using System;
 using Gdk;
 
 public class JpegUtils {
-//	[DllImport ("libfspot")]
-//	static extern IntPtr f_load_scaled_jpeg (string path,
-//						 int target_width,
-//						 int target_height,
-//						 out int original_width_return,
-//						 out int original_height_return);
-//
-//	/* FIXME */
-//	[DllImport("libgobject-2.0-0.dll")]
-//	static extern void g_object_unref (IntPtr raw);
-//
-//	public static Pixbuf LoadScaled (string path, int target_width, int target_height,
-//					 out int original_width, out int original_height)
-//	{
-//		Pixbuf pixbuf = new Pixbuf (f_load_scaled_jpeg (path, target_width, target_height,
-//								out original_width, out original_height));
-//		g_object_unref (pixbuf.Handle);
-//		return pixbuf;
-//	}
-
-//	public static Pixbuf LoadScaled (string path, int target_width, int target_height)
-//	{
-//		int unused;
-//		return LoadScaled (path, target_width, target_height, out unused, out unused);
-//	}
-
-	[DllImport ("libfspot")]
-	static extern void f_save_jpeg_exif (string path, HandleRef data);
-
-	public static void SaveExif (string path, Exif.ExifData data)
-	{
-		f_save_jpeg_exif (path, data.Handle);
-	}		
 
 	[DllImport ("libfspot")]
 	static extern void f_get_jpeg_size (string path, out int width_return, out int height_return);
diff --git a/src/Imaging/RafFile.cs b/src/Imaging/RafFile.cs
index 13a191b..cff1128 100644
--- a/src/Imaging/RafFile.cs
+++ b/src/Imaging/RafFile.cs
@@ -12,15 +12,6 @@ namespace FSpot.Raf {
 	// completely figured out yet.  More to follow.
 
 	// ALL the sample files I have begin with "FUJIFILMCCD-RAW "
-
-	
-	public class WhiteBalance {
-		// see dcraw parse_fuli
-		public WhiteBalance (System.IO.Stream stream)
-		{
-
-		}
-	}
 	
 	public class RafFile : ImageFile, SemWeb.StatementSource {
 
@@ -84,12 +75,12 @@ namespace FSpot.Raf {
 
 		public void Select (SemWeb.StatementSink sink)
 		{
-			byte [] data = GetEmbeddedJpeg ();
+			/*byte [] data = GetEmbeddedJpeg ();
 			if (data != null) {
 				System.IO.Stream stream = new System.IO.MemoryStream (data);
 				JpegHeader header = new JpegHeader (stream);
 				header.Select (sink);
-			}
+			}*/
 		}
 
 		private byte [] GetEmbeddedJpeg ()
diff --git a/src/Jobs/SyncMetadataJob.cs b/src/Jobs/SyncMetadataJob.cs
index 0ecda15..ab0b379 100644
--- a/src/Jobs/SyncMetadataJob.cs
+++ b/src/Jobs/SyncMetadataJob.cs
@@ -48,6 +48,12 @@ namespace FSpot.Jobs {
 		void WriteMetadataToImage (Photo photo)
 		{
 			string path = photo.DefaultVersion.Uri.LocalPath;
+
+            Tag [] tags = photo.Tags;
+            string [] names = new string [tags.Length];
+
+            for (int i = 0; i < tags.Length; i++)
+                names [i] = tags [i].Name;
 	
 			using (FSpot.ImageFile img = FSpot.ImageFile.Create (photo.DefaultVersion.Uri)) {
 				if (img is FSpot.JpegFile) {
@@ -55,7 +61,13 @@ namespace FSpot.Jobs {
 				
 					jimg.SetDescription (photo.Description);
 					jimg.SetDateTimeOriginal (photo.Time);
-					jimg.SetXmp (UpdateXmp (photo, jimg.Header.GetXmp ()));
+
+                    var meta = jimg.Metadata;
+                    meta.GetTag (TagLib.TagTypes.XMP, true);
+
+                    var tag = meta.ImageTag;
+                    tag.Keywords = names;
+                    tag.Rating = photo.Rating;
 	
 					jimg.SaveMetaData (path);
 				} else if (img is FSpot.Png.PngFile) {
diff --git a/src/Utils/GIOTagLibFileAbstraction.cs b/src/Utils/GIOTagLibFileAbstraction.cs
new file mode 100644
index 0000000..46a5626
--- /dev/null
+++ b/src/Utils/GIOTagLibFileAbstraction.cs
@@ -0,0 +1,33 @@
+using System;
+using System.IO;
+using GLib;
+
+namespace FSpot.Utils
+{
+    public sealed class GIOTagLibFileAbstraction : TagLib.File.IFileAbstraction
+    {
+        public string Name {
+            get {
+                return Uri.ToString ();
+            }
+            set {
+                Uri = new Uri (value);
+            }
+        }
+
+        public Uri Uri { get; set; }
+
+        public Stream ReadStream {
+            get { return new GioStream (FileFactory.NewForUri(Uri).Read (null)); }
+        }
+
+        public Stream WriteStream {
+            get { throw new NotImplementedException (); }
+        }
+
+        public void CloseStream (Stream stream)
+        {
+            stream.Close ();
+        }
+    }
+}
diff --git a/src/Utils/Unix.cs b/src/Utils/Unix.cs
index 099e510..ac5db78 100644
--- a/src/Utils/Unix.cs
+++ b/src/Utils/Unix.cs
@@ -9,9 +9,6 @@ namespace FSpot.Utils {
 			[DllImport ("libc", EntryPoint="rename", CharSet = CharSet.Auto)]
 			public static extern int Rename (string oldpath, string newpath);
 
-			[DllImport ("libc", EntryPoint="mkstemp")]
-			public static extern int MkSTemp (byte []template);
-
 			[DllImport("libc", EntryPoint="prctl")]
 			public static extern int PrCtl(int option, string name, ulong arg3, ulong arg4, ulong arg5);
 
@@ -24,22 +21,6 @@ namespace FSpot.Utils {
 			return NativeMethods.Rename (oldpath, newpath);
 		}
 
-
-		public static Mono.Unix.UnixStream MakeSafeTemp (ref string template)
-		{
-			byte [] template_bytes = System.Text.Encoding.UTF8.GetBytes (template + ".XXXXXX\0");
-
-			int fd = NativeMethods.MkSTemp (template_bytes);
-
-			if (fd < 0) {
-				//Mono.Unix.Error error = Mono.Unix.Stdlib.GetLastError ();
-				throw new System.ApplicationException (Mono.Unix.Catalog.GetString ("Unable to create temporary file"));
-			}
-
-			template = System.Text.Encoding.UTF8.GetString (template_bytes, 0, template_bytes.Length - 1);
-			return new Mono.Unix.UnixStream (fd);
-		}
-
 		public static void SetProcessName (string name)
 		{
 			try {



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