简体   繁体   中英

How to save edited System.Drawing.Bitmap to the same file

I am developing a simple graphic application: Upload an image, edit it, and save it. I have tried various ways and they all fail somehow.

I have first tried loading the bitmap like this:

imageFromName = new Bitmap(FileName1);

and save it like this:

imageFromName.Save(FileName1);

but it threw a "Generic error in GDI +." exception.Also, at this point the windows explorer did not allow me to delete the file, so I thought the problem was that the object "imageFromName" kept the file open and did not allow to overwrite it, so I modified the code like this:

imageFromName = new Bitmap(FileName1);
imageCloned = (Bitmap)imageFromName.Clone();
imageFromName.Dispose();
imageCloned.Save(FileName1);

The program keeps throwing the same exception in imageCloned.Save (FileName1) So I looked for help on Stackoverflow and saw several similar questions with answers that advised to check if the app had write permission. So I modified the code to check it like this:

imageFromName = new Bitmap(FileName1);
imageFromName.Save(FileName2);

In this case, the program did not throw any exceptions when saving the file, but I still couldn't modify the original file and still couldn't delete it with Windows Explorer. It just created a copy of the file for me.

So I thought about loading the Bitmap in an alternative way and modified the code like this:

 try
 {
       System.IO.FileStream fs = new System.IO.FileStream(FileName1, System.IO.FileMode.Open);
       imageFromStream = new System.Drawing.Bitmap(fs);
       fs.Close();
 }
 catch (Exception ex)
 {
       Console.WriteLine("Error loading Bitmap.", ex);
 }

In this case the app did not throw any exceptions and the bitmap could be seen well in a PictureBox. Also, Explorer allowed me to delete the file. However, when saving the file with imageFromStream.Save (imageFromStream) it kept generating an exception for me.

The difference this time is that the Save () method, despite throwing the exception, would overwrite the original file, instead generating a 54-byte file with the header information instead.

Opening both files, original and copy, with a hex editor, I verified that the header information was the same except the image size and the offset of the BITMAPINFOHEADER. Only the information of the drawing is missing.

I have read the official Microsoft documentation on the System.Drawing.Bitmap.Save () method and have not found any kind of limitation. But I would say that it has problems with certain pixel formats.

However, I would like not to have to limit my app to 32bpp files, then:

1-What is the best way to save an image of a System.Drawing.Bitmap object to a 24bpp file?

2-Are there any more limitations on System.Drawing.Bitmap.Save () that I should know about?

When you initializing a Bitmap object from an image stored on hard disk, it creates a lock on the underlying image file. Due to lock when you try to save your modified bitmap, it throws this error.

There are two ways to fix this issue

  • Instead of overwriting the file, save a new file with a different name than the original file
  • Only when the Bitmap object is disposed, the underlying lock on the file is removed. Once the lock is removed, you may overwrite the file. If you must overwrite the existing file, create a separate bitmap object from existing bitmap object. Now dispose the old bitmap object which will release the lock on the image file. Go ahead and make the needed changes in new bitmap object and save the new bitmap object with original image file name.

The best way to save an image to a 24bpp file is to use PixelFormat.Format24bppRgb for new bitmap object.

Here is an example:

using Bitmap imageCopy = null;
using(var imageFromName = new Bitmap(FileName1))
{
    // you can modify your image here
    ...
    // Before this block ends we need to copy Bitmap
    imageCopy = new Bitmap(imageFromName); // or imageFromName.Clone with expected format
}

imageCopy.Save(FileName1);

The other way is to read image instantly without file system lock on edit:

using(var ms = new MemoryStream(File.ReadAllBytes(FileName1))
using(var image = new Bitmap(ms))
{
    // you can modify your image here
    ...
    image.Save(FileName1); 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM