75

I am working on to upload and save a thumbnail copy of that image in a thumbnail folder.

I am using following link:

http://weblogs.asp.net/markmcdonnell/archive/2008/03/09/resize-image-before-uploading-to-server.aspx

but

newBMP.Save(directory + "tn_" + filename);   

is causing exception "A generic error occurred in GDI+."

I have tried to give permission on folder, also tried to use a new separate bmp object when saving.

Edit:

    protected void ResizeAndSave(PropBannerImage objPropBannerImage)
    {
        // Create a bitmap of the content of the fileUpload control in memory
        Bitmap originalBMP = new Bitmap(fuImage.FileContent);

        // Calculate the new image dimensions
        int origWidth = originalBMP.Width;
        int origHeight = originalBMP.Height;
        int sngRatio = origWidth / origHeight;
        int thumbWidth = 100;
        int thumbHeight = thumbWidth / sngRatio;

        int bannerWidth = 100;
        int bannerHeight = bannerWidth / sngRatio;

        // Create a new bitmap which will hold the previous resized bitmap
        Bitmap thumbBMP = new Bitmap(originalBMP, thumbWidth, thumbHeight);
        Bitmap bannerBMP = new Bitmap(originalBMP, bannerWidth, bannerHeight);

        // Create a graphic based on the new bitmap
        Graphics oGraphics = Graphics.FromImage(thumbBMP);
        // Set the properties for the new graphic file
        oGraphics.SmoothingMode = SmoothingMode.AntiAlias; oGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

        // Draw the new graphic based on the resized bitmap
        oGraphics.DrawImage(originalBMP, 0, 0, thumbWidth, thumbHeight);

        Bitmap newBitmap = new Bitmap(thumbBMP);
        thumbBMP.Dispose();
        thumbBMP = null;

        // Save the new graphic file to the server
        newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);

        oGraphics = Graphics.FromImage(bannerBMP);
        // Set the properties for the new graphic file
        oGraphics.SmoothingMode = SmoothingMode.AntiAlias; oGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

        // Draw the new graphic based on the resized bitmap
        oGraphics.DrawImage(originalBMP, 0, 0, bannerWidth, bannerHeight);
        // Save the new graphic file to the server
        bannerBMP.Save("~/image/" + objPropBannerImage.ImageId + ".jpg");


        // Once finished with the bitmap objects, we deallocate them.
        originalBMP.Dispose();

        bannerBMP.Dispose();
        oGraphics.Dispose();
    }
Cœur
  • 32,421
  • 21
  • 173
  • 232
donstack
  • 2,193
  • 3
  • 22
  • 39

17 Answers17

104

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...

save to an 'intermediary' memory stream, that should work

e.g. try this one - replace

    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);
    }
}
Community
  • 1
  • 1
NSGaga-mostly-inactive
  • 13,264
  • 3
  • 38
  • 50
  • thanks, using these i got it working. I am posting the code working again. – donstack Apr 07 '13 at 14:49
  • 2
    A related issue, maybe it will help someone - I got the "A Generic error occured in GDI+" on _opening_ a bitmap already. And only on a remote webserver, not on my local test machine. Turns out that the GDI+ present on Azure IIS servers can't handle new format BMPs generated by GIMP. I had to either a) resave BMP with Paint b) use an uncompressed PNG instead c) save as 24bit BMP with GIMP (worse quality) – Andrew Apr 20 '15 at 08:20
  • Not sure what I was doing wrong in a project I was tinkering with... but for some reason, the MemoryStream/FileStream combo worked for me (with minor variations to account for my particular method call). Here's a +1 for a 5 year old post. – WernerCD Mar 23 '18 at 13:11
  • 1
    @WernerCD I know, the problem (and the fix) is a bit counterintuitive - but the oversimplified explanation underlying this (in many cases, depending on the specifics) is that you need to break away from the original bitmap object (and its references), and memory stream helps with that. – NSGaga-mostly-inactive Mar 23 '18 at 15:20
  • @NSGaga Well I was using MS's (I pulled a file from a PDF into an Bitmap/Image object)... but when I tried to pull that Bitmap/Image object out and put it onto the disk it was crapping itself. The `Memory /FileStream` vs `bitmap.Save(...)` is I think the counter-intuitive step that worked for me. I think. Irregardless, this gave me the push I was looking for after HOURS of circling the problem. – WernerCD Mar 23 '18 at 15:23
53

