Loading images from a relative path - c#

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)

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;

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;

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.

Related

Why Image not loading on android - xamarin

I put crypto.png image into drawable folder under Resources in Android Project.
After I right click on the image -> Build Action -> Embedded Resource.
In MainPage.xaml on the main project I try to load the image like that:
<Image x:Name="HeadImage"
WidthRequest="100"
HeightRequest="100"
MinimumHeightRequest="100"
MinimumWidthRequest="100"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
Aspect="AspectFit"
Source="crypto.png"/>
But the image not load.
I try a second method like this in the c# code:
var HeadImage = new Image { Aspect = Aspect.AspectFit };
HeadImage.Source = ImageSource.FromFile("crypto.png");
And this method not worked again..
You need to let your image in drawable folder as Android Resource instead of Embedded Resource, and to use it, you need to:
HeadImage.Source = "crypto.png";
Also, before set the image, is a good practice to remove MinimumWidthRequest and MinimumHeightRequest. This is safe ONLY if you are sure the image have this minimum size. Otherwise, your image will not appear.
To know more about image in Xamarin, see here.
And to understand the difference between the ways of set an ImageSource see here.

Including Optional Resource in WPF Window

I want to be able to use either a default bitmap resource or one provided by a separate assembly in a WPF window.I thought I could do this by defining the default bitmap in the Window.Resources section, and then search for and load if found the resources from the separate optional assembly:
[xaml file for window]
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<BitmapImage x:Key="J4JWizardImage" UriSource="../assets/install.png"/>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
[code behind for window constructor]
try
{
var resDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Olbert.JumpForJoy.DefaultResources.dll");
if( File.Exists( resDllPath ) )
{
var resAssembly = Assembly.LoadFile( resDllPath );
var uriText =
$"pack://application:,,,/{resAssembly.GetName().Name};component/DefaultResources.xaml";
ResourceDictionary j4jRD =
new ResourceDictionary
{
Source = new Uri( uriText )
};
Resources.Add( J4JWizardImageKey, j4jRD[ "J4JWizardImage" ] );
}
}
catch (Exception ex)
{
}
InitializeComponent();
However, the default image was always displayed, even when the separate resource assembly was present. Apparently, resources defined within a Window definition take precedence over resources added when the window is constructed.
So I removed the Window.Resources section, added a standalone resource xaml file:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Olbert.Wix.views">
<BitmapImage x:Key="DefaultWizardImage" UriSource="../assets/install.png"/>
</ResourceDictionary>
and modified the window constructor code so that if the separate assembly wasn't found, the resource from the standalone xaml file would be added instead:
if( File.Exists( resDllPath ) )
{
// same as above
}
else
Resources.Add( J4JWizardImageKey, TryFindResource( "DefaultWizardImage" ) );
This worked when the separate assembly was present. However, it failed when the separate assembly was left out, because the default image resource was not found. That may be because this Window isn't part of a WPF app; it's the UI for a Wix bootstrapper project.
It feels like there should be a simpler solution for what I'm trying to do, which I imagine is pretty common whenever a WPF library is designed (i.e., you need some way to allow customization of bitmaps, but you also want to provide a default/fallback).
It sounds like you're only ever getting the initial value of the resource, as of when the XAML was parsed. If it's not there at that time, there's nothing; if it's a thing then, it's only ever that thing.
That is the behavior you'll see when you use StaticResource to retrieve the resources rather than DynamicResource. DynamicResource will update the target when the resource is replaced.
<Label Content="{DynamicResource MyImageSomewhere}" />

Replace dynamically BitmapImage in Button (xaml)

