2

I load an image into a picturebox:

myPictureBox.Image = Image.FromFile(strImageFile);

and works perfectly, but the image file is locked and I can't manage until my application is closed..

I need, from another window of the program, save a new image to reload when this child window is closed..

leppie
  • 115,091
  • 17
  • 196
  • 297
ghiboz
  • 7,863
  • 21
  • 85
  • 131

4 Answers4

5

Image.FromFile will keep the File open which prevents access to the image file till the Image is disposed. If you want to release the lock, you need to keep the Image file in memory.

myPictureBox.Image = Image.FromStream(new MemoryStream(File.ReadAllBytes(strImageFile)));
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
  • Reading image from `FileStream` instead of copying file content to `MemoryStream` first looks slightly more elegant. – Andrey Korneyev May 05 '15 at 12:37
  • 2
    @AndyKorneyev Elegant, yes. But you need to keep the `FileStream` open for the lifetime of the `Image`. That is same as calling `Image.FromFile`. It isn't going to help OP. – Sriram Sakthivel May 05 '15 at 12:39
1

An easy approach is to copy the image from the file to a new Bitmap and dispose the instance from the file after that. This is best done with a proper using construct:

using(var fromFile = Image.FromFile(strImageFile))
{
    myPictureBox.Image = new Bitmap(fromFile);
}
abto
  • 1,583
  • 1
  • 12
  • 31
1

As documented load the image from the file and assign a cloned instance to the picture box.

If you want to use the same image in multiple PictureBox controls, create a clone of the image for each PictureBox. Accessing the same image from multiple controls causes an exception to occur.

And to keep the file unlocked, just use it only for the clone time:

using ( var img = Image.FromFile( fileName ) )
{
    pictureBox2.Image = (Image) img.Clone();
}
Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
  • That doesn't work. The clone retains the link to the original file. – Nyerguds Jan 24 '18 at 13:16
  • @Nyerguds ReferenceSource says: [No, it does not](https://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/Image.cs,331) – Sir Rufo Jan 24 '18 at 13:45
  • The actual cloning is done by the GDI+ system, which is also what does the original creation from file. That code says nothing, since you don't know what's inside `GdipCloneImage`. – Nyerguds Jan 24 '18 at 13:50
  • @Nyerguds It says enough: Image class is not aware of the stream of the Bitmap class or the link to the original file. How can the link be copied without knowing it? – Sir Rufo Jan 24 '18 at 14:04
  • @Nyerguds BTW: Did you test it? I did, and it was working like a charm – Sir Rufo Jan 24 '18 at 14:05
  • Image class isn't what is manipulating the image. It is just a wrapper around GDI+ handling of the image. [Here's an extensive study.](https://stackoverflow.com/questions/12709360/whats-the-difference-between-bitmap-clone-and-new-bitmapbitmap/13935966#13935966) – Nyerguds Jan 24 '18 at 14:06
  • Do note, "It works when I tested it" is a _very_ dangerous distinction from "it always works reliably", especially when external unmanaged systems like GDI+ are involved. – Nyerguds Jan 24 '18 at 14:07
0

Well, you can use Image.FromStream instead Image.FromFile and wrap stream you're reading from into using to make sure it will be released after you've done reading.

using (var stream = File.Open(strImageFile, FileMode.Open))
{
     myPictureBox.Image = Image.FromStream(stream);
}
Andrey Korneyev
  • 26,353
  • 15
  • 70
  • 71
  • That won't work I guess. You're closing the stream which the Image class is in need of. Think of it, what should happen when you call `Bitmap.SetPixel`. – Sriram Sakthivel May 05 '15 at 12:36
  • @SriramSakthivel Your guess is wrong. ;) Actually I've tested it, and it works - so it looks like you don't need to keep stream open after you've done with `Image.FromStream` – Andrey Korneyev May 05 '15 at 12:42
  • 1
    `Image.FromStream` [documentation says](https://msdn.microsoft.com/en-us/library/93z9ee4x%28v=vs.110%29.aspx) that **You must keep the stream open for the lifetime of the Image.** – Sriram Sakthivel May 05 '15 at 12:44
  • @SriramSakthivel As I've said - I tested this approach, and it works - image was dispayed correctly in picturebox and source file was not locked. More than - if you'll have a look into `Image` class sources (`EnsureSave` method which in fact reads image from stream) - you'll see there is no need for stream to be open after `EnsureSave` completion). So I don't know why MSDN insists on stream to be open after `Image.FromStream` completion. – Andrey Korneyev May 05 '15 at 12:56
  • 1
    The fact that it merely works doesn't mean it will continue to work. If documentation doesn't talks about it, we could assume it will work, but when docs explicitly says you must keep the stream open, you ought to keep it open. I'm afraid to use something which is against the documentation, because they could change the implementation anytime they want. – Sriram Sakthivel May 05 '15 at 13:17
  • The only way to do this right is [a deep clone of the image data](https://stackoverflow.com/a/48170549/395685) into a new `Bitmap` object created with a constructor without any kind of source argument. – Nyerguds Jan 24 '18 at 13:18