Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading images from a relative path

Tags:

c#

wpf

resx

I'm making a Blackjack game for a project in college (semester-long) and I've hit a road block that I can't seem to get over.

I'm trying to load the card images so they can be displayed onscreen, but I've been having very little luck in doing so. I've got absolute references down; I can load from those, but any attempt to load from a relative path fails. The project must be standalone; I can't instruct my professor to copy these images onto the root.

#if FROMDISK
        Uri myUri = new Uri(@"C:\cards\" + getFilename(r, s, "png"), UriKind.Absolute);
        PngBitmapDecoder decoder2 = new PngBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
        BitmapSource bmp = decoder2.Frames[0];
#else
        System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();
        Stream myStream = myAssembly.GetManifestResourceStream("Blackjack." + getFilename(r, s, "png"));
        BitmapImage bmp = new BitmapImage();
        bmp.StreamSource = myStream;
#endif
        // Draw the Image
        im.Source = bmp;
        im.Stretch = Stretch.Uniform;
        im.Width = CARD_WIDTH;

(Context)

like image 878
Sean Allred Avatar asked Oct 25 '12 23:10

Sean Allred


3 Answers

You can use:

Uri uri = new Uri(@"FolderName\FileName.png",UriKind.Relative);
PngBitmapDecoder decoder2 = new PngBitmapDecoder(uri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);

Remember to set the properties for the image file to (otherwise the compiler will skip them) you can look the bin/debug folder after build and verify that the file is where it should be:

  • Build action: content
  • Copy to output directory: Copy always

Another option is to make the file an embedded resource then you can access it like this:

Bitmap bitmap = Properties.Resources.FileName;
like image 171
Johan Larsson Avatar answered Nov 09 '22 01:11

Johan Larsson


I like to declare images as resources in my XAML. I will assume that you can still play around with the code structure at this point, and hopefully there aren't too many new concepts for you. Here's how I do it:

Start y creating a folder in your project called "Images". Add the images of your cards by drag and dropping them onto the folder in Visual Studio. Make sure their "Build Action" is set to Resource.

Create a new "Resource Dictionary" by pressing CTRL-SHIFT-A. Name it CardImages.xaml.

Link this file in App.xaml like this (showing how to link multiple XAML files at once, but for this of course remove the "AnyDictionary" line!)

App.XAML:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Controls/CardImages.xaml" />
            <ResourceDictionary Source="Controls/AnyDictionaryYouWant.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

Add this code to CardImages.xaml. Rename "MyBlackJackAssembly" to the assembly name of your proejct.

<Style TargetType="Image">
    <Setter Property="RenderOptions.BitmapScalingMode" Value="HighQuality" />
</Style>

<DataTemplate x:Key="Spade1">
    <Image Source="MyBlackJackAssembly;component/Images/Spade1.png" />
</DataTemplate>

<DataTemplate x:Key="Spade2">
    <Image Source="MyBlackJackAssembly;component/Images/Spade2.png" />
</DataTemplate>

Then, you can locate them in your code like this:

Label label = new Label();
label.ContentTemplate = (DataTemplate)label.FindResource("Spade1");

This will get you a WPF Label object that should show your card. This technique works with anything that supports ContentTemplate. You can then add your Label to a grid on your UI, I'm not sure how you display your cards on screen.

For a blackjack application, I would probably create a UserControl called "Card" in order to be able to generate it kind of like this. This encapsulates the "card generation" logic into its own Control so the rest of the code can just focus on dealing the cards.

XAML:

<myControls:CardImage Kind="Spades" Digit="1" />

Or like this in c#:

CardImage aCard = new CardImage();
aCard.Kind = CardImage.Kinds.Spades; //enum
aCard.Digit = 1;
like image 20
Joe Avatar answered Nov 09 '22 03:11

Joe


The way I'm loading some background images that are imported in the project's resources:

this.staticBg.Source = new BitmapImage(
    new Uri(@"/Project;component/Images/" + ((App)App.Current).bgImage
                                          + ".jpg", UriKind.Relative));

Where "Project" is project name. So basically you should add images to resources and call them with relative uri.

like image 36
Clone Avatar answered Nov 09 '22 01:11

Clone