Reputation: 387
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
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
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