0

I'm creating a simple tool application for create image titles that will be used in web maps. My problem is, when I'm loading and resize the biggest image ( 8192px per side )that represents the max zoom level, I'm getting randoms OutofMemoryException and InvalidParameterException

 // Always will resize the image to fit the zoom level size
 // Will not resize if the image has already the correspondig
 // width and height of the zoom level ( ie level 5, w= 8192px 
 // h = 8192px )
 using (Bitmap actualBitmap = new Bitmap(resizeImage(imgActualLevel, actualLevel)))
 { 
       // ... code that crop the file in to 256px tiles
 }





 private Bitmap resizeImage(Image originalImage, int zoomLevel)
    {

                int maxTilesPerZoomLevel = (int)(Math.Pow(2, zoomLevel));
                int IMG_WIDTH = maxTilesPerZoomLevel * TILE_SIZE;
                int IMG_HEIGHT = maxTilesPerZoomLevel * TILE_SIZE;

                Image resizedImage = originalImage;
                if ((originalImage.Height != IMG_HEIGHT) || (originalImage.Width != IMG_WIDTH))
                {

                    resizedImage = new Bitmap(IMG_WIDTH, IMG_HEIGHT);
                    Graphics graphics = Graphics.FromImage(resizedImage);

                    graphics.SmoothingMode = SmoothingMode.AntiAlias;
                    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    graphics.DrawImage(originalImage, new Rectangle(0, 0, IMG_WIDTH,IMG_HEIGHT));

                }

                 return (Bitmap)resizedImage;
    }

But the problem is: sometimes works fine and the application runs well, and then I come back the next day to continue and I get the error without doing any modification. I put already many Dispose() methods and using() {} and I got sure that I don't have leave images in ram but I got the error.

Do you have any idea what is going wrong ?

5
  • 3
    Uhm... maybe you are out of memory... Commented Dec 18, 2013 at 5:07
  • add try..catch and start debugging there you will see where in the line is having a problem and what parameters having invalid value. Perhaps check your available physical memory. Commented Dec 18, 2013 at 5:25
  • Which line of code is causing the InvalidParameterException? I can't help with that aspect without additional context. Commented Dec 18, 2013 at 5:48
  • Even if you have called Dispose, the memory of your application is limited by the operating system. You should try to carefully check the memory usage by using a profiler and see how many images you can hold in the memory at the same time. The best practice is to load the image only when necessary and free them immediately to avoid high memory usage. Compared to a 32 bit app, a 64 bit app can use more memory. Thus, you might try to compile your app as 64 bit and run it on a 64 bit Windows machine. Commented Dec 18, 2013 at 6:48
  • This is very weird. I applied some suggested modifications and everything worked fine. Next day it started to crash in another sections ( that used Drawing2D objects ) that were not crashing before. I implemented an alternative method that uses ImageMagick command line tools for manipulate the images. I'm really done with this, is too random. It is frustrating, but thank you for your help. Commented Jan 11, 2014 at 18:38

2 Answers 2

1

It looks like you have a memory leak with your using statement. You are creating a new bitmap from the result of resizeImage which also creates a new bitmap. The bitmap created in resizeImage is never properly disposed. I also don't see why you need to make an immediate copy of the returned bitmap. Try something like this instead:

 using (Bitmap actualBitmap = resizeImage(imgActualLevel, actualLevel))
 { 
       // ... code that crop the file in to 256px tiles
 }

You are also not disposing your Graphics object in resizeImage. You should wrap that in a using statement as thus:

private Bitmap resizeImage(Image originalImage, int zoomLevel)
{
    int maxTilesPerZoomLevel = (int)(Math.Pow(2, zoomLevel));
    int IMG_WIDTH = maxTilesPerZoomLevel * TILE_SIZE;
    int IMG_HEIGHT = maxTilesPerZoomLevel * TILE_SIZE;

    Image resizedImage = originalImage;
    if ((originalImage.Height != IMG_HEIGHT) || (originalImage.Width != IMG_WIDTH))
    {
        resizedImage = new Bitmap(IMG_WIDTH, IMG_HEIGHT);
        using (Graphics graphics = Graphics.FromImage(resizedImage))
        {
            graphics.SmoothingMode = SmoothingMode.AntiAlias;
            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            graphics.DrawImage(originalImage, new Rectangle(0, 0, IMG_WIDTH,IMG_HEIGHT));
        }
    }

    return (Bitmap)resizedImage;
}
Sign up to request clarification or add additional context in comments.

1 Comment

I was going to pick up this answer as the good one. I applied your suggested modifications and everything worked find ( that day ). Next morning everything started to crash as usual. I'm done, I will use ImageMagick and execute everything as command line instructions. That's the only method that worked fine, even if it is slower. Thanks for your help anyways
0

Just as an extra hint: Don't relly on the type of exception returned by the bitmap constructor. It can throw ArgumentOutOfRange when it actualy means OutOfMemory and also vice-versa. Can sometimes be very confusing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.