[f-spot] Switch to mime-type based image loading.



commit f680fd0dfd56522e399bc52452c69808856ed9d9
Author: Ruben Vermeersch <ruben savanne be>
Date:   Thu Jul 8 20:02:49 2010 +0200

    Switch to mime-type based image loading.
    
    The mime type is now used for detecting how to load an image.
    
    A test to ensure that we load everything Taglib# supports is added.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=622147

 src/Imaging/ImageFile.cs    |  187 ++++++++++++++++++++++--------------------
 src/Makefile.am             |    1 +
 src/Tests/ImageFileTests.cs |   45 ++++++++++
 src/Utils/Metadata.cs       |   26 ++++--
 4 files changed, 161 insertions(+), 98 deletions(-)
---
diff --git a/src/Imaging/ImageFile.cs b/src/Imaging/ImageFile.cs
index 5f8f910..7a1d659 100644
--- a/src/Imaging/ImageFile.cs
+++ b/src/Imaging/ImageFile.cs
@@ -2,13 +2,14 @@ using Hyena;
 
 using System;
 using System.IO;
-using System.Collections;
+using System.Collections.Generic;
 
 using FSpot.Utils;
 using Mono.Unix;
 using Mono.Unix.Native;
 using Gdk;
 
+using GLib;
 using TagLib.Image;
 
 using GFileInfo = GLib.FileInfo;
