Photography

Yesterday I worked on a new version of my FlickrMetadataSynchr tool and published the 1.3.0.0 version on CodePlex. I wasn’t really planning on creating a new version, but I was annoyed by the old version in a new usage scenario. When you have an itch you have to scratch it! And it is always good to catch up on some programming if recent assignments at work don’t include any coding. So what caused this itch?

FlickrMetadataSynchr-v1.3.0.0About two weeks ago I got back from my holiday in China with about 1,500 pictures on my 16 GB memory card. I always make a first selection immediately after taking a picture, so initially there were lots more. After selection and stitching panoramic photos, I managed to get this down to about 1,200 pictures. Still a lot of pictures. But storage is cheap, tagging makes search easy, so why throw away any more? One of the perks of a Pro account on Flickr is that I have unlimited storage, so I uploaded 1,1173 pictures (5.54 GB). This took over 12 hours because Flickr has limited uploading bandwidth.

Adding metadata doesn’t stop at tagging pictures. You can add a title, description and geolocation to a picture. Sometimes this is easier to do on your local pictures, and sometimes I prefer to do it on Flickr. The FlickrMetadataSynchr tool that I wrote is a solution to keeping this metadata in sync. You should always try to stay in control of your data, so I keep backups of my e-mail stored in the “cloud” and I store all metadata in the original picture files on my hard drive. Of course I backup those files too. Even offsite by storing an external hard drive outside my house.

Back to the problem. Syncing the metadata for 1,1173 pictures took an annoyingly long time. The Flickr API has some batch operations, but for my tool I have to fetch metadata and update metadata for pictures one-by-one. So each fetch and each update uses one HTTP call. Each operation is not unreasonably show, but when adding latency to the mix it adds up to slow performance if you do it sequentially.

Imperative programming languages like C# promote a sequential way of doing things. It is really hard to exploit multiple processor cores by splitting up work so that it can run in parallel. You run into things like data concurrency for shared memory, coordinating results and exceptions, making operations cancellable, etc. Even with a single processor core, my app would benefit from exploiting parallelism because the processor spends most of its time waiting on the result of the HTTP call. This time can be utilized by creating additional calls or processing results of other calls. Microsoft has realized that this is hard work for a programmer and great new additions are coming in .NET Framework 4.0 and Visual Studio 2010. Things like the Task Parallel Library and making debugging parallel applications easier.

However, these improvements are still in the beta stage and not usable yet for production software like my tool. I am not the only user of my application and “xcopy deployability” remains a very important goal to me. For example, the tool does not use .NET 3.5 features and only depends on .NET 3.0, This is  because Windows Vista comes with .NET 3.0 out of the box and .NET 3.5 requires an additional hefty install. I might make the transition to .NET 3.5 SP1 soon, because it is now pushed out to all users of .NET 2.0 and higher through Windows Update.

So I added parallelism the old-fashioned way, by manually spinning up threads, locking shared data structures appropriately, propagate exception information through callbacks, making asynchronous processes cancellable, waiting on all worker threads to finish using WaitHandles, etc. I don’t use the standard .NET threadpool for queing work because it is tuned for CPU bound operations. I want to have fine grained control over the number of HTTP connections that I open to Flickr. A reasonable number is a maximum of 10 concurrent connections. This gives me almost 10 ten times the original speed for the Flickr fetch and update steps in the sync process. Going any higher puts me at risk of being seen as launching a denial-of-service attack against the Flickr web services.

If you want to take a look at my source code, you can find it at CodePlex. The app was already nicely factored, so I didn’t have to rearchitect it to add parallelism. The sync process was already done on a background thread (albeit sequentially) in a helper class, because you should never block the UI thread in WinForms or WPF applications. The app already contained quite a bit of thread synchronization stuff. The new machinery is contained in the abstract generic class AsyncFlickerWorker<TIn, Tout> class. Its signature is

/// <summary>
/// Abstract class that implements the machinery to asynchronously process metadata on Flickr. This can either be fetching metadata
/// or updating metadata.
/// </summary>
/// <typeparam name="TIn">The type of metadata that is processed.</typeparam>
/// <typeparam name="TOut">The type of metadata that is the result of the processing.</typeparam>
internal abstract class AsyncFlickrWorker<TIn, TOut>

