web-dev-qa-db-de.com

Out of Memory-Ausnahme für System.Drawing.Image.FromFile ()

Ich habe einen Bilduploader und Zuschneider, der Miniaturansichten erstellt, und in der folgenden Zeile wird gelegentlich eine Out Of Memory-Ausnahme angezeigt:

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

Das Auftreten des Fehlers ist winzig und sehr selten, aber ich möchte immer gerne wissen, was den Fehler verursachen könnte. Die imageFile-Variable ist nur ein Server.MapPath für den Pfad des Images.

Ich war neugierig, ob jemand dieses Problem schon einmal erlebt hat und ob er Ideen hatte, woran es liegen könnte. Ist es vielleicht die Größe des Bildes?

Ich kann den Kodex bei Bedarf und alle unterstützenden Informationen veröffentlichen, würde aber gerne die Meinungen der Menschen dazu hören.

41
dooburt

Es ist wichtig zu wissen, dass OutOfMemoryException nicht immer wirklich nicht genug Arbeitsspeicher hat - insbesondere nicht beim Umgang mit Dateien. Ich glaube, es kann auch passieren, wenn Sie aus irgendeinem Grund keine Handles mehr haben.

Entsorgen Sie alle Ihre Bitmaps, nachdem Sie damit fertig sind? Geschieht dies wiederholt für ein einzelnes Bild?

40
Jon Skeet

Wenn dies keine schlechte Bilddatei war, sondern tatsächlich das normale Problem mit Image.FromFile war, bei dem die Dateihandles geöffnet bleiben, wird stattdessen Image.FromStream verwendet.

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

Durch die Verwendung einer expliziten Dispose(), einer using()-Anweisung oder der Einstellung des Werts null in der Bitmap wird das Problem nicht mit Image.FromFile gelöst.

Wenn Sie also eine Zeit lang laufen und viele Dateien öffnen, sollten Sie stattdessen Image.FromStream() verwenden.

33
Ian Mercer

Ich bin heute beim Erstellen von Miniaturbildern für einen Ordner voller Bilder mit demselben Problem aufgetreten. Es stellt sich heraus, dass "Out Of Memory" jedes Mal genau am selben Punkt aufgetreten ist. Als ich den Ordner mit den zu konvertierenden Bildern sah, stellte ich fest, dass die Datei, die das Problem erstellt hat, thumbs.db war. Ich habe etwas Code hinzugefügt, um sicherzustellen, dass nur Bilddateien konvertiert werden und das Problem behoben wurde.

Mein Code ist im Wesentlichen

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

Hoffe das hilft.

6

Sie können es auch im Lesemodus öffnen (wenn Sie es gleichzeitig an zwei Stellen verwenden möchten)

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

Überprüfen Sie auch, ob Sie dieselbe Datei nicht an anderer Stelle geöffnet haben. Offenbar, wenn Sie eine Datei zweimal öffnen (sogar mit File.Open ()), wird auch OutOfMemoryException ausgelöst ...

2
pinus.acer

Ich hatte das gleiche Problem mit einem Hilfsprogramm, das ich geschrieben habe, um TIFF (s) in PDF (s) zu konvertieren. Oft würde ich den "out of memory" -Fehler in derselben Zeile wie Sie erhalten.

System.Drawing.Image.FromFile(imageFile)

Dann entdeckte ich, dass der Fehler nur aufgetreten ist, wenn die Dateierweiterung ".tiff" war, und funktionierte gut, nachdem ich sie mit der Erweiterung ".tif" umbenannt hatte.

1
Jeff Chapin

Ich hatte heute ein ähnliches Problem, als ich versuchte, die Größe eines Bildes zu ändern und es dann zuzuschneiden. Was passiert ist, habe ich diesen Code verwendet, um die Größe des Bildes zu ändern.

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

Und dann dieser Code für die Ernte ...

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

Dann habe ich den obigen Code so genannt ...

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;

Ich habe immer Fehler beim Zuschneiden erhalten, der Resizer hat gut funktioniert!

Es stellte sich heraus, dass das, was innerhalb des Resizers passiert ist, Fehler in der Zuschneidefunktion ausgelöst hat. Bei den Berechnungen, deren Größe geändert wurde, wurden die tatsächlichen Abmessungen des Bildes auf 399 eingestellt, anstatt 400, die ich übergeben habe.

Als ich also 400 als Argument für den Zuschnitt übergeben hatte, wurde versucht, ein 399px-breites Bild mit einem 400px-Breiten-BMP-Bildausschnitt zu beschneiden, und der Speicherfehler wurde ausgelöst.

Der größte Teil des obigen Codes wurde auf http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing gefunden.

1
jcreamer898

Wenn ein Bild ein Symbol ist, ist ein anderes Ladeverhalten erforderlich, wie in der nächsten Funktion:

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
IrinaL

Ich habe das gleiche Problem gehabt, bevor ich an anderer Stelle gesucht habe, wo im Code sichergestellt werden soll, ob ich das Image mit einem Image-Viewer öffnen kann, und festgestellt habe, dass das Image beschädigt ist, obwohl es eine .PNG-Datei mit 1 KB Größe ist. Ein neues Image wurde am selben Ort hinzugefügt, dann funktionierte es einwandfrei.

0
Kiran Modini

Versuchen Sie, den Anwendungspool zu recyceln, wenn Sie über IIS dienen. Dies löste einen ähnlichen Bild-Upload-Fehler "Out of Memory" für mich.

0
Rich

Dies passiert, wenn die Bilddatei beschädigt ist. Es ist eine schlechte Fehlermeldung, da der Speicher nichts damit zu tun hat. Ich habe die Codierung noch nicht ausgearbeitet, aber ein Versuch/Fang/beendet das Programm endgültig.

0
David Grund

Ich habe das gleiche Problem bei der Stapelverarbeitung von Tiff-Dateien. Die meisten Dateien geben keine Ausnahme aus, aber wenige Dateien werfen eine Ausnahme von "Out of Memory" in ASP.NET 4.0 aus. Ich habe binäre Daten verwendet, um herauszufinden, warum nur für wenige Dateien und innerhalb desselben Ordners. Es kann kein Berechtigungsproblem für das ASP.NET ASPNET- oder NETWORK SERVICE-Konto sein, da andere Dateien eine Arbeitsdatei sind. 

Ich habe die iTextSharp.text.Image-Klasse geöffnet und festgestellt, dass es viele überladene Methoden für GetInstance () gibt. Ich habe mein Problem mit folgendem Code gelöst: note: catch block wird für problematische Dateien ausgeführt.

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

                }
0
Nilesh Hirpara