I have following code snippet in xaml:
<UserControl x:Class="Ournamespace.OurClassName"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
...
d:DesignHeight="250" d:DesignWidth="774" Loaded="UserControl_Loaded">
....
<Button Grid.Column="0" x:Name="Button_NewMarker" Style="{StaticResource ViewpointFlatButtonStyle}" Width="90" Height="65"
VerticalAlignment="Top" Click="Button_NewMarker_Click" x:FieldModifier="public" Margin="0,0,0,0" Grid.Row="1">
<BitmapImage UriSource="Icons/markers_add_disabled.png" />
</Button>
and I have tried to replace image on button dynamically, by loading new image
if( !imgCache.ContainsKey(path) )
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(path, UriKind.Relative);
bi.DownloadFailed += bi_DownloadFailed;
bi.DecodeFailed += bi_DecodeFailed;
bi.EndInit();
imgCache[path] = bi;
}
Button_NewMarker.BeginInit();
Button_NewMarker.Content = imgCache[path];
//Button_NewMarker.Content = oldbmp;
Button_NewMarker.EndInit();
There is no error occurring (overridden events for this)
and BitmapImage seems to be replaced - but for some reason it's grey.
Images are added to project as resources, and first image loaded seems to be working - but not dynamically replaced one.
I have tried also to use <Image ... > and even <Image ... <ImageBitmap - but all of them are not working - I suspect it has something to do with our control being UserControl.
What I have seen in internet - there is huge amount of recommendations of what and how should be done - I want now this to be done with absolute minimum amount of code - and preferably without using binding and templating. Binding can be proposed as second step after everything is done manually.
If image files are managed as resource files (i.e. project files which have their Build Action set to Resource) you should load them by a Resource File Pack URI.
Assuming a project folder Images with an image file Test.png:
var bi = new BitmapImage(new Uri("pack://application:,,,/Images/Test.png"));
Using the file name as key, the abobe would probably look like:
var path = "Test.png";
var uri = "pack://application:,,,/Images/" + path;
imgCache[path] = new BitmapImage(new Uri(uri));

Change PictureBox's image to image from my resources?

How do I set a PictureBox image to an image from my resources?
(I tried this without success: pictuerbox.Image = "img_location";)
If you loaded the resource using the visual studio UI, then you should be able to do this:
picturebox.Image = project.Properties.Resources.imgfromresource
Ken has the right solution, but you don't want to add the picturebox.Image.Load() member method.
If you do it with a Load and the ImageLocation is not set, it will fail with a "Image Location must be set" exception. If you use the picturebox.Refresh() member method, it works without the exception.
Completed code below:
public void showAnimatedPictureBox(PictureBox thePicture)
{
thePicture.Image = Properties.Resources.hamster;
thePicture.Refresh();
thePicture.Visible = true;
}
It is invoked as:
showAnimatedPictureBox( myPictureBox );
My XAML looks like:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="myApp.MainWindow"
Title="myApp" Height="679.079" Width="986">
<StackPanel Width="136" Height="Auto" Background="WhiteSmoke" x:Name="statusPanel">
<wfi:WindowsFormsHost>
<winForms:PictureBox x:Name="myPictureBox">
</winForms:PictureBox>
</wfi:WindowsFormsHost>
<Label x:Name="myLabel" Content="myLabel" Margin="10,3,10,5" FontSize="20" FontWeight="Bold" Visibility="Hidden"/>
</StackPanel>
</Window>
I realize this is an old post, but loading the image directly from a resource is was extremely unclear on Microsoft's site, and this was the (partial) solution I came to. Hope it helps someone!
Ok...so first you need to import in your project the image
1)Select the picturebox in Form Design
2)Open PictureBox Tasks (it's the little arrow pinted to right on the edge on the picturebox)
3)Click on "Choose image..."
4)Select the second option "Project resource file:" (this option will create a folder called "Resources" which you can acces with Properties.Resources)
5)Click on import and select your image from your computer (now a copy of the image with the same name as the image will be sent in Resources folder created at step 4)
6)Click on ok
Now the image is in your project and you can use it with Properties command.Just type this code when you want to change the picture from picturebox:
pictureBox1.Image = Properties.Resources.myimage;
Note: myimage represent the name of the image...after typing the dot after Resources,in your options it will be your imported image file
try the following:
myPictureBox.Image = global::mynamespace.Properties.Resources.photo1;
and replace namespace with your project namespace
You can use a ResourceManager to load the image.
See the following link:
http://www.java2s.com/Code/CSharp/Development-Class/Saveandloadimagefromresourcefile.htm
You must specify the full path of the resource file as the name of 'image within the resources of your application, see example below.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
PictureBox1.Image = My.Resources.Chrysanthemum
End Sub
In the path assigned to the Image property after MyResources specify the name of the resource.
But before you do whatever you have to import in the resource section of your application from an image file exists or it can create your own.
Bye