It has the following public method

/// <summary>
/// Starts the async process. This method should not be called when the asychronous process is already in progress.
/// </summary>
/// <param name="metadataList">The list with <typeparamref name="TIn"/> instances of metadata that should
/// be processed on Flickr.</param>
/// <param name="resultCallback">A callback that receives the result. Is not allowed to be null.</param>
/// <typeparam name="TIn">The type of metadata that is processed.</typeparam>
/// <typeparam name="TOut">The type of metadata that is the result of the processing.</typeparam>
/// <returns>Returns a <see cref="WaitHandle"/> that can be used for synchronization purposes. It will be signaled when
/// the async process is done.</returns>
public WaitHandle BeginWork(IList<TIn> metadataList, EventHandler<AsyncFlickrWorkerEventArgs<TOut>> resultCallback)

It uses the generic class AsyncrFlickrWorkerEventArgs<TOut> to report the results:

/// <summary>
/// Class with event arguments for reporting the results of asynchronously processing metadata on Flickr.
/// </summary>
/// <typeparam name="TOut">The "out" metadata type that is the result of the asynchronous processing.</typeparam>
public class AsyncFlickrWorkerEventArgs<TOut> : EventArgs

The subclass AsyncPhotoInfoFetcher is one of its implementations.

/// <summary>
/// Class that asynchronously fetches photo information from Flickr.
/// </summary>
internal sealed class AsyncPhotoInfoFetcher: AsyncFlickrWorker<Photo, PhotoInfo>

These async workers are used by the FlickrHelper class (BTW: this class has grown a bit too big, so it is a likely candidate for future refactoring). Its method that calls async workers is generic and has this signature:

/// <summary>
/// Processes a list of photos with multiple async workers and returns the result.
/// </summary>
/// <param name="metadataInList">The list with metadata of photos that should be processed.</param>
/// <param name="progressCallback">A callback to receive progress information.</param>
/// <param name="workerFactoryMethod">A factory method that can be used to create a worker instance.</param>
/// <typeparam name="TIn">The "in" metadata type for the worker.</typeparam>
/// <typeparam name="TOut">The "out" metadata type for the worker.</typeparam>
/// <returns>A list with the metadata result of processing <paramref name="metadataInList"/>.</returns>
private IList<TOut> ProcessMetadataWithMultipleWorkers<TIn, TOut>(
    IList<TIn> metadataInList,
    EventHandler<PictureProgressEventArgs> progressCallback,
    CreateAsyncFlickrWorker<TIn, TOut> workerFactoryMethod)

This method contains an anonymous delegate that acts as the result callback for the async workers. Generics and anonymous delegates make multithreaded life bearable in C# 2.0. Anonymous delegates allow you to use local variables and fields of the containing method and class in the callback method and thus easily access and change those to store the result of the worker thread. Of course, make sure you lock access to shared data appropriately because multiple threads might callback simultaneously to report their results.

And somewhere in 2010 when .NET 4.0 is released, I could potentially remove all this manual threading stuff and just exploit Parallel.For 😉

Yesterday Microsoft published a ~ 100 TB image update to Live Search Maps. And finally, we have bird’s eye imagery for Amsterdam, The Netherlands. Since I live in Amsterdam, you can imagine that I am pretty thrilled about this.

This is the bird’s eye image of Dam Square in Amsterdam:

 Bird's Eye Imagery for Amsterdam in Live Search Maps

The platform that powers Live Search Maps is called Virtual Earth. It is a developer friendly platform that allows you to easily embed maps, aerial and satellite photography on your own web pages. The UI is customizable, so you are not stuck with what is provided by default. You can overlay icons, pictures and text on the map.

The Dutch version of Live Search Maps is an example of a site that is build on the Virtual Earth platform. It looks like the standard version, but it integrates with De Telefoongids en Gouden Gids data to locate people and businesses. If you live in the Netherlands this version is probably better suited for you than the international version.