This error message is displayed if the path you pass to Bitmap.Save() is invalid (folder doesn't exist etc).

Reg Edit
  • 5,712
  • 1
  • 29
  • 41
  • 7
    certainly this was the case with me, I up voted it so no one else should waste any further time. also make sure your path does include filename as well. – ahsant Sep 19 '16 at 01:49
  • 23
    how stupid that the error cant just report such a basic issue – Dan Hastings Jul 24 '17 at 11:23
14
    // Once finished with the bitmap objects, we deallocate them.
    originalBMP.Dispose();

    bannerBMP.Dispose();
    oGraphics.Dispose();

This is a programming style that you'll regret sooner or later. Sooner is knocking on the door, you forgot one. You are not disposing newBitmap. Which keeps a lock on the file until the garbage collector runs. If it doesn't run then the second time you try to save to the same file you'll get the klaboom. GDI+ exceptions are too miserable to give a good diagnostic so serious head-scratching ensues. Beyond the thousands of googlable posts that mention this mistake.

Always favor using the using statement. Which never forgets to dispose an object, even if the code throws an exception.

using (var newBitmap = new Bitmap(thumbBMP)) {
    newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);
}

Albeit that it is very unclear why you even create a new bitmap, saving thumbBMP should already be good enough. Anyhoo, give the rest of your disposable objects the same using love.

Hans Passant
  • 873,011
  • 131
  • 1,552
  • 2,371
8

In my case the bitmap image file already existed in the system drive, so my app threw the error "A Generic error occured in GDI+".

  1. Verify that the destination folder exists
  2. Verify that there isn't already a file with the same name in the destination folder
Marcos Dimitrio
  • 5,592
  • 3
  • 33
  • 56
Palanikumar
  • 6,172
  • 4
  • 34
  • 47
6

Check your folder's permission where the image is saved Right cLick on folder then go :

Properties > Security > Edit > Add-- select "everyone" and check Allow "Full Control"

Tolga Evcimen
  • 6,438
  • 10
  • 52
  • 82
Asad
  • 289
  • 3
  • 5
5

I was facing the same issue A generic error occurred in GDI+ on saving while working on MVC app, I was getting this error because I was writing wrong path to save image, I corrected saving path and it worked fine for me.

img1.Save(Server.MapPath("/Upload/test.png", System.Drawing.Imaging.ImageFormat.Png);


--Above code need one change, as you need to put close brackets on Server.MapPath() method after writing its param.

Like this-

img1.Save(Server.MapPath("/Upload/test.png"), System.Drawing.Imaging.ImageFormat.Png);
Chandan
  • 149
  • 1
  • 15
Anjan Kant
  • 3,168
  • 31
  • 34
4

GDI+ exceptions occured due to below points

  1. Folder access issue
  2. Missing properties of images

If folder issue - please provide access to application If Missing properties then use below code

Code 1

using (Bitmap bmp = new Bitmap(webStream))
{
     using (Bitmap newImage = new Bitmap(bmp))
     {
         newImage.Save("c:\temp\test.jpg", ImageFormat.Jpeg);
     }
}

Code 2

using (Bitmap bmp = new Bitmap(webStream))
{

     using (Bitmap newImage = new Bitmap(bmp))
     {
        newImage.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
        Rectangle lockedRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        BitmapData bmpData = newImage.LockBits(lockedRect, ImageLockMode.ReadWrite, bmp.PixelFormat);
        bmpData.PixelFormat = bmp.PixelFormat;
        newImage.UnlockBits(bmpData);
        using (Graphics gr = Graphics.FromImage(newImage))
         {
             gr.SmoothingMode = SmoothingMode.HighQuality;
             gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
             gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
         }

         foreach (var item in bmp.PropertyItems)
         {
             newImage.SetPropertyItem(item);
         }
         newImage.Save("c:\temp\test.jpg", ImageFormat.Jpeg);
    }
}

Different between code 1 and code 2

Code - 1 : it will just create image and can open it on normal image viewer

  • the image can't open in Photoshop
  • Image size will be double

Code - 2 : to open image in image edition tools use code

by using code 1 it just create images but it not assign image marks.

3

I always check/test these:

  • Does the path + filename contain illegal characters for the given filesystem?
  • Does the file already exist? (Bad)
  • Does the path already exist? (Good)
  • If the path is relative: am I expecting it in the right parent directory (mostly bin/Debug ;-) )?
  • Is the path writable for the program and as which user does it run? (Services can be tricky here!)
  • Does the full path really, really not contain illegal chars? (some unicode chars are close to invisible)

I never had any problems with Bitmap.Save() apart from this list.

Xan-Kun Clark-Davis
  • 1,877
  • 1
  • 24
  • 32
2

I had a different issue with the same exception.

In short:

Make sure that the Bitmap's object Stream is not being disposed before calling .Save .

Full story:

There was a method that returned a Bitmap object, built from a MemoryStream in the following way:

private Bitmap getImage(byte[] imageBinaryData){
    .
    .
    .
    Bitmap image;
    using (var stream = new MemoryStream(imageBinaryData))
    {
        image = new Bitmap(stream);
    }
    return image;
}

then someone used the returned image to save it as a file

image.Save(path);

The problem was that the original stream was already disposed when trying to save the image, throwing the GDI+ exeption.

A fix to this problem was to return the Bitmap without disposing the stream itself but the returned Bitmap object.

