Search code examples
c#memorygdi

How to solve Generic error in GDI+ and Out of memory


In C# I Start a thread that find,crop and saves some cells in a picture. But while running throws an exception :

C# Out of memory

This is my code :

Global.ThreadManager.StartThread(a =>
            {
                try
                {
                    System.Drawing.Bitmap croppedBitmap = new System.Drawing.Bitmap(this.Path + "image.jpg");
                    croppedBitmap = croppedBitmap.Clone(
                    new System.Drawing.Rectangle(
                        Convert.ToInt32(xCenter - width),
                        Convert.ToInt32(yCenter - width),
                        width * 2,
                        width * 2),
                        System.Drawing.Imaging.PixelFormat.DontCare
                    );
                    if (!File.Exists(Path + "MorphologySperms"))
                    {
                        Directory.CreateDirectory(Path + "MorphologySperms");
                    }
                    croppedBitmap.Save(Path + "Sperms\\" + "sperm_" + i.ToString() + ".jpg");
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message);
                };
            });

Solution

  • You need to dispose your images, you cant rely on the garbage collector to find these in-time and release the unmanaged GDI resources, this is a one way street to an exception

    Also

    Fixed

    using (var image = new System.Drawing.Bitmap(this.Path + "image.jpg"))
    {
       using (var croppedBitmap = image.Clone(new Rectangle((int)xCenter - width, (int)yCenter - width, width * 2, width * 2), PixelFormat.DontCare))
       {
          // not sure what you are doing here, though it doesnt make sense
          if (!File.Exists(Path + "MorphologySperms"))
          {
             // why are you creating a directory and not using it
             Directory.CreateDirectory(Path + "MorphologySperms");
          }
    
          // use Path.Combine
          var somePath = Path.Combine(path, "Sperms");
          croppedBitmap.Save( Path.Combine(somePath, $"sperm_{I}.jpg"));
       }
    }
    

    Also its extremely debatable and suspect to use clone like this