views:

4341

answers:

5

When I try to save a BitmapSource that I loaded earlier, a System.IO.IOException is thrown stating another process is accessing that file and the filestream cannot be opened.

If I only save whithout loading earlier, everything works fine.

The loading code:

BitmapImage image = new BitmapImage();

image.BeginInit();
image.UriSource = uri;

if (decodePixelWidth > 0)
image.DecodePixelWidth = decodePixelWidth;

image.EndInit();

the saving code:

using (FileStream fileStream = new FileStream(Directory + "\\" + FileName + ".jpg", FileMode.Create))
{
 JpegBitmapEncoder encoder = new JpegBitmapEncoder();
 encoder.Frames.Add(BitmapFrame.Create((BitmapImage)image));
 encoder.QualityLevel = 100;
 encoder.Save(fileStream);
}

It seems like after loading the image data, the file is still locked an can never be overwritten while the application who opened it is still running. Any ideas how to solve this? Thanks alot for any solutions.

A: 

Now i'm not sure if this can be applied to BitmapImage but i had a very similar problem with saving a modified image to the original file in GDI+ here

The method of loading the image from file keeps a lock open on the file until the image object is disposed.

Maybe it's the same thing with bitmapimage.urisource. Without playing around could you copy the image in memory and dispose the original thus unlocking the file?

Crippeoblade
+2  A: 

Add the following line to your loading code:

image.CacheOption = BitmapCacheOption.OnLoad;

This will load open the file, read it into memory, and close it all during image.EndInit. The default of BitmapCacheOption.Default has the odd behavior of opening the file, reading it into memory, but not yet closing it during image.EndInit.

C. Dragon 76
This works, but you also need to use BitmapCreateOptions.IgnoreImageCache in case you create a new BitmapImage using the same path later on in the process. This is because BitmapImage will cache the image data across instances of the BitmapImage class.
manu08
A: 

Setting CacheOption to BitmapCacheOption.OnLoad, will not solve your problem. I think there is a bug, but I had the same problem. Finally i loaded my image to a memory stream and disposed the BitmapImage before saving the image to the file.

Mohammadreza
Actually it works just fine for me. You have to create the BitmapImage, call BeginInit() then set the CacheOption, then set the UriSource then call EndInit().
Caleb Vear
+3  A: 

Inspired by the comments I got on this issue, I solved the problem by reading all bytes into a memorystream and using it as the BitmapImage's Sreamsource.

This one works perfectly:

if (File.Exists(filePath))
{
 MemoryStream memoryStream = new MemoryStream();

 byte[] fileBytes = File.ReadAllBytes(filePath);
 memoryStream.Write(fileBytes, 0, fileBytes.Length);
 memoryStream.Position = 0;

 image.BeginInit();
 image.StreamSource = memoryStream;

 if (decodePixelWidth > 0)
     image.DecodePixelWidth = decodePixelWidth;

 image.EndInit();
}
You took others' comments, didn't upvote anyone, created a derivative solution that you posted as an answer, and you gave yourself the Poster-Approved-Answer vote?
hughdbrown
I'm new to stackoverflow. As you may see. Therefore I just cannot upvote others until I have a reputation of 15. And since the others kindly provided good suggestions, but no real solution for people having the same problem, I provided the answer myself as a result of my very own research. Problem?
+1  A: 

Here is another solution, based upon the original loading code:

BitmapImage image = new BitmapImage();
image.BeginInit();
// add the following two lines
image.CreateOptions = BitmapCreateOptions.IgnoreImageCache; (overwrite cache if already exists, to refresh image)
image.CacheOption = BitmapCacheOption.OnLoad; (load into memory and unlock file)
image.UriSource = uri;
if (decodePixelWidth > 0)image.DecodePixelWidth = decodePixelWidth;
image.EndInit();