Исключение из нехватки памяти в System.Drawing.Image.FromFile () - PullRequest
41 голосов
/ 10 июля 2009

У меня есть загрузчик изображений и обрезка, которые создают эскизы, и я иногда получаю исключение Out Of Memory в следующей строке:

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

Возникновение ошибки крошечное и очень редкое, но я всегда хотел бы знать, что может быть его причиной. Переменная imageFile - это просто Server.MapPath для пути к изображению.

Мне было любопытно, сталкивался ли кто-нибудь с этой проблемой ранее, и если у них были какие-либо идеи, что могло вызвать это? Возможно, это размер изображения?

При необходимости я могу опубликовать код и любую имеющуюся у меня информацию, но хотел бы услышать мнение людей по этому поводу.

Ответы [ 12 ]

40 голосов
/ 10 июля 2009

Стоит знать, что OutOfMemoryException не всегда на самом деле означает, что ему не хватает памяти - особенно не при работе с файлами. Я верю, что это также может произойти, если у вас по какой-то причине закончились ручки.

Вы избавляетесь от всех своих растровых изображений после того, как с ними покончено? Это повторяется для одного изображения?

33 голосов
/ 07 февраля 2010

Если это не был плохой файл изображения, но на самом деле это была обычная проблема с 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.

Так что, если ваше приложение запускается какое-то время и открывает много файлов, рассмотрите возможность использования Image.FromStream().

6 голосов
/ 18 августа 2011

Сегодня я столкнулся с той же проблемой при создании миниатюр изображений для папки, полной изображений. Получается, что «Недостаточно памяти» возникало точно в одной и той же точке каждый раз. Когда я посмотрел на папку с изображениями для конвертации, я обнаружил, что файл, который создавал проблему, был 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 голосов
/ 31 августа 2010

Также вы можете открыть его в режиме чтения (если вы хотите использовать его в двух местах одновременно)

 public Image OpenImage(string previewFile)
        {
            FileStream fs = new FileStream(previewFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            return Image.FromStream(fs);
        }
2 голосов
/ 23 октября 2014

Также проверьте, не открывали ли вы тот же файл где-нибудь еще. По-видимому, когда вы открываете файл дважды (даже с File.Open ()), OutOfMemoryException также генерируется ...

1 голос
/ 24 июня 2014

У меня была такая же проблема с утилитой, которую я написал для преобразования TIFF (s) в PDF (s). Часто я получаю сообщение об ошибке «недостаточно памяти» в той же строке, что и вы.

System.Drawing.Image.FromFile(imageFile)

Тогда я обнаружил, что ошибка произошла только тогда, когда расширение файла было ".tiff", и нормально работало после того, как я переименовал его с расширением ".tif"

1 голос
/ 24 марта 2014

Если изображение является значком, то требуется другая обработка загрузки, как в следующей функции:

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;
    }
1 голос
/ 29 марта 2011

У меня была похожая проблема сегодня, когда я пытался изменить размер изображения, а затем обрезать его, в результате я использовал этот код для изменения размера изображения.

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 в качестве аргумента для кадрирования, он пытался обрезать изображение шириной 399px с шириной bmp 400px, и это вызвало ошибку нехватки памяти!

Большая часть вышеуказанного кода была найдена на http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing

0 голосов
/ 20 мая 2019

Если вы работаете с IIS, попробуйте переработать пул приложений. Это решило для меня ошибку загрузки аналогичного изображения "Out of Memory".

0 голосов
/ 19 мая 2019

Это происходит, когда файл изображения поврежден. Это плохое сообщение об ошибке, потому что память не имеет к этому никакого отношения. Я не разработал кодирование, но попытка / отлов / наконец остановит завершение программы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...