Исключения из памяти в System.Drawing.Image.FromFile()
У меня есть загрузчик изображений и обрезщик, который создает эскизы, и я иногда получаю исключение Out Of Memory в следующей строке:
Dim bm As Bitmap = System.Drawing.Image.FromFile(imageFile)
Происхождение ошибки крошечное и очень редкое, но мне всегда нравится знать, что может быть причиной этого. Переменная imageFile - это просто файл Server.MapPath на пути к изображению.
Мне было любопытно, есть ли у кого-нибудь опыт этой проблемы раньше, и если бы у них были какие-то идеи, что могло бы вызвать это? Возможно ли это размер изображения?
Я могу опубликовать код, если необходимо, и любую вспомогательную информацию, которую я имею, но хотел бы услышать мнение людей на этом.
Ответы
Ответ 1
Стоит знать, что OutOfMemoryException не всегда означает, что это не в памяти - особенно при работе с файлами. Я считаю, что это может произойти, если по какой-то причине у вас закончились ручки.
Вы удаляете все ваши растровые изображения после того, как вы закончите с ними? Повторяется ли это для одного изображения?
Ответ 2
Если это был не плохой файл изображения, но на самом деле это была нормальная проблема с Image.FromFile
, в которой он оставил открытые дескрипторы файлов, вместо этого вместо этого используется Image.FromStream
.
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (Image original = Image.FromStream(fs))
{
...
Использование явного выражения Dispose()
, a using()
или установки значения null
в растровом изображении не решает проблему с Image.FromFile
.
Итак, если приложение работает какое-то время и открывает много файлов, используйте вместо него Image.FromStream()
.
Ответ 3
Сегодня я сталкиваюсь с той же проблемой при создании изображений миниатюр для папки с изображениями. Оказывается, что "Из памяти" происходило точно в одной и той же точке каждый раз. Когда я посмотрел папку с изображениями, которые нужно преобразовать, я обнаружил, что файл, создавший проблему, был 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
Надеюсь, что это поможет.
Ответ 4
Также вы можете открыть его в режиме чтения (если вы хотите использовать его в два раза в то же время)
public Image OpenImage(string previewFile)
{
FileStream fs = new FileStream(previewFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Image.FromStream(fs);
}
Ответ 5
Также проверьте, не открылся ли тот же файл где-то еще. По-видимому, когда вы открываете файл дважды (даже с File.Open()) OutOfMemoryException тоже выбрасывается...
Ответ 6
У меня была аналогичная проблема сегодня, когда я пытался изменить размер изображения, а затем обрезал его, что случилось, я использовал этот код для изменения размера изображения.
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;
Я продолжал получать ошибки в части обрезки, размерщик работал нормально!
Оказывается, что то, что происходило внутри resizer, бросало ошибки в функцию crop. Измененные размеры вычислений привели к тому, что фактические размеры изображения выглядели как 399, а не 400, в которые я прошел.
Итак, когда я передал в качестве аргумента для урока в 400, он пытался обрезать изображение шириной 399 пикселей с шириной bmp 400 пикселей и выкинул ошибку из памяти!
Большая часть приведенного выше кода была найдена на http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing
Ответ 7
Если изображение является значком, требуется другая обработка загрузки, как в следующей функции:
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;
}
Ответ 8
У меня была та же проблема с утилитой, которую я написал для преобразования TIFF (ов) в PDF (ы). Часто я получаю ошибку "из памяти" в той же строке, что и вы.
System.Drawing.Image.FromFile(imageFile)
Затем я обнаружил, что ошибка произошла только тогда, когда расширение файла было ".tiff" и отлично работало после того, как я переименовал его с расширением ".tif"
Ответ 9
У меня такая же проблема с пакетной обработкой Tiff файлов. Большинство файлов не выбрасывают исключение, но несколько файлов бросают исключение "Out of Memory" в ASP.NET 4.0. Я использовал двоичные данные, чтобы узнать, почему именно для нескольких файлов и из одной папки. Это не может быть проблемой разрешения для учетной записи ASP.NET ASPNET или NETWORK SERVICE, поскольку другие файлы являются рабочим файлом.
Я открыл класс iTextSharp.text.Image и обнаружил, что для GetInstance() существует много перегруженных методов. Я решил проблему, используя следующий код: note: catch block будет запущен для проблемных файлов.
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();
}
Ответ 10
У меня была такая же проблема, прежде чем смотреть еще раз, где в коде нужно было убедиться, что я смогу открыть изображение с помощью любого средства просмотра изображений и выясню, что изображение повреждено/повреждено, хотя это файл .PNG размером 1 КБ, Добавлено новое изображение в том же месте, затем оно отлично работало.
Ответ 11
Это происходит, когда файл изображения поврежден. Это плохое сообщение об ошибке, потому что память не имеет к этому никакого отношения. Я не разработал кодирование, но попытка/отлов/наконец остановит завершение программы.
Ответ 12
Если вы работаете с IIS, попробуйте переработать пул приложений. Это решило ошибку загрузки аналогичного изображения "Out of Memory" для меня.