Check out how easy it is to use the Virtual Earth platform by using the Interactive SDK on http://dev.live.com/virtualearth/. It is one of the Live Services that we provide. Check out the Virtual Earth Mashups Library to get an idea of what is possible with this platform.

 

One of the cool features of Live Search Maps is that it allows you to discover community content like geotagged Photosynths. For instance, by going to Leeuwarden and clicking “Verzamelingen” in the upper right corner, you can find my Photosynth of the train station in Leeuwarden:

Discover Photosynths on Live Search Maps

Since last week I have a new digital SLR camera: a 15 megapixel Canon EOS 50D. With it I took my first photo set with Photosynth in mind. I am very happy with the result: 98 photos that are 100% synthy (meaning that they all connect into one seamless 3D scene).

Here is a screenshot of this scene of the main hall of the train station in Leeuwarden:

Photosynth (Build 10683) - Train Station Leeuwarden

Of course, this synth is best experienced live because then it is fully navigable. You can move around using the mouse, cursor keys or keyboard shortcuts. Also try to zoom in. Fifteen megapixel pictures give you quite some leeway for zooming into details.

Have you created a nice synth? Leave the link as a comment so that I can check it out.

1 Comment

For the last week, I have been in love with Photosynth. It was a tech preview in view-only mode for quite a while, but now we finally released it to the masses.

I've created three synths from existing pictures, i.e., from pictures I took without having Photosynth in mind. These are my first experiments:

  Photosynth (Build 10683) - Sunset Amsterdam

But these ones are much better:

Photosynth is a prime example of the execution on our Software + Services vision. It combines the best of the web with local computing power (on Windows).

Go create!

PS: I have a 40 Megapixel picture of Mount Rainier stitched from the same pictures as above. For the stitching I used Windows Live Photo Gallery. You can view it using Silverlight DeepZoom technology.

During the lunch break Carlo and I walked around the Microsoft Corporate Campus in Redmond. It is autumn here as well. Lots of deciduous trees are shedding their leaves. The campus now shows lots of shades of red and yellow on leaves.

I took some pictures during the walk. You can see some below. Click on the images to see larger versions on Flickr:

Autumn in Redmond 

Carlo on the Microsoft Way Carlo standing at a Microsoft Way street sign.

Building 42 Building 42. Home to the .NET Framework teams.

Building 42 The other side of building 42.

Microsoft Conference Center The Microsoft Conference Center.

More pictures can be found on my Flickr page.

1 Comment

After a long day and night of coding, I released version 0.8.0.0 of my Flickr Metadata Synchr tool on CodePlex this morning. I finally solved the long-standing problem I was having with the Windows Imaging Component (WIC) to update metadata. So this is the first fully-functional release of my application.

Functionality of FlickrMetadataSynchr v0.8.0.0

This is what the app does:

  • It allows you to select a set of your photos on Flickr and a folder on your hard drive with images.
  • It reads the metadata for both Flickr images and the local images. The metadata that is read is:
    • Title
    • Description
    • Author
    • Tags
    • Geo-info (GPS coordinates)
    • Date and time taken
    • Last update date and time
  • It matches images on Flickr with local images based on the date and time taken.
  • It determines on a per picture basis in what direction the metadata should by synced, i.e., which side should be updated, if any. Currently the most recently updated side wins. I am getting help from Timo Proescholdt for a better algorithm that will allow for a merge of metadata, i.e., a two-way synch.
  • It updates the metadata on Flickr and in the local images.

This is a screenshot of the app:

 

Previous posts on this tool

Workaround for WIC problems

During my holiday in France in July I received e-mail from Robert A. Wlodarczyk who works at Microsoft. He pinged me to say that he had released new sample code to update metadata using WIC. Yesterday, I tried to incorporate similar code into my application and ran into the same type of problems as before.

Because his sample was working, I wasn't ready to give up again. I finally tracked the problem down to a threading issue. WIC is throwing strange InvalidOperationException and InvalidFormatException exceptions with messages like "Cannot write to the stream" when it is called from a background thread. My app is multi-threaded so that the UI doesn't hang when it is busy syncing.

