Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image file copy, is being used by another process

I'm trying create a user perfil edit window, in this window has a Image control
When I selected a image file, it will show in this Image control and copy this file at my image folder, first time is all right, but second time, it show a error

"The process cannot access the file 'C:\1.jpg' because it is being used by another process."

I think it is because my Image control is using this file, so, I don't know what can I do

private void Select_Click(object sender, RoutedEventArgs e)
{
    OpenFileDialog od = new OpenFileDialog();
    if (od.ShowDialog() == true)
    {
        string imageLocal = @"C:/1.jpg";
        File.Copy(od.FileName, imageLocal, true);
        image1.Source = new BitmapImage(new Uri(imageLocal));
    }
}
like image 462
Lai32290 Avatar asked Aug 10 '13 23:08

Lai32290


2 Answers

If you want to load and display an image, and keep the file amenable to operations in the file system (like reloading it or moving it to another directory), the Uri constructor will not work because (as you point out), the BitmapImage class hangs on to the file handle.

Instead, use a method like this...

    private static BitmapImage ByStream(FileInfo info)
    {   //http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/dee7cb68-aca3-402b-b159-2de933f933f1
        try
        {
            if (info.Exists)
            {
                // do this so that the image file can be moved in the file system
                BitmapImage result = new BitmapImage();
                // Create new BitmapImage   
                Stream stream = new MemoryStream(); // Create new MemoryStream   
                Bitmap bitmap = new Bitmap(info.FullName);
                // Create new Bitmap (System.Drawing.Bitmap) from the existing image file 
                                             (albumArtSource set to its path name)   
                bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
                // Save the loaded Bitmap into the MemoryStream - Png format was the only one I 
                              tried that didn't cause an error (tried Jpg, Bmp, MemoryBmp)   
                bitmap.Dispose(); // Dispose bitmap so it releases the source image file   
                result.BeginInit(); // Begin the BitmapImage's initialisation   
                result.StreamSource = stream;
                // Set the BitmapImage's StreamSource to the MemoryStream containing the image   
                result.EndInit(); // End the BitmapImage's initialisation   
                return result; // Finally, set the WPF Image component's source to the 
                                BitmapImage  
            }
            return null;
        }
        catch
        {
            return null;
        }
    }

This method takes a FileInfo and returns a BitmapImage which you can display and simultaneously move it to another directory or display it again.

A much simpler method, copied from another answer below, is this:

public static BitmapImage LoadBitmapImage(string fileName)
{
    using (var stream = new FileStream(fileName, FileMode.Open))
    {
        var bitmapImage = new BitmapImage();
        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource = stream;
        bitmapImage.EndInit();
        bitmapImage.Freeze(); 
        return bitmapImage;
    }
}
like image 76
Gayot Fow Avatar answered Nov 12 '22 03:11

Gayot Fow


The method shown below loads a BitmapImage from file and immediately closes the file after loading. Note that it is necessary to set the BitmapCacheOption.OnLoad flag when the source stream is closed right after EndInit.

public static BitmapImage LoadBitmapImage(string fileName)
{
    using (var stream = new FileStream(fileName, FileMode.Open))
    {
        var bitmapImage = new BitmapImage();
        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource = stream;
        bitmapImage.EndInit();
        bitmapImage.Freeze(); // just in case you want to load the image in another thread
        return bitmapImage;
    }
}

This code will work for any image format that is supported by WPF. When passing the image file content as stream to the StreamSource property, WPF will automatically create the appropriate decoder.

like image 27
Clemens Avatar answered Nov 12 '22 02:11

Clemens