System.Drawing.Image.FromFile()上的Out of Memory异常

时间:2009-07-10 09:27:01

标签: asp.net image bitmap

我有一个图像上传器和裁剪器,它会创建缩略图,我偶尔会在以下行中获得Out Of Memory异常:

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

错误的发生是微小的,非常罕见,但我总是想知道可能导致它的原因。 imageFile变量只是一个Server.MapPath到图像的路径。

我很好奇,如果有人之前遇到过这个问题,他们是否有任何想法可能导致它?这可能是图像的大小吗?

如果有必要,我可以发布代码和我所拥有的任何支持信息,但我很乐意听到人们对此的看法。

13 个答案:

答案 0 :(得分:40)

值得知道的是OutOfMemoryException并不总是真的意味着内存不足 - 尤其是在处理文件时。我相信如果你出于某种原因用完手柄也会发生这种情况。

你完成它们之后是否处理了所有的位图?对于单个图像,这是否会重复发生?

答案 1 :(得分:33)

如果这不是一个糟糕的图像文件,但实际上是Image.FromFile的正常问题,其中文件句柄打开,那么解决方案就是使用Image.FromStream

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

使用明确的Dispose()using()语句或在位图上将值设置为null无法解决Image.FromFile的问题。

因此,如果您的App运行一段时间并打开了大量文件,请考虑使用Image.FromStream()

答案 2 :(得分:6)

今天我在为一个装满图片的文件夹创建缩略图图像时遇到了同样的问题。事实证明,“Out Of Memory”每次恰好出现在同一点。当我查看包含要转换的图像的文件夹时,我发现创建问题的文件是thumbs.db。我添加了一些代码以确保只转换图像文件并解决了问题。

我的代码基本上是

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

希望这有帮助。

答案 3 :(得分:3)

你也可以在阅读模式下打开它(如果你想在同一时间在两个地方使用它)

 public Image OpenImage(string previewFile)
        {
            FileStream fs = new FileStream(previewFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            return Image.FromStream(fs);
        }

答案 4 :(得分:2)

同时检查您是否在其他地方没有打开同一个文件。显然,当您打开文件两次时(即使使用File.Open())也会抛出OutOfMemoryException ......

答案 5 :(得分:1)

今天我遇到类似的问题,当我试图调整图像大小然后裁剪它时,发生的事情是我使用此代码来调整图像大小。

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;
}

然后这个作物的代码......

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

然后我就是这样调用上面的代码......

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;

我一直在作物部分出现错误,缩放器工作正常!

事实证明,缩放器内部发生的事情是在裁剪功能中抛出错误。调整大小的计算使得图像的实际尺寸达到了399而不是我传入的400.

所以,当我传入400作为裁剪的参数时,它试图裁剪宽度为400像素bmp的399像素宽的图像并且它抛出了内存不足错误!

上述大部分代码都在http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing

上找到

答案 6 :(得分:1)

如果图像是图标,则需要不同的加载处理,如下一个功能:

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;
    }

答案 7 :(得分:1)

我在编写将TIFF转换为PDF(s)的实用程序时遇到了同样的问题。通常我会得到内存和#34;与你在同一条线上的错误。

System.Drawing.Image.FromFile(imageFile)

然后我发现错误只发生在文件扩展名为&#34; .tiff&#34;我用#34; .tif&#34;

的扩展名重命名后工作得很好

答案 8 :(得分:0)

我有同样的问题批处理Tiff文件。大多数文件都没有抛出异常,但很少有文件丢弃&#34; Out of Memory&#34; ASP.NET 4.0中的异常。我已经使用二进制数据来找出为什么只有少数文件和来自同一文件夹。它不是ASP.NET ASPNET或NETWORK SERVICE帐户的权限问题,因为其他文件是工作文件。

我打开了iTextSharp.text.Image类,发现GetInstance()有很多重载方法。我使用以下代码解决了我的问题:注意:catch块将针对有问题的文件运行。

                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();

                }

答案 9 :(得分:0)

我遇到了同样的问题,在查找其他代码之前需要确保我是否可以使用任何图像查看器打开图像,并发现图像已损坏/损坏,尽管它是一个1KB大小的.PNG文件。在同一位置添加了一个新图像,然后它工作正常。

答案 10 :(得分:0)

当图像文件损坏时会发生这种情况。这是一个错误的错误消息,因为内存与它无关。我还没有完成编码,但是尝试/抓住/最后将阻止程序异常终止。

答案 11 :(得分:0)

如果从IIS提供服务,请尝试回收应用程序池。这为我解决了类似的图片上传“内存不足”错误。

答案 12 :(得分:0)

我创建了一个仍然给我错误的最小表单示例。

        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;
            }
        }
    }

我尝试了使用 Image.FromFile() 注释掉的行以及使用 FileStream() 的行。两者都产生了文件错误。

Image.FromFile() 错误是: System.OutOfMemoryException: '内存不足'

filestream() 错误是: System.UnaurthorizedAccessException: '访问路径 'E:\DCIM\100Canon\dsc_7218.jpg' 被拒绝。

我在产生错误的行之前放置了一个断点,并且我能够使用 Windows 图像查看器打开图像文件。然后我关闭了查看器,在我前进到下一行并收到错误后,我无法再使用 Windows 查看器查看图像。相反,我收到一条消息,指出我无权访问该文件。我可以删除文件。

此错误是可重复的。我已经做了 10 多次了。每次出现错误后,我都会删除用于 FileName 的文件。

所有文件均经验证未损坏。

我使用 Image.FromFile() 的原始代码在我 2 年前编译时运行良好。事实上,.exe 文件运行得很好。我在代码的其他地方做了一个小改动,并惊讶地发现如果没有这个错误,代码将无法编译。我根据此页面上的信息尝试了 FileStream() 方法。