3

I'm having a lot of issues running out of memory resizing images. I was at first convinced that I was simply leaking, so I switched my custom code for something based around https://github.com/JimBobSquarePants/ImageProcessor and the same issues occur.

So a source image causing problems might be 7137x10096 Uncompressed that should be 7137x10096x4 = 288220608 bytes or 274Mb. OK, thats "big" but why is it troublingly big? Running it IISExpress (32bit) its throws out-of-memory. Running on Azure in a 64bit server with 3.5GB it simply unreliable.

Error is "An exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll but was not handled in user code"

Code based on ImageProcessor throws on the imageFactory.Load statement

   public bool ProcessStream(Size size, Func<MemoryStream, bool> resultCallback, string gravity, Stream inStream, int quality=80)
    {
        inStream.Position = 0;
        bool res = false;
        using (var outStream = new MemoryStream())
        {
            using (var imageFactory = new ImageFactory())
            {
                var anchor = AnchorPosition.Center;
                if (gravity == "top") anchor = AnchorPosition.Top;
                if (gravity == "bottom") anchor = AnchorPosition.Bottom;
                var layer = new ResizeLayer(size, ResizeMode.Pad, anchor);

                imageFactory.Load(inStream)
                    .Resize(layer)
                    .BackgroundColor(System.Drawing.ColorTranslator.FromHtml("#FFFFFF"))
                    .Quality(quality)
                    .Save(outStream);
                res = resultCallback(outStream);
            }
        }
        return res;
    }

In its simplest test case I'm calling the above with

     public bool nop(MemoryStream s)
     {
         return true;
     }

     public string TestResize()
     {
         var resizer = new ResizeImage();
         var size = new System.Drawing.Size(300, 400);
         using (
             var filestream =
                 new FileStream(
                     @"C:\Users\Andrew\problem issues\NastyLargeImageThatBreaksThings.jpg",
                     FileMode.Open, FileAccess.Read))
         {
             var res = resizer.ProcessStream(size, nop, "top", filestream, 75);
             return res.ToString();
         }
     }

I can:

1) Try a different technique

2) Upgrade my Azure servers to have more memory (not sure if that will help)

3) Try resizing via a 3rd party service such as http://www.blitline.com/ which has some Azure specific integration.

Any understanding of why images this size can't be handled in Systen.Drawing would be much appreciated.

Andiih
  • 12,285
  • 10
  • 57
  • 88
  • Graphics object must be disposed otherwise they can exhaust GDI+ resources faster than they exhaust RAM. Sometimes though GDI+ will return an error code that gets translated to OutOfMemoryException even if it isn't – Panagiotis Kanavos Jun 10 '15 at 09:57
  • I was pretty certain I was disposing of my objects carefully, and I'm even more certain that @james-south is in ImageProcessor – Andiih Jun 10 '15 at 10:02
  • Could be a memory leask. Can you see if you are saving a similar problem like this? https://github.com/JimBobSquarePants/ImageProcessor/issues/126 – Suresh Kumar Veluswamy Jun 10 '15 at 10:03
  • The memory leak in that issue was due to user code NOT ImageProcessor. – James South Jun 10 '15 at 10:08
  • 1
    I don't think so. The above code fails reliably in a 32 bit environment and does dispose of all of its streams. – Andiih Jun 10 '15 at 10:10
  • A similar issue https://github.com/JimBobSquarePants/ImageProcessor/issues/113 – Suresh Kumar Veluswamy Jun 10 '15 at 10:13
  • You should use a profiler to see what is going on around this part of the code, or at least check with Task Manager to see the memory consumption. There may be inefficiencies in ImageProcessor, eg if buffers get copied from one method to another you'll end up with 4 times the image size in temporaries – Panagiotis Kanavos Jun 10 '15 at 10:16
  • Searching in SO I see that a lot of OutOfMemoryExceptions are caused by values that are too small, eg very small sizes or arcs. Could this be the case here, eg in ResizeLayer? – Panagiotis Kanavos Jun 10 '15 at 10:17

0 Answers0