50

I have an image uploader and cropper which creates thumbnails and I occasionally get an Out Of Memory exception on the following line:

Dim bm As Bitmap = System.Drawing.Image.FromFile(imageFile)

The occurance of the error is tiny and very rare, but I always like to know what might be causing it. The imageFile variable is just a Server.MapPath to the path of the image.

I was curious if anyone had experience this issue previously and if they had any ideas what might be causing it? Is it the size of the image perhaps?

I can post the code if necessary and any supporting information I have, but would love to hear people's opinions on this one.

dooburt
  • 3,010
  • 10
  • 41
  • 59
  • Is the image you're trying to load exceptionally large? – RCIX Jul 10 '09 at 09:28
  • All images are less than ~700kb. – dooburt Jul 10 '09 at 09:55
  • 3
    Are you sure the file in question is a valid image file? I have also run into exactly the same situation, but the the file hasn't been able to load in any other program either. – Dan Byström Jul 10 '09 at 09:57
  • Note: with valid image file I didn't refer to the file type but the content. That is: could the image data be damaged? – Dan Byström Jul 10 '09 at 09:58
  • 1
    I danby, thanks for the response. It isn't my image, so I'm having it sent over and will get it checked. The person uploading is particularly incompetent so I'm hoping it is just that! – dooburt Jul 10 '09 at 10:47
  • 1
    Ok, the image was damaged. Problem solved. Thanks guys. Danby, if you add you answer, I'll mark it as correct ;) – dooburt Jul 10 '09 at 11:02
  • Had a similar problem. Noticed System.Drawing.Image.FromFile raises an OutOfMemoryException when trying to read corrupt files. This can be reproduce if you create a 0 byte image file and then try to read it from file as you have done. – Sola Oderinde Jan 21 '15 at 10:20
  • I had the same issue trying to open some PNG files. I looked at them with a text editor and saw that the first line was `RIFF¶Q WEBPVP8X`... so I renamed them with the extension `.webp` and all worked; so looks like they'd just been misnamed – JohnLBevan Jul 22 '23 at 08:24

13 Answers13

48

It's worth knowing that OutOfMemoryException doesn't always really mean it's out of memory - particularly not when dealing with files. I believe it can also happen if you run out of handles for some reason.

Are you disposing of all your bitmaps after you're done with them? Does this happen repeatably for a single image?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Hi Jon, thanks for the quick reply. Yes, I dispose of both the image and the graphics. Dim bmPhoto As New Bitmap(targetW, targetH, PixelFormat.Format24bppRgb) Dim grPhoto As Graphics = Graphics.FromImage(bmPhoto) bmPhoto.Dispose() bmPhoto = Nothing grPhoto.Dispose() grPhoto = Nothing As for the repeatability, no it is exceedingly random - but the images always tend to be larger (though no bigger than 700k~). – dooburt Jul 10 '09 at 09:55
  • 4
    I suspect that it may not be file size, but in-memory image size - a very heavily compressed image with a massive number of pixels might cause you issues... – Jon Skeet Jul 10 '09 at 09:56
  • 2
    Hi Jon, thanks for the comment. Turns out to be a damaged image all along. *sigh*. An incompetent user. Thanks for your answers though :) – dooburt Jul 10 '09 at 11:10
  • 10
    How did you determine that the image was corrupted? I'm also having these OutOfMemoryException errors when doing Image.FromFile. What's peculiar is that it only throws the exception on one server, and not another. Could I be missing some essential encoder? This is a 4256x2832 24bpp sRGB JPEG downloaded from Getty images. – Mark Richman Jun 21 '10 at 15:27
  • 1
    Hey Mark, I simply tried to open the image directly via the OS. It couldn't open it. Neither could Photoshop or any other image software. This was causing the throw. – dooburt Sep 16 '14 at 10:49
38

If this wasn't a bad image file but was in fact the normal issue with Image.FromFile wherein it leaves file handles open, then the solution is use Image.FromStream instead.

