2016-05-07 6 views
0

Im den folgenden Code mit der Ausrichtung der Bilder zu fixieren abhängig von EXIF-DatenOut of Memory Exception bei der Verarbeitung von großer Anzahl von Bildern

Image FixImageOrientation(Image srce) 
     { 
      const int ExifOrientationId = 0x112; 
      // Read orientation tag 
      if (!srce.PropertyIdList.Contains(ExifOrientationId)) return srce; 
      var prop = srce.GetPropertyItem(ExifOrientationId); 
      var orient = BitConverter.ToInt16(prop.Value, 0); 
      // Force value to 1 
      prop.Value = BitConverter.GetBytes((short)1); 
      srce.SetPropertyItem(prop); 
      // MessageBox.Show(orient.ToString()); 
      // Rotate/flip image according to <orient> 
      switch (orient) 
      { 

       case 1: 
        srce.RotateFlip(RotateFlipType.RotateNoneFlipNone); 
        return srce; 


       case 2: 
        srce.RotateFlip(RotateFlipType.RotateNoneFlipX); 
        return srce; 

       case 3: 
        srce.RotateFlip(RotateFlipType.Rotate180FlipNone); 
        return srce; 

       case 4: 
        srce.RotateFlip(RotateFlipType.Rotate180FlipX); 
        return srce; 

       case 5: 
        srce.RotateFlip(RotateFlipType.Rotate90FlipX); 
        return srce; 

       case 6: 
        srce.RotateFlip(RotateFlipType.Rotate90FlipNone); 
        return srce; 

       case 7: 
        srce.RotateFlip(RotateFlipType.Rotate270FlipX); 
        return srce; 

       case 8: 
        srce.RotateFlip(RotateFlipType.Rotate270FlipNone); 
        return srce; 

       default: 
        srce.RotateFlip(RotateFlipType.RotateNoneFlipNone); 
        return srce; 
      } 
     } 

ich einen großen Stapel von Bildern wie diese

for (x= 0; x<list.Count; x++) 
{ 
filepath= list.ElementAt(x); 
Bitmap image = new Bitmap(FixImageOrientation(Bitmap.FromFile(filepath))); 
//Do long processing and at the end i do image.dispose(); 
image.dispose(); 
} 
verarbeiten Aber

bei der Verarbeitung einer großen Stapel von Bildern i Out of Memory Exception bei

Bitmap image = new Bitmap(FixImageOrientation(Bitmap.FromFile(filepath))); 

Warum bekomme ich das .. Ich habe dieses Bild am Ende der Schleife, denke ich.

+1

Sie erstellen 2 Bilder und Entsorgung nur eine 'Bitmap.FromFile (filepath)' und 'neue Bitmap ('. –

+0

Ghetto Art und Weise, offene Fenster Aufgabe verwalten, wenn Sie Ihr Programm ausführen. Wenn Sie sehen, der Speicher steigt schnell, Sie haben irgendwo ein Speicherleck, –

Antwort

5

In Ihrem Code erstellen Sie zwei Bitmaps, aber nur einen. Ändern Code:

using(var source = Bitmap.FromFile(filepath)) { 
    using(var image = new Bitmap(FixImageOrientation(source))) { 
     // ... do long processing 
    } 
} 

Dies sollte Ihre Probleme lösen.

+0

Danke .. seit Bild ist ein globales Objekt .. ich denke, ich kann einfach verwenden (var source = Bitmap.FromFile (Dateipfad)) {Bitmap-Bild = neue Bitmap (FixImageOrientation (source));} 'und disposed' image' mit 'image.dispose();' .. funktioniert das? – techno

+0

@techno Sorry, aber ich habe nicht verstanden, was meinst du. Du musst beide Bitmaps entsorgen . –

+0

Ich meinte .. im Zuweisen von 'Image' Objekt im Code.Ich kann dies nicht tun, wenn ich die' using' Stateme verwenden nt für 'image', also benutze ich einfach' var source = Bitmap.FromFile (Dateipfad)) {'und erzeuge' image' aus 'source' und entferne manuell' image' Objekt ... anstatt den zweiten zu verwenden 'using' Anweisung. – techno

0

Wie Sie in dieser Antwort https://stackoverflow.com/a/7520919/6439999 finden können, gibt der Aufruf zum Entsorgen nicht unbedingt Speicher frei. Dies ist die Aufgabe des Garbage Collectors. Ich nehme an, dass Sie die Bilder recht schnell in den Speicher laden. Das Problem ist, dass die Garbage Collection nur hin und wieder gemacht wird. Wenn Sie eine große Menge an Speicher verwenden, indem Sie neue Objekte erstellen, ist die Speicherbereinigung möglicherweise zu langsam und der Speicher wird wieder freigegeben.

Sie könnten versuchen, es direkt von innerhalb der Schleife mit GC.Collect() aufrufen. Wenn dies nicht genug ist, können Sie auch den blocking-Parameter versuchen, der Ihren Thread pausiert, bis der GC-Lauf abgeschlossen ist.

Als einen anderen Ansatz können Sie Ihr Projekt als x64 kompilieren, dies wird Ihrem Programm Zugriff auf mehr als 1 GB Speicher geben. Aber mit dieser Lösung schieben Sie das Problem nur weiter nach unten.

Thomas

Verwandte Themen