2012-07-19 104 views
5

soy nuevo en C#. Por lo tanto, no estoy tan seguro de cuál es el problema con mi programa. El programa funciona con una imagen pequeña pero muestra "Excepción de falta de memoria" cuando funciona con una imagen grande que es de tamaño A4. Sin embargo, el programa sería inútil si no puede funcionar con una imagen grande. ¿Cómo puedo resolver el problema? Gracias.Excepción de memoria insuficiente en C#

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Drawing; 
using System.Drawing.Drawing2D; 
using System.Drawing.Imaging; 


namespace ConsoleApplication6 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      //Bitmap objects 

      //input image 
      Bitmap bmOrg = (Bitmap)Bitmap.FromFile(@"C:\B.png"); 
      Bitmap bmTransparentLayover = new Bitmap(bmOrg.Width, bmOrg.Height); 

      //Create Graphic Objects. 
      Graphics gOriginal = Graphics.FromImage(bmOrg); 
      Graphics gTransparentLayover = Graphics.FromImage(bmTransparentLayover); 

      //Set Transparent Graphics back ground to an "odd" color 
      //  that hopefully won't be used to 
      //Be changed to transparent later. 
      gTransparentLayover.FillRectangle 
           (Brushes.Pink, 
            new Rectangle 
            (0, 
            0, 
            bmTransparentLayover.Width, 
            bmTransparentLayover.Height 
           ) 
           ); 

      //Draw "transparent" graphics that will look through 
      // the overlay onto the original. 
      //Using LimeGreen in hopes that it's not used. 

      Point[] points = new Point[5]; 
      points[0] = new Point(130, 140); 
      points[1] = new Point(130, 370); 
      points[2] = new Point(420, 370); 
      points[3] = new Point(420, 140); 
      points[4] = new Point(130, 140); 
      System.Drawing.Drawing2D.GraphicsPath gp = new 
      System.Drawing.Drawing2D.GraphicsPath(); 
      gp.AddPolygon(points); 
      gTransparentLayover.FillPath(Brushes.LimeGreen, gp); 

      //Now make the LimeGreen Transparent to see through overlay. 
      bmTransparentLayover.MakeTransparent(Color.LimeGreen); 

      //draw the overlay on top of the original. 
      gOriginal.DrawImage(bmTransparentLayover, 
      new Rectangle(0, 0, bmTransparentLayover.Width, bmTransparentLayover.Height)); 

      //Create new image to make the overlays background tranparent 
      Bitmap bm3 = new Bitmap(bmOrg); 
      bm3.MakeTransparent(Color.Pink); 

      //Save file. 
      //to save the output image 
      bm3.Save(@"save.png",System.Drawing.Imaging.ImageFormat.Png); 

      Image img = new Bitmap(480, 480); 

      //the background image 
      img = Image.FromFile(@"a.png"); 
      Graphics g = Graphics.FromImage(img); 

      //to save the combined image 
      g.DrawImage(Image.FromFile(@"save.png"), new Point(-50, -70)); 
      img.Save(@"final.png", ImageFormat.Png); 
     } 
    } 
} 
+0

No relacionado con la respuesta a su pregunta, debe tener en cuenta que debe cerrar y deshacerse de sus objetos gráficos. Fragmentos de código de almohadilla con declaraciones 'using'. Eso haría el trabajo. –

+5

El tamaño A4 no dice nada. Puedo crear una imagen de tamaño A4 con solo 4 píxeles :) –

+0

No estoy seguro de cuál es el problema, pero intente agregar instrucciones de uso alrededor de cada objeto que implemente IDisposable (Mapa de bits, Gráficos). ¿Cuánta memoria usa el proceso cuando observa el administrador de tareas? – Maarten

Respuesta

0

Sospecho que su principal problema es que tiene varias instancias de mapa de bits y gráficos en uso al mismo tiempo.

Probablemente valga la pena tratar de reorganizar el código para que algunos de ellos estén presentes al mismo tiempo, usando .Dispose() para eliminar elementos con los que haya terminado.

8

es una imagen de 9992x8750

Sí, estás en la zona de peligro para un proceso de 32 bits. Esa imagen requiere una gran porción de espacio de direcciones contiguas, 334 megabytes. Obtendrá fácilmente eso cuando cargue la imagen temprano, justo después de que comience su programa. Puedes obtener unos 650 megabytes en ese punto, dar o recibir.

Pero eso va cuesta abajo ya que su programa asigna y libera memoria y carga un par de conjuntos. El espacio de direcciones se fragmenta, los agujeros entre las asignaciones se hacen más pequeños. Solo cargar un archivo DLL con una dirección base incómoda puede repentinamente cortar el agujero más grande en más de un factor de dos. El problema no es la cantidad total de memoria virtual disponible, puede ser un gigabyte o más, es el tamaño del fragmento más grande disponible. Después de un tiempo, tener una asignación de 90 megabytes no es completamente inusual. Solo que la asignación de one puede fallar, aún podría asignar un grupo de, por ejemplo, fragmentos de 50 megabytes.

No hay cura para la fragmentación del espacio de direcciones y no se puede solucionar la forma en que la clase Bitmap almacena los datos de píxeles. Pero uno, especifique una versión de 64 bits de Windows como requisito para su programa. Proporciona gran cantidad de memoria virtual, la fragmentación no es un problema. Si quiere perseguirlo, puede obtener información sobre el diseño de VM con el VMMap utility de SysInternals. Tenga cuidado con la sobrecarga de información que puede experimentar.

0

Trate de trabajar en Windows de 64 bits, esa es la solución de la mayoría de los problemas de memoria.

Cuestiones relacionadas