After I got confirmation from Robert that WIC indeed suffers from a threading issue, I solved the problem with a work around. I now marshal the call to the code that uses WIC to update metadata to the UI thread using the WPF Dispatcher object. This causes the app to become non-responsive for small amounts of time during the update of local metadata. But that is better than a non-fully-functional app.

Fully functional, give it a try

So all is well that ends well. After finally getting WIC to work, I could do away with the C++ code that was causing me headaches 😉 And my app now works on Windows XP again. You just need to have the .NET Framework 3.0 installed.

If you have images on Flickr and you have been busy tagging them, give my app a spin! You can always find the latest release on CodePlex. The source code is also available under a GPL license on CodePlex.

Installing is easy. You just need to unzip the ZIP-file, which contains three files, to a folder. Start the FlickrMetadataSynchr.exe file and you are done. The app remembers the last settings.

If you find any issues, please report them using the Issue Tracker for my app on CodePlex.

The Future

Even though the app is now able to sync metadata in both Flickr images and local images, there is always room for improvement. Here are my ideas, some of which are based of suggestions by people on CodePlex:

  • Improve the synchronization to also allow two-way synchronization for a picture pair. I.e., one side doesn't have to win. For example, if the Flickr image has just the title set and the local image the description, the metadata should be merged.
  • Add UI to see the match that is made by the tool and how it proposes to sync the metadata.
  • Allow you to exclude images if the match isn't good.
  • Allow you to overrule the sync proposal and sync the metadata in a different direction (on a per property basis) .
  • Add UI to store multiple mappings between Flickr sets and local folders. Currently the app only remembers the last folder and Flickr set that was used.
  • Add click-once deployment. That way the app can automatically check for new versions and update itself.

If you have any other ideas please post them at the discussions page for my app on CodePlex.

The situation


I am currently working on version 0.6.0.0 of my Flickr Metadata Synchr tool. The goals for my open source project on CodePlex are described on the Flickr Metadata Synchr wiki page and you can always find the latest status there.


At the moment the latest public release is version 0.5.5.0. The feature set for v0.5.5.0 is roughly:



  • Allow you to select a Flickr photoset and a local directory with images.
  • Load metadata from both local and Flickr images into internal metadata structures.
  • Compare these metadata structures and synchronize them.
  • Update metadata on Flickr after the synchronization.

One of the features planned for v0.6.0.0 is updating the XMP and IPTC metadata in locally stored images. I was planning on doing this through the Windows Imaging Component (WIC) which is part of the .NET Framework 3.0. WIC is also available as a separate download for Windows XP and Windows Server 2003.


Windows Presentation Foundation provides a nice managed API for reading and writing metadata through WIC. It provides the SetQuery and GetQuery methods on the BitmapMetadata class. I was already using the GetQuery method, which works fine. However, I hit a snag when I wanted to use the SetQuery method to update metadata.


Plan A