Load and use barcode font in TextBlock

Hey, I am trying to create a BarCode input box. On it a textblock is showing a preview of what the text input will look like in the specified Barcode type.
I have a bunch of .TTF files that are the barcode fonts, they have been used in a WinForms app so I am sure they are correct. I try to load them to memory (don't want to install them) using:
sBarCodeFonts = new PrivateFontCollection();
unsafe
{
fixed (byte* p = Resources.Code39)
{
IntPtr MyIntPtr = (IntPtr)p;
sBarCodeFonts.AddMemoryFont(MyIntPtr, Resources.Code39.Length);
}
fixed (byte* p = Resources.Code128b)
{
IntPtr MyIntPtr = (IntPtr)p;
sBarCodeFonts.AddMemoryFont(MyIntPtr, Resources.Code128b.Length);
}
fixed (byte* p = Resources.i2of5)
{
IntPtr MyIntPtr = (IntPtr)p;
sBarCodeFonts.AddMemoryFont(MyIntPtr, Resources.i2of5.Length);
}
fixed (byte* p = Resources.ean13)
{
IntPtr MyIntPtr = (IntPtr)p;
sBarCodeFonts.AddMemoryFont(MyIntPtr, Resources.ean13.Length);
}
}
This seems to load the PrivateFontCollection correctly, quickwatch indicates so.
In the Barcode class, I have a MyFontFamily property, which contains the System.Media.FontFamily that corresponds to the loaded file.
This property is loaded like this:
MyFontFamily = new System.Windows.Media.FontFamily(sBarCodeFonts.Families[0].Name);
And it seems to be loaded correctly as well.
Then, I have a Barcode object, and I'm using a TextBlock to display it's text, using it's FontFamily:
<TextBlock Text="{Binding Path=MyBarcode.TextContent, RelativeSource={RelativeSource AncestorType={x:Type UserControl}, Mode=FindAncestor}, Mode=OneWay}"
FontFamily="{Binding Path=MyBarcode.MyFontFamily, RelativeSource={RelativeSource AncestorType={x:Type UserControl}, Mode=FindAncestor}, Mode=OneWay}"
Name="txt"
Grid.Row="2" />
The TextBlock displays the text using a default font every time. I've debugged and the FontFamily is correctly set to one of the loaded ones in the previous C# code.
Any clues?
Thanks.
EDIT:
Trying to simplify the problem, I've created a very quick and dirty test app to load the TTF and show it, this is the only code (besides the XAML with only a grid):
System.Windows.Media.FontFamily lFamily = new System.Windows.Media.FontFamily(new Uri(#"E:\Prototypes\TestApp\Resources\Code128b.ttf", UriKind.Absolute), "Code128bWin");
TextBlock lTextBlock = new TextBlock();
lTextBlock.Text = "jsldkasjLKJOSDIFUEWR32849792837.,ยด` ";
lTextBlock.FontFamily = lFamily;
lTextBlock.FontSize = 50.0;
grid.Children.Add(lTextBlock);
And it still shows the default font.
<FontFamily x:Key="MyFont">/WpfTest;component/Resources/#Airplanes in the Night Sky</FontFamily>
<TextBlock FontFamily="{StaticResource MyFont}">Hello world</TextBlock>
Given that when you open the .ttf the "Font name: .." is "Airplanes in the Night Sky" and your project namespace is "WpfTest" and you dragged the font into a folder called "Resources"
I don't know about the method you're using, but I've successfully embedded fonts in a WPF application before by adding the files to the project as resources, and then creating a WPF/XAML resource in markup to reference the font file (using a pack Uri). This doesn't require the fonts to be installed on the machine - they're embedded in your .exe or a .dll file.
I did not find any answer for exactly this.
But I found a solution that I did not see on Internet.
I followed a recommendation of doing a folder and marking all the files inside as Resources.
But I needed to enumerate them, and that was my main problem, because I need to load all to my screen without recording the name somewhere. I just want to simple drop another font to that folder and list it.
I found this as a solution to list all the files inside my resources/fonts folder
Fonts.GetFontFamilies(new Uri("pack://application:,,,/resources/fonts/#"))
I expect it to help you organize your fonts.

Categories

Resources