2008-10-13 18 views
41

¿Por qué me sale una excepción de falta de memoria?C# Image.Clone Excepción de memoria

Así que este muere en C# en el primer tiempo a través de:

splitBitmaps.Add (neededImage.Clone (rectDimensions, neededImage.PixelFormat));

Dónde splitBitmaps es una lista < memoria de imagen > pero esto funciona en VB durante al menos 4 iteraciones:

arlSplitBitmaps.Add (Image.Clone (rectDimensions, Image.PixelFormat))

Dónde arlSplitBitmaps es una lista de matriz simple. (Y sí, yo he intentado ArrayList en C#)

Ésta es la fullsection:

for (Int32 splitIndex = 0; splitIndex <= numberOfResultingImages - 1; splitIndex++) 
{ 
    Rectangle rectDimensions; 

    if (splitIndex < numberOfResultingImages - 1) 
    { 
    rectDimensions = new Rectangle(splitImageWidth * splitIndex, 0, 
     splitImageWidth, splitImageHeight); 
    } 
    else 
    { 
    rectDimensions = new Rectangle(splitImageWidth * splitIndex, 0, 
    sourceImageWidth - (splitImageWidth * splitIndex), splitImageHeight); 
    } 

    splitBitmaps.Add(neededImage.Clone(rectDimensions, neededImage.PixelFormat)); 

}

neededImage es un mapa de bits por cierto.

No puedo encontrar ninguna respuesta útil en el intarweb, especialmente no por qué funciona bien en VB.

Actualización:

realidad me encontré con una razón (más o menos) para este trabajo, pero se olvidó de publicarlo. Tiene que ver con la conversión de la imagen a un mapa de bits en lugar de solo intentar clonar la imagen sin procesar si mal no recuerdo.

Respuesta

2

Asegúrese de estar llamando .Dispose() correctamente en sus imágenes, de lo contrario los recursos no administrados no se liberarán. Me pregunto cuántas imágenes estás creando aquí, ¿cientos? ¿Miles?

+1

Duda es memoria, explota por primera vez. –

+0

Sí, mapa de bits. El objetivo no afecta estas excepciones de OoM, según mi experiencia. –

3

Esto es un alcance, pero a menudo he encontrado que si tira imágenes directamente del disco, es mejor copiarlas en un nuevo mapa de bits y desechar la imagen en disco. He visto una gran mejora en el consumo de memoria al hacerlo.

Dave M. también está en el dinero ... asegúrese de desechar cuando haya terminado.

142

Clone() también puede lanzar una excepción de memoria insuficiente cuando las coordenadas especificadas en el rectángulo están fuera de los límites del mapa de bits. No los recortará automáticamente.

+25

Llegó aquí desde la calle de Google y este 100% respondió mi pregunta. – brian

+1

Esta fue la respuesta para mí también :-) – JTech

+6

Solo una nota rápida en caso de que no sea obvia (no era para mí al principio): los parámetros de ancho y alto del constructor de rectángulo representan la _area_ del rectángulo quieres, no los acordes de abajo a la derecha. Ex. en una imagen de 100x100, si desea el rectángulo (15,10) a (100,100), necesita un nuevo 'Rectángulo (15, 10, 85, 90)'. Ancho = ancho de la imagen-x (100-15 = 85), altura = altura de la imagen-y (100-10 = 90). 'Rectangle (15,10,100,100)' le dará una excepción de falta de memoria. – hawkke

4

Obtuve esto también cuando traté de usar el método Clone() para cambiar el formato de píxeles de un mapa de bits. Si la memoria sirve, estaba tratando de convertir un mapa de bits de 24 bpp en un formato indexado de 8 bits, esperando ingenuamente que la clase Bitmap manejara mágicamente la creación de la paleta, y así sucesivamente. Obviamente no: -/

+1

Para mí, esto fue un problema entre el uso de Windows 2003 Server y Windows 7 o Windows 2008 Server. La clonación con algunos PixelFormats falla en Windows 2003. – CrnaStena

+0

Este también fue mi problema. Estaba clonando desde un formato de píxeles sin igual. – allen1

6

Encontré que estaba usando Image.Clone para recortar un mapa de bits y el ancho tomó el recorte fuera de los límites de la imagen original. Esto causa un error de falta de memoria. Parece un poco extraño, pero puede ser útil saberlo.

+0

este era mi problema también, se devolvía una coordenada de -1 desde un dll de detección de matrícula. – SteveCav

3

Tuve dificultades para resolver esto recientemente - las respuestas anteriores son correctas. La clave para resolver este problema es garantizar que el rectángulo esté realmente dentro de los límites de la imagen. Vea un ejemplo de cómo resolví esto.

En pocas palabras, verifique si el área que estaba siendo clonada estaba fuera del área de la imagen.

int totalWidth = rect.Left + rect.Width; //think -the same as Right property 

int allowableWidth = localImage.Width - rect.Left; 
int finalWidth = 0; 

if (totalWidth > allowableWidth){ 
    finalWidth = allowableWidth; 
} else { 
    finalWidth = totalWidth; 
} 

rect.Width = finalWidth; 

int totalHeight = rect.Top + rect.Height; //think same as Bottom property 
int allowableHeight = localImage.Height - rect.Top; 
int finalHeight = 0; 

if (totalHeight > allowableHeight){ 
    finalHeight = allowableHeight; 
} else { 
    finalHeight = totalHeight; 
} 

rect.Height = finalHeight; 
cropped = ((Bitmap)localImage).Clone(rect, System.Drawing.Imaging.PixelFormat.DontCare); 
+0

Funciona para mí. –

+0

increíble contento de ayudar – dellyjm

+0

Gracias. Como referencia, puede simplemente usar el método 'Intersecar' en lugar de hacer los cálculos usted mismo:' rect.Intersect (new Rectangle (0, 0, localImage.Width, localImage.Height)); ':) –

Cuestiones relacionadas