private Bitmap getImage(byte[] imageBinaryData){
   .
   .
   .
   Bitmap image;
   var stream = new MemoryStream(imageBinaryData))
   image = new Bitmap(stream);

   return image;
}

then:

using (var image = getImage(binData))
{
   image.Save(path);
}
Yan
  • 413
  • 2
  • 16
  • This is a great answer and it is a shame it is buried under the many duplicate answers related to bad path. The underlying stream cannot be destroyed. An alternative is to create a new bitmap from the old one: new Bitmap(oldBitmap).Save(...) – Corey Alix Jul 27 '20 at 17:49
1

I got it working using FileStream, get help from these
http://alperguc.blogspot.in/2008/11/c-generic-error-occurred-in-gdi.html http://csharpdotnetfreak.blogspot.com/2010/02/resize-image-upload-ms-sql-database.html

System.Drawing.Image imageToBeResized = System.Drawing.Image.FromStream(fuImage.PostedFile.InputStream);
        int imageHeight = imageToBeResized.Height;
        int imageWidth = imageToBeResized.Width;
        int maxHeight = 240;
        int maxWidth = 320;
        imageHeight = (imageHeight * maxWidth) / imageWidth;
        imageWidth = maxWidth;

        if (imageHeight > maxHeight)
        {
            imageWidth = (imageWidth * maxHeight) / imageHeight;
            imageHeight = maxHeight;
        }

        Bitmap bitmap = new Bitmap(imageToBeResized, imageWidth, imageHeight);
        System.IO.MemoryStream stream = new MemoryStream();
        bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
        stream.Position = 0;
        byte[] image = new byte[stream.Length + 1];
        stream.Read(image, 0, image.Length);
        System.IO.FileStream fs
= new System.IO.FileStream(Server.MapPath("~/image/a.jpg"), System.IO.FileMode.Create
, System.IO.FileAccess.ReadWrite);
            fs.Write(image, 0, image.Length);
donstack
  • 2,193
  • 3
  • 22
  • 39
1

For me it was a permission problem. Somebody removed write permissions on the folder for the user account under which the application was running.

Krisztián Balla
  • 15,886
  • 11
  • 58
  • 69
0

Create folder path image/thumbs on your hard disk => Problem solved!

Chưa biết
  • 751
  • 7
  • 5
0
    I used below logic while saving a .png format. This is to ensure the file is already existing or not.. if exist then saving it by adding 1 in the filename

Bitmap btImage = new Bitmap("D:\\Oldfoldername\\filename.png");
    string path="D:\\Newfoldername\\filename.png";
            int Count=0;
                if (System.IO.File.Exists(path))
                {
                    do
                    {
                        path = "D:\\Newfoldername\\filename"+"_"+ ++Count + ".png";                    
                    } while (System.IO.File.Exists(path));
                }

                btImage.Save(path, System.Drawing.Imaging.ImageFormat.Png);
0

I encountered this error while trying to convert Tiff images to Jpeg. For me the issue stemmed from the tiff dimensions being too large. Anything up to around 62000 pixels was fine, anything above this size produced the error.

RichTea88
  • 11
  • 2
0

for me it was a path issue when saving the image.

int count = Directory.EnumerateFiles(System.Web.HttpContext.Current.Server.MapPath("~/images/savedimages"), "*").Count();

var img = Base64ToImage(imgRaw);

string path = "images/savedimages/upImages" + (count + 1) + ".png";

img.Save(Path.Combine(System.Web.HttpContext.Current.Server.MapPath(path)));

return path;

So I fixed it by adding the following forward slash

String path = "images/savedimages....

should be

String path = "/images/savedimages....

Hope that helps anyone stuck!

imBlue
  • 114
  • 1
  • 11
0

from msdn: public void Save (string filename); which is quite surprising to me because we dont just have to pass in the filename, we have to pass the filename along with the path for example: MyDirectory/MyImage.jpeg, here MyImage.jpeg does not actually exist yet, but our file will be saved with this name.

Another important point here is that if you are using Save() in a web application then use Server.MapPath() along with it which basically just returns the physical path for the virtual path which is passed in. Something like: image.Save(Server.MapPath("~/images/im111.jpeg"));

Fakhar Ahmad Rasul
  • 1,253
  • 12
  • 24
0

I use this solution

int G = 0;

private void toolStripMenuItem17_Click(object sender, EventArgs e)
{
  Directory.CreateDirectory("picture");// هذه العملية للرسم بدون ان يحذف بقية الرسومات
  G = G + 1;
  FormScreen();
  memoryImage1.Save("picture\\picture" + G.ToString() + ".jpg");
  pictureBox1.Image = Image.FromFile("picture\\picture" + G.ToString() + ".jpg");
}
LarsTech
  • 77,282
  • 14
  • 135
  • 204
Raho
  • 1
  • 1