Trying to load png from assembly - c#

I am trying to write helper assembly with a helper class with a static method that loads Image from resource.
Here is the code
public static BitmapImage GetImageFromResource(Assembly assembly, string file)
{
BitmapImage src = new BitmapImage();
src.BeginInit();
src.UriSource = new Uri(#"pack://application:,,,/" + assembly.GetName().Name + #";component/" + file, UriKind.Absolute);
src.CacheOption = BitmapCacheOption.OnLoad;
src.EndInit();
return src;
}
I am trying to call this from a different assembly which has the png file with Build Action as Resource (Have also tried, Embedded Resource and Content)
I am getting the following error
Additional information: Cannot locate resource 'coffee.png'.
What am I doing wrong ? Also, the C is uppercase, but somehow in error message it appears that it is trying to locate coffee.png instead of Coffee.png.
Anybody knows what am I missing here ?

Make sure that the assembly that you are loading has the updated dll. Try doing a rebuild on your class library file that has the image. What you have should work. It is only the matter that the image is not really in the dll.

Related

Load Embedded Resources from dynamically loaded assemblies

I have Class Library project that creates a dll that I side load into my main application dynamically. The main application contains API calls that I use and one of the calls is to load an icon image into a WPF button. I provide "pack://application:,,,/NamespaceOfMyDll;Component/Resources/embeddedresource.ico"
as my URI source and following is the code that tries to load this image
var logo = new BitmapImage();
logo.BeginInit();
logo.UriSource = new Uri(source);
logo.EndInit();
The image is an embedded resource of the dll that I am side loading. Doing this throws an exception saying the source is not found.
The project that is trying to load the image has no reference to the dll that I am side loading.
Is there a way to load the image without having to put it in the main application project?
Here's a workaround you can go with :
When you add images to the class's resource(I mean in Resources.resx file of the class), create public variables for each resource you add/you want to access. Sample :
public static class TestClass
{
public static Bitmap Image1 { get { return Resource1.Image1; } }
public static Bitmap Image2 { get { return Resource1.Image2; } }
}
Now, let's move on to loading the .dll into the main project :
Assembly Mydll = Assembly.Load("dll path here");
Type MyLoadClass = MyDALL.GetType("dllAssemblyName.ClassName");
object obj = Activator.CreateInstance(MyLoadClass);
Now, try to access the Bitmap variables :
Bitmap img1 = (Bitmap)obj.GetType().GetField("Image1").GetValue(obj);
///use the bitmap the way you want :)
Hope this helps
Using Build Action "Resource" instead of "Embedded Resource" solved the issue.
"Resource is for WPF applications when you want to use uri's to link to resources. Embedded resource is an embedded resource for WinForms applications that should be accessed via a ResourceManager."
https://social.msdn.microsoft.com/Forums/vstudio/en-US/29b6d203-18fb-40b0-a01f-d5b787ccf3be/build-action-resource-vs-embedded-resource?forum=netfxbcl

Why packing an URI for an image in a WPF project doesn't work if the Build Action property of the image is Content

I'm trying to use an image file in a WPF project implementing Pack URI. According to the book Head First C#, changing the Build Action property of the image to Content is a good practice. Following this guide for an image as Content I could not make it work, nevertheless, changing the image Build Action property to Resource makes it work without a problem. Here is my method code:
public static BitmapImage CreateImageFromAssets(string imageFilename)
{
try
{
Uri uri =
new Uri("pack://application:,,,/Assets/" +
imageFilename, UriKind.Absolute);
return new BitmapImage(uri);
}
catch (IOException)
{
return new BitmapImage();
}
}
I tried using other options like:
Uri uri =
new Uri("pack://application:,,,/BeesOnAStarryNight;component/Assets/"
+ imageFilename, UriKind.RelativeOrAbsolute);
Uri uri =
new Uri("pack://application:,,,/BeesOnAStarryNight;component/Assets/"
+ imageFilename, UriKind.Absolute);
The name of the image file is "Bee1.png". This is the error I got:
An unhandled exception of type 'System.InvalidOperationException' occurred in PresentationCore.dll
I tried without the try catch and got this:
An unhandled exception of type 'System.IO.DirectoryNotFoundException' occurred in mscorlib.dll
Additional information: Could not find a part of the path 'C:\Users\myuser\TRAINING\DEV\Assets\Bee1.png'.
Don't know why I got an incomplete path to the solution folder. It is several folders in after /DEV.
Want to know why it only works if the image has a Build Action property of Resource? and Is it really a good practice to use it as Content instead?
Your URI is a Resource File Pack URI, and it is sufficient to create it without specifying the UriKind, like
var uri = new Uri("pack://application:,,,/Assets/" + imageFilename);
As the name "Resource File Pack URI" implies, the image file must be a resource file, i.e. its Build Action must be Resource.

How can I include an image as a Resource in my project?

I want to add an image as a resource in my project so that I can reference it for programmatically inserting into a range in a spreadsheet.
I added the image by right-clicking the project and selecting Add > Existing Item...
I hoped that the image (.png file) would then be available using this code:
var logoRange = _xlSheet.Range[
_xlSheet.Cells[1, LOGO_FIRST_COLUMN],
_xlSheet.Cells[5, LOGO_LAST_COLUMN]];
//System.Drawing.Bitmap logo =
//ReportRunner.Properties.Resources.pa_logo_notap.png;
System.Drawing.Image logo =
ReportRunner.Properties.Resources.pa_logo_notap.png;
_xlSheet.Paste(logoRange, logo);
...but using either Bitmap or Image, I get, "'ReportRunner.Properties.Resources' does not contain a definition for 'pa_logo_notap'"
This seemed like sensible code based on what I read here, but it seems that the image has to be explicitly marked as a resource for this to work. How do I accomplish that?
UPDATE
I tried this:
System.Drawing.Image logo = (System.Drawing.Image)ReportRunner.Properties.Resources.ResourceManager.GetObject("pa_logo_notag.png");
_xlSheet.Paste(logoRange, logo);
...but not only did I get a confirmation msg about the item being pasted not being the same size and shape as the place where it was being inserted, and did I really want to do that, it also inserted some seemingly unrelated text ("avgOrderAmountCell.Style") instead of the image.
UPDATE 2
Okay, I tried this:
Assembly myAssembly = Assembly.GetExecutingAssembly();
System.Drawing.Image logo = (System.Drawing.Image)myAssembly.GetName().Name + ".pa_logo_notap.png";
Clipboard.SetDataObject(logo, true);
_xlSheet.Paste(logoRange, logo);
...but get, "Cannot convert type 'string' to 'System.Drawing.Image' on the second line of that code.
UPDATE 3
This works:
private System.Drawing.Image _logo;
. . .
_logo = logo; // logo (the image) is passed in an overloaded constructor
. . .
var logoRange = _xlSheet.Range[
_xlSheet.Cells[1, LOGO_FIRST_COLUMN], _xlSheet.Cells[6,
LOGO_LAST_COLUMN]];
Clipboard.SetDataObject(_logo, true);
_xlSheet.Paste(logoRange, _logo);
...but I'm not crazy about it, because I'm using an image that is on a form, and passing the image to this class's constructor. Passing images around seems kind of goofy when it should be possible to store the image as a resource and just load the resource. I still haven't gotten that methodology to work, though...
UPDATE 4
I reckon I'll just stick with what I've got (in Update 3), kludgy as it is, because this:
Assembly myAssembly = Assembly.GetExecutingAssembly();
Stream myStream =
myAssembly.GetManifestResourceStream(myAssembly.GetName().Name +
"pa_logo_notap.png");
Bitmap bmp = new Bitmap(myStream);
Clipboard.SetDataObject(bmp, true);
_xlSheet.Paste(logoRange, bmp);
...fails with, "Value of 'null' is not valid for 'stream'"
You have change the build action of the image to be embedded resource.
Then you can reference by doing:
UPDATED
Assembly myAssembly = Assembly.GetExecutingAssembly();
Stream myStream = myAssembly.GetManifestResourceStream( myAssembly.GetName().Name + ".images.pa_logo_notap.png");
Bitmap bmp = new Bitmap(myStream);
My method is to open Resources.resx under Properties. You'll see all your resources laid out on screen.
Click on the downarrow next to 'Add Resource' and you'll see the option Add Existing File. Choose your image name.

c# WPF URI syntax

I am just learning c# and have been struggling to work with URIs in WPF. I've googled around a fair bit but not having much luck.
Essentially I'm trying to have a BitmapImage object stored as a property in a Car object. I then want to display the BitmapImage in an Image control on a WPF form.
The app is a simple app (it's for a Uni assignment), so no database, etc.
I have two methods of doing this. The first is that I'm preloading Car data from a text file, including the filename of the JPG I want to load. I have included the JPG in a directory called Files which is off the main directory where my source code and class files are. I have set the JPG file to 'Content' and 'Always copy'. When I run a Debug, it copies the Files directory and the JPG to the debug\bin directory.
My code creates a BitmapImage by referring to the JPG using a URI as follows;
BitmapImage myImage = new BitmapImage (new Uri("Files/" + Car.Imagefilename, UriKind.Relative);
Car.Image = myImage;
ImageControl.Source = myImage;
If I step through this code in the debugger, it sometimes works and displays the image, but most of the time it doesn't.
My second method is when a user creates a new Car. This method always works. In this one, I use a file dialog box (dlg) to select the image and use an absolute path.
BitmapImage myImage = new BitmapImage (new Uri(dlg.Filename, UriKind.Absolute);
Car.Image = myImage;
ImageControl.Source = myImage;
So....I can't work out why the first method doesn't work. I think it's got something to do with the relative reference, but I can't work out how to syntax that properly to work. I've tried using "pack:,,,", I've tried adding "component", I've tried an '#' before the "pack". I can't seem to find something that explains this simply.
Apologies if this is straight forward but it's doing my head in! Appreciate any pointers.
If the image files are located in a "Files" folder of your Visual Studio project, you should set their Build Action to Resource (and Copy to Output Directory to Do not copy), and load them by a Resource File Pack URI:
var image = new BitmapImage(new Uri("pack://application:,,,/Files/" + Car.Imagefilename));
Car.Image = image;
ImageControl.Source = image;
There is no need to copy the files anywhere. Images are loaded directly from the assembly.
First try to load the image file using its absolute path. For example if the images are stored in c:\projects\yourproject\files, then try using something like
BitmapImage myImage = new BitmapImage (new Uri("c:/projects/yourproject/files/carname.jpg", UriKind.Absolute);
If it works, what you are facing is an path calculation issue.
At this point you may either calculate the Absolute with reference to your executable using AppDomain.CurrentDomain.BaseDirectory at runtime or use App.Config to store the path and reference it from there.
Cheers

Prism embedded image

I have a module called xModule. I have an image inside it marked as embedded resource.
Inside the initialization of the module I tried :
string stFileName = "SmallIcon.png";
string stAssembly = "xModule"; // That's the full name of the assembly
//img.BeginInit();
Uri uri = new Uri(String.Format(#"/{0};component/Images/{1}", stAssembly , stFileName),
UriKind.Relative);
ImageSource imgSource = new BitmapImage(uri);
During it's coming to the breakpoint on the ImageSource imgSource =.. line, it seems the ImageSource can't find the image...
Why? What's wrong with it?
I get no errors, the assembly is referenced. I did something similar in the Xaml and it worked.
Also used : VS11, Unity
I think you need to mark the image as "ressource" not "embedded ressource" ( WPF )
also See : What's the difference between a Resource and an Embedded Resource in a C# application?

Categories