2009-07-10 4 views
40

Ho un uploader di immagini e Cropper che crea miniature e occasionalmente ottenere un'eccezione di memoria sulla riga seguente:Out Of eccezione della memoria a System.Drawing.Image.FromFile()

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

il verificarsi l'errore è minuscolo e molto raro, ma mi piace sempre sapere cosa potrebbe causarlo. La variabile imageFile è solo un Server.MapPath per il percorso dell'immagine.

Ero curioso di sapere se qualcuno aveva già riscontrato questo problema in precedenza e se aveva qualche idea su cosa potrebbe causarlo? Forse è la dimensione dell'immagine?

Posso inserire il codice se necessario e qualsiasi informazione di supporto che ho, ma mi piacerebbe sentire le opinioni delle persone su questo.

+0

L'immagine che stai cercando di caricare è eccezionalmente grande? – RCIX

+0

Tutte le immagini sono inferiori a ~ 700kb. – dooburt

+3

Sei sicuro che il file in questione sia un file immagine valido? Ho anche incontrato esattamente la stessa situazione, ma il file non è stato in grado di caricare in nessun altro programma. –

risposta

38

Vale la pena di sapere che OutOfMemoryException non sempre davvero significa che sia la memoria - in particolare, non quando si tratta di file. Credo che possa accadere anche se manchi le maniglie per qualche motivo.

Stai eliminando tutti i tuoi bitmap dopo aver finito con loro? Succede ripetutamente per una singola immagine?

+0

Ciao Jon, grazie per la rapida risposta. Sì, dispongo sia dell'immagine che della grafica. Dim bmPhoto come nuovo bitmap (targetW, targetH, PixelFormat.Format24bppRgb) Dim grPhoto Come Graphics = Graphics.FromImage (bmPhoto) bmPhoto.Dispose() bmPhoto = Nothing grPhoto.Dispose() grPhoto = Nothing Per quanto riguarda la ripetibilità, no è eccessivamente casuale - ma le immagini tendono sempre ad essere più grandi (anche se non più grandi di 700k ~). – dooburt

+4

Sospetto che potrebbe non essere la dimensione del file, ma la dimensione dell'immagine in memoria: un'immagine molto pesante con un numero enorme di pixel potrebbe causare problemi ... –

+2

Ciao Jon, grazie per il commento. Risulta essere sempre un'immagine danneggiata. *sospiro*. Un utente incompetente. Grazie per le risposte però :) – dooburt

30

Se non si trattava di un file immagine errato, ma in realtà era il problema normale con Image.FromFile in cui lascia aperti gli handle di file, la soluzione viene invece utilizzata Image.FromStream.

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

Utilizzando un esplicito Dispose(), una dichiarazione using() o impostando il valore null sulla bitmap non risolve il problema con Image.FromFile.

Quindi, se l'app viene eseguita per qualche tempo e apre molti file, prendere in considerazione l'utilizzo di Image.FromStream().

+0

In realtà, se si smaltisce uno stream associato a un file tramite un handle non gestito, l'handle verrà chiuso lì e quindi non ci sarà alcun attesa per il GC. Dopotutto, questo è l'intero punto di IDisposable per cominciare. –

+0

Anche questo può essere fatto un passo avanti. http://blogs.msdn.com/b/omars/archive/2004/03/29/100941.aspx, sembra ancora applicarsi. –

+0

che dire di pdf con alfa in questo caso? –

4

Inoltre è possibile aprirlo in modalità di lettura, (se si desidera utilizzarlo in due posti contemporaneamente)

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

Ho avuto un problema simile oggi, quando stavo cercando di ridimensionare un'immagine e poi ritagliare ciò che è successo è che ho usato questo codice per ridimensionare l'immagine.

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

E poi questo codice per il raccolto ...

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

Allora questo è il modo ho chiamato il codice di cui sopra ...

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; 

ho continuato a ottenere gli errori sulla coltura parte, il resizer ha funzionato bene!

Si scopre che ciò che stava accadendo all'interno del resizer stava causando errori nella funzione di ritaglio. I calcoli ridimensionati stavano facendo diventare le dimensioni reali dell'immagine come 399 anziché 400 che ho passato.

Quindi, quando ho passato 400 come argomento per il ritaglio, si cercava di ritagliare un 399 px immagine ampia con un bmp di larghezza 400px e ha gettato l'errore di memoria insufficiente!

La maggior parte del codice di cui sopra è stato trovato sul http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing

5

mi ha colpito lo stesso problema di oggi durante la creazione di immagini in miniatura per una cartella piena di immagini. Si scopre che la "Memoria insufficiente" si è verificata esattamente nello stesso punto ogni volta. Quando ho guardato la cartella con le immagini da convertire ho scoperto che il file che stava creando il problema era thumbs.db. Ho aggiunto del codice per assicurarmi che solo i file immagine fossero convertiti e il problema è stato risolto.

Il mio codice è fondamentalmente

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

Spero che questo aiuti.

0

Sto riscontrando lo stesso problema durante l'elaborazione di file Tiff. La maggior parte dei file non genera un'eccezione, ma pochi file generano un'eccezione "Memoria insufficiente" in ASP.NET 4.0. Ho usato dati binari per scoprire perché solo per pochi file e all'interno della stessa cartella. Non può essere un problema di autorizzazione per ASP.NET ASPNET o account SERVIZIO DI RETE perché altri file stanno funzionando.

Ho aperto la classe iTextSharp.text.Image e ho scoperto che esistono numerosi metodi di overload per GetInstance(). Ho risolto il mio problema usando il seguente codice: nota: il blocco catch verrà eseguito per i file problematici.

   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

Dove si trova il metodo GetImageStream (percorso) in questo caso? Una volta che hai l'oggetto immagine di iTextSharp.text.Image, come lo converti in oggetto System.Drawing.Image? – Chirag

1

Se l'immagine è un'icona, allora è necessaria diversa movimentazione di carico, come in funzione successiva:

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

Ho avuto lo stesso problema con un programma di utilità ho scritto per convertire TIFF (s) in PDF (S). Spesso avrei l'errore "memoria esaurita" sulla tua stessa linea.

System.Drawing.Image.FromFile(imageFile) 

poi ho scoperto l'errore è accaduto solo quando l'estensione del file è ".tiff" e funzionava bene dopo ho rinominato con estensione ".tif"

1

Verificate anche se non è stato aperto lo stesso file da qualche altra parte. Apparentemente, quando apri un file due volte (anche con File.Open()) viene generata anche OutOfMemoryException ...

0

Ho avuto lo stesso problema, prima di cercare altro in cui nel codice volevo essere sicuro di poter aprire l'immagine con qualsiasi visualizzatore di immagini e ha capito che l'immagine è danneggiata/danneggiata anche se si tratta di un file .PNG con dimensioni di 1 KB. Aggiunta una nuova immagine nella stessa posizione, quindi ha funzionato bene.