2012-07-19 21 views
5

Sono nuovo in C#. Quindi, non sono sicuro di quale sia il problema con il mio programma. Il programma funziona con un'immagine piccola ma mostra "Esaurimento memoria esaurita" quando funziona con un'immagine grande che è circa A4. Tuttavia, il programma sarebbe inutile se non può funzionare con un'immagine grande. Come posso risolvere il problema? Grazie.Eccezione memoria insufficiente in 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

Non correlato alla risposta alla domanda, è necessario tenere presente che è necessario chiudere e disporre gli oggetti grafici. Frammenti di codice pad con istruzioni 'using'. Quello farebbe il lavoro. –

+5

La dimensione A4 non dice nulla. Posso creare un'immagine in formato A4 con solo 4 pixel in essa :) –

+0

Non sei sicuro di quale sia il problema, ma prova ad aggiungere usando le istruzioni attorno ad ogni oggetto che implementa IDisposable (Bitmap, Grafica). Quanta memoria utilizza il processo quando si guarda il task manager? – Maarten

risposta

0

Ho il sospetto che il tuo problema principale sia che hai un numero di istanze bitmap e grafiche in uso allo stesso tempo.

Probabilmente vale la pena provare a riorganizzare il codice in modo che, in pochi di questi, siano presenti in qualsiasi momento possibile, utilizzando .Dispose() per rimuovere gli elementi con cui hai finito.

8

È un'immagine 9992x8750

Sì, sei nella zona di pericolo per un processo a 32 bit. Quell'immagine richiede una grande porzione di spazio di indirizzamento contiguo, 334 megabyte. Lo otterrai facilmente quando carichi l'immagine in anticipo, subito dopo l'avvio del programma. Puoi ottenere circa 650 megabyte a quel punto, dare o avere.

Ma questo va giù in discesa da lì mentre il programma assegna e rilascia memoria e carica un paio di assiemi. Lo spazio degli indirizzi viene frammentato, i buchi tra le allocazioni si stanno riducendo. Il solo caricamento di una DLL con un indirizzo di base scomodo può improvvisamente ridurre il buco più grande di più di un fattore due. Il problema non è la quantità totale di memoria virtuale disponibile, può essere un gigabyte o più, è la dimensione del più grande chunk disponibile. Dopo un po ', avere un'assegnazione di 90 megabyte non è del tutto inusuale. Solo che l'allocazione non può riuscire nell'allocazione, è comunque possibile allocare un gruppo di, ad esempio, blocchi da 50 megabyte.

Non esiste una cura per la frammentazione dello spazio degli indirizzi e non è possibile correggere il modo in cui la classe Bitmap memorizza i dati dei pixel. Ma uno, specifica una versione a 64 bit di Windows come requisito per il tuo programma. Fornisce gocce di memoria virtuale, la frammentazione è un non-problema. Se vuoi inseguirlo, puoi ottenere informazioni dettagliate sul layout della VM con lo VMMap utility di SysInternals. Fai attenzione all'eccesso di informazioni che potresti riscontrare.

0

Prova a lavorare su Windows 64-bit, questa è la soluzione della maggior parte dei problemi di memoria.

Problemi correlati