@@ -24,91 +25,99 @@ namespace FSpot.Imaging {
 
 #region Factory functionality
 
-		static Hashtable name_table;
-		internal static Hashtable NameTable { get { return name_table; } }
+		static Dictionary<string, Type> name_table;
+		internal static Dictionary<string, Type> NameTable { get { return name_table; } }
 
-		static ImageFile ()
-		{
-			name_table = new Hashtable ();
-			name_table [".svg"] = typeof (BaseImageFile);
-			name_table [".gif"] = typeof (BaseImageFile);
-			name_table [".bmp"] = typeof (BaseImageFile);
-			name_table [".pcx"] = typeof (BaseImageFile);
-			name_table [".jpeg"] = typeof (BaseImageFile);
-			name_table [".jpg"] = typeof (BaseImageFile);
-			name_table [".png"] = typeof (BaseImageFile);
-			name_table [".cr2"] = typeof (FSpot.Imaging.Tiff.Cr2File);
-			name_table [".nef"] = typeof (FSpot.Imaging.Tiff.NefFile);
-			name_table [".pef"] = typeof (FSpot.Imaging.Tiff.NefFile);
-			name_table [".raw"] = typeof (FSpot.Imaging.Tiff.NefFile);
-			name_table [".kdc"] = typeof (FSpot.Imaging.Tiff.NefFile);
-			name_table [".arw"] = typeof (FSpot.Imaging.Tiff.NefFile);
-			name_table [".rw2"] = typeof (FSpot.Imaging.DCRawFile);
-			name_table [".tiff"] = typeof (BaseImageFile);
-			name_table [".tif"] = typeof (BaseImageFile);
-			name_table [".orf"] =  typeof (FSpot.Imaging.Tiff.NefFile);
-			name_table [".srf"] = typeof (FSpot.Imaging.Tiff.NefFile);
-			name_table [".dng"] = typeof (FSpot.Imaging.Tiff.DngFile);
-			name_table [".crw"] = typeof (FSpot.Imaging.Ciff.CiffFile);
-			name_table [".ppm"] = typeof (BaseImageFile);
-			name_table [".mrw"] = typeof (FSpot.Imaging.DCRawFile);
-			name_table [".raf"] = typeof (FSpot.Imaging.Raf.RafFile);
-			name_table [".x3f"] = typeof (FSpot.Imaging.DCRawFile);
-
-			// add mimetypes for fallback
-			name_table ["image/bmp"]     = name_table ["image/x-bmp"] = name_table [".bmp"];
-			name_table ["image/gif"]     = name_table [".gif"];
-			name_table ["image/pjpeg"]   = name_table ["image/jpeg"] = name_table ["image/jpg"] = name_table [".jpg"];
-			name_table ["image/x-png"]   = name_table ["image/png"]  = name_table [".png"];
-			name_table ["image/svg+xml"] = name_table [".svg"];
-			name_table ["image/tiff"]    = name_table [".tiff"];
-			name_table ["image/x-dcraw"] = name_table [".raw"];
-			name_table ["image/x-ciff"]  = name_table [".crw"];
-			name_table ["image/x-mrw"]   = name_table [".mrw"];
-			name_table ["image/x-x3f"]   = name_table [".x3f"];
-			name_table ["image/x-orf"]   = name_table [".orf"];
-			name_table ["image/x-nef"]   = name_table [".nef"];
-			name_table ["image/x-cr2"]   = name_table [".cr2"];
-			name_table ["image/x-raf"]   = name_table [".raf"];
-
-			//as xcf pixbufloader is not part of gdk-pixbuf, check if it's there,
-			//and enable it if needed.
-			foreach (Gdk.PixbufFormat format in Gdk.Pixbuf.Formats)
-				if (format.Name == "xcf") {
-					if (format.IsDisabled)
-						format.SetDisabled (false);
-					name_table [".xcf"] = typeof (ImageFile);
-				}
-		}
+        static ImageFile ()
+        {
+            var base_type = typeof (BaseImageFile);
+            var raw_type = typeof (DCRawFile);
+            var nef_type = typeof (FSpot.Imaging.Tiff.NefFile);
+
+            name_table = new Dictionary<string, Type> ();
+
+            // Plain image files
+            name_table ["image/gif"] = name_table [".gif"] = base_type;
+            name_table ["image/x-pcx"] = name_table [".pcx"] = base_type;
+            name_table ["image/x-portable-anymap"] = name_table [".pnm"] = base_type;
+            name_table ["image/x-portable-bitmap"] = name_table [".pbm"] = base_type;
+            name_table ["image/x-portable-graymap"] = name_table [".pgm"] = base_type;
+            name_table ["image/x-portable-pixmap"] = name_table [".ppm"] = base_type;
+            name_table ["image/x-bmp"] = name_table ["image/x-MS-bmp"] = name_table [".bmp"] = base_type;
+            name_table ["image/jpeg"] = name_table [".jfi"] = name_table [".jfif"] = name_table [".jif"] = name_table [".jpe"] = name_table [".jpeg"] = name_table [".jpg"] = base_type;
+            name_table ["image/png"] = name_table [".png"] = base_type;
+            name_table ["image/tiff"] = name_table [".tif"] = name_table [".tiff"] = base_type;
+
+            // RAW files
+            name_table ["image/arw"] = name_table ["image/x-sony-arw"] = name_table [".arw"] = nef_type;
+            name_table ["image/cr2"] = name_table ["image/x-canon-cr"] = name_table [".cr2"] = typeof (FSpot.Imaging.Tiff.Cr2File);
+            name_table ["image/dng"] = name_table ["image/x-adobe-dng"] = name_table [".dng"] = typeof (FSpot.Imaging.Tiff.DngFile);
+            name_table ["image/nef"] = name_table ["image/x-nikon-nef"] = name_table [".nef"] = nef_type;
+            name_table ["image/rw2"] = name_table ["image/x-raw"] = name_table [".rw2"] = raw_type;
+
+            // Other types (FIXME: Currently unsupported by Taglib#, this list should shrink).
+            name_table ["image/svg+xml"] = name_table [".svg"] = base_type;
+            name_table [".pef"] = nef_type;
+            name_table [".raw"] = typeof (FSpot.Imaging.Tiff.NefFile);
+            name_table [".kdc"] = typeof (FSpot.Imaging.Tiff.NefFile);
+            name_table [".rw2"] = typeof (FSpot.Imaging.DCRawFile);
+            name_table [".orf"] =  typeof (FSpot.Imaging.Tiff.NefFile);
+            name_table [".srf"] = typeof (FSpot.Imaging.Tiff.NefFile);
+            name_table [".crw"] = typeof (FSpot.Imaging.Ciff.CiffFile);
+            name_table [".mrw"] = typeof (FSpot.Imaging.DCRawFile);
+            name_table [".raf"] = typeof (FSpot.Imaging.Raf.RafFile);
+            name_table [".x3f"] = typeof (FSpot.Imaging.DCRawFile);
+            name_table ["image/x-dcraw"] = name_table [".raw"];
+            name_table ["image/x-ciff"]  = name_table [".crw"];
+            name_table ["image/x-mrw"]   = name_table [".mrw"];
+            name_table ["image/x-x3f"]   = name_table [".x3f"];
+            name_table ["image/x-orf"]   = name_table [".orf"];
+            name_table ["image/x-raf"]   = name_table [".raf"];
+
+            // as xcf pixbufloader is not part of gdk-pixbuf, check if it's there,
+            // and enable it if needed.
+            foreach (Gdk.PixbufFormat format in Gdk.Pixbuf.Formats)
+                if (format.Name == "xcf") {
+                    if (format.IsDisabled)
+                        format.SetDisabled (false);
+                    name_table [".xcf"] = base_type;
+                }
+        }
 
-		public static bool HasLoader (SafeUri uri)
-		{
-			return GetLoaderType (uri) != null;
-		}
+        public static bool HasLoader (SafeUri uri)
+        {
+            return GetLoaderType (uri) != null;
+        }
 
-		static Type GetLoaderType (SafeUri uri)
-		{
-			string extension = uri.GetExtension ().ToLower ();
-			if (extension == ".thm") {
-				// Ignore video thumbnails.
-				return null;
-			}
+        static Type GetLoaderType (SafeUri uri)
+        {
+            // check if GIO can find the file, which is not the case
+            // with filenames with invalid encoding
+            var file = GLib.FileFactory.NewForUri (uri);
+            if (!file.Exists) {
+                return null;
+            }
 
-			Type t = (Type) name_table [extension];
+            var extension = uri.GetExtension ().ToLower ();
+            if (extension == ".thm") {
+                // Ignore video thumbnails.
+                return null;
+            }
 
-			if (t == null) {
-				// check if GIO can find the file, which is not the case
-				// with filenames with invalid encoding
-				GLib.File f = GLib.FileFactory.NewForUri (uri);
-				if (f.QueryExists (null)) {
-					GLib.FileInfo info = f.QueryInfo ("standard::type,standard::content-type", GLib.FileQueryInfoFlags.None, null);
-					t = (Type) name_table [info.ContentType];
-				}
-			}
+            // Detect mime-type
+            var info = file.QueryInfo ("standard::content-type", FileQueryInfoFlags.None, null);
+            var mime = info.ContentType;
+
+            Type t = null;
+
+            if (name_table.TryGetValue (mime, out t)) {
+                return t;
+            } else if (name_table.TryGetValue (extension, out t)) {
+                return t;
+            }
+            return null;
+        }
 
-			return t;
-		}
-		
         public static IImageFile Create (SafeUri uri)
         {
             var t = GetLoaderType (uri);
@@ -160,11 +169,11 @@ namespace FSpot.Imaging {
 
     public interface IImageFile : IDisposable {
         SafeUri Uri { get; }
-		Gdk.Pixbuf Load ();
-		Cms.Profile GetProfile ();
-		Gdk.Pixbuf Load (int max_width, int max_height);
-		Stream PixbufStream ();
-		ImageOrientation Orientation { get; }
+        Gdk.Pixbuf Load ();
+        Cms.Profile GetProfile ();
+        Gdk.Pixbuf Load (int max_width, int max_height);
+        Stream PixbufStream ();
+        ImageOrientation Orientation { get; }
     }
 
     public class BaseImageFile : IImageFile {
@@ -192,7 +201,7 @@ namespace FSpot.Imaging {
 
 		public virtual Stream PixbufStream ()
 		{
-			Log.DebugFormat ("open uri = {0}", Uri.ToString ());
+			Hyena.Log.DebugFormat ("open uri = {0}", Uri.ToString ());
 			return new GLib.GioStream (GLib.FileFactory.NewForUri (Uri).Read (null));
 		}
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 0bab324..92568a8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -188,6 +188,7 @@ SOURCES = \
 	Widgets/ViewContext.cs \
 	Widgets/Wipe.cs \
 	main.cs \
+	Tests/ImageFileTests.cs \
 	Tests/UpdaterTests.cs
 
 
diff --git a/src/Tests/ImageFileTests.cs b/src/Tests/ImageFileTests.cs
new file mode 100644
index 0000000..cbc6fd8
--- /dev/null
+++ b/src/Tests/ImageFileTests.cs
@@ -0,0 +1,45 @@
+#if ENABLE_TESTS
+using NUnit.Framework;
+using System;
+using Hyena;
+using Banshee.Database;
+using FSpot.Imaging;
+
+namespace FSpot.Tests
+{
+    [TestFixture]
+    public class ImageFileTests
+    {
+        [SetUp]
+        public void Initialize () {
+            GLib.GType.Init ();
+        }
+
+        [Test]
+        public void CheckLoadableTypes ()
+        {
+            bool missing = false;
+
+            // Test that we have loaders defined for all Taglib# parseable types.
+            foreach (var key in TagLib.FileTypes.AvailableTypes.Keys) {
+                Type type = TagLib.FileTypes.AvailableTypes [key];
+                if (!type.IsSubclassOf (typeof (TagLib.Image.File))) {
+                    continue;
+                }
+
+                var test_key = key;
+                if (key.StartsWith ("taglib/")) {
+                    test_key = "." + key.Substring (7);
+                }
+
+                if (!ImageFile.NameTable.ContainsKey (test_key)) {
+                    Log.InformationFormat ("Missing key for {0}", test_key);
+                    missing = true;
+                }
+            }
+
+            Assert.IsFalse (missing, "No missing loaders for Taglib# parseable files.");
+        }
+    }
+}
+#endif
diff --git a/src/Utils/Metadata.cs b/src/Utils/Metadata.cs
index 2ab9471..882b818 100644
--- a/src/Utils/Metadata.cs
+++ b/src/Utils/Metadata.cs
@@ -1,24 +1,32 @@
 using Hyena;
 using TagLib;
 using System;
+using GLib;
 
 namespace FSpot.Utils
 {
     public static class Metadata
     {
         public static TagLib.Image.File Parse (SafeUri uri)
-		{
-			var res = new GIOTagLibFileAbstraction () { Uri = uri };
+        {
+            // Detect mime-type
+            var gfile = FileFactory.NewForUri (uri);
+            var info = gfile.QueryInfo ("standard::content-type", FileQueryInfoFlags.None, null);
+            var mime = info.ContentType;
+
+            // Parse file
+            var res = new GIOTagLibFileAbstraction () { Uri = uri };
             var sidecar_uri = uri.ReplaceExtension (".xmp");
             var sidecar_res = new GIOTagLibFileAbstraction () { Uri = sidecar_uri };
-            var file = File.Create (res) as TagLib.Image.File;
+            var file = TagLib.File.Create (res, mime, ReadStyle.Average) as TagLib.Image.File;
 
+            // Load XMP sidecar
             var sidecar_file = GLib.FileFactory.NewForUri (sidecar_uri);
-			if (sidecar_file.Exists) {
-				file.ParseXmpSidecar (sidecar_res);
-			}
+            if (sidecar_file.Exists) {
+                file.ParseXmpSidecar (sidecar_res);
+            }
 
-			return file;
-		}
-	}
+            return file;
+        }
+    }
 }



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