using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
   using (Image original = Image.FromStream(fs))
   {
      ...

Using an explicit Dispose(), a using() statement or setting the value to null on the bitmap doesn't solve the issue with Image.FromFile.

So if you App runs for a time and opens a lot of files consider using Image.FromStream() instead.

Ian Mercer
  • 38,490
  • 8
  • 97
  • 133
  • Actually, if you dispose of a stream that is bound to a file through an unmanaged handle, the handle will be closed there and then, no waiting for GC to occur at all. After all, that's the whole point of IDisposable to begin with. – Lasse V. Karlsen Mar 29 '11 at 19:44
  • This can be taken a step further too. http://blogs.msdn.com/b/omars/archive/2004/03/29/100941.aspx, still seems to apply. –  Mar 30 '11 at 18:11
  • 1
    what about pdf with alpha in this case? – Berker Yüceer Jun 12 '12 at 08:26
  • 2
    Why doesn't calling Dispose() release the file handle for the image? Is this just a bug in the implementation? Why has Microsoft never fixed this bug? Obviously, using a stream is better for many reasons, but seems that Microsoft should've fixed this issue or removed the method altogether. – crush Dec 15 '15 at 16:11
7

I hit the same issue today while creating Thumbnail images for a folder full of images. It turns out that the "Out Of Memory" occured exactly at the same point each time. When I looked at the folder with the images to be converted I found that the file that was creating the problem was thumbs.db. I added some code to make sure that only image files were being converted and the issue was resolved.

My code is basically

For Each imageFile as FileInfo in fileList
If imageFile.Extension = ".jpg" Or imageFile.Extension = ".gif" Then
    ...proceed with the conversion
End If
Next

Hope this helps.

sjngm
  • 12,423
  • 14
  • 84
  • 114
4

Also check if you haven't opened the same file somewhere else. Apparently, when you open a file twice (even with File.Open()) OutOfMemoryException is thrown too...

pinus.acer
  • 962
  • 1
  • 9
  • 28
3

Also you can open it in read mode, (if you want to use it in two place same time)

 public Image OpenImage(string previewFile)
        {
            FileStream fs = new FileStream(previewFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            return Image.FromStream(fs);
        }
Avram
  • 4,267
  • 33
  • 40
2

This happens when the image file is corrupted. It is a bad error message, because memory has nothing to do with it. I haven;t worked out the coding, but a try/catch/finally will stop the program from abending.

1

If an image is an icon then different loading handling is required, like in next function:

public static Image loadImage(string imagePath)
    {
        Image loadedImage = null;
        if (!File.Exists(imagePath)) return loadedImage;
        try
        {
            FileInfo fileInfo = new FileInfo(imagePath);
            if (fileInfo.Extension.Equals(".jpg") || fileInfo.Extension.Equals(".jpeg") ||
               fileInfo.Extension.Equals(".bmp") || fileInfo.Extension.Equals(".png") ||
               fileInfo.Extension.Equals(".gif"))
            {
                loadedImage = Image.FromFile(imagePath);
            }
            else if (fileInfo.Extension.Equals(".ico"))
            {
                Bitmap aBitmap = Bitmap.FromHicon(new
                                           Icon(imagePath, new Size(200, 200)).Handle);
                loadedImage = ImageFuncs.ResizeImage(aBitmap, new Size(30, 30));
            }
        }
        catch (Exception eLocal)
        {
            MessageBox.Show(imagePath + " loading error: " + eLocal.Message);
        }
        return loadedImage;
    }
IrinaL
  • 11
  • 2
1

I had the same problem with a utility I wrote to convert TIFF(s) to PDF(s). Often I would get the "out of memory" error on the same line as you.

System.Drawing.Image.FromFile(imageFile)

Then I discovered the error only happened when the file extension was ".tiff" and worked fine after I renamed it with an extension of ".tif"

1

I have had the same issue, before looking else where in the code wanted to make sure if I can open the Image with any Image viewer and figured out that the Image is corrupted/damaged though it's a .PNG file with 1KB size. Added a new Image in the same location, then It worked fine.

Kiran Modini
  • 1,184
  • 8
  • 5
1

I had a similar problem today when I was trying to resize an image and then crop it, what happened is I used this code to resize the image.

private static Image resizeImage(Image imgToResize, Size size)
{
   int sourceWidth = imgToResize.Width;
   int sourceHeight = imgToResize.Height;

   float nPercent = 0;
   float nPercentW = 0;
   float nPercentH = 0;

   nPercentW = ((float)size.Width / (float)sourceWidth);
   nPercentH = ((float)size.Height / (float)sourceHeight);

   if (nPercentH < nPercentW)
      nPercent = nPercentH;
   else
      nPercent = nPercentW;

   int destWidth = (int)(sourceWidth * nPercent);
   int destHeight = (int)(sourceHeight * nPercent);

   Bitmap b = new Bitmap(destWidth, destHeight);
   Graphics g = Graphics.FromImage((Image)b);
   g.InterpolationMode = InterpolationMode.HighQualityBicubic;

   g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
   g.Dispose();

   return (Image)b;
}

And then this code for the crop...

private static Image cropImage(Image img, Rectangle cropArea)
{
   Bitmap bmpImage = new Bitmap(img);
   Bitmap bmpCrop = bmpImage.Clone(cropArea,
   bmpImage.PixelFormat);
   return (Image)(bmpCrop);
}

Then this is how I called the above code...

Image img = Image.FromFile(@"C:\Users\****\Pictures\image.jpg");
img = ImageHandler.ResizeImage(img, new Size(400, 300));
img = ImageHandler.CropImage(img, new Rectangle(0, 25, 400, 250));
long quality = 90;

I kept getting errors on the crop part, the resizer worked fine!

Turns out, what was happening inside the resizer was throwing errors in the crop function. The resized calculations were making the actual dimensions of the image come out to be like 399 rather than 400 that I passed in.

So, when I passed in 400 as the argument for the crop, it was trying to crop a 399px wide image with a 400px width bmp and it threw the out of memory error!

Most of the above code was found on http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing

jcreamer898
  • 8,109
  • 5
  • 41
  • 56
0

I am having same problem batch processing Tiff files. Most of the files aren't throwing an exception but few files are throwing "Out of Memory" exception in ASP.NET 4.0. I have used binary data to find out why just for few files and from within same folder. It can't be permission issue for ASP.NET ASPNET or NETWORK SERVICE account because other files are working file.

I have opened iTextSharp.text.Image class and found that there are many overloaded methods for GetInstance(). I have resolved my problem using following code: note: catch block will run for problematic files.

                iTextSharp.text.Image image = null;
            try
                {
                    var imgStream = GetImageStream(path);
                     image = iTextSharp.text.Image.GetInstance(imgStream);
                }
                catch {
                    iTextSharp.text.pdf.RandomAccessFileOrArray ra = null;
                    ra = new iTextSharp.text.pdf.RandomAccessFileOrArray(path);
                    image = iTextSharp.text.pdf.codec.TiffImage.GetTiffImage(ra, 1);

                    if (ra != null)
                        ra.Close();

                }
  • Where is GetImageStream(path) method in this case? Once you have image object of iTextSharp.text.Image, how do you convert it to System.Drawing.Image object? – Chirag Apr 23 '15 at 19:01
0

If you're serving from IIS, try recycling the Application Pool. This solved a similar image upload "Out of Memory" error for me.

Rich
  • 2,164
  • 1
  • 25
  • 39
  • I did this after trying numerous things - stripping meta data from the image, renaming the file before upload, uploading to another part of the system, uploading a simple (and smaller image) - all without success, tried the aforementioned recycle before successfully uploading the original image. – Rich May 20 '19 at 15:32
0

I created a minimal form example that still gives me errors.

        private void button1_Click(object sender, EventArgs e)
    {
        string SourceFolder = ImageFolderTextBox.Text;
        string FileName = "";
        DirectoryInfo Mydir = new DirectoryInfo(SourceFolder);
        FileInfo[] JPEGS = Mydir.GetFiles("*.jpg");
        for (int counter = 0; counter < JPEGS.Count(); counter++)
        {
            FileName = Mydir + "\\" + JPEGS[counter].Name;
            //using (Image MyImage = System.Drawing.Image.FromFile(FileName))
            using (FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                StatusBtn.BackColor = Color.Green;
            }
        }
    }

I tried both the commented out line using Image.FromFile() as well as the line using FileStream(). Both produced file errors.

The Image.FromFile() error was: System.OutOfMemoryException: 'Out of Memory'

The filestream() error was: System.UnaurthorizedAccessException: 'Access to the path 'E:\DCIM\100Canon\dsc_7218.jpg' is denied.

I placed a Breakpoint just prior to the lines producing the error and I am able to open the image file using the Windows image viewer. I then closed the viewer and after I advanced to the next line and get the error, I can no longer view the image with the Windows viewer. Instead, I get a message that I do not have permission to access the file. I am able to delete the file.

This error is repeatable. I've done it over 10 times. Each time, after I get the error, I delete the file used for FileName.

All files were verified to be non-corrupt.

My original code that used Image.FromFile() worked fine when I compiled it 2 years ago. In fact, the .exe file runs just fine. I made a minor change somewhere else in the code and was surprised to find that the code would not compile without this error. I tried the FileStream() method based on the information on this page.

Adrian Hood Sr
  • 405
  • 5
  • 18