C# Picturebox

HavocXphere

Honorary Master
Joined
Oct 19, 2007
Messages
33,153
Reaction score
1,297
Location
Europe
[Issue Resolved]



So I'm slowly learning .NET C#.

This works as expected:
Code:
 pictureBox2.Image = Image.FromFile(@"C:\Windows\Web\Wallpaper\Windows\img0.jpg");

This renders a white area, with a red border and red diagonal lines (i.e. crossed out)
Code:
Bitmap Pic = new Bitmap(@"C:\Windows\Web\Wallpaper\Windows\img0.jpg");
           pictureBox1.Image = (Image)Pic;

I think the Bitmap line is correct, so I'm guessing the Bitmap -> Image conversion is somehow bad. So how do I correctly convert between Image & Bitmap on the fly (both directions pls)?

Thanks
 
Last edited:
Code works fine for me.

Built a sample app and found no issues with it.

PictureBox.Image is a System.Drawing.Image. Bitmap inherits from System.Drawing.Image, so it should be fine. You can leave out the cast "(Image)Pic" and leave it as pictureBox1.Image = Pic; as Bitmap already inherits the base type of System.Drawing.Image.

The only thing I can think of is that you may have the incorrect namespaces somewhere (although this is not likely unless u've added some extra namespaces in the using directives - even then it should prompt you for the correct one) ... try fully qualify the classes just to be sure:

System.Drawing.Bitmap Pic = new System.Drawing.Bitmap(@"C:\Windows\Web\Wallpaper\Windows\img0.jpg");
pictureBox1.Image = Pic;



EDIT: On a side note... why learn normal GDI style windows forms over WPF? If you're going to pick up C#... i'd recommend the WPF route.
 
Code works fine for me.

Built a sample app and found no issues with it.
Excellent. Worked out the problem from that via process of elimination.

I had a Pic.Dispose(); further down. Didn't realize that the assignment works pointer style not copying the data itself. Noob mistake I guess.

Thanks shogun.

EDIT: On a side note... why learn normal GDI style windows forms over WPF? If you're going to pick up C#... i'd recommend the WPF route.
Looking into that right now. Thanks.
 
WPF rocks! Have only built 3 full-featured apps (released to clients) with it so far... My true love is still ASP.NET (MVC or WebForms) though.
 
Thanks for replies everyone.

So let me get this straight: Assuming I'm not using stevenv's clone trick, one would just not dispose of it at all & let this garbage collector thing sort it out? Or do I need a dispose somewhere in Form.close or something?

@dequad: Will read the article. Thx

WPF rocks! Have only built 3 full-featured apps (released to clients) with it so far...
Yeah ended up porting the (tiny amount of) code to WPF & worked well. I don't get why WPF isnt the default selection for the new solution screen. I figured Microsoft could be relied on to always push their latest & greatest tech.:p Guess not.
 
Thanks for replies everyone.

So let me get this straight: Assuming I'm not using stevenv's clone trick, one would just not dispose of it at all & let this garbage collector thing sort it out? Or do I need a dispose somewhere in Form.close or something?

Steve was just pointing out that if you didn't want a pointer to Pic then u'd have to clone (i.e. make a new one). You'd still have a pointer to a Bitmap though. That wouldn't help you with the disposing. Being a windows application, and using GDI graphics, I have a sneaky suspicion that the PictureBox needs that image reference for the life of the picturebox... for rendering reasons. Let me explain.

When GDI paints, it redraws everything from scratch all the time. Immediate Mode Graphics is what it's called it i'm not mistaken. This means that if you get rid of it's source, it cannot redraw.

In WPF, they do it a little differently. The graphics are pumped into the rendering pipeline, and converted into serialized data. That means you can set up a brush from an image, then go and delete that image once the brush has been created if you want to... the serialized data is already created, and that will be used from then on.

Bing "Immediate Mode Graphics" and "Retained Mode Graphics" for more info.

With regards to disposing. You could wait for the garbage collector, or you could explicitly implement IDisposable and clear up the references in the Dispose method (remember u'd need to explicitly call Dispose()). Alternatively, you could set up a destructor, although i'm not sure how effective that would be. In some cases, you might have references preventing the class from destructing.

I'd go the IDisposable route.
 
Thanks Shogun. Got most of that, though the IDisposable thing is still greek to me because my OO understanding is super weak.

I'm still doing Hello World's atm so I'll use Garbage Disposer unless I can clearly see that a dispose is possible. I get what you're saying about WPF & memory.

New question: Why doesn't BitmapImage have a Dispose()? I gather that when used in combination with src.CacheOption = BitmapCacheOption.OnLoad; it does load something into mem, so I should be able to dispose of it.
 
When implementing this method, ensure that all held resources are freed by propagating the call through the containment hierarchy. For example, if an object A allocates an object B, and object B allocates an object C, then A's Dispose implementation must call Dispose on B, which must in turn call Dispose on C. An object must also call the Dispose method of its base class if the base class implements IDisposable.

If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times. Instance methods other than Dispose can throw an ObjectDisposedException when resources are already disposed.

Users might expect a resource type to use a particular convention to denote an allocated state versus a freed state. An example of this is stream classes, which are traditionally thought of as open or closed. The implementer of a class that has such a convention might choose to implement a public method with a customized name, such as Close, that calls the Dispose method.

Because the Dispose method must be called explicitly, objects that implement IDisposable must also implement a finalizer to handle freeing resources when Dispose is not called. By default, the garbage collector automatically calls an object's finalizer prior to reclaiming its memory. However, once the Dispose method has been called, it is typically unnecessary for the garbage collector to call the disposed object's finalizer. To prevent automatic finalization, Dispose implementations can call the GC.SuppressFinalize method.

For more information on implementing finalizers and the Dispose method, see the GC class, the Object.Finalize method, and Implementing Finalize and Dispose to Clean Up Unmanaged Resources.

When you use an object that accesses unmanaged resources, such as a StreamWriter, a good practice is to create the instance with a using statement. The using statement automatically closes the stream and calls Dispose on the object when the code that is using it has completed. For an example, see the StreamWriter class.
http://msdn.microsoft.com/en-us/library/system.idisposable.dispose.aspx
 
New question: Why doesn't BitmapImage have a Dispose()? I gather that when used in combination with src.CacheOption = BitmapCacheOption.OnLoad; it does load something into mem, so I should be able to dispose of it.

I might be wrong here, but it may be because BitmapImage inherits from Freezable. Properties on frozen objects (i.e. a Freezable object on which the Freeze() method has been called) cannot be modified. If they are, then the object will throw an exception. (Side note: Freezing an object reduces its resource usage considerably, and allows you to move it between threads). If BitmapImage had a Dispose method, the logic inside the Dispose Method would inevitably change properties on the object, which would throw the exception if the BitmapImage was indeed frozen. I think the data loaded into memory is also not stored in the BitmapImage (ImageSource). I think it's actually stored in the rendering pipeline.

Setting the reference to the BitmapImage to null should suffice. If you are setting a LOT of BitmapImages to null at some point and the GC is not keeping up, you can always invoke it using GC.Collect() to force a garbage collect. It's safe to do, but you don't really want to do it too often as it can slow down the app at the wrong places. Best to pick a spot after all the images you no longer need are nulled... if it even becomes a problem that is. 99% of the time it's not necessary.

If you are interested, do some reading here: http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.bitmapimage.aspx

On that page, you will see "Inheritance Hierarchy". Click on each of those classes and check them out (the "Remarks" sections hold the meat). In fact, I recommend this for everything WPF related. IMO, it's the fastest way to pick up WPF and understand the internals (side by side with Adam Nathan's book "Sams Windows Presentation Foundation Unleashed"). Be warned though, it's addictive, and you may end up clicking around for days. The MSDN documentation on WPF is really top notch.
 
Last edited:
I think I'll need some more OO & C# understanding before I can follow that. Back to basics...

Thanks guys
 
I'm happy to see some good .Net questions cropping up here. Not many people care enough to ask the more tricky questions. If more of this happens, we're going to have to spin off a .Net development forum:P
 
With regards to disposing. You could wait for the garbage collector, or you could explicitly implement IDisposable and clear up the references in the Dispose method (remember u'd need to explicitly call Dispose()). Alternatively, you could set up a destructor, although i'm not sure how effective that would be. In some cases, you might have references preventing the class from destructing.

Without going and refreshing my memory ... implementing IDisposable would assume you've created a class that contains a reference to your image i.e.

Code:
public class MyClass : IDisposable 
{
  public MyImage(String path)
  {
    MyImage = new Bitmap(path);
  }

  public Image MyImage { get; }

  public void Dispose()
  {
    if (MyImage != null)
      MyImage.Dispose
  }
}

public class Test
{
  public void main(String[] args)
  {
    using (MyClass me = new MyClass(@"..."))
    {
      //Do something with me.MyImage
    } //At this point IDisposable.Dispose() will be called implicitly
  }
}

Disclaimer: this is a pretty simple example illustrating a point rather than being functional. Also, wrote the above without checking syntax AND without following the proper pattern for implementing IDisposable (this can be obtained on MSDN).

From MSDN on IDisposable:
The primary use of this interface is to release unmanaged resources. The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used. However, it is not possible to predict when garbage collection will occur. Furthermore, the garbage collector has no knowledge of unmanaged resources such as window handles, or open files and streams.

By "disposing" the object it doesn't necessarily free up the memory used by that object, it just indicates to the garbage collector that it "can" be collected. If the runtime doesn't require the memory it won't actually garbage collect the object. There are very intersting articles on how the garbage collector works internally with things like generations etc. If you're serious about development, it's important to know this stuff especially in "memory-maintenance-free" languages like C#.

Destructors are a whole other topic ...

Execution of the destructor for the instance may occur at any time after the instance becomes eligible for destruction.

I got that from here. Basically although you can write a destructor for your class you cannot control when it gets invoked and as a result should not rely on it for releasing resources that other code is dependant on. Destructors are helpful in releasing resources when the program executes i.e. closing database connections although you can also implement that type of functionality inside IDisposable.Dispose();

Side note: found a pretty good article on CodeProject that goes into more detail and provides a more "correct" example.
 

Yes you are quite correct. In referencing IDisposable, I should have been more clear that calling Dispose() prepares the object for garbage collection, and does not actually deallocate the memory. If you don't dispose the object, and release event handlers and references that may keep it alive, it's quite possible that the object will just hang about in memory until something higher up the tree is disposed or destructed. In some cases (e.g. PRISM framework), the references (although supposed to be weak references) can keep the object alive unless you explicitly implement and call Dispose().


Thanks for clearing that up stevenv.
 
Top
Sign up to the MyBroadband newsletter
X