views:

50

answers:

3

How to do this in C#?

If I use Bitmap.FromFile(), the original file is locked.

If I use Bitmap.FromStream(), the original file is not locked, but the documentation says "You must keep the stream open for the lifetime of the Image." This probably means that the file is still linked to the image object, (for example, perhaps if the file change so do the object or vice versa).

what i want to do is just reading the bitmap and save it to an object and after that there is no link whatsoever between the file and the Image object

+4  A: 

Read the file into memory by copying it from a FileStream into a MemoryStream. (Search for CopyStream in Stack Overflow to find plenty of examples of how to do that safely. Basically loop while reading, writing each chunk to the memory stream, until there's no more data to read.) Then rewind the MemoryStream (set Position = 0) and then pass that to Bitmap.FromStream.

Jon Skeet
+3  A: 

In order to create an image without locking the file, you'll have to create a copy of the image's FileStream. Check this page Best way to copy between two Stream instances - C# for how to copy the stream.

Afterwards just create your image from the copied stream and you're ready to go.

Alex Essilfie
+1 for doing the search for us that Jon suggested we should do... You found a very good post for this.
awe
+3  A: 

Some background info on this behavior: Bitmap uses a memory-mapped file to access the pixels in the bitmap. That's a very basic facility in the Windows API, it allows very efficient mapping of memory to file data. Data is read from the file only when the program read the memory, the virtual memory pages don't take any space in the Windows paging file.

The exact same mechanism is used to load .NET assemblies. It is the memory mapping that puts a lock on the file. Which is basically why assemblies are locked when they are used in a .NET program. The Image.Dispose() method releases the lock. Fighting the lock often indicates that you are forgetting to dispose your bitmaps. Very important, forgetting to call Dispose() doesn't often cause problems for .NET classes, except for Bitmap since it can need so much (unmanaged) memory.

Yes, FromStream() prevents the class from making this optimization. The cost is significant, you'll need double the memory when the bitmap is loaded. This will be a problem when the bitmap is large, you're skirting OOM when the program has been running for a while (fragmenting the address space) and its not running on a 64-bit operating system. Definitely avoid doing this if the bitmap's Width x Height x 4 >= 45 MB, give or take.

Some code, you don't have to jump through the CopyStream hoop:

    public static Image LoadImageNoLock(string path) {
        using (var ms = new MemoryStream(File.ReadAllBytes(path))) {
            return Image.FromStream(ms);
        }
    }
Hans Passant