views:

705

answers:

3

I've found the common way to get image metadata in WPF is to create a BitmapFrame object and inspect the Metadata property on it. However I can't seem to create a BitmapFrame object that fulfills these two requirements:

  1. Does not lock the file
  2. Does not throw weird, undocumented exceptions when given certain files

Using these lines seems to create the BitmapImage reliably:

BitmapFrame.Create(new Uri(imageName));
BitmapFrame.Create(new Uri(imageName), BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);

However they leave the file locked for an indeterminate amount of time. There is no dispose method on the BitmapFrame as far as I can tell.

This keeps the file from being locked:

BitmapFrame.Create(new Uri(imageName), BitmapCreateOptions.None, BitmapCacheOption.OnLoad);

However on Vista it throws ArgumentExceptions and InvalidOperationExceptions on certain files and on Win7 it throws FileFormatExceptions and IOExceptions. This makes me think that caching the BitmapFrame is unsupported/untested.

Can you get metadata from an image in WPF without leaving a lock on the file for an indeterminate length of time?

A: 

Have you tried using a converter approach? For example, my Intuipic application does this. See BitmapFrameConverter for details on loading without locking, and BitmapOrientationConverter for getting at metadata.

HTH, Kent

Kent Boogaart
I tried your BitmapOrientationConverter but that still locks the file outside of the using(FileStream) block. It's only for a few seconds, but it still happens. And BitmapFrameConverter actually uses a BitmapImage, which I have had no problems with.
RandomEngy
Though I might have been a bit hasty... I tested outside of my program and it seems to have released the lock. Probably had a typo or something when I tried it. I'll confirm when I get back home.
RandomEngy
A: 

Try either bitmapImage.StreamSource.Dispose() or bitmapImage.Freeze();

Anthony Bouch
A: 

I don't know if an answer at this time can still be useful to anybody but since I got here only today, I assume that somebody else may be interested.

I had a similar problem when trying to use BitmapFrame to test if an image is valid, then trying to rename the image file. With this code, the image is locked and the Move command does not work:

bool isImageValid = true;
try
{
    BitmapFrame bmpFrame = BitmapFrame.Create(new Uri("C:\\Images\\Test.jpg"));
}
catch
{
    isImageValid = false;
}
File.Move("C:\\Images\\Test.jpg", "C:\\Images\\Test0.jpg");

However, when I first read the image file in a file stream, the file is released as soon as the using block is done and the Move command works:

bool isImageValid = true;
try
{
    using (FileStream fs = new FileStream("C:\\Images\\Test.jpg", FileMode.Open))
    {
        BitmapFrame bmpFrame = BitmapFrame.Create(fs);
    }
}
catch
{
    isImageValid = false;
}
File.Move("C:\\Images\\Test.jpg", "C:\\Images\\Test0.jpg");
mparento