2009-07-10 81 views
40

Tengo un cargador de imágenes y cosechador que crea imágenes en miniatura y en ocasiones me sale un excepción de memoria insuficiente en la línea siguiente:excepción de memoria insuficiente en System.Drawing.Image.FromFile()

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

La ocurrencia El error es minúsculo y muy raro, pero siempre me gusta saber qué podría estar causándole. La variable imageFile es solo un Server.MapPath para la ruta de la imagen.

Tenía curiosidad si alguien había experimentado este problema anteriormente y si tenían alguna idea de lo que podría estar causando? ¿Es el tamaño de la imagen quizás?

Puedo publicar el código si es necesario y cualquier información de respaldo que tenga, pero me encantaría escuchar las opiniones de las personas sobre esta.

+0

¿La imagen que intenta cargar es excepcionalmente grande? – RCIX

+0

Todas las imágenes son menos de ~ 700kb. – dooburt

+3

¿Estás seguro de que el archivo en cuestión es un archivo de imagen válido? También me he encontrado exactamente en la misma situación, pero el archivo tampoco se ha podido cargar en ningún otro programa. –

Respuesta

38

Vale la pena saber que OutOfMemoryException no siempre realmente significa que se ha quedado sin memoria, especialmente cuando se trata de archivos. Creo que también puede suceder si se queda sin asas por alguna razón.

¿Desea deshacerse de todos sus mapas de bits una vez que haya terminado con ellos? ¿Esto sucede repetitivamente para una sola imagen?

+0

Hola Jon, gracias por la respuesta rápida. Sí, dispongo tanto de la imagen como de los gráficos. Dim bmPhoto Como nuevo mapa de bits (targetW, targetH, PixelFormat.Format24bppRgb) Dim grPhoto como gráficos = Graphics.FromImage (bmPhoto) bmPhoto.Dispose() bmPhoto = Nada grPhoto.Dispose() grPhoto = Nada En cuanto a la repetibilidad, no es excesivamente aleatorio, pero las imágenes siempre tienden a ser más grandes (aunque no más de 700k ~). – dooburt

+4

Sospecho que puede no ser el tamaño del archivo, pero el tamaño de la imagen en la memoria: una imagen muy comprimida con una gran cantidad de píxeles podría causarle problemas ... –

+2

Hola Jon, gracias por el comentario. Resulta ser una imagen dañada todo el tiempo. *suspiro*. Un usuario incompetente. Gracias por sus respuestas :) – dooburt

30

Si este no era un archivo de imagen incorrecto pero de hecho era el problema normal con Image.FromFile en el que deja los identificadores de archivo abiertos, la solución es usar Image.FromStream en su lugar.

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

El uso de un explícito Dispose(), una declaración using() o establecer el valor a null en el mapa de bits no resuelve el problema con Image.FromFile.

Así que si su aplicación se ejecuta durante un tiempo y abre una gran cantidad de archivos, considere usar Image.FromStream() en su lugar.

+0

En realidad, si desecha una secuencia que está vinculada a un archivo a través de un manejador no administrado, el manejador se cerrará en ese momento, sin esperar a que se produzca el GC. Después de todo, ese es el objetivo de IDisposable para empezar. –

+0

Esto también se puede dar un paso más. http://blogs.msdn.com/b/omars/archive/2004/03/29/100941.aspx, todavía parece aplicarse. –

+0

¿qué pasa con el pdf con alfa en este caso? –

4

También se puede abrir en modo de lectura, (si desea utilizarlo en dos lugares simultáneamente)

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

que tenía un problema similar en la actualidad, cuando yo estaba tratando de cambiar el tamaño de una imagen y luego la cosecha lo que sucedió es que utilicé este código para cambiar el tamaño de la imagen.

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

Y a continuación, el código para el cultivo ...

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

Entonces esta es la forma en que se llama el código de seguridad ...

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; 

seguí recibiendo errores en el cultivo parte, el redimensionador funcionó bien!

Resulta que lo que sucedía dentro del resizer estaba arrojando errores en la función de recorte. Los cálculos redimensionados hacían que las dimensiones reales de la imagen fueran como 399 en lugar de 400 en las que pasé.

Entonces, cuando pasé en 400 como argumento para el cultivo, estaba tratando de recortar 399px imagen ancha con una anchura de 400px bmp y arrojó el error de memoria insuficiente!

La mayor parte del código anterior se encontró en http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing

5

llegué a la misma edición de hoy, mientras que la creación de imágenes en miniatura para una carpeta llena de imágenes. Resulta que el "Sin memoria" ocurrió exactamente en el mismo punto cada vez. Cuando miré la carpeta con las imágenes a convertir, encontré que el archivo que creaba el problema era thumbs.db. Agregué un código para asegurarme de que solo se convertían los archivos de imagen y se resolvió el problema.

Mi código es básicamente

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

Espero que esto ayude.

0

Estoy teniendo el mismo problema de procesamiento por lotes archivos Tiff. La mayoría de los archivos no arrojan una excepción, pero pocos archivos arrojan una excepción de "Memoria insuficiente" en ASP.NET 4.0. He usado datos binarios para descubrir por qué solo para algunos archivos y desde la misma carpeta. No puede tratarse de un problema de permiso para ASP.NET ASPNET o NETWORK SERVICE account porque otros archivos son archivos de trabajo.

He abierto la clase iTextSharp.text.Image y he descubierto que hay muchos métodos sobrecargados para GetInstance(). He resuelto mi problema usando el siguiente código: nota: catch block se ejecutará para archivos problemáticos.

   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

¿Dónde está el método GetImageStream (ruta) en este caso? Una vez que tiene el objeto de imagen de iTextSharp.text.Image, ¿cómo lo convierte en objeto System.Drawing.Image? – Chirag

1

Si una imagen es un icono a continuación, se requiere diferente manejo de carga, al igual que en la siguiente función:

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

que tenía el mismo problema con una utilidad que escribió para convertir TIFF (s) a PDF (s) A menudo me sale el error de "falta de memoria" en la misma línea que tú.

System.Drawing.Image.FromFile(imageFile) 

Entonces descubrí el error sólo sucedió cuando la extensión del archivo era ".tiff" y funcionó bien después de que le cambió el nombre con la extensión ".tif"

1

También puedes ver si no se ha abierto el mismo archivo en otro lugar. Aparentemente, cuando abre un archivo dos veces (incluso con File.Open()) también se lanza OutOfMemoryException ...

0

He tenido el mismo problema, antes de buscar en otro lugar en el código quería asegurarse de que si puedo abrir la imagen con cualquier visor de imágenes y descubrió que la imagen está dañada/dañada a pesar de que es un archivo .PNG con un tamaño de 1 KB. Se agregó una nueva imagen en la misma ubicación, luego funcionó bien.

Cuestiones relacionadas