1

I have the following code to resize an image to a certain size:

Public Sub ResizeBitmap(ByRef uSource As Bitmap, ByVal uSize As Size)

    Dim nBmp As New Bitmap(uSize.Width, uSize.Height)

    Using g As Graphics = Graphics.FromImage(nBmp)
        g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
        g.DrawImage(uSource, New Rectangle(0, 0, uSize.Width, uSize.Height))
    End Using

    uSource = nBmp

End Sub

I'm experiencing an Unknown GDI+ exception if I call this frequently, but not an out of memory exception. Since GDI+ is not always clear in it's errors, I'm suspecting a memory leak anyways as TaskManager shows a rising amount of RAM being used.

I would therefore like to ask if the above code contains any flaws and if yes, how to get rid of them.

I think I'm quite ok at memory management, but bitmaps really bring me to my limits sometimes.

Thank you.

tmighty
  • 10,734
  • 21
  • 104
  • 218
  • 2
    The bitmap being passed in is replaced without the original being disposed, so yes it looks like it is leaking. – Ňɏssa Pøngjǣrdenlarp Aug 13 '18 at 14:29
  • 2
    Why do you want to pass a bitmap by reference? If you need to create a new bitmap for some reason, keep a reference to previous one, create a new one using the function and return it from the function, assign it to the variable of the previous one, then dispose the previous one using the reference which you kept at first. – Reza Aghaei Aug 13 '18 at 14:45
  • [Value vs Reference Types](http://www.albahari.com/valuevsreftypes.aspx) – Reza Aghaei Aug 13 '18 at 14:50
  • I think it can be certainly left behind and can cause issues in the long run, so definitely have your bitmap codes in a Using Statement that way they are disposed when no longer needed. – traveler3468 Aug 13 '18 at 15:03
  • See [this method](https://stackoverflow.com/questions/51789730/image-size-when-capturing-a-screenshot-of-another-application-changes-if-applica?answertab=active#tab-top) for returning a newly created Bitmap. – Jimi Aug 13 '18 at 15:30

1 Answers1

1

I think the leak you are experiencing happens when you set the uSource to something else in the middle of the subroutine, which can be fine, but that also can lead to problems. Maybe someone more knowledgable than me can fill in the blanks on how vb.net handles this. EDIT: As kindly commented on this answer, the ByRef is what is causing the leak. I'm keeping the rest of the answer intact since the Asker marked this as the helpful, and as I think this is good general practice.

When using this type of manipulation, it is generally better to use Function instead of Sub (as also @Reza Aghaei suggested in a comment).

Change the Sub to a Function and then add as Bitmap to the end to define the return type. Remember to change the End tag as well. You get:

Public Function ResizeBitmap(ByVal uSource As Bitmap, ByVal uSize As Size) as Bitmap
   '/.../
End Function

This will allow you to do the following in the (complete) function:

Public Function ResizeBitmap(ByVal uSource As Bitmap, ByVal uSize As Size) as Bitmap

   Dim nBmp As New Bitmap(uSize.Width, uSize.Height)

   Using g As Graphics = Graphics.FromImage(nBmp)
      g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
      g.DrawImage(uSource, New Rectangle(0, 0, uSize.Width, uSize.Height))
   End Using

   Return nBmp

End Function

...and to resize your image using Dim bSmall as Bitmap = ResizeBitmap(bBig, New Size(250,250)) wherever you need to, elsewhere in the code.

Viktor Ek
  • 353
  • 1
  • 13
  • 4
    The `uSource` parameter should not be declared as `ByRef`. The method has nothing to do with the `uSource` reference. – Reza Aghaei Aug 13 '18 at 15:47
  • 1
    Sorry to say it, but this is the wrong way to do it. What's important is not to use `ByRef` passing that object. If there was a leak in the original code (there is, even if this might depend on what happens next), this won't solve it. – Jimi Aug 13 '18 at 16:14
  • I don't see where you have changed your code. It is still passing `uSource` `ByRef` – Chris Dunaway Aug 14 '18 at 19:33
  • This still means that the caller now has two images to dispose of when the time comes! – Emond Aug 14 '18 at 20:30