There is a way to do this through the InPlaceBitmapMetadataWriter class. It just touches the metadata structures in the image file and doesn't have to read or write the entire stream with pixel information. This will give you excellent performance and so you don't run the risk of having to reencode the pixel stream or loosing metadata. The sad thing is that it almost never works. The image file often does not have enough room in its metadata structures to allow metadata fields to be filled or updated. When you try to save the updated metadata, the InPlaceBitmapMetadataWriter fails. That is probably why the save method is called TrySave. By the way, the code sample on that MSDN Page is dead wrong. If you call TrySave before updating metadata, it always succeeds. Probably because there is nothing to save yet. You have to call it after you update the metadata, and then it returns false ;( Which means your metadata was not updated successfully.


Plan B


So I tried plan B: Creating a new image file by writing out a copy of the original image, but now with updated metadata. This means you have to grab the original BitmapFrame from the JpegBitmapDecoder. Clone it, update its metadata and write it out again using the JpegBitmapEncoder.


This is where I hit a major problem. The Save() method on the JpegBitmapEncoder almost always fails with an InvalidOperationException with the error message "Cannot write to the stream". When the encoder is able to write out the image, the JPEG turns out to be reencoded with a different quality than the original. This is noticeable through a significant change in size of the file. This happens even though I specified the BitmapCreateOptions.PreservePixelFormat option when opening the image with the decoder. Googling (or Windows Live Searching if you will) for a solution didn't yield anything useful.


Plan C


I had to come up with a Plan C. The Windows Vista Shell is obviously able to update metadata in images without affecting the JPEG quality and without creating a copy of the image file. This led me to an MSDN article titled "Photo Metadata Policy". This is the introduction:



Metadata (file properties) for photo files can be stored using multiple metadata schemas, in different data formats and in different locations within a file. In Windows Vista™, the Microsoft® Windows® Shell provides a built-in property handler for photo files formats, such as JPEG, TIFF, and PNG, to simplify metadata retrieval.


When a piece of metadata is present in different underlying schemas, the built-in property handler determines which value to return . For instance, the Author property may be stored in the following locations in a TIFF file:


  • The Creator tag in the XMP Dublin Core schema:
    /ifd/xmp/purl.org/dc/elements/1.1/dc:creator

  • The Artist tag in the EXIF schema:
    /ifd/{ushort=315}

  • The Artist tag in the EXIF schema embedded in an XMP block:
    /ifd/xmp/ns.adobe.com/tiff/1.0/tiff:artist

On read, the property handler determines the value that takes precedence over the others that exist in the file and returns it. On write, the property handler makes sure it leaves each schema in a resolved and consistent state with the others. This may mean either updating or removing the tag in question in a given schema.


This would also help to solve another piece of the metadata puzzle: what to do with the several different options of putting metadata in image files (XMP versus IPTC, multiple possible XMP places, etc.). After updating an image, I want the metadata in the different blocks to be consistent. WIC doesn't help with this. You have to sort it out yourself. The Windows Vista Shell does help with metadata reconciliation.


So all seems to be well. Just use the Shell API to update the metadata. I would love to be able to do this from C#. Yet that doesn't seem to be possible or it is extraordinarily difficult. The "file property" handling is implemented in propsys.dll through a COM based API. But you can't add a reference to this COM library in a C# project. It doesn't have a type library ;( The only option I can find is to use C++ and use the propsys.h and propsys.idl files that are distributed in the Windows SDK. This is horrible. I guess I have to dust off my C++ skills to be able to call a brand-new Windows Vista API. WTF?!


The "Longhorn" promise for managed code


Do you remember the promises Microsoft made back in 2003 for the new Windows Client OS codenamed "Longhorn"? I sure do, since I visited the PDC03 conference where this was all announced. Microsoft promised us a brave new world where all Windows APIs could be accessed easily from managed code. Three and a bit years later we have a new Windows Client OS called Vista that doesn't live up to this promise. Microsoft has implemented new APIs that seem to be inaccessible from managed code other than through C++.


Now I can understand why part of the promise was lost during the infamous "Longhorn Reset" at Microsoft. Microsoft's ambition to completely wrap all existing Win32 APIs in WinFX was too big. But why Microsoft would be creating new APIs without managed code in mind is beyond me...


I found some C++ code on the blog of Ben Karas that is indeed able to update metadata  I hate having to add this C++ code to my project. It would require people to have Visual C++ and the Windows SDK (especially the Windows Vista header and library (*.h, *.idl, *.lib) files) installed to be able to build my code in Visual Studio.


A plan D might be to manually create C# wrappers for the COM interfaces of propsys.dll. This article describes how to do this for COM interfaces in general.

1 Comment

My app on CodePlex has reached the v0.3.0.0 stadium. It does not sync the metadata yet, but it fetches the metadata from images on Flickr and on a local disk in a form that can easily be compared.

 

Jan kindly donated some C# code using GDI+ and direct file operations for reading and writing EXIF and IPTC information. After digging deeper into the .NET 3.0 documentation, I found out that the Windows Imaging Component that is part of the .NET Framework 3.0 should allow me to do this as well. Because I need to display the images at some point using Windows Presentation Foundation, I would like to take as few dependencies on different image libraries as possible. Image files tend to get large (couple of MB) and it takes some time to read them into memory for processing. I hope to prevent the need for processing them using both WPF/WIC and GDI+ (the pre-WPF way on the Windows platform).

For instance, this is the code to read out the GPS longitude and latitude from a picture on disk:

         using (Stream pictureFileStream = new FileStream(pictureFilename, FileMode.Open, FileAccess.Read))
         {
            JpegBitmapDecoder decoder = new JpegBitmapDecoder(pictureFileStream, BitmapCreateOptions.None, BitmapCacheOption.None);
 
            BitmapMetadata bitmapMetadata = (BitmapMetadata)decoder.Frames[0].Metadata;
 
            ulong[] latitudes = bitmapMetadata.GetQuery("/app1/ifd/gps/subifd:{ulong=2}") as ulong[];
            ulong[] longitudes = bitmapMetadata.GetQuery("/app1/ifd/gps/subifd:{ulong=4}") as ulong[];
         }

It took me quite some time before I found the query strings for these metadata fields through trial-and-error. I could not find them documented anywhere in this form yet.

Unfortunately aiding someone else by testing his application, doing bug reporting and giving suggestions for improvements hasn't turned out to be reciprocal yet ;( So I am looking for other people who are willing to give my app a try and let me know what they think.

You can download the app in binary form from the release page and in source form as well.

The binary form is useful if you just want to look at the UI of the application. The source form is useful if you want to review the code and/or to run the program in the Visual Studio debugger so you can see the metadata that is fetched by setting breakpoints.

If you find any issues or have suggestions, the best way to give feedback is to add them to the Issue Tracker on CodePlex. That way they go directly into Team Foundation Server as work items. Releases and check-ins can be coupled to work items providing you with feedback on how issues are being tackled.

1 Comment

[Update 2007-02-24: My Flickr Metadata Synchr project is now live on CodePlex. I will keep the Wiki page on CodePlex updated and will not further update this blog post. If you are interested in the progress, you can subscribe to the Flickr Metadata Synchr project's RSS feed.]

I blogged previously on my digital workflow for photographs here and here. In that last post I described how I violated the golden rule of metadata. Now, I am thinking of writing an application that will fix this for me. I already thought of a name: the Flickr Metadata Synchr. Once I get a skeleton version of the app up-and-running, you will be able to view this project on CodePlex. If I fail miserably, the project will never show up 😉

Here is what I am planning of building:

Name of the application

Flickr Metadata Synchr

Purpose

To synchronize relevant metadata added to images stored on Flickr with the original versions of those images stored locally on your hard drive.

Relevant metadata on Flickr is:

  • Title
  • Description
  • Tags
  • GPS location info

The synchronization will be one-way in the first release. The embedded metadata in EXIF, IPTC and XMP sections in locally stored images can be updated with the metadata of matching pictures on Flickr.

Functionality

  • Ability to authenticate the user with Flickr, i.e., obtain a user token to let the app have read permissions for the user on Flickr.
  • Ability to select a folder with pictures on a local hard disk or network drive. Optionally include subfolders. These pictures will be called the local set.
  • Ability to select a set of pictures on Flickr. This set should belong to the authenticated user. Or the ability to select all pictures of the user tagged with a certain keyword. These pictures will be called the Flickr set.
  • Ability to let the app match pictures between the local and the Flickr set. Match will be done on “date captured”.
  • Ability for the user to cancel the matching process which might be time-consuming.
  • Ability to show the user the match that was made by the application to give the user the opportunity to review for any matching errors.
  • Ability to show the relevant metadata for pictures in both the local and the Flickr set.
  • Ability for the user to deselect matched image pairs that he or she does not want to process.
  • Ability to update the matched local images with metadata from Flickr.
  • Ability for the user to cancel the updating process which might be time-consuming.

Possible future functionality

  • Cache metadata retrieved from Flickr between app restarts to improve performance. Ask the user if it is okay to not update the data. If the user has made significant updates on Flickr, caching will cause more harm than good.
  • Ability to sync Flickr metadata the other way around. Read metadata from local images and update the metadata of matching pictures on Flickr.

Dependencies

Development tools

1 Comment

 


I am still looking for a good solution for my digital workflow for pictures on Windows Vista. I want to be able to easily tag my pictures locally on my hard-drive and on Flickr and keep the metadata in sync.


Let me describe the state of affairs.


Metadata in images


With metadata I mean the info I add manually to a picture, like the title, author, description, tags and GPS info. A digital camera already adds lots of other data to your pictures like aperture, camera model, if the flash fired or not, etc. This info is usually stored in an EXIF section in the JPEG file. For other metadata there are several options: EXIF, IPTC of XMP. IPTC is an older standard. XMP is more flexible (e.g., it allows Unicode) and modern.


The Golden Rule


This page states the golden rule of metadata:



Store the metadata in your images


Adding metadata to pictures


While in Redmond two weeks ago, I uploaded a subset of the pictures that I took to Flickr. I added the metadata through the site. Flickr does not embed this metadata in the file. If you download the original image file, the title, description and tags are gone. So I basically violated the Golden Rule.


A better option is to add the metadata before you upload your images to Flickr. Locally I can embed the metadata as IPTC or XMP in the JPEGs using a variety of tools. This way your metadata flows with your image to Flickr. If you download it again, the metadata is stil there.


The easiest option to add metadata to your images is to use the Windows Photo Gallery built into Windows Vista. This stores metadata in an XMP section in the image file.


Unfortunately, Flickr only imports metadata from EXIF and IPTC and not from the XMP section. So all the images that you tag in Vista show up untagged on Flickr.


Vista Flickr Uploader


My colleague Matthijs (who still won't reboot his blog, not even to market his own app 😉 has written a Vista Flickr Uploader tool to solve this problem.


His Vista Flickr Uploader app is written in C# and uses .NET 3.0, most notably Windows Presentation Foundation and the Windows Imaging Component. He open sourced it through CodePlex. This tool solves one way of the problem. When uploading your pictures, it extracts XMP info from your pictures and adds it to Flickr as metadata.


Microsoft Photo Info


As an alternative to tagging through Windows Vista Photo Gallery, you might want to try out the Microsoft Photo Info tool. This is a free download from Microsoft that works on both XP and Vista. It integrates into the Windows Explorer. The great thing about this tool is that it can read and write both IPTC and XMP info. So your metadata is recognized by Flickr when you upload your images.


Embedding metadata from Flickr


So Vista Flickr Uploader or Microsoft Photo Info solve one way of the problem: getting metadata from your images onto Flickr. The other problem still remains: getting metadata from Flickr into your images. I found one tool (.NET 2.0 based) that is able to download images from Flickr and embed the Flickr metadata as IPTC. It was quite unstable and wasn't really able to find my images so I won't link to it.


Remaining problem


Another problem that this download tool caused was inconsistency between the IPTC and XMP info in the image files. Imagine the following scenario:



  • Tag your images with XMP info in Vista.

  • Upload them with the Vista Flickr Uploader.

  • Flickr now shows the metadata from the XMP.

  • Change the title, description or tags on the Flickr site.

  • Download the image from Flickr with a tool that embeds the Flickr metadata into IPTC.

You end up with an image file with both IPTC and XMP info. The XMP info is out-of-date, yet it takes precedence in Windows Vista ;(


So I am looking for a tool that downloads pictures from the Flickr site that embeds the Flickr metadata as both IPTC and XMP info or just as XMP. I wasn't able to find such a tool, so I will probably have to write my own app to do this.


[Update 2007-08-31: I have now written such a tool: FlickrMetadataSynchr.]


ExifTool


A possible alternative might be to use a really powerful metadata tool and library written in Perl that allows you to extract and embed metadata in almost all known formats. Phil Harvey's ExifTool can even be used to read ID3 info from MP3 files. I could use it to wipe XMP info from images so the IPTC info is used again by Vista.


The problem with this command line tool is that it works really low-level with the potential of damaging the metadata beyond repair. I.e., other programs refuse to load your images because they can't make sense of the metadata.