tags:

views:

490

answers:

3

Good day all,

I am having some trouble with image permissions.

I am loading an image from file, resizing it and then saving it out to another folder. I am then displaying this like so:

    uriSource = new Uri(Combine(imagesDirectoryTemp, generatedFileName), UriKind.Absolute);

    imgAsset.Source = new BitmapImage(uriSource);

This is working fine, the trouble comes if the user then selects another image immediately after and tries to save it over the original file.

An exception is generated upon saving my image "ExternalException: A generic error occurred in GDI+."

After some playing around i have narrowed the error down to imgAsset.Source = new BitmapImage(uriSource); as removing this line and not setting the imagesource will allow me to overwrite this file many times.

I have also tried setting the source to something else, before re-saving in the hope that the old reference would be disposed, this was not the case.

How can i get past this error?

Thanks, Kohan

Edit

Now using this code i am not getting the exception however the image source is not updating. Also since i am not using a SourceStream, im not sure what i need to dispose of to get this working.

       uriSource = new Uri(Combine(imagesDirectoryTemp, generatedFileName), UriKind.Absolute);

       imgTemp = new BitmapImage();
       imgTemp.BeginInit();
       imgTemp.CacheOption = BitmapCacheOption.OnLoad;
       imgTemp.UriSource = uriSource;
       imgTemp.EndInit();

       imgAsset.Source = imgTemp;
A: 

Sounds very much like the problem I had developing Intuipic, where WPF would not dispose of the image, thus locking the file. Check out this converter I wrote to deal with the problem.

HTH,
Kent

Kent Boogaart
Hi there, thanks for that, i am no longer generating an error but after the update the image source is not updating. Do i need to dispose of something as per your example or do i need to cause the imagesource to refresh somehow? Thanks.
Kohan
A: 

When you load an Image in any WPF control it let's handle to your image and doesn't release it until you close your application. The reason for this... I dont know exactly, problably is relaying on some DirectX code behind the scene which never knows when the WPF application releases the image.. Use this code to load the image..

        MemoryStream mstream = new MemoryStream();
        System.Drawing.Bitmap bitmap = new Bitmap(imgName);
        bitmap.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg);
        bitmap.Dispose(); // Releases the file.

        mstream.Position = 0;

        image.BeginInit();
        image.StreamSource = mstream;
        image.EndInit();
        this.img.Source = image ;

it worked for me..

jmayor
This works but is much less efficient than using BitmapCacheOptions.OnLoad and BitmapCreateOptions.IgnoreImageCache because: 1. It keeps two copies of the data in RAM, 2. It is slower because there is a lot of parsing and processing during the System.Drawing.Bitmap.Save call. It also won't work if imgName is a URI that is only handled by WPF.
Ray Burns
+2  A: 

You're almost there.

  • Using BitmapCacheOption.OnLoad was the best solution to keep your file from being locked.

  • To cause it to reread the file every time you also need to add BitmapCreateOptions.IgnoreImageCache.

Adding one line to your code should do it:

  imgTemp.CreateOption = BitmapCreateOptions.IgnoreImageCache;

thus resulting in this code:

  uriSource = new Uri(Combine(imagesDirectoryTemp, generatedFileName), UriKind.Absolute);
  imgTemp = new BitmapImage();
  imgTemp.BeginInit();
  imgTemp.CacheOption = BitmapCacheOption.OnLoad;
  imgTemp.CreateOption = BitmapCreateOptions.IgnoreImageCache;
  imgTemp.UriSource = uriSource;
  imgTemp.EndInit();
  imgAsset.Source = imgTemp;
Ray Burns
Perfect, many thanks for this.
Kohan