7

I'm currently working on a Card DLL in which I would need the image files for each card as an embedded resource, the current project looks like this:

Card images are in the Resources folder

Note: The card images (.png) are in the Resources folder.

The code I've been trying & is pretty much the only code I can find, is this:

Assembly _assembly;
Stream _imageStream;

private Image img;
public Image Img
{ 
get
    {
        return img;
    }
}

public Kaart() : this(5, "Spades") { }

public Kaart(int val, string s)
{
    this.KaartWaarde = val;
    this.Figuur = s;
    this._imageStream = imgS();
    this.img = new Image(_imageStream);
}

private Stream imgS()
{
    try
    {
        _assembly = Assembly.GetExecutingAssembly();
        Stream s = _assembly.GetManifestResourceStream(string.Format("{0}{1}.png", this.kaartWaarde, this.figuur.Substring(0, 1)));
        if (s != null)
            return s;
        else
            return null ;
    }
    catch
    {
        throw new Exception("Kaart kan niet geladen worden.");
    }
}

The only exception I seem to get is an exception in the creation of the Kaart object for which the code is here:

Kaart k = null;
try
{
    k = new Kaart();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message); //This MessageBox is being shown
}
ImageSourceConverter c = new ImageSourceConverter();
testBox.Source = (ImageSource)c.ConvertFrom(k.Img);

The exception being caught & shown by use of MessageBox is as follows:

Value of 'null' is not valid for 'stream'.

While watching my variables during code execution, I noticed somehow the line

Stream s = _assembly.GetManifestResourceStream(string.Format("{0}{1}.png", this.kaartWaarde, this.figuur.Substring(0, 1)));

Fails to find the image, even when using the format Kaarten.{0}{1}.png

This simply makes me wonder if I'm doing something wrong here or if I'm using the wrong syntax. Any ideas?

EDIT: Images are now being loaded properly, however the ImageSourceConverter is still throwing a NullReferenceException

Card creation & loading the Stream objects (and unloading them into an Image object) are working fine now as far as I can tell, however when trying to actually show the images in my WPF Image control using the code below, the NullRefException is thrown.

Kaartspel kaarten = new Kaartspel();

Kaart k = kaarten.kaarten[7];

ImageSourceConverter c = new ImageSourceConverter();
testBox.Source = (ImageSource)c.ConvertFrom(k.Img); //Exception here
Yorrick
  • 377
  • 2
  • 8
  • 28
  • (1) What happens if you call exactly this: `_assembly.GetManifestResourceStream("Kaarten.Resources.5S.png");` (2) where is the exception thrown? (3) show it's full stack trace. – Alex May 02 '15 at 20:17
  • @Alex The exception's being thrown here: `testBox.Source = (ImageSource)c.ConvertFrom(k.Img);` As for the stack trace, I've tried figuring out how it works, but I can't seem to... All I've found so far is using some "k" command in the immediate window, but I can't seem to figure out the right syntax? Also, when I try `_assembly.GetManifestResourceStream("Kaarten.Resources.5S.png");` nothing different happens – Yorrick May 03 '15 at 14:26
  • Your question is a typical [XY question](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). If you would have asked "how do I get my image control to show an image stored in my application resources in WPF", you would have gotten a different answer much faster. Doing an internet search for that will provide you with answers. – Alex May 03 '15 at 15:53
  • I see, however that's what I searched for at first & that search landed me with the solution I'm trying now. The thing is, for some reason that solution simply isn't working for me & I want/need to figure out why. Also, that specific search wouldn't help me completely as I need the images being stored in my Class Library, not my actual application :) – Yorrick May 03 '15 at 16:08
  • 1
    set the image resources to embedded resource in the build action – juanvan May 06 '15 at 19:12
  • The problem with `ImageSourceConverter` must be posted in a new question. – Yoh Deadfall May 07 '15 at 11:11

5 Answers5

3

To get a resource you should use GetManifestResourceStream(string) with the case-sensitive qualified resource name which consists of two dot separated parts:

  1. The default namespace of the project which contains the resource. In most cases the default namespace equals to the project name.
  2. The resource file name including the relative path to the project. All directory delimiters must be replaced by dots.
resource_name ::= default_namespace '.' full_file_name
full_file_name ::= (directory_name '.')* file_name

In your case:

string name = string.Format("Kaarten.Resources.{0}{1}.png", this.kaartWaarde, this.figuur.Substring(0, 1)));
Stream stream = _assembly.GetManifestResourceStream(name);

Another way to get a resource is using GetManifestResourceStream(Type, string). In this case the name is relative to the specified type's namespace (MSDN, see Remarks).

string name = string.Format("Resources.{0}{1}.png", this.kaartWaarde, this.figuur.Substring(0, 1)));
Stream stream = _assembly.GetManifestResourceStream(typeof(Kaart), name);
Yoh Deadfall
  • 2,711
  • 7
  • 28
  • 32
2

The easiest way to resolve this is to fetch a list of the embedded resource names:

string[] result = myAssembly.GetManifestResourceNames();

Run that in a unit test, or create a separate console application that references the assembly, do a typeof().Assembly.GetManifestResourceNames().

Remember to specify on each file Build Action: Embedded Resource and build the assembly at least once to embed the files.

I'm not to sure, but I think the file names you should use follow the pattern of (?.

Shelakel
  • 1,070
  • 9
  • 16
  • I've already used the `.GetManifestResourceNames();` method & they have already confirmed the fact that the names are `Kaarten.Resources.[name].png` I thought I already had that updated in my question, but appearantly I don't, I'll update it in a sec. – Yorrick May 11 '15 at 21:12
1

Which Image class provides a constructor that accepts a stream?

Guess you could use System.Drawing.Image.FromStream and cast it to System.Drawing.Bitmap. Then you can use the following:

System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

Robert S.
  • 1,942
  • 16
  • 22
0

_assembly.GetManifestResourceStream("{ProjectName}.resources.{ImageName.ext}");

This will load the image correctly.

Resources != resources this will cause it to error.

juanvan
  • 671
  • 7
  • 19
  • Tried both `.Resources.img.` and `.resources.img.`, small "r" returns null, large "R" does return a value, however it's still not being converted. – Yorrick May 06 '15 at 21:28
  • 1
    @Yorrick, you should ask the second question in a new post. It's a rule on Stack Overflow. – Yoh Deadfall May 12 '15 at 09:52
0

I'd like to access my images from Properties.Resources in a strong-typed way.

To achieve this right-click on your project root and select Properties then open Resources tab and drag&drop your images here (you can select them from you project's folder called resources).

Mauro Sampietro
  • 2,739
  • 1
  • 24
  • 50