20

I loaded an image into a Picture Box using:

picturebox1.Image = Image.FromFile()

and I save it by using:

Bitmap bm = new Bitmap(pictureBox1.Image);
bm.Save(FileName, ImageFormat.Bmp);

It works perfectly fine when creating a new file, but when I try to replace the existing image, I get thrown the following runtime error:

A generic error occurred in GDI+

So what can I do to solve this problem??

Vito Gentile
  • 13,336
  • 9
  • 61
  • 96
Lakshani
  • 213
  • 1
  • 3
  • 6

11 Answers11

18

That because the image file is used by your picturebox1.Image, try to save it to different file path instead:

picturebox1.Image = Image.FromFile(FileName);
Bitmap bm = new Bitmap(pictureBox1.Image); 
bm.Save(@"New File Name", ImageFormat.Bmp);

Edit: You could also add a copy from the image at the first place like:

picturebox1.Image = new Bitmap(Image.FromFile(FileName));
Bitmap bm = new Bitmap(pictureBox1.Image); 
bm.Save(FileName, ImageFormat.Bmp);//no error will occurs here.
Jalal Said
  • 15,906
  • 7
  • 45
  • 68
  • 1
    Thanks. If I want to replace, can't I do that? – Lakshani Aug 18 '11 at 09:59
  • If you want to replace, you should remove the image first from the `pictureBox.Image` then replace, and then re-add it to the `pictureBox.Image`, you can also add a copy of your image in the picture box at the first place... – Jalal Said Aug 18 '11 at 10:02
  • @Lakshani: don't forget to mark the answer that answers your question right as [accepted answer](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235) so others will know how your problem solved. – Jalal Said Aug 18 '11 at 10:22
  • plus 1 for you bud – RyeGuy Aug 29 '17 at 21:16
7

The FromFile method locks the file, so use the Image.FromStream() method for reading the image:

byte[] bytes = System.IO.File.ReadAllBytes(filename);
System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes);
pictureBox1.Image = Image.FromStream(ms);

Then save like you were before.

tronman
  • 9,862
  • 10
  • 46
  • 61
KV Prajapati
  • 93,659
  • 19
  • 148
  • 186
  • 1
    I think this may have fixed a problem I have been experiencing for months! – ScruffyDuck Aug 18 '11 at 10:23
  • Of course! @ScruffyDuck, the method **Image.FromFile** will open that image file. – KV Prajapati Aug 18 '11 at 10:26
  • @Jon nut there isn't a saving method? – Lakshani Aug 18 '11 at 11:40
  • @Lakshani I'm sorry. I didn't get you. If you want to save picturebox's image then use - Bitmap bm = new Bitmat(pictureBox1.Image); bm.Save(filename, ImageFormat.Bmp); – KV Prajapati Aug 18 '11 at 12:11
  • I'm getting this same error while trying to save the file using .Save() method. Please refer to my code which is posted here: http://stackoverflow.com/a/25968726/84199 – MoizNgp Sep 22 '14 at 10:06
  • I also tried to read from memory stream instead of using .FromFile() method, but the error is still there while trying to save. – MoizNgp Sep 22 '14 at 10:07
  • @MoizNgp Take look at this thread - http://stackoverflow.com/questions/8624071/save-and-load-memorystream-to-from-a-file/8624114#8624114 – KV Prajapati Sep 22 '14 at 10:48
4

This can also happen if the path does not exist.

You could create the dir with:

System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(FileName));
weston
  • 54,145
  • 21
  • 145
  • 203
2

When either a Bitmap object or an Image object is constructed from a file, the file remains locked for the lifetime of the object. As a result, you cannot change an image and save it back to the same file where it originated. http://support.microsoft.com/?id=814675

A generic error occurred in GDI+, JPEG Image to MemoryStream:

Image.Save(..)  // throws a GDI+ exception because the memory stream is closed

http://alperguc.blogspot.in/2008/11/c-generic-error-occurred-in-gdi.html

EDIT: Just writing from memory. Saving to an 'intermediary' MemoryStream should work:

For example, replace this:

Bitmap newBitmap = new Bitmap(thumbBMP);
thumbBMP.Dispose();
thumbBMP = null;
newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);

with something like:

string outputFileName = "...";
using (MemoryStream memory = new MemoryStream())
{
    using (FileStream fs = new FileStream(outputFileName, FileMode.Create, FileAccess.ReadWrite))
    {
        thumbBMP.Save(memory, ImageFormat.Jpeg);
        byte[] bytes = memory.ToArray();
        fs.Write(bytes, 0, bytes.Length);
    }
}
Diego Jancic
  • 7,280
  • 7
  • 52
  • 80
Mou
  • 15,673
  • 43
  • 156
  • 275
1

try this.

