Search code examples
c#gdi+system.drawing

A generic error occurred in GDI+ again


I understand, what this message means (need to do Dispose for unmanaged resources), but really don't understand why it happens in my case:

    System.Drawing.Image imgAnimaha, imgNoanimaha;
                using (System.IO.Stream file = thisExe.GetManifestResourceStream("WindowsApplication1.img.noanimaha135.gif"))
                {

                    using (System.Drawing.Image img = Image.FromStream(file))
                    {
                        imgNoanimaha = (System.Drawing.Image)img.Clone();
                    }
                }

                using (System.IO.Stream file = thisExe.GetManifestResourceStream("WindowsApplication1.img.animaha135.gif"))
                {

                    using (System.Drawing.Image img = Image.FromStream(file))
                    {
                        imgAnimaha = (System.Drawing.Image)img.Clone();
                    }
                }

            pbDiscovery.Image = imgAnimaha;

In this case I get "A generic error occurred in GDI+" Why and how to solve? PS. If I write the following:

            pbDiscovery.Image = imgNoanimaha;

It works correctly. I really don't understand where and which unmanaged resource is not disposed...


Solution

  • The problem is that Image.Clone(), as in:

    using (System.Drawing.Image img = Image.FromStream(file))
    {
      imgAnimaha = (System.Drawing.Image)img.Clone();
    }
    

    ... does not create a deep copy of the image. It creates a copy of all the header information, but not the actual pixel data (it just points to the original pixel data). The original (and only) pixel data is disposed along with the original img object when the using goes out of scope.

    So the question then becomes, what is the point of the using here? I would suggest there is none. Read the image into a System.Drawing.Image object and keep it alive as long as you need the pixel data (e.g. as long as the Image will need to be redrawn) and only Dispose it after it does not need to be displayed again.