I\'m suffering from an OutOfMemoryException when obtaining an Image from an ImageList I\'ve been unable to find an appropriate solution to the problem.
I\'ve got a C
Are you disposing graphics
? Also, it you dispose your image like you mentioned then you would need to make sure it is taken out of the ImageList or you will cause more issues. What what format are the images?
In general when you get out of memory issues when images are involved, your issue will be either some method does not like some image format, or 9/10 times, you misunderstood the lifecycle of one of the graphic objects.
Graphics
usage and put them in using
blocks.Image
life cycle and be careful with copying them, disposing them, closing underlying streams, etc.EDIT:
Here is the best option I can find, use ImageList.Draw(graphics, x, y, width, height, index)
. This will use the internal handle instead of creating a copy of the image.
I have managed to solve this issue in my application.
Jason has the answer, you have to make sure you use "using" blocks, or their equivalent.
I use VB, and the equivalent was to use Try... Catch... Finally whenever I created a new bitmap, calling BitMap.Dispose and setting the Bitmap = nothing in the "Finally" part.
This seems to be a really common problem, judging from the hours I have spent trying to Google this. The code below also allows any image to retain its aspect ratio when being reduced to a thumbnail, another issue that seems to be hard to Google!
Code:
Private Function AspectedImage(ByVal ImagePath As String, ByVal SizeWanted As Integer) As Image
Dim myBitmap, WhiteSpace As System.Drawing.Bitmap
Dim myGraphics As Graphics
Dim myDestination As Rectangle
Dim MaxDimension As Integer
Dim ReductionRatio As Double
Try
'create an instance of bitmap based on a file
myBitmap = New System.Drawing.Bitmap(ImagePath)
'create a new square blank bitmap the right size
If myBitmap.Height >= myBitmap.Width Then MaxDimension = myBitmap.Height Else MaxDimension = myBitmap.Width
ReductionRatio = SizeWanted / MaxDimension
WhiteSpace = New System.Drawing.Bitmap(SizeWanted, SizeWanted)
'get the drawing surface of the new blank bitmap
myGraphics = Graphics.FromImage(WhiteSpace)
'find out if the photo is landscape or portrait
Dim WhiteGap As Double
If myBitmap.Height > myBitmap.Width Then 'portrait
WhiteGap = ((myBitmap.Width - myBitmap.Height) / 2) * -1
myDestination = New Rectangle(x:=CInt(WhiteGap * ReductionRatio), y:=0, Width:=Int(myBitmap.Width * ReductionRatio), Height:=Int(myBitmap.Height * ReductionRatio))
Else 'landscape
WhiteGap = ((myBitmap.Width - myBitmap.Height) / 2)
'create a destination rectangle
myDestination = New Rectangle(x:=0, y:=CInt(WhiteGap * ReductionRatio), Width:=Int(myBitmap.Width * ReductionRatio), Height:=Int(myBitmap.Height * ReductionRatio))
End If
'draw the image on the white square
myGraphics.DrawImage(image:=myBitmap, rect:=myDestination)
AspectedImage = WhiteSpace
Catch ex As Exception
myBitmap = New System.Drawing.Bitmap("")
AspectedImage = New System.Drawing.Bitmap(4, 4)
ImageBufferExceeded = True
MsgBox("Image Buffer exceeded, too many images in memory. If the one(s) you want can't be seen, please restart the application and navigate straight to your images")
Finally
myBitmap.Dispose()
myBitmap = Nothing
WhiteSpace = Nothing
End Try
End Function