-1

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?

Vadim Martynov
  • 8,602
  • 5
  • 31
  • 43
  • You may try the overloads of save, which allows you to specify an [ImageFormat](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.imaging.imageformat?view=dotnet-plat-ext-3.1) – Oguz Ozgul May 01 '20 at 23:02

1 Answers1

1

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); 
}
Vadim Martynov
  • 8,602
  • 5
  • 31
  • 43
  • Yes, but answer to "Are there any more limitations on System.Drawing.Bitmap.Save" it "It's not Bitmap.Save limition, it's lock on your file system". And the the best way to save an image of a System.Drawing.Bitmap object to a 24bpp file is to use PixelFormat.Format24bppRgb and Save method – Vadim Martynov May 02 '20 at 10:31
  • Also, here is a good explanation of cloning issues https://stackoverflow.com/a/13935966/5649561 – Vadim Martynov May 02 '20 at 10:42
  • Re: "It's not Bitmap.Save limition, it's lock on your file system": If you had read my question you would have read: "Explorer allowed me to delete the file." after using System.IO.FileStream to load the Bitmap. Re: " is to use PixelFormat.Format24bppRgb and Save method" is a very vague answer. PixelFormat can be used only with new black Bitmaps or with Clone () method. Which of the two methods are you talking about? – ORParga ORParga May 02 '20 at 19:40
  • 1-Clone: If you had read my question you would know that Clone () locks the original file even if you use Dispose (). 2- "New Bitmap (width, height, PixelFormat)" what is it for me ... do I copy the original 24bpp Bitmap over the new 24bpp file with LockBits or Graphics? Your best answer has been send me to another answer....If you had read the reply you sent me you would know that the only way to unlink the clone from the original is not to use PixelFormat.blahblahblah but to perform some kind of write operation on the clone. – ORParga ORParga May 02 '20 at 19:41
  • PD: StackOverflow gives extra reputation just clicking on "edit question" button? – ORParga ORParga May 02 '20 at 19:41