[f-spot/taglib-metadata: 8/20] Big leap closer to Taglib# usage.
- From: Ruben Vermeersch <rubenv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [f-spot/taglib-metadata: 8/20] Big leap closer to Taglib# usage.
- Date: Sat, 26 Jun 2010 19:36:45 +0000 (UTC)
commit fa35e1729f46d50e2478f5728288d9dd80a6ee4a
Author: Ruben Vermeersch <ruben savanne be>
Date: Sat Jun 12 17:50:43 2010 +0200
Big leap closer to Taglib# usage.
WARNING: this commit causes file corruption! See below!
Changes:
* Migrated from PixbufOrientation to TagLib.Image.ImageOrientation.
* Parse dates and descriptions directly using TagLib, instead of in
ImageFile.
* Move metadata writing mostly to TagLib.
* Added (non-working) unit test for GIOTagLibFileAbstraction.
There seems to be an interesting corruption happening when using the
GIOTagLibFileAbstraction. This does not occur when using normal IO. Am
puzzled, but I suspect it is something related to the read/write
behavior of GIO that trips this up.
Apparently GIO has atomic write support, which we should use. Needs
fixing.
src/Accelerometer.cs | 7 +-
src/FileBrowsableItem.cs | 23 ++--
src/Filters/OrientationFilter.cs | 15 ++-
src/Imaging/Ciff.cs | 19 ++--
src/Imaging/ImageFile.cs | 13 +-
src/Imaging/JpegFile.cs | 65 +--------
src/Imaging/PngFile.cs | 22 ---
src/Imaging/RafFile.cs | 11 +-
src/Imaging/Tiff.cs | 15 +--
src/Imaging/X3fFile.cs | 15 +-
src/Import/FileImportSource.cs | 17 ++-
src/Jobs/SyncMetadataJob.cs | 165 ++++++++++------------
src/Loaders/GdkImageLoader.cs | 7 +-
src/Loaders/IImageLoader.cs | 3 +-
src/MetadataStore.cs | 2 +-
src/PhotoImageView.cs | 6 +-
src/PixbufUtils.cs | 27 ++--
src/RotateCommand.cs | 82 +++++------
src/Tests/UpdaterTests.cs | 2 +
src/Utils/GIOTagLibFileAbstraction.cs | 25 +++-
src/Utils/Makefile.am | 2 +-
src/Utils/PixbufOrientation.cs | 37 -----
src/Utils/PixbufUtils.cs | 103 +++++++-------
src/Utils/Tests/GIOTagLibFileAbstractionTests.cs | 132 +++++++++++++++++
src/Widgets/ImageView.cs | 7 +-
tests/Makefile.am | 3 +-
tests/data/taglib-sample.jpg | Bin 0 -> 41921 bytes
27 files changed, 422 insertions(+), 403 deletions(-)
---
diff --git a/src/Accelerometer.cs b/src/Accelerometer.cs
index 3978f12..f7148ea 100644
--- a/src/Accelerometer.cs
+++ b/src/Accelerometer.cs
@@ -7,6 +7,7 @@ using System.IO;
using FSpot.Utils;
using Hyena;
+using TagLib.Image;
namespace FSpot {
@@ -33,7 +34,7 @@ namespace FSpot {
{
}
- public static PixbufOrientation GetViewOrientation (PixbufOrientation po)
+ public static ImageOrientation GetViewOrientation (ImageOrientation po)
{
if (timer == 0 && available)
SetupAccelerometer ();
@@ -52,7 +53,7 @@ namespace FSpot {
public static void SetupAccelerometer ()
{
- if (!File.Exists(SYSFS_FILE)) {
+ if (!System.IO.File.Exists (SYSFS_FILE)) {
available = false;
return;
}
@@ -105,7 +106,7 @@ namespace FSpot {
private static void GetHDAPSCoords (out int x, out int y)
{
try {
- using (Stream file = File.OpenRead (SYSFS_FILE)) {
+ using (Stream file = System.IO.File.OpenRead (SYSFS_FILE)) {
StreamReader sr = new StreamReader (file);
string s = sr.ReadLine ();
diff --git a/src/FileBrowsableItem.cs b/src/FileBrowsableItem.cs
index be92366..37066f7 100644
--- a/src/FileBrowsableItem.cs
+++ b/src/FileBrowsableItem.cs
@@ -35,11 +35,12 @@ namespace FSpot {
if (metadata_parsed)
return;
- var res = new GIOTagLibFileAbstraction () { Uri = DefaultVersion.Uri };
- var metadata_file = TagLib.File.Create (res) as TagLib.Image.File;
- var date = metadata_file.ImageTag.DateTime;
- time = date.HasValue ? date.Value : CreateDate;
- description = metadata_file.ImageTag.Comment;
+ var res = new GIOTagLibFileAbstraction () { Uri = DefaultVersion.Uri };
+ using (var metadata = TagLib.File.Create (res) as TagLib.Image.File) {
+ var date = metadata.ImageTag.DateTime;
+ time = date.HasValue ? date.Value : CreateDate;
+ description = metadata.ImageTag.Comment;
+ }
metadata_parsed = true;
}
@@ -50,13 +51,13 @@ namespace FSpot {
}
}
- private DateTime time;
- public DateTime Time {
- get {
+ private DateTime time;
+ public System.DateTime Time {
+ get {
EnsureMetadataParsed ();
- return time;
- }
- }
+ return time;
+ }
+ }
private DateTime CreateDate {
get {
diff --git a/src/Filters/OrientationFilter.cs b/src/Filters/OrientationFilter.cs
index fef3886..12f3fca 100644
--- a/src/Filters/OrientationFilter.cs
+++ b/src/Filters/OrientationFilter.cs
@@ -18,9 +18,11 @@ namespace FSpot.Filters {
string source = req.Current.LocalPath;
var dest_uri = req.TempUri (System.IO.Path.GetExtension (source));
string dest = dest_uri.LocalPath;
+ bool changed = false;
+ // FIXME: needs to be re-added https://bugzilla.gnome.org/show_bug.cgi?id=621369
+ /*
using (ImageFile img = ImageFile.Create (req.Current)) {
- bool changed = false;
if (img.Orientation != PixbufOrientation.TopLeft && img is JpegFile) {
JpegFile jimg = img as JpegFile;
@@ -58,12 +60,13 @@ namespace FSpot.Filters {
jimg.Dispose ();
}
}
-
- if (changed)
- req.Current = dest_uri;
-
- return changed;
}
+ */
+
+ if (changed)
+ req.Current = dest_uri;
+
+ return changed;
}
}
diff --git a/src/Imaging/Ciff.cs b/src/Imaging/Ciff.cs
index 97994ba..b44e548 100644
--- a/src/Imaging/Ciff.cs
+++ b/src/Imaging/Ciff.cs
@@ -1,6 +1,7 @@
using System;
using FSpot.Utils;
using Hyena;
+using TagLib.Image;
namespace FSpot.Ciff {
public enum Tag {
@@ -89,7 +90,7 @@ namespace FSpot.Ciff {
- public struct ImageSpec {
+ internal struct ImageSpec {
public uint ImageWidth; // Number of horizontal pixels
public uint ImageHeight; // Number of vertical pixels
public float PixelAspectRatio;
@@ -111,19 +112,19 @@ namespace FSpot.Ciff {
Log.DebugFormat ("0x{0}", ColorBW.ToString ("x"));
}
- public PixbufOrientation Orientation {
+ public ImageOrientation Orientation {
get {
int angle = RotationAngle % 360;
if (angle < 45)
- return PixbufOrientation.TopLeft;
+ return ImageOrientation.TopLeft;
else if (angle < 135)
- return PixbufOrientation.RightTop;
+ return ImageOrientation.RightTop;
else if (angle < 225)
- return PixbufOrientation.BottomRight;
+ return ImageOrientation.BottomRight;
else if (angle < 315)
- return PixbufOrientation.LeftBottom;
+ return ImageOrientation.LeftBottom;
else
- return PixbufOrientation.TopLeft;
+ return ImageOrientation.TopLeft;
}
}
@@ -418,9 +419,9 @@ namespace FSpot.Ciff {
get { return version; }
}
- public override PixbufOrientation GetOrientation ()
+ public override ImageOrientation GetOrientation ()
{
- PixbufOrientation orientation = PixbufOrientation.TopLeft;
+ var orientation = ImageOrientation.TopLeft;
ImageDirectory props = Root.ReadDirectory (Tag.ImageProps);
byte [] data = props.ReadEntry (Tag.ImageSpec);
diff --git a/src/Imaging/ImageFile.cs b/src/Imaging/ImageFile.cs
index 1e8ee4d..0ef7ebc 100644
--- a/src/Imaging/ImageFile.cs
+++ b/src/Imaging/ImageFile.cs
@@ -9,6 +9,8 @@ using Mono.Unix;
using Mono.Unix.Native;
using Gdk;
+using TagLib.Image;
+
using GFileInfo = GLib.FileInfo;
namespace FSpot {
@@ -105,15 +107,10 @@ namespace FSpot {
get { return this.uri; }
}
- public PixbufOrientation Orientation {
+ public ImageOrientation Orientation {
get { return GetOrientation (); }
}
- public virtual string Description
- {
- get { return null; }
- }
-
public virtual void Save (Gdk.Pixbuf pixbuf, System.IO.Stream stream)
{
throw new NotImplementedException (Catalog.GetString ("Writing to this file format is not supported"));
@@ -155,9 +152,9 @@ namespace FSpot {
}
}
- public virtual PixbufOrientation GetOrientation ()
+ public virtual ImageOrientation GetOrientation ()
{
- return PixbufOrientation.TopLeft;
+ return ImageOrientation.TopLeft;
}
// FIXME this need to have an intent just like the loading stuff.
diff --git a/src/Imaging/JpegFile.cs b/src/Imaging/JpegFile.cs
index 5a7d8e6..c2ffb80 100644
--- a/src/Imaging/JpegFile.cs
+++ b/src/Imaging/JpegFile.cs
@@ -5,6 +5,7 @@ using FSpot.Tiff;
using FSpot.Utils;
using Hyena;
using TagLib;
+using TagLib.Image;
namespace FSpot {
public interface IThumbnailContainer {
@@ -32,62 +33,6 @@ namespace FSpot {
return null;
}
- public override string Description {
- get {
- return metadata_file.ImageTag.Comment;
- }
- }
-
- public void SetDescription (string value)
- {
- metadata_file.GetTag (TagTypes.XMP, true); // Ensure XMP tag
- metadata_file.ImageTag.Comment = value;
- }
-
- private void UpdateMeta ()
- {
- 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)
- {
- JpegHeader header = new JpegHeader (input);
- UpdateMeta ();
-
- // Console.WriteLine ("updated metadata");
- header.SetExif (this.ExifData);
- // Console.WriteLine ("set exif");
- if (xmp != null)
- header.SetXmp (xmp);
- // Console.WriteLine ("set xmp");
- header.Save (output);
- // Console.WriteLine ("saved");
- }*/
-
- public void SaveMetaData (string path)
- {
- // 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
-
- var uri = new SafeUri (path);
- var tmp = System.IO.Path.GetTempFileName ();
- var tmp_uri = new SafeUri (tmp);
-
- var orig_file = GLib.FileFactory.NewForUri (uri);
- var tmp_file = GLib.FileFactory.NewForUri (tmp_uri);
-
- orig_file.Copy (tmp_file, GLib.FileCopyFlags.AllMetadata, null, null);
-
- 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
@@ -167,15 +112,15 @@ namespace FSpot {
return null;
}
- public override PixbufOrientation GetOrientation ()
+ public override ImageOrientation GetOrientation ()
{
var orientation = metadata_file.ImageTag.Orientation;
- return (PixbufOrientation) orientation;
+ return orientation;
}
- public void SetOrientation (PixbufOrientation orientation)
+ public void SetOrientation (ImageOrientation orientation)
{
- metadata_file.ImageTag.Orientation = (TagLib.Image.ImageOrientation) orientation;
+ metadata_file.ImageTag.Orientation = orientation;
}
public void SetDateTimeOriginal (DateTime time)
diff --git a/src/Imaging/PngFile.cs b/src/Imaging/PngFile.cs
index be87c09..ea07d9d 100644
--- a/src/Imaging/PngFile.cs
+++ b/src/Imaging/PngFile.cs
@@ -1320,28 +1320,6 @@ namespace FSpot.Png {
return null;
}
- public override string Description {
- get {
- string description = Header.LookupText ("Description");
-
- if (description != null)
- return description;
- else
- return Header.LookupText ("Comment");
- }
- }
-
- public void SetDescription (string description)
- {
- TextChunk text = null;
- text = Header.LookupTextChunk ("Description");
-
- if (text != null)
- text.SetText (description);
- else
- Header.Insert (new TextChunk ("Description", description));
- }
-
public XmpFile GetXmp ()
{
TextChunk xmpchunk = Header.LookupTextChunk ("XML:com.adobe.xmp");
diff --git a/src/Imaging/RafFile.cs b/src/Imaging/RafFile.cs
index cff1128..826e6e3 100644
--- a/src/Imaging/RafFile.cs
+++ b/src/Imaging/RafFile.cs
@@ -1,5 +1,6 @@
using FSpot.Utils;
using Hyena;
+using TagLib.Image;
namespace FSpot.Raf {
// This is reverse engineered from looking at the sample files I have
@@ -34,17 +35,17 @@ namespace FSpot.Raf {
}
}
- public override PixbufOrientation GetOrientation (){
- PixbufOrientation orientation = PixbufOrientation.TopLeft;
+ public override ImageOrientation GetOrientation (){
+ var orientation = ImageOrientation.TopLeft;
Exif.ExifEntry e = this.ExifData.GetContents (Exif.Ifd.Zero).Lookup (Exif.Tag.Orientation);
if (e != null) {
ushort [] value = e.GetDataUShort ();
- orientation = (PixbufOrientation) value [0];
+ orientation = (ImageOrientation) value [0];
}
- if (orientation < PixbufOrientation.TopLeft || orientation > PixbufOrientation.LeftBottom)
- orientation = PixbufOrientation.TopLeft;
+ if (orientation < ImageOrientation.TopLeft || orientation > ImageOrientation.LeftBottom)
+ orientation = ImageOrientation.TopLeft;
return orientation;
}
diff --git a/src/Imaging/Tiff.cs b/src/Imaging/Tiff.cs
index e7df951..75816c8 100644
--- a/src/Imaging/Tiff.cs
+++ b/src/Imaging/Tiff.cs
@@ -6,6 +6,7 @@ using System;
using System.IO;
using System.Collections.Generic;
using Hyena;
+using TagLib.Image;
namespace FSpot.Tiff {
@@ -2035,13 +2036,13 @@ namespace FSpot.Tiff {
Header.SelectDirectory (Header.Directory, sink);
}
- public override PixbufOrientation GetOrientation ()
+ public override ImageOrientation GetOrientation ()
{
ShortEntry e = (ShortEntry)(this.Header.Directory.Lookup (TagId.Orientation));
if (e != null)
- return (PixbufOrientation)(e.ShortValue[0]);
+ return (ImageOrientation)(e.ShortValue[0]);
else
- return PixbufOrientation.TopLeft;
+ return ImageOrientation.TopLeft;
}
public System.IO.Stream LookupJpegSubstream (ImageDirectory directory)
@@ -2226,13 +2227,6 @@ namespace FSpot.Tiff {
{
}
- /*
- public override PixbufOrientation GetOrientation ()
- {
- return PixbufOrientation.TopLeft;
- }
- */
-
public Gdk.Pixbuf GetEmbeddedThumbnail ()
{
ImageDirectory directory;
@@ -2240,7 +2234,6 @@ namespace FSpot.Tiff {
return TransformAndDispose (LoadJpegInterchangeFormat (directory));
}
-
public override System.IO.Stream PixbufStream ()
{
uint offset = Header.Directory.Lookup (TagId.StripOffsets).ValueAsLong [0];
diff --git a/src/Imaging/X3fFile.cs b/src/Imaging/X3fFile.cs
index 233b3a9..486d704 100644
--- a/src/Imaging/X3fFile.cs
+++ b/src/Imaging/X3fFile.cs
@@ -4,6 +4,7 @@ using FSpot;
using FSpot.Utils;
using SemWeb;
using Hyena;
+using TagLib.Image;
namespace FSpot.X3f {
internal class Info {
@@ -15,19 +16,19 @@ namespace FSpot.X3f {
uint rows;
uint rotation;
- public PixbufOrientation Orientation {
+ public ImageOrientation Orientation {
get {
switch (rotation) {
case 0:
- return PixbufOrientation.TopLeft;
+ return ImageOrientation.TopLeft;
case 270:
- return PixbufOrientation.LeftBottom;
+ return ImageOrientation.LeftBottom;
case 180:
- return PixbufOrientation.BottomRight;
+ return ImageOrientation.BottomRight;
case 90:
- return PixbufOrientation.RightTop;
+ return ImageOrientation.RightTop;
default:
- return PixbufOrientation.TopLeft;
+ return ImageOrientation.TopLeft;
}
}
}
@@ -101,7 +102,7 @@ namespace FSpot.X3f {
MetadataStore.AddLiteral (sink, "tiff:ImageLength", Info.Height.ToString ());
}
- public override PixbufOrientation GetOrientation ()
+ public override ImageOrientation GetOrientation ()
{
return Info.Orientation;
}
diff --git a/src/Import/FileImportSource.cs b/src/Import/FileImportSource.cs
index 2bc051d..76a66e8 100644
--- a/src/Import/FileImportSource.cs
+++ b/src/Import/FileImportSource.cs
@@ -155,11 +155,12 @@ namespace FSpot.Import
if (metadata_parsed)
return;
- var res = new GIOTagLibFileAbstraction () { Uri = DefaultVersion.Uri };
- var metadata_file = TagLib.File.Create (res) as TagLib.Image.File;
- var date = metadata_file.ImageTag.DateTime;
- time = date.HasValue ? date.Value : CreateDate;
- description = metadata_file.ImageTag.Comment;
+ var res = new GIOTagLibFileAbstraction () { Uri = DefaultVersion.Uri };
+ using (var metadata = TagLib.File.Create (res) as TagLib.Image.File) {
+ var date = metadata.ImageTag.DateTime;
+ time = date.HasValue ? date.Value : CreateDate;
+ description = metadata.ImageTag.Comment;
+ }
metadata_parsed = true;
}
@@ -169,10 +170,10 @@ namespace FSpot.Import
private DateTime time;
public System.DateTime Time {
- get {
+ get {
EnsureMetadataParsed ();
- return time;
- }
+ return time;
+ }
}
private string description;
diff --git a/src/Jobs/SyncMetadataJob.cs b/src/Jobs/SyncMetadataJob.cs
index ab0b379..04d1463 100644
--- a/src/Jobs/SyncMetadataJob.cs
+++ b/src/Jobs/SyncMetadataJob.cs
@@ -13,99 +13,86 @@ using FSpot.Utils;
using Hyena;
namespace FSpot.Jobs {
- public class SyncMetadataJob : Job
- {
- public SyncMetadataJob (uint id, string job_options, int run_at, JobPriority job_priority, bool persistent) : this (id, job_options, DbUtils.DateTimeFromUnixTime (run_at), job_priority, persistent)
- {
- }
-
- public SyncMetadataJob (uint id, string job_options, DateTime run_at, JobPriority job_priority, bool persistent) : base (id, job_options, job_priority, run_at, persistent)
- {
- }
-
- //Use THIS static method to create a job...
- public static SyncMetadataJob Create (JobStore job_store, Photo photo)
- {
- return (SyncMetadataJob) job_store.CreatePersistent (typeof (FSpot.Jobs.SyncMetadataJob), photo.Id.ToString ());
- }
-
- protected override bool Execute ()
- {
- //this will add some more reactivity to the system
- System.Threading.Thread.Sleep (500);
- Log.Debug ("Syncing metadata to file...");
- try {
- Photo photo = FSpot.App.Instance.Database.Photos.Get (Convert.ToUInt32 (JobOptions)) as Photo;
- WriteMetadataToImage (photo);
- return true;
- } catch (System.Exception e) {
- Log.ErrorFormat ("Error syncing metadata to file\n{0}", e);
- }
- return false;
- }
-
- //FIXME: Won't work on non-file uris
- void WriteMetadataToImage (Photo photo)
- {
- string path = photo.DefaultVersion.Uri.LocalPath;
+ public class SyncMetadataJob : Job
+ {
+ public SyncMetadataJob (uint id, string job_options, int run_at, JobPriority job_priority, bool persistent) : this (id, job_options, DbUtils.DateTimeFromUnixTime (run_at), job_priority, persistent)
+ {
+ }
+
+ public SyncMetadataJob (uint id, string job_options, DateTime run_at, JobPriority job_priority, bool persistent) : base (id, job_options, job_priority, run_at, persistent)
+ {
+ }
+
+ //Use THIS static method to create a job...
+ public static SyncMetadataJob Create (JobStore job_store, Photo photo)
+ {
+ return (SyncMetadataJob) job_store.CreatePersistent (typeof (FSpot.Jobs.SyncMetadataJob), photo.Id.ToString ());
+ }
+
+ protected override bool Execute ()
+ {
+ //this will add some more reactivity to the system
+ System.Threading.Thread.Sleep (500);
+ Log.Debug ("Syncing metadata to file...");
+ try {
+ Photo photo = FSpot.App.Instance.Database.Photos.Get (Convert.ToUInt32 (JobOptions)) as Photo;
+ WriteMetadataToImage (photo);
+ return true;
+ } catch (System.Exception e) {
+ Log.ErrorFormat ("Error syncing metadata to file\n{0}", e);
+ }
+ return false;
+ }
+
+ public void SaveMetaData (TagLib.File image, string path)
+ {
+ // 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
+
+ var uri = new SafeUri (path);
+ var tmp = System.IO.Path.GetTempFileName ();
+ var tmp_uri = new SafeUri (tmp);
+
+ var orig_file = GLib.FileFactory.NewForUri (uri);
+ var tmp_file = GLib.FileFactory.NewForUri (tmp_uri);
+
+ tmp_file.Delete ();
+ orig_file.Copy (tmp_file, GLib.FileCopyFlags.AllMetadata | GLib.FileCopyFlags.Overwrite, null, null);
+
+ try {
+ image.Save ();
+ } catch (Exception e) {
+ Log.DebugException (e);
+ tmp_file.Copy (orig_file, GLib.FileCopyFlags.AllMetadata | GLib.FileCopyFlags.Overwrite, null, null);
+ }
+ }
+
+ 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) {
- FSpot.JpegFile jimg = img as FSpot.JpegFile;
-
- jimg.SetDescription (photo.Description);
- jimg.SetDateTimeOriginal (photo.Time);
-
- 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) {
- FSpot.Png.PngFile png = img as FSpot.Png.PngFile;
-
- if (img.Description != photo.Description)
- png.SetDescription (photo.Description);
-
- png.SetXmp (UpdateXmp (photo, png.GetXmp ()));
-
- png.Save (path);
- }
- }
- }
-
- private static FSpot.Xmp.XmpFile UpdateXmp (FSpot.IBrowsableItem item, FSpot.Xmp.XmpFile xmp)
- {
- if (xmp == null)
- xmp = new FSpot.Xmp.XmpFile ();
-
- Tag [] tags = item.Tags;
- string [] names = new string [tags.Length];
-
- for (int i = 0; i < tags.Length; i++)
- names [i] = tags [i].Name;
-
- xmp.Store.Update ("dc:subject", "rdf:Bag", names);
- if ((item as Photo).Rating > 0) {
- xmp.Store.Update ("xmp:Rating", (item as Photo).Rating.ToString());
- // FIXME - Should we also store/overwrite the Urgency field?
- // uint urgency_value = (item as Photo).Rating + 1; // Urgency valid values 1 - 8
- // xmp.Store.Update ("photoshop:Urgency", urgency_value.ToString());
- } else {
- xmp.Store.Delete ("xmp:Rating");
- }
- xmp.Dump ();
-
- return xmp;
- }
- }
+
+ //var res = new GIOTagLibFileAbstraction () { Uri = photo.DefaultVersion.Uri };
+ var res = photo.DefaultVersion.Uri.AbsolutePath;
+ using (var metadata = TagLib.File.Create (res) as TagLib.Image.File) {
+ metadata.GetTag (TagLib.TagTypes.XMP, true);
+
+ var tag = metadata.ImageTag;
+ tag.DateTime = photo.Time;
+ tag.Comment = photo.Description;
+ tag.Keywords = names;
+ tag.Rating = photo.Rating;
+ tag.Software = FSpot.Defines.PACKAGE + " version " + FSpot.Defines.VERSION;
+
+ SaveMetaData (metadata, path);
+ }
+ }
+ }
}
diff --git a/src/Loaders/GdkImageLoader.cs b/src/Loaders/GdkImageLoader.cs
index 930f6ed..e88f7bf 100644
--- a/src/Loaders/GdkImageLoader.cs
+++ b/src/Loaders/GdkImageLoader.cs
@@ -15,6 +15,7 @@ using Gdk;
using FSpot.Utils;
using FSpot.Platform;
using Hyena;
+using TagLib.Image;
namespace FSpot.Loaders {
public class GdkImageLoader : Gdk.PixbufLoader, IImageLoader
@@ -37,7 +38,7 @@ namespace FSpot.Loaders {
//First, send a thumbnail if we have one
if ((thumb = XdgThumbnailSpec.LoadThumbnail (uri, ThumbnailSize.Large, null)) != null) {
- pixbuf_orientation = PixbufOrientation.TopLeft;
+ pixbuf_orientation = ImageOrientation.TopLeft;
EventHandler<AreaPreparedEventArgs> prep = AreaPrepared;
if (prep != null)
prep (this, new AreaPreparedEventArgs (true));
@@ -84,8 +85,8 @@ namespace FSpot.Loaders {
get { return prepared; }
}
- PixbufOrientation pixbuf_orientation = PixbufOrientation.TopLeft;
- public PixbufOrientation PixbufOrientation {
+ ImageOrientation pixbuf_orientation = ImageOrientation.TopLeft;
+ public ImageOrientation PixbufOrientation {
get { return pixbuf_orientation; }
}
diff --git a/src/Loaders/IImageLoader.cs b/src/Loaders/IImageLoader.cs
index 3934547..19b2d73 100644
--- a/src/Loaders/IImageLoader.cs
+++ b/src/Loaders/IImageLoader.cs
@@ -13,6 +13,7 @@ using FSpot.Utils;
using System;
using Gdk;
using Hyena;
+using TagLib.Image;
namespace FSpot.Loaders {
public interface IImageLoader : IDisposable {
@@ -25,6 +26,6 @@ namespace FSpot.Loaders {
void Load (SafeUri uri);
Pixbuf Pixbuf { get; }
- PixbufOrientation PixbufOrientation { get; }
+ ImageOrientation PixbufOrientation { get; }
}
}
diff --git a/src/MetadataStore.cs b/src/MetadataStore.cs
index 8b646f0..3a65705 100644
--- a/src/MetadataStore.cs
+++ b/src/MetadataStore.cs
@@ -29,7 +29,7 @@ namespace FSpot {
new Description ("tiff:PlanarConfiguration", Catalog.GetString ("Planar Configuration"),
typeof (FSpot.Tiff.PlanarConfiguration)),
new Description ("tiff:Orientation", Catalog.GetString ("Orientation"),
- typeof (PixbufOrientation)),
+ typeof (TagLib.Image.ImageOrientation)),
new Description ("tiff:PhotometricInterpretation", Catalog.GetString ("Photometric Interpretation"),
typeof (FSpot.Tiff.PhotometricInterpretation)),
new Description ("tiff:ResolutionUnit", Catalog.GetString ("Resolution Unit"),
diff --git a/src/PhotoImageView.cs b/src/PhotoImageView.cs
index 465420c..e2aa723 100644
--- a/src/PhotoImageView.cs
+++ b/src/PhotoImageView.cs
@@ -18,6 +18,8 @@ using FSpot.Loaders;
using Hyena;
using Gdk;
+using TagLib.Image;
+
namespace FSpot.Widgets {
public class PhotoImageView : ImageView {
#region public API
@@ -241,7 +243,7 @@ namespace FSpot.Widgets {
if (loader.Pixbuf != null) //FIXME: this test in case the photo was loaded with the direct loader
PixbufOrientation = Accelerometer.GetViewOrientation (loader.PixbufOrientation);
else
- PixbufOrientation = PixbufOrientation.TopLeft;
+ PixbufOrientation = ImageOrientation.TopLeft;
if (Pixbuf == null)
LoadErrorImage (null);
@@ -281,7 +283,7 @@ namespace FSpot.Widgets {
if (old != null)
old.Dispose ();
- PixbufOrientation = PixbufOrientation.TopLeft;
+ PixbufOrientation = ImageOrientation.TopLeft;
ZoomFit (false);
}
diff --git a/src/PixbufUtils.cs b/src/PixbufUtils.cs
index 1bd2a26..2ab1044 100644
--- a/src/PixbufUtils.cs
+++ b/src/PixbufUtils.cs
@@ -17,6 +17,7 @@ using System.IO;
using FSpot;
using FSpot.Utils;
using Hyena;
+using TagLib.Image;
public class PixbufUtils {
static Pixbuf error_pixbuf = null;
@@ -76,7 +77,7 @@ public class PixbufUtils {
Gdk.PixbufLoader loader = new Gdk.PixbufLoader ();
int max_width;
int max_height;
- PixbufOrientation orientation;
+ ImageOrientation orientation;
public AspectLoader (int max_width, int max_height)
{
@@ -88,10 +89,10 @@ public class PixbufUtils {
private void HandleSizePrepared (object obj, SizePreparedArgs args)
{
switch (orientation) {
- case PixbufOrientation.LeftTop:
- case PixbufOrientation.LeftBottom:
- case PixbufOrientation.RightTop:
- case PixbufOrientation.RightBottom:
+ case ImageOrientation.LeftTop:
+ case ImageOrientation.LeftBottom:
+ case ImageOrientation.RightTop:
+ case ImageOrientation.RightBottom:
int tmp = max_width;
max_width = max_height;
max_height = tmp;
@@ -109,7 +110,7 @@ public class PixbufUtils {
loader.SetSize (scale_width, scale_height);
}
- public Pixbuf Load (System.IO.Stream stream, PixbufOrientation orientation)
+ public Pixbuf Load (System.IO.Stream stream, ImageOrientation orientation)
{
int count;
byte [] data = new byte [8192];
@@ -131,7 +132,7 @@ public class PixbufUtils {
{
try {
orientation = GetOrientation (path);
- using (FileStream fs = File.OpenRead (path)) {
+ using (FileStream fs = System.IO.File.OpenRead (path)) {
return Load (fs, orientation);
}
} catch (Exception) {
@@ -642,7 +643,7 @@ public class PixbufUtils {
{
byte [] thumb_data = data.Data;
if (thumb_data.Length > 0) {
- PixbufOrientation orientation = GetOrientation (data);
+ ImageOrientation orientation = GetOrientation (data);
using (MemoryStream mem = new MemoryStream (thumb_data)) {
Gdk.Pixbuf thumb = new Gdk.Pixbuf (mem);
@@ -657,21 +658,21 @@ public class PixbufUtils {
return null;
}
- public static PixbufOrientation GetOrientation (Exif.ExifData data)
+ public static ImageOrientation GetOrientation (Exif.ExifData data)
{
- PixbufOrientation orientation = PixbufOrientation.TopLeft;
+ ImageOrientation orientation = ImageOrientation.TopLeft;
Exif.ExifEntry e = data.GetContents (Exif.Ifd.Zero).Lookup (Exif.Tag.Orientation);
if (e != null) {
ushort [] value = e.GetDataUShort ();
- orientation = (PixbufOrientation) value [0];
+ orientation = (ImageOrientation) value [0];
}
return orientation;
}
- public static PixbufOrientation GetOrientation (SafeUri uri)
+ public static ImageOrientation GetOrientation (SafeUri uri)
{
using (FSpot.ImageFile img = FSpot.ImageFile.Create (uri)) {
return img.Orientation;
@@ -679,7 +680,7 @@ public class PixbufUtils {
}
[Obsolete ("Use GetOrientation (SafeUri) instead")]
- public static PixbufOrientation GetOrientation (string path)
+ public static ImageOrientation GetOrientation (string path)
{
return GetOrientation (new SafeUri (path));
}
diff --git a/src/RotateCommand.cs b/src/RotateCommand.cs
index c890ff0..74b1e49 100644
--- a/src/RotateCommand.cs
+++ b/src/RotateCommand.cs
@@ -60,50 +60,46 @@ namespace FSpot {
private static void RotateOrientation (string original_path, RotateDirection direction)
{
- using (FSpot.ImageFile img = FSpot.ImageFile.Create (new SafeUri (original_path))) {
- if (img is JpegFile) {
- FSpot.JpegFile jimg = img as FSpot.JpegFile;
- PixbufOrientation orientation = direction == RotateDirection.Clockwise
- ? FSpot.Utils.PixbufUtils.Rotate90 (img.Orientation)
- : FSpot.Utils.PixbufUtils.Rotate270 (img.Orientation);
-
- jimg.SetOrientation (orientation);
- jimg.SaveMetaData (original_path);
- } else if (img is PngFile) {
- PngFile png = img as PngFile;
- bool supported = false;
-
- //FIXME there isn't much png specific here except the check
- //the pixbuf is an accurate representation of the real file
- //by checking the depth. The check should be abstracted and
- //this code made generic.
- foreach (PngFile.Chunk c in png.Chunks) {
- PngFile.IhdrChunk ihdr = c as PngFile.IhdrChunk;
-
- if (ihdr != null && ihdr.Depth == 8)
- supported = true;
- }
-
- if (!supported) {
- throw new RotateException (Catalog.GetString ("Unable to rotate this type of photo"), original_path);
- }
-
- string backup = ImageFile.TempPath (original_path);
- using (Stream stream = File.Open (backup, FileMode.Truncate, FileAccess.Write)) {
- using (Pixbuf pixbuf = img.Load ()) {
- PixbufOrientation fake = (direction == RotateDirection.Clockwise) ? PixbufOrientation.RightTop : PixbufOrientation.LeftBottom;
- using (Pixbuf rotated = FSpot.Utils.PixbufUtils.TransformOrientation (pixbuf, fake)) {
- img.Save (rotated, stream);
- }
- }
- }
- File.Copy (backup, original_path, true);
- File.Delete (backup);
- } else {
- throw new RotateException (Catalog.GetString ("Unable to rotate this type of photo"), original_path);
- }
- }
+ try {
+ var res = new GIOTagLibFileAbstraction () { Uri = new SafeUri (original_path) };
+ using (var metadata = TagLib.File.Create (res) as TagLib.Image.File) {
+ var tag = metadata.ImageTag;
+ var orientation = direction == RotateDirection.Clockwise
+ ? FSpot.Utils.PixbufUtils.Rotate90 (tag.Orientation)
+ : FSpot.Utils.PixbufUtils.Rotate270 (tag.Orientation);
+
+ tag.Orientation = orientation;
+ SaveMetaData (metadata, original_path);
+ }
+ } catch (Exception e) {
+ throw new RotateException (Catalog.GetString ("Unable to rotate this type of photo"), original_path);
+ }
}
+
+ private static void SaveMetaData (TagLib.File image, string path)
+ {
+ // 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
+
+ var uri = new SafeUri (path);
+ var tmp = System.IO.Path.GetTempFileName ();
+ var tmp_uri = new SafeUri (tmp);
+
+ var orig_file = GLib.FileFactory.NewForUri (uri);
+ var tmp_file = GLib.FileFactory.NewForUri (tmp_uri);
+
+ tmp_file.Delete ();
+ orig_file.Copy (tmp_file, GLib.FileCopyFlags.AllMetadata | GLib.FileCopyFlags.Overwrite, null, null);
+
+ try {
+ image.Save ();
+ } catch (Exception e) {
+ tmp_file.Copy (orig_file, GLib.FileCopyFlags.AllMetadata | GLib.FileCopyFlags.Overwrite, null, null);
+ throw e;
+ }
+ }
private void Rotate (string original_path, RotateDirection dir)
{
diff --git a/src/Tests/UpdaterTests.cs b/src/Tests/UpdaterTests.cs
index 193eb56..a5529b7 100644
--- a/src/Tests/UpdaterTests.cs
+++ b/src/Tests/UpdaterTests.cs
@@ -67,6 +67,8 @@ namespace FSpot.Tests
CheckPhotosTable (db);
CheckPhotoVersionsTable (db);
CheckTagsTable (db);
+
+ file2.Delete ();
}
private void ValidateRevision (QueuedSqliteDatabase db, string revision)
diff --git a/src/Utils/GIOTagLibFileAbstraction.cs b/src/Utils/GIOTagLibFileAbstraction.cs
index 7d79b6d..1f559a5 100644
--- a/src/Utils/GIOTagLibFileAbstraction.cs
+++ b/src/Utils/GIOTagLibFileAbstraction.cs
@@ -7,7 +7,7 @@ namespace FSpot.Utils
{
public sealed class GIOTagLibFileAbstraction : TagLib.File.IFileAbstraction
{
- private FileInputStream gio_stream;
+ private GioStream stream;
public string Name {
get {
@@ -22,23 +22,32 @@ namespace FSpot.Utils
public Stream ReadStream {
get {
- if (gio_stream == null) {
- var file = FileFactory.NewForUri(Uri);
- gio_stream = file.Read (null);
+ if (stream == null) {
+ var file = FileFactory.NewForUri (Uri);
+ stream = new GioStream (file.Read (null));
}
- return new GioStream (gio_stream);
+ return stream;
}
}
public Stream WriteStream {
- get { throw new NotImplementedException (); }
+ get {
+ if (stream == null) {
+ var file = FileFactory.NewForUri (Uri);
+ stream = new GioStream (file.ReplaceReadwrite (null, true, FileCreateFlags.None, null));
+ }
+ if (!stream.CanWrite) {
+ throw new Exception ("Stream still open in reading mode!");
+ }
+ return stream;
+ }
}
public void CloseStream (Stream stream)
{
stream.Close ();
- gio_stream.Dispose ();
- gio_stream = null;
+ if (stream == this.stream)
+ this.stream = null;
}
}
}
diff --git a/src/Utils/Makefile.am b/src/Utils/Makefile.am
index facebf4..e8af1a6 100644
--- a/src/Utils/Makefile.am
+++ b/src/Utils/Makefile.am
@@ -11,7 +11,6 @@ SOURCES = \
GdkUtils.cs \
GIOTagLibFileAbstraction.cs \
GtkUtil.cs \
- PixbufOrientation.cs \
PixbufUtils.cs \
RecursiveFileEnumerator.cs \
SafeUri.cs \
@@ -20,6 +19,7 @@ SOURCES = \
UriExtensions.cs \
UriUtils.cs \
XdgThumbnailSpec.cs \
+ Tests/GIOTagLibFileAbstractionTests.cs \
Tests/SafeUriTests.cs \
Tests/XdgThumbnailSpecTests.cs
diff --git a/src/Utils/PixbufUtils.cs b/src/Utils/PixbufUtils.cs
index ad611ef..933769b 100644
--- a/src/Utils/PixbufUtils.cs
+++ b/src/Utils/PixbufUtils.cs
@@ -12,29 +12,30 @@
using Gdk;
using System;
using System.Runtime.InteropServices;
+using TagLib.Image;
namespace FSpot.Utils
{
public static class PixbufUtils
{
- static public PixbufOrientation Rotate270 (PixbufOrientation orientation)
+ static public ImageOrientation Rotate270 (ImageOrientation orientation)
{
- PixbufOrientation [] rot = new PixbufOrientation [] {
- PixbufOrientation.LeftBottom,
- PixbufOrientation.LeftTop,
- PixbufOrientation.RightTop,
- PixbufOrientation.RightBottom,
- PixbufOrientation.BottomLeft,
- PixbufOrientation.TopLeft,
- PixbufOrientation.TopRight,
- PixbufOrientation.BottomRight
+ ImageOrientation [] rot = new ImageOrientation [] {
+ ImageOrientation.LeftBottom,
+ ImageOrientation.LeftTop,
+ ImageOrientation.RightTop,
+ ImageOrientation.RightBottom,
+ ImageOrientation.BottomLeft,
+ ImageOrientation.TopLeft,
+ ImageOrientation.TopRight,
+ ImageOrientation.BottomRight
};
orientation = rot [((int)orientation) -1];
return orientation;
}
- static public PixbufOrientation Rotate90 (PixbufOrientation orientation)
+ static public ImageOrientation Rotate90 (ImageOrientation orientation)
{
orientation = Rotate270 (orientation);
orientation = Rotate270 (orientation);
@@ -42,45 +43,45 @@ namespace FSpot.Utils
return orientation;
}
- public static Rectangle TransformOrientation (Pixbuf src, Rectangle args, PixbufOrientation orientation)
+ public static Rectangle TransformOrientation (Pixbuf src, Rectangle args, ImageOrientation orientation)
{
return TransformOrientation (src.Width, src.Height, args, orientation);
}
- public static Rectangle TransformOrientation (int total_width, int total_height, Rectangle args, PixbufOrientation orientation)
+ public static Rectangle TransformOrientation (int total_width, int total_height, Rectangle args, ImageOrientation orientation)
{
Rectangle area = args;
switch (orientation) {
- case PixbufOrientation.BottomRight:
+ case ImageOrientation.BottomRight:
area.X = total_width - args.X - args.Width;
area.Y = total_height - args.Y - args.Height;
break;
- case PixbufOrientation.TopRight:
+ case ImageOrientation.TopRight:
area.X = total_width - args.X - args.Width;
break;
- case PixbufOrientation.BottomLeft:
+ case ImageOrientation.BottomLeft:
area.Y = total_height - args.Y - args.Height;
break;
- case PixbufOrientation.LeftTop:
+ case ImageOrientation.LeftTop:
area.X = args.Y;
area.Y = args.X;
area.Width = args.Height;
area.Height = args.Width;
break;
- case PixbufOrientation.RightBottom:
+ case ImageOrientation.RightBottom:
area.X = total_height - args.Y - args.Height;
area.Y = total_width - args.X - args.Width;
area.Width = args.Height;
area.Height = args.Width;
break;
- case PixbufOrientation.RightTop:
+ case ImageOrientation.RightTop:
area.X = total_height - args.Y - args.Height;
area.Y = args.X;
area.Width = args.Height;
area.Height = args.Width;
break;
- case PixbufOrientation.LeftBottom:
+ case ImageOrientation.LeftBottom:
area.X = args.Y;
area.Y = total_width - args.X - args.Width;
area.Width = args.Height;
@@ -93,37 +94,37 @@ namespace FSpot.Utils
return area;
}
- public static Point TransformOrientation (int total_width, int total_height, Point args, PixbufOrientation orientation)
+ public static Point TransformOrientation (int total_width, int total_height, Point args, ImageOrientation orientation)
{
Point p = args;
switch (orientation) {
default:
- case PixbufOrientation.TopLeft:
+ case ImageOrientation.TopLeft:
break;
- case PixbufOrientation.TopRight:
+ case ImageOrientation.TopRight:
p.X = total_width - p.X;
break;
- case PixbufOrientation.BottomRight:
+ case ImageOrientation.BottomRight:
p.X = total_width - p.X;
p.Y = total_height - p.Y;
break;
- case PixbufOrientation.BottomLeft:
+ case ImageOrientation.BottomLeft:
p.Y = total_height - p.Y;
break;
- case PixbufOrientation.LeftTop:
+ case ImageOrientation.LeftTop:
p.X = args.Y;
p.Y = args.X;
break;
- case PixbufOrientation.RightTop:
+ case ImageOrientation.RightTop:
p.X = total_height - args.Y;
p.Y = args.X;
break;
- case PixbufOrientation.RightBottom:
+ case ImageOrientation.RightBottom:
p.X = total_height - args.Y;
p.Y = total_width - args.X;
break;
- case PixbufOrientation.LeftBottom:
+ case ImageOrientation.LeftBottom:
p.X = args.Y;
p.Y = total_width - args.X;
break;
@@ -131,58 +132,58 @@ namespace FSpot.Utils
return p;
}
- public static PixbufOrientation ReverseTransformation (PixbufOrientation orientation)
+ public static ImageOrientation ReverseTransformation (ImageOrientation orientation)
{
switch (orientation) {
default:
- case PixbufOrientation.TopLeft:
- case PixbufOrientation.TopRight:
- case PixbufOrientation.BottomRight:
- case PixbufOrientation.BottomLeft:
+ case ImageOrientation.TopLeft:
+ case ImageOrientation.TopRight:
+ case ImageOrientation.BottomRight:
+ case ImageOrientation.BottomLeft:
return orientation;
- case PixbufOrientation.LeftTop:
- return PixbufOrientation.RightBottom;
- case PixbufOrientation.RightTop:
- return PixbufOrientation.LeftBottom;
- case PixbufOrientation.RightBottom:
- return PixbufOrientation.LeftTop;
- case PixbufOrientation.LeftBottom:
- return PixbufOrientation.RightTop;
+ case ImageOrientation.LeftTop:
+ return ImageOrientation.RightBottom;
+ case ImageOrientation.RightTop:
+ return ImageOrientation.LeftBottom;
+ case ImageOrientation.RightBottom:
+ return ImageOrientation.LeftTop;
+ case ImageOrientation.LeftBottom:
+ return ImageOrientation.RightTop;
}
}
- public static Pixbuf TransformOrientation (Pixbuf src, PixbufOrientation orientation)
+ public static Pixbuf TransformOrientation (Pixbuf src, ImageOrientation orientation)
{
Pixbuf dest;
switch (orientation) {
default:
- case PixbufOrientation.TopLeft:
+ case ImageOrientation.TopLeft:
dest = PixbufUtils.ShallowCopy (src);
break;
- case PixbufOrientation.TopRight:
+ case ImageOrientation.TopRight:
dest = src.Flip (false);
break;
- case PixbufOrientation.BottomRight:
+ case ImageOrientation.BottomRight:
dest = src.RotateSimple (PixbufRotation.Upsidedown);
break;
- case PixbufOrientation.BottomLeft:
+ case ImageOrientation.BottomLeft:
dest = src.Flip (true);
break;
- case PixbufOrientation.LeftTop:
+ case ImageOrientation.LeftTop:
using (var rotated = src.RotateSimple (PixbufRotation.Clockwise)) {
dest = rotated.Flip (false);
}
break;
- case PixbufOrientation.RightTop:
+ case ImageOrientation.RightTop:
dest = src.RotateSimple (PixbufRotation.Clockwise);
break;
- case PixbufOrientation.RightBottom:
+ case ImageOrientation.RightBottom:
using (var rotated = src.RotateSimple (PixbufRotation.Counterclockwise)) {
dest = rotated.Flip (false);
}
break;
- case PixbufOrientation.LeftBottom:
+ case ImageOrientation.LeftBottom:
dest = src.RotateSimple (PixbufRotation.Counterclockwise);
break;
}
diff --git a/src/Utils/Tests/GIOTagLibFileAbstractionTests.cs b/src/Utils/Tests/GIOTagLibFileAbstractionTests.cs
new file mode 100644
index 0000000..ed2d965
--- /dev/null
+++ b/src/Utils/Tests/GIOTagLibFileAbstractionTests.cs
@@ -0,0 +1,132 @@
+#if ENABLE_TESTS
+using NUnit.Framework;
+using System;
+using Hyena;
+using TagLib;
+using TagLib.IFD;
+using TagLib.IFD.Entries;
+using TagLib.IFD.Tags;
+using TagLib.Xmp;
+
+namespace FSpot.Utils.Tests
+{
+ // This is a trimmed down test case from Taglib# to test the file abstraction.
+ [TestFixture]
+ public class GIOTagLibFileAbstractionTests
+ {
+ static bool initialized = false;
+ static void Initialize () {
+ GLib.GType.Init ();
+ initialized = true;
+ }
+
+ [Test]
+ public void StraightIOTest ()
+ {
+ var uri = CreateTempFile ();
+
+ var file = File.Create (uri.AbsolutePath) as TagLib.Image.File;
+ Assert.IsTrue (file != null);
+
+ Validate (file);
+ ChangeMetadata (file);
+
+ file = File.Create (uri.AbsolutePath) as TagLib.Image.File;
+ Assert.IsTrue (file != null);
+
+ Validate (file);
+ ValidateChangedMetadata (file);
+
+ DeleteTempFile (uri);
+ }
+
+ [Test]
+ public void GIOTest ()
+ {
+ var uri = CreateTempFile ();
+
+ var res = new GIOTagLibFileAbstraction () { Uri = uri };
+
+ var file = File.Create (res) as TagLib.Image.File;
+ Assert.IsTrue (file != null);
+
+ Validate (file);
+ ChangeMetadata (file);
+
+ file = File.Create (res) as TagLib.Image.File;
+ Assert.IsTrue (file != null);
+
+ Validate (file);
+ ValidateChangedMetadata (file);
+
+ DeleteTempFile (uri);
+ }
+
+ private SafeUri CreateTempFile ()
+ {
+ if (!initialized)
+ Initialize ();
+
+ var uri = new SafeUri (Environment.CurrentDirectory + "/../tests/data/taglib-sample.jpg");
+ var file = GLib.FileFactory.NewForUri (uri);
+
+ var tmp = System.IO.Path.GetTempFileName ()+".jpg"; // hack!
+ var uri2 = new SafeUri (tmp);
+ var file2 = GLib.FileFactory.NewForUri (uri2);
+ file.Copy (file2, GLib.FileCopyFlags.Overwrite, null, null);
+ return uri2;
+ }
+
+ private void DeleteTempFile (SafeUri uri)
+ {
+ var file = GLib.FileFactory.NewForUri (uri);
+ file.Delete ();
+ }
+
+ private void Validate (TagLib.Image.File file)
+ {
+ // Note: these don't correspond to the image data, only to the metadata. We hacked the file for size.
+ Assert.AreEqual (2000, file.Properties.PhotoWidth);
+ Assert.AreEqual (3008, file.Properties.PhotoHeight);
+ Assert.AreEqual (96, file.Properties.PhotoQuality);
+
+ var tag = file.GetTag (TagTypes.TiffIFD) as IFDTag;
+ Assert.IsNotNull (tag, "IFD tag not found");
+
+ var structure = tag.Structure;
+
+ // Image.0x010F (Make/Ascii/18) "NIKON CORPORATION"
+ {
+ var entry = structure.GetEntry (0, (ushort) IFDEntryTag.Make);
+ Assert.IsNotNull (entry, "Entry 0x010F missing in IFD 0");
+ Assert.IsNotNull (entry as StringIFDEntry, "Entry is not a string!");
+ Assert.AreEqual ("NIKON CORPORATION", (entry as StringIFDEntry).Value);
+ }
+
+ XmpTag xmp = file.GetTag (TagTypes.XMP) as XmpTag;
+ // Xmp.MicrosoftPhoto_1_.DateAcquired (XmpText/20) "2009-08-04T20:42:36Z"
+ {
+ var node = xmp.NodeTree;
+ node = node.GetChild (XmpTag.MS_PHOTO_NS, "DateAcquired");
+ Assert.IsNotNull (node);
+ Assert.AreEqual ("2009-08-04T20:42:36Z", node.Value);
+ Assert.AreEqual (XmpNodeType.Simple, node.Type);
+ Assert.AreEqual (0, node.Children.Count);
+ }
+ }
+
+ private void ChangeMetadata (TagLib.Image.File file)
+ {
+ file.ImageTag.Comment = "Testing!";
+ file.ImageTag.Keywords = new string [] { "One", "Two", "Three" };
+ file.Save ();
+ }
+
+ private void ValidateChangedMetadata (TagLib.Image.File file)
+ {
+ Assert.AreEqual ("Testing!", file.ImageTag.Comment);
+ Assert.AreEqual (new string [] { "One", "Two", "Three" }, file.ImageTag.Keywords);
+ }
+ }
+}
+#endif
diff --git a/src/Widgets/ImageView.cs b/src/Widgets/ImageView.cs
index 4b7682c..8796ee9 100644
--- a/src/Widgets/ImageView.cs
+++ b/src/Widgets/ImageView.cs
@@ -15,6 +15,7 @@ using Gtk;
using Gdk;
using FSpot.Utils;
+using TagLib.Image;
namespace FSpot.Widgets
{
@@ -61,8 +62,8 @@ namespace FSpot.Widgets
}
}
- PixbufOrientation pixbuf_orientation;
- public PixbufOrientation PixbufOrientation {
+ ImageOrientation pixbuf_orientation;
+ public ImageOrientation PixbufOrientation {
get { return pixbuf_orientation; }
set {
if (value == pixbuf_orientation)
@@ -688,7 +689,7 @@ namespace FSpot.Widgets
if (zoom == 1.0 &&
!Pixbuf.HasAlpha &&
Pixbuf.BitsPerSample == 8 &&
- pixbuf_orientation == PixbufOrientation.TopLeft) {
+ pixbuf_orientation == ImageOrientation.TopLeft) {
GdkWindow.DrawPixbuf (Style.BlackGC,
Pixbuf,
area.X - x_offset, area.Y - y_offset,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c4a60be..26b39c5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -4,7 +4,8 @@ EXTRA_DIST = \
data/f-spot-0.6.1.5.db \
data/f-spot-0.6.2.db \
data/f-spot-0.7.0-17.2.db \
- data/f-spot-0.7.0-18.0.db
+ data/f-spot-0.7.0-18.0.db \
+ data/taglib-sample.jpg
if ENABLE_TESTS
diff --git a/tests/data/taglib-sample.jpg b/tests/data/taglib-sample.jpg
new file mode 100644
index 0000000..96955e7
Binary files /dev/null and b/tests/data/taglib-sample.jpg differ
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]