picturebox1.Image = Image.FromFile(FileName);
Bitmap bm = new Bitmat(pictureBox1.Image); 
Image img = (Image)b;
img.Save(FileName, ImageFormat.Bmp);
TheMuyu
  • 579
  • 2
  • 12
  • 31
  • you must define openfiledialog firstly. than read image from file and use these code. it will help to you. – TheMuyu Aug 18 '11 at 11:38
0

Just like @Jalal Aldeen Saa'd said, the picture box is using the file and locked from file replacement.

//unlock file by clearing it from picture box
if (picturebox1.Image != null)
{
   picturebox1.Image.Dispose();
   picturebox1.Image = null;
}

//put back the picture inside the pictureBox?
V-SHY
  • 3,925
  • 4
  • 31
  • 47
0

try this it will work

public void SavePicture()
{
     Bitmap bm = new Bitmap(this.myBitmap)
     bm.Save("Output\\out.bmp" ,System.Drawing.Imaging.ImageFormat.Bmp );
}
user1859022
  • 2,585
  • 1
  • 21
  • 33
Saurabh Solanki
  • 2,146
  • 18
  • 31
0

This can also happen if you forget to add the filename:

bm.Save(@"C:\Temp\Download", System.Drawing.Imaging.ImageFormat.Png);

And can be fixed by adding the file name:

bm.Save(@"C:\Temp\Download\Image.png", System.Drawing.Imaging.ImageFormat.Png);

Note: You don't actually have to add the extension for it to work.

AzzamAziz
  • 2,144
  • 1
  • 24
  • 34
0

Try this:

private void LoadPictureBoxWithImage( string ImagePath)
{
    Stream objInputImageStream = null;
    BitmapData bmdImageData = null;
    Bitmap bmpSrcImage = null, bmTemp = null;
    byte[] arrImageBytes = null;
    int bppModifier = 3;
    try
    {

        objInputImageStream = new MemoryStream();
        using (FileStream objFile = new FileStream(ImagePath, FileMode.Open, FileAccess.Read))
        {
            objFile.CopyTo(objInputImageStream);
        }

        bmpSrcImage = new Bitmap(objInputImageStream);
        bppModifier = bmpSrcImage.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4;

        //reda from byte[] to bitmap               
        bmdImageData = bmpSrcImage.LockBits(new Rectangle(0, 0, bmpSrcImage.Width, bmpSrcImage.Height), ImageLockMode.ReadOnly, bmpSrcImage.PixelFormat);
        arrImageBytes = new byte[Math.Abs(bmdImageData.Stride) * bmpSrcImage.Height];

        System.Runtime.InteropServices.Marshal.Copy(bmdImageData.Scan0, arrImageBytes, 0, arrImageBytes.Length);
        bmpSrcImage.UnlockBits(bmdImageData);

        pbSetup.Image = (Bitmap)bmpSrcImage.Clone();
        pbSetup.Refresh();

    }
    catch (Exception ex)
    {
        throw new Exception("Error in Function " + System.Reflection.MethodInfo.GetCurrentMethod().Name + "; " + ex.Message);
    }
    finally
    {
        if (objInputImageStream != null)
        {
            objInputImageStream.Dispose();
            objInputImageStream = null;
        }
        if (bmdImageData != null)
        {
            bmdImageData = null;
        }
        if (bmpSrcImage != null)
        {
            bmpSrcImage.Dispose();
            bmpSrcImage = null;
        }
        if (bmTemp != null)
        {
            bmTemp.Dispose();
            bmTemp = null;
        }
        if (arrImageBytes != null)
        {
            arrImageBytes = null;
        }
    }

}
clemens
  • 16,716
  • 11
  • 50
  • 65
0

A generic error occurred in GDI+

I also faced the same issue. I tried so many ways to fix this issue. Finally, I found a place where I have gone wrong. The problem is that I used space in the file path, which is not acceptable. Now it is working fine after removing the space in front of C after the apostrophe:

"SupplyItems":"C:\\inetpub\\HIBMS_Ver1\\BarcodeImages\\Supply\\"

instead... I used below one.

"SupplyItems":" C:\\inetpub\\HIBMS_Ver1\\BarcodeImages\\Supply\\"

Minor mistake but took a long time to find and to fix it.

pappbence96
  • 1,164
  • 2
  • 12
  • 20
0

Note that images created by Image.Clone() will still cause GDI+ errors as shown by the BAD code below, you must use the Image.FromStream() method for reading the image as shown in the solution on this page.


    //BAD CODE: the image we will try to save AFTER the original image has been cloned and disposed
    Image clonedImage;
    //load image from file, clone it then dispose
    using (var loadedFromDiskImage = Image.FromFile(filePath))
    {
         clonedImage = (Image) loadedFromDiskImage.Clone();
    } 

//you might think the new image can be saved given the original is disposed
 //but this doesn't seem to be the way Clone() works
 //expect GDI+ error in line below:
 clonedImage.Save(filePath);

yodag123
  • 141
  • 1
  • 6