Am I responsible for Disposing a BackgroundImage? - c#

I have a windows form where I set the BackgroundImage property to a custom bitmap image.
private Image MakeCustomBackground()
{
Bitmap result = new Bitmap(100, 100);
using(Graphics canvas = Graphics.FromImage(result))
{
// draw the custom image
}
return result;
}
private void UpdateFromBackground()
{
this.BackgroundImage = MakeCustomBackground();
}
My question is, Image is disposable and I am creating it, does that mean that I must dispose of it? Or when I pass the image to the form, via BackgroundImage, does it take ownership and dispose of it when it no longer needs it?

Assuming that UpdateFromBackground() is called more than once, you probably should Dispose the old Image when (before) setting a new one. If you don't then the GC will do it eventually but that is less efficient. The Form will only Dispose the last BgImage you assigned.
private void UpdateFromBackground()
{
if (this.BackgroundImage != null)
{
this.BackgroundImage.Dispose();
}
this.BackgroundImage = MakeCustomBackground();
}

Related

The program takes up a lot of RAM, when the button is pressed (winforms) [duplicate]

I'm a newby in C#. I have to repeatedly refresh a GUI picture box in a worker thread. The image is acquired from a camera polling a driver with a GetImage method that retrives the image to be displayed. Even if I allocate the bitmap using directive "using" and explicitly call G.C, memory seems to be never deallocated.
The worker thread is something like this:
while (true)
{
// request image with IR signal values (array of UInt16)
image = axLVCam.GetImage(0);
lut = axLVCam.GetLUT(1);
DrawPicture(image, lut);
//GC.Collect();
}
While the DrawPicture method is something like
public void DrawPicture(object image, object lut)
{
[...]
// We have an image - cast it to proper type
System.UInt16[,] im = image as System.UInt16[,];
float[] lutTempConversion = lut as float[];
int lngWidthIrImage = im.GetLength(0);
int lngHeightIrImage = im.GetLength(1);
using (Bitmap bmp = new Bitmap(lngWidthIrImage, lngHeightIrImage)) {
[...many operation on bitmap pixel...]
// Bitmap is ready - update image control
//SetControlPropertyThreadSafe(tempTxtBox, "Text", string.Format("{0:0.#}", lutTempConversion[im[160, 100]]));
//tempTxtBox.Text = string.Format("{0:00000}", im[160, 100]);
//System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
}
}
Problems arises with the
pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
In fact commenting that line of code, garbage collection works as it would.
Better, the problem seems to be with
System.Drawing.Image.FromHbitmap(bmp.GetHbitmap())
Any advice to solve this memory leak?
Thanks a lot!
Image implements IDisposable, so you should call Dispose on each Image instance that you create, when it is no longer needed. You could try to replace this line in your code:
pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
With this:
if (pic.Image != null)
{
pic.Image.Dispose();
}
pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
This will dispose the previous image (if any) before the new one is assigned.
The thing is, you're making a GDI bitmap of bmp with GetHbitmap, which according to msdn:
You are responsible for calling the
GDI DeleteObject method to free the
memory used by the GDI bitmap object.
Then the FromHbitmap method makes a copy of the GDI bitmap; so you can release the incoming GDI bitmap using the GDI DeleteObject method immediately after creating the new Image.
So basically I would add:
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
...
IntPtr gdiBitmap = bmp.GetHbitmap();
// Release the copied GDI bitmap
if (pic.Image != null)
{
pic.Image.Dispose();
}
pic.Image = System.Drawing.Image.FromHbitmap(gdiBitmap);
// Release the current GDI bitmap
DeleteObject(gdiBitmap);
I am unsure if you need the GDI bitmap to perform some kind of transformation. In case you don't you can just assign the bitmap to the Image property of your PictureBox, and ignore the former solution:
// Since we're not using unmanaged resources anymore, explicitly disposing
// the Image only results in more immediate garbage collection, there wouldn't
// actually be a memory leak if you forget to dispose.
if (pic.Image != null)
{
pic.Image.Dispose();
}
pic.Image = bmp;
There are several ways to release an image from pbox. I strongly recommend the way is that do not use pbox.Image = Image.FromFile.... If you do not use FileStream and you want to read it from file use BitMap class. Like this:
Bitmap bmp = new Bitmap(fileName);
pbox.Image = bmp; // notice that we used bitmap class to initialize pbox.
... and then you want to release the image file bmp.Dispose();
Now you can delete, move or whatever you want to the file.

Bitmap access violation exception with camera image

In my WPF application images are taken with a camera use a view and then passed as bitmaps to another when it's closed via eventargs. However, when I then try to process the images I get the AccessViolationException. This does not occure when I process the images before they are passed or when I use images loaded from a file.
Getting the image from the camera (The PtCamera class is my wrapper for the Camera class from the API)
Bitmap GetRefImage(PtCamera cam)
{
Bitmap image = new Bitmap(2560, 1920, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
if (cam.IsConnected)
{
cam.FetchImage(out image);
}
else
{
ErrorOccurred?.Invoke(this, $"GetRefImage: {cam.Error}");
}
return image;
}
In this context I can access the bitmap and process it as I like.
After passing the bitmap when the view is closed:
void CloseZoomedView(bool isConf)
{
if (cam is object && cam.IsConnected)
cam.Close();
ZoomClosingArgs eArg = new ZoomClosingArgs()
{
IsConfirmed = isConf,
RefImage = refImage,
};
ClosingZoom?.Invoke(this, eArg);
}
The exception occurs directly when accessing the data in the other viewmodel:
void HandleZoomImageClosed(object sender, ZoomClosingArgs e)
{
if (e is object && e.IsConfirmed)
{
Color test = e.RefImage.GetPixel(0, 0);
//...
}
}
The bitmap is generated by accessing the memory of the camera via FetchImage()
public void FetchImage(out Bitmap image)
{
camera.Memory.GetActive(out int memID);
camera.Memory.ToBitmap(memID, out image);
}
If i replace the code in FetchImage() with just a new Bitmap from file
image = new Bitmap(#"d:\testimage.png")
It works without problems in any context.
The API documentation simply states the following:
Accessible
Camera.Memory.ToBitmap
Syntax
uEye.Memory.ToBitmap(int s32MemId, out System.Drawing.Bitmap bitmap)
Description
Returns a bitmap which contains the image. The method uses the already
allocated image memory and the image is displayed in the format you
specified when allocating the image memory.
Any hints are much appreciated.
I was closing my camera object too early. In CloseZoomedView() the cam.Close() method releases all the memory areas taken up by the camera. With passing a new Bitmap before closing it works like a charm.
void CloseZoomedView(bool isConf)
{
ZoomClosingArgs eArg = new ZoomClosingArgs()
{
IsConfirmed = isConf,
RefImage = new Bitmap(refImage),
};
if (cam is object && cam.IsConnected)
cam.Close();
ClosingZoom?.Invoke(this, eArg);
}

Paint event organization/Design issues

I have a program that edits images in different ways... i have a Paint event that is called every time i do this.Invalidate()...
My paint method looks like this:
private void EditImage_Paint(object sender, PaintEventArgs e)
{
if (isLOaded == true)
{
Graphics graphicsWindow; // reference to the graphic surface of this window
Graphics graphicsImage; // reference to in-memory surface
theImage = new Bitmap(Width, Height); // bitmap for window surface copy
graphicsWindow = e.Graphics; // get our current window's surface
graphicsImage = Graphics.FromImage(theImage); // create surfaces from the bitmaps
graphicsImage.DrawImage(firstLoaded, 0, 0, Width, Height);
if (isInvert == true)
{
theImage = InvertBitmap(theImage);
}
else if (isGrayscale == true)
{
theImage = GrayscaleBitmap(theImage);
}
else if (isThreshold == true)
{
theImage = ThresholdBitmap(theImage);
}
else if (isResize == true)
{
theImage = resizeImage(theImage, 10, 100);
}
else if (isFilterRed == true)
{
theImage = FilterRedBitmap(theImage);
}
else if (isFilterGreen == true)
{
theImage = FilterGreenBitmap(theImage);
}
else if (isFilterBlue == true)
{
theImage = FilterBlueBitmap(theImage);
}
graphicsWindow.DrawImage(theImage, 0, 0);
}
}
i have another area in my code which sets some boolean values to true or false within the Click events....(as my program uses winforms) and hence my program knows which method to call. However, i think putting all of these things inside of paint is just bad design. My issue is that i don't know how to pass in a bitmap image into a Click event? Is that possible? I would much rather deal with what happens in the Click events rather than within the paint methods. Any idea on how i could design this better?
You should keep your paint events as fast as possible.
You should store the final image in a field in the class and regenerate it when the options change.
You can then replace your entire Paint event with a simple PictureBox.
On a side note, you should either change the various Filter functions to modify the image in-place (preferred), or dispose the old image each time you create a new one.

C# Threading Bitmap objects/PictureBox

I have some code to display video-like graphics of points moving around.
I am writing the points to a bitmap, and placing it on a picturebox.
The graphics computation has to be done on its own thread. The graphics work fine as long as you don't move the window around "too" much.
I'm using winforms. When I run the code, and move the window around wildly, I SOMETIMES get the following errors:
# this.Invoke(d, new object[ ] { bmp
}); "Cannot access a disposed
object. Object name: 'Form1'."
# gfx.DrawImage(bmpDestination, new
Point()); "Object is currently in
use elsewhere."
Here is the code:
private void button2_Click(object sender, EventArgs e)
{
Thread demoThread = new Thread(new ThreadStart(ThreadProcSafe));
demoThread.Start();
}
private void ThreadProcSafe()
{
creategraphics();
}
private void creategraphics()
{
Bitmap bmpDestination = new Bitmap(988, 588);
Bitmap bmp = new Bitmap(988, 588);
for (int i = 0; i < numtimesteps; i++)
{
bmp = GraphingUtility.create(apple, i, 988, 588, -30, 30, -30, 30);
using (Graphics gfx = Graphics.FromImage(bmp))
{
gfx.DrawImage(bmpDestination, new Point());
}
bmpDestination = bmp;
updateimage(bmp);
}
}
delegate void graphicscallback(Bitmap bmp);
private void updateimage(Bitmap bmp)
{
if (pictureBox1.InvokeRequired)
{
graphicscallback d = new graphicscallback(updateimage);
this.Invoke(d, new object[] { bmp });
}
else
{
pictureBox1.Image = bmp;
pictureBox1.Refresh();
}
}
There are problems using GDI objects across threads.
Look at Hans' double-clone suggestions in this thread.
Cannot access a disposed object. Object name: 'Form1
You get this because you don't do anything to stop the thread when the user closes the form. You'll have to keep the form alive until you know that the thread is dead. Pretty hard to do reliable, check this answer for a solution.
As an aside, calling InvokeRequired is an anti-pattern. You know that you are making the call from a worker thread. If InvokeRequired would return false then there's something really wrong. Don't bother, call Invoke() directly.
Object is currently in use elsewhere
It is an exception raised by GDI+ (Graphics) when it sees that two threads are trying to access a bitmap at the same time. It isn't obvious in your snippet but I can't see what GraphingUtility.create() does. Make sure it creates a new bitmap, not return an existing one. Because that will bomb when your thread writes to it again and the picture box repaints itself at the same time. The bmp constructor you use above it doesn't do anything.
Your PictureBox.Image assignment is forgetting to dispose the old one.

c# picturebox memory releasing problem

I'm a newby in C#. I have to repeatedly refresh a GUI picture box in a worker thread. The image is acquired from a camera polling a driver with a GetImage method that retrives the image to be displayed. Even if I allocate the bitmap using directive "using" and explicitly call G.C, memory seems to be never deallocated.
The worker thread is something like this:
while (true)
{
// request image with IR signal values (array of UInt16)
image = axLVCam.GetImage(0);
lut = axLVCam.GetLUT(1);
DrawPicture(image, lut);
//GC.Collect();
}
While the DrawPicture method is something like
public void DrawPicture(object image, object lut)
{
[...]
// We have an image - cast it to proper type
System.UInt16[,] im = image as System.UInt16[,];
float[] lutTempConversion = lut as float[];
int lngWidthIrImage = im.GetLength(0);
int lngHeightIrImage = im.GetLength(1);
using (Bitmap bmp = new Bitmap(lngWidthIrImage, lngHeightIrImage)) {
[...many operation on bitmap pixel...]
// Bitmap is ready - update image control
//SetControlPropertyThreadSafe(tempTxtBox, "Text", string.Format("{0:0.#}", lutTempConversion[im[160, 100]]));
//tempTxtBox.Text = string.Format("{0:00000}", im[160, 100]);
//System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
}
}
Problems arises with the
pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
In fact commenting that line of code, garbage collection works as it would.
Better, the problem seems to be with
System.Drawing.Image.FromHbitmap(bmp.GetHbitmap())
Any advice to solve this memory leak?
Thanks a lot!
Image implements IDisposable, so you should call Dispose on each Image instance that you create, when it is no longer needed. You could try to replace this line in your code:
pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
With this:
if (pic.Image != null)
{
pic.Image.Dispose();
}
pic.Image = System.Drawing.Image.FromHbitmap(bmp.GetHbitmap());
This will dispose the previous image (if any) before the new one is assigned.
The thing is, you're making a GDI bitmap of bmp with GetHbitmap, which according to msdn:
You are responsible for calling the
GDI DeleteObject method to free the
memory used by the GDI bitmap object.
Then the FromHbitmap method makes a copy of the GDI bitmap; so you can release the incoming GDI bitmap using the GDI DeleteObject method immediately after creating the new Image.
So basically I would add:
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
...
IntPtr gdiBitmap = bmp.GetHbitmap();
// Release the copied GDI bitmap
if (pic.Image != null)
{
pic.Image.Dispose();
}
pic.Image = System.Drawing.Image.FromHbitmap(gdiBitmap);
// Release the current GDI bitmap
DeleteObject(gdiBitmap);
I am unsure if you need the GDI bitmap to perform some kind of transformation. In case you don't you can just assign the bitmap to the Image property of your PictureBox, and ignore the former solution:
// Since we're not using unmanaged resources anymore, explicitly disposing
// the Image only results in more immediate garbage collection, there wouldn't
// actually be a memory leak if you forget to dispose.
if (pic.Image != null)
{
pic.Image.Dispose();
}
pic.Image = bmp;
There are several ways to release an image from pbox. I strongly recommend the way is that do not use pbox.Image = Image.FromFile.... If you do not use FileStream and you want to read it from file use BitMap class. Like this:
Bitmap bmp = new Bitmap(fileName);
pbox.Image = bmp; // notice that we used bitmap class to initialize pbox.
... and then you want to release the image file bmp.Dispose();
Now you can delete, move or whatever you want to the file.

Categories