understanding resources/image loading

bwells

Regular
Joined
Feb 25, 2003
Messages
84
I am trying to understand the use of resources when it comes to using a bitmap image in my program.

If I add an image to a background or a picture box, it somehow gets incorporated into my assembly, and all wired up and all I see is a resources.getObject being casted to a Bitmap call on a variable name and there is no where in my program anything about the actual file name of the image.

If I want to add an image to my assembly to use in a program, I understand about creating a bitmap from a file, but how can I incporporate the file in my program so I dont have to worry about distributing the file and instead it gets embedded in the assembly simliarly to how a picturebox gets its image. It seems like a great way to reference files that I want to keep hidden from the distribution, but I dont understand how to do it.

So for instance, if I set one background image in design view, it works without having a file reference in my code. What if I want to have a second, alternate background image that I can switch at runtime. How can I create this second image without having to reference the image file?

I see if I look at the resource file for the class, that the bitmap I set on the background seems to be embedded in the XML resource file. But how did this happen? Is this a good way to distribute an alternate background image, or is opening and loading a binary image file faster or better for other reasons?


thanks
Bryan
 
Last edited:
Here are directions for embedding a resource such as this in your assembly:

1) Right-click on your project, go to Add, then Existing Item. Select the image file and it will be added to your project tree.
2) Highlight the newly added file, and in the property grid change its BuildAction to Embedded Resource.
3)
(VB) Make a note of your root namespace, set in the project options. You'll need to specify this when extracting the image at runtime.
(C#) Make a note of the default namespace for your project, found in project options. If you place the resource in a subfolder on your project tree you will have to specify that as well.
4) In code, use the following to get the image:

Visual Basic:
Dim b As Bitmap

b = New Bitmap(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("MyRootNamespace.logo.jpg"))

C#:
Bitmap b;

b = new Bitmap(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("MyDefaultNamespace.logo.jpg"));

5) You can now do what you like to it, including assigning it to a picturebox -

myPictureBox.Image = b
 
This technique loads an image at runtime. And the other technique I see where the bitmap image ends up as ascii in an XML resource file means the image file is no longer used to load the image, right? It seems that if the image is converted to ascii in an XML file, it could take longer than a binary read of the image like your above example shows.

But if I select a background image at design time, it ends up in an XML resource file. Is this slower or less desirable than making using the techique you show above?

thanks
Bryan
 
Both techniques are essentially the same. The image gets encoded the same, and embedded in the executable the same. The image is copied and embedded in both cases, so the original image file is not a dependancy.

I'm pretty sure the image format is maintained too, I've often used embedded gifs because I needed the transparency channel.
 
Divil,
I've tried following your instructions for imbedding a resource. I don't seem to have any problems added them to the project, and setting the BuildAction.

However, when I try to execute the line to extract the file, I get the following error:

An unhandled exception of type 'System.ArgumentException' occurred in system.drawing.dll
Additional information: 'null' is not a valid value for 'stream'.

My namespace is My_VB.net_Notes
The image is imgButton.bmp
and my code is

Dim b As Bitmap
b = New Bitmap(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("My_VB.net_Notes.imgButton.bmp"))

Any ideas?
Dave
 
Yes, you got something wrong. I suggest you get Reflector by Lutz Roeder, it's an essential tool to have. You can open your executable in it and see what the resource got embedded as (its name) and then any error in your code should become obvious.

Get it at http://www.aisto.com/roeder/dotnet/
 
Reflector is a nice utility, thanks for the tip.

It did indeed show me my mistake, as I had a typo in the name of the image I was using. Everything is now working.

Thanks again,
Dave
 
There's a good chance it's your string, "My_VB.net_Notes.imgButton.bmp" but I'm not sure what it should be without seeing your project.

As for the efficiency of storing the bitmaps in the XML file (the resource file specific to a form) or as an embedded resource (through Add Existing Item), they are exactly the same. The one in the form only looks odd because XML must be a string so some encoding is necessary to get it in that format. divil is right in assuming that the file type is preserved as well (a gif is a gif, a jpg is a jpg) - no conversion is occurring, just encoding.

There might be a difference in how the two images are loaded, since one loads from the form's resource and, I assume, is loaded in memory with the form since the constructor calls InitializeComponent which loads the embedded image. The other embedded resource (in your assembly) won't get loaded until you explicitly load it. Although there are two methods to loading resources (the one the form uses and the code divil gave), I would imagine they're both wrappers and eventually call the same code to load a chunk of data from a resource and then cast it to the appropriate type (a Bitmap or Image object).

Just more (mostly useless) information :)

-Nerseus
 
Back
Top