3

I am running the below code to create a thumbnail when a user sends us an image:

public int AddThumbnail(byte[] originalImage, File parentFile)
    {
        File tnFile = null;
        try
        {
            System.Drawing.Image image;
            using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(originalImage))
            {
                image = System.Drawing.Image.FromStream(memoryStream);
            }
            Log.Write("Original image width of [" + image.Width.ToString() + "] and height of [" + image.Height.ToString() + "]");
            //dimensions need to be changeable
            double factor = (double)m_thumbnailWidth / (double)image.Width;

            int thHeight = (int)(image.Height * factor);
            byte[] tnData = null;
            Log.Write("Thumbnail width of [" + m_thumbnailWidth.ToString() + "] and height of [" + thHeight + "]");
            using (System.Drawing.Image thumbnail = image.GetThumbnailImage(m_thumbnailWidth, thHeight, () => false, IntPtr.Zero))
            {                    
                using (System.IO.MemoryStream tnStream = new System.IO.MemoryStream())
                {
                    thumbnail.Save(tnStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                    tnData = new byte[tnStream.Length];
                    tnStream.Position = 0;
                    tnStream.Read(tnData, 0, (int)tnStream.Length);
                }
            }
//there is other code here that is not relevant to the problem

        }
        catch (Exception ex)
        {
            Log.Error(ex);
        }

        return (tnFile == null ? -1 : tnFile.Id);
    }

This works fine on my machine, but when I run it on a test server I always get an out of memory exception on the line: using (System.Drawing.Image thumbnail = image.GetThumbnailImage(m_thumbnailWidth, thHeight, () => false, IntPtr.Zero)) It is not manipulating a large image: it is trying to convert a 480*640 image into a 96*128 thumbnail. I don't know how to investigate / resolve this issue. Has anyone got any suggestions? It always happens, even after I have restarted IIS. I did initially think that the image might be corrupt but the dimensions are correct. Thanks.

  • Are you simply running out of memory on the server? Get out your performance monitor, track heap sizes, GC gens, overall memory consumption. –  Dec 17 '14 at 14:43
  • Just a wild guess, maybe your machine is 64 bit architecture, whereas the server is 32 bit, which means you have a lot more memory available on your machine – barca_d Dec 17 '14 at 14:43
  • 2
    GDI is [notorious](http://stackoverflow.com/a/6506231/492405) for throwing OOMs even when memory is not a problem. GDI often returns "failed to allocate memory" under just about any error condition, which the .NET library translates to an OOM, even when the allocation failed for some other reason. It's *possible* it is a legit memory problem, but I've seen many other people chase this white whale, and it turned out to be something else (a bad setting for the codec's flags, for example). – vcsjones Dec 17 '14 at 14:46
  • The server is 64 bit. I am surprised that manipulating a small image is giving me this issue. I'll have a look at the memory consumption etc – David Christopher Reynolds Dec 17 '14 at 14:47

2 Answers2

8

We also had similar problems using GDI+ Operations in our ASP.Net server. Your mention of your code running on a server made me think, that this could be the same problem.

Please be aware, that the usage of classes in the System.Drawing Namespace is not supported on a server. The fatal thing is, that it may work for some time and suddenly (even without code changes) errors occur.

We had to rewrite a significant part of our server code.

See the comment:

Caution note

Classes within the System.Drawing namespace are not supported for use within a Windows or ASP.NET service. Attempting to use these classes from within one of these application types may produce unexpected problems, such as diminished service performance and run-time exceptions. For a supported alternative, see Windows Imaging Components.

Source: http://msdn.microsoft.com/de-de/library/system.drawing(v=vs.110).aspx

stefan.s
  • 3,489
  • 2
  • 30
  • 44
6

Many thanks @vcsjones for pointing me in the right direction. Instead of using image.GetThumbnailImage I call:

public static Image ResizeImage(Image imgToResize, Size size)
    {
        return (Image)(new Bitmap(imgToResize, size));
    }

The troublesome line of code is now:

using(Image thumbnail = ResizeImage(image, new Size(m_thumbnailWidth, thHeight)))

I got this line from Resize an Image C# It now works!

Community
  • 1
  • 1