tapatio
tapatio

Reputation: 387

Random OutofMemory and Invalid Parameter when creating a new Bitmap object in c#

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 ?

Upvotes: 0

Views: 318

Answers (2)

PMF
PMF

Reputation: 17248

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.

Upvotes: 0

Scott
Scott

Reputation: 1876

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;
}

Upvotes: